def test_deck_61mountains(self): tlh = TestLoadHelper() tlh.basics_loader() tformat = Format.objects.filter(format='Standard_2015-01-23').first() tdeck = Deck() tdeck.name = 'My Deck Name' tdeck.url = 'http://card.ninja/' tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = tformat tdeck.save() c1 = Card.objects.filter(multiverseid=1004).first() dc1 = DeckCard() dc1.physicalcard = c1.basecard.physicalcard dc1.deck = tdeck dc1.cardcount = 61 dc1.board = dc1.MAIN dc1.save() self.assertEquals(tdeck.get_card_count(), 61) self.assertTrue(tdeck.is_legal())
def test_tcbf(self): tlh = TestLoadHelper() tlh.basics_loader() mountain = BaseCard.objects.filter(name='Mountain').first().physicalcard island = BaseCard.objects.filter(name='Island').first().physicalcard formats = Format.objects.filter(formatname='Modern').order_by('-start_date') myform = formats[0] prev_form = formats[1] tdeck = Deck() tdeck.name = 'My Deck Name' tdeck.url = 'http://card.ninja/' tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = myform tdeck.save() tdeck = Deck.objects.get(pk=tdeck.id) dc1 = DeckCard() dc1.physicalcard = island dc1.deck = tdeck dc1.cardcount = 60 dc1.board = DeckCard.MAIN dc1.save() self.assertEquals(tdeck.get_card_count(), 60) tourny = Tournament(name='Test', url='http://foo.dog/', format=myform, start_date=myform.start_date, end_date=myform.start_date) tourny.save() td = TournamentDeck(tournament=tourny, deck=tdeck, place=1) td.save() FormatStat.calc_all() FormatCardStat.calc_all() fstat = FormatStat.objects.filter(format=myform).first() mstat = FormatCardStat.objects.filter(format=myform, physicalcard=mountain).first() istat = FormatCardStat.objects.filter(format=myform, physicalcard=island).first() cc = FormatCardStat.objects.top_cards_by_format(myform) self.assertEquals(cc.count(), 5, "5 cards, the basic lands, are all in this format") first_cc = cc.first() self.assertEquals(first_cc.physicalcard, island, "Top card in this format is Island") self.assertEquals( first_cc.previous_format_ids, str( prev_form.pk), "The previous format ids on the FormatCardStat object should be the previous format id") self.assertIsNone(first_cc.percentage_of_all_cards_previous(), 'None previously, so no number is returned') self.assertEquals( first_cc.percentage_of_all_cards_delta(), 1.0, 'There has been a change that is positive {}'.format( first_cc.percentage_of_all_cards_delta())) self.assertIsNone(first_cc.percentage_of_all_cards_perchange(), 'None previously, so no number is returned')
def manabaseanalysis(request): context = BASE_CONTEXT.copy() context['current_formats'] = Format.objects.filter(start_date__lte=timezone.now(), end_date__gt=timezone.now()).order_by('format') # REVISIT - unsafe index context['format'] = context['current_formats'][0] card_list = '''1 Pithing Needle 4 Chromatic Star 1 Ancient Grudge 1 Boil 3 Nature's Claim 3 Pyroclasm 4 Expedition Map 3 Oblivion Stone 4 Sylvan Scrying 4 Ancient Stirrings 1 Relic of Progenitus 4 Wurmcoil Engine 3 Thragtusk 4 Chromatic Sphere 4 Karn Liberated 1 Grafdigger's Cage 2 Ugin, the Spirit Dragon 2 Ulamog, the Ceaseless Hunger 2 Warping Wail 1 Kozilek's Return 1 World Breaker''' if 'format' in request.POST: for ff in context['current_formats']: if request.POST['format'] == ff.format: context['format'] = ff break if 'cardlist' in request.POST: card_list = request.POST['cardlist'] deck_cards = Deck.read_cards_from_text(card_list, throw_exception=False) if 'errors' in deck_cards: context['errors'] = deck_cards['errors'] context['card_list'] = list() for key in deck_cards: if key != 'errors' and isinstance(deck_cards[key], dict) and 'physicalcard' in deck_cards[key]: context['card_list'].append('{} {}'.format(deck_cards[key]['card_count'], deck_cards[key]['physicalcard'].get_card_name())) analyzer = Analyzer(format=context['format']) deck_score_tuples, query = analyzer.analyze(deck_cards) context['analysis'] = query context['analysis_json'] = json.dumps(query, sort_keys=True, indent=2, cls=DjangoJSONEncoder) context['deckcards'] = list() if len(deck_score_tuples): all_deckcards = DeckCard.objects.filter(deck=deck_score_tuples[0][0]) context['recommendation_score'] = 1000.0 - deck_score_tuples[0][1] for dc in all_deckcards: if dc.physicalcard.get_face_basecard().is_land(): context['deckcards'].append(dc) return render(request, 'decks/manabase.html', context)
def test_tcbf_2b(self): tlh = TestLoadHelper() tlh.basics_loader() mountain = BaseCard.objects.filter(name='Mountain').first().physicalcard island = BaseCard.objects.filter(name='Island').first().physicalcard formats = Format.objects.filter(formatname='Modern').order_by('-start_date') myform = formats[0] prev_form = formats[1] for fformat in [myform, prev_form]: tdeck = Deck() tdeck.name = 'My Deck Name in {}'.format(fformat.format) tdeck.url = 'http://card.ninja/{}'.format(fformat.id) tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = fformat tdeck.save() tdeck = Deck.objects.get(pk=tdeck.id) dc1 = DeckCard() dc1.physicalcard = island dc1.deck = tdeck dc1.cardcount = 60 dc1.board = DeckCard.MAIN dc1.save() tourny = Tournament( name='Test {}'.format( fformat.pk), url='http://foo.dog/', format=fformat, start_date=fformat.start_date, end_date=fformat.start_date) tourny.save() td = TournamentDeck(tournament=tourny, deck=tdeck, place=1) td.save() FormatStat.calc_all() FormatCardStat.calc_all() fstat = FormatStat.objects.filter(format=myform).first() mstat = FormatCardStat.objects.filter(format=myform, physicalcard=mountain).first() istat = FormatCardStat.objects.filter(format=myform, physicalcard=island).first() first_cc = istat self.assertEquals(first_cc.percentage_of_all_cards_previous(), 1.0, 'All previously, so 100% is returned') self.assertEquals(first_cc.percentage_of_all_cards_delta(), 0.0, 'Same as last format, so no delta') self.assertEquals(first_cc.percentage_of_all_cards_perchange(), 0.0, 'No change... still 100%') self.assertEquals(first_cc.percentage_of_all_cards_previous(format_lookback_days=10), 1.0, 'F All previously, so 100% is returned') self.assertEquals(first_cc.percentage_of_all_cards_delta(format_lookback_days=10), 0.0, 'F Same as last format, so no delta') self.assertEquals(first_cc.percentage_of_all_cards_perchange(format_lookback_days=10), 0.0, 'F No change... still 100%')
def validate_master_vault_url(value): master_vault_id = Deck.get_id_from_master_vault_url(value) try: master_vault_id = uuid.UUID(master_vault_id) except ValueError: raise(ValidationError( _('Master vault link is invalid'), code='invalid' ))
def get_or_create(cls, puuid, deck_code): account = LorAccount.get_or_create(puuid=puuid) deck = Deck.get_or_create(deck_code=deck_code) account_deck, _ = AccountDeck.objects.get_or_create(account=account, deck=deck) return account_deck
def test_one_deck(self): tlh = TestLoadHelper() tlh.basics_loader() island = BaseCard.objects.filter(name='Island').first().physicalcard myform = Format.objects.filter(formatname='Modern').order_by('-start_date').first() tdeck = Deck() tdeck.name = 'My Deck Name' tdeck.url = 'http://card.ninja/' tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = myform tdeck.save() tdeck = Deck.objects.get(pk=tdeck.id) dc1 = DeckCard() dc1.physicalcard = island dc1.deck = tdeck dc1.cardcount = 60 dc1.board = DeckCard.MAIN dc1.save() self.assertEquals(tdeck.get_card_count(), 60) tourny = Tournament(name='Test', url='http://foo.dog/', format=myform, start_date=myform.start_date, end_date=myform.start_date) tourny.save() #tourny = Tournament.objects.all().first() td = TournamentDeck(tournament=tourny, deck=tdeck, place=1) td.save() #td = TournamentDeck.objects.filter(tournament=tourny, deck=tdeck, place=1).first() FormatStat.calc_all() FormatCardStat.calc_all() fstat = FormatStat.objects.filter(format=myform).first() mstat = FormatCardStat.objects.filter(format=myform, physicalcard=island).first() dcount = mstat.deck_count self.assertEquals(dcount, 1) tdcount = fstat.tournamentdeck_count self.assertEquals(tdcount, 1) tdccount = fstat.tournamentdeckcard_count self.assertEquals(tdccount, 60) self.assertEquals(mstat.in_decks_percentage(), 100.0)
def test_deck_inst(self): tlh = TestLoadHelper() tlh.basics_loader() tformat = Format.objects.all().first() tdeck = Deck() tdeck.name = 'My Deck Name' tdeck.url = 'http://card.ninja/' tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = tformat tdeck.save() self.assertEquals(tdeck.format.id, tformat.id) c1 = Card.objects.filter(multiverseid=1002).first() self.assertEquals(c1.basecard.name, 'Island') dc1 = DeckCard() dc1.physicalcard = c1.basecard.physicalcard dc1.deck = tdeck dc1.cardcount = 8 dc1.board = dc1.MAIN dc1.save() self.assertEquals(tdeck.get_card_count(), 8) c2 = Card.objects.filter(multiverseid=1004).first() self.assertEquals(c2.basecard.name, 'Mountain') dc2 = DeckCard() dc2.physicalcard = c2.basecard.physicalcard dc2.deck = tdeck dc2.cardcount = 3 dc2.board = dc2.MAIN dc2.save() self.assertEquals(tdeck.get_card_count(), 11)
def ajax_createDeck(request): if request.is_ajax(): get_all_cards = request.POST['cards[]'] name = request.POST['name'] deck1 = Deck() deck1.name = name deck1.user = request.user deck1.save() arrayGetcountDoublon = [] for i in json.loads(get_all_cards): entry = Deck.objects.get(id=deck1.id) insert_cards = Deck_user(card_id=i['card_id'], deck_id=entry.id) insert_cards.save() arrayGetcountDoublon.append(i['card_id']) count_cards = {k: arrayGetcountDoublon.count(k) for k in set(arrayGetcountDoublon)} for i in count_cards: cccmoi = list(Card_user.objects.filter(card_id=i)) if count_cards[i] == 1: Card_user.objects.filter(user_id=request.user.id, card_id=i).delete() else: for zizi in range(count_cards[i]): Card_user.objects.filter(user_id=request.user.id, id=cccmoi[zizi].id).delete() return HttpResponse('ok')
def test_all_decks_as_dict(self): """Tests the get_all_decks_as_dict() classmethod of the Deck model.""" # Get the dict containing all decks decks_dict = Deck.get_all_decks_as_dict() # Check if the dict is correct # Note: The order is important because of the way the models get ordered defined in the Meta class of Deck self.assertDictEqual( decks_dict, { "decks": [{ "id": 2, "name": "Second", "official": True }, { "id": 1, "name": "First", "official": False }] }, "get_all_decks_as_dict() doesn't give the right result!")
def recommendations(request): context = BASE_CONTEXT.copy() context['current_formats'] = Format.objects.filter(start_date__lte=timezone.now(), end_date__gt=timezone.now()).order_by('format') # REVISIT - unsafe index context['format'] = context['current_formats'][0] include_lands = 'exclude_lands' not in request.POST context['exclude_lands'] = not include_lands pcs = list() if 'format' in request.POST: for ff in context['current_formats']: if request.POST['format'] == ff.format: context['format'] = ff break if 'cardlist' in request.POST: try: pcs_dict = Deck.read_cards_from_text(request.POST['cardlist'], throw_exception=False) for key in pcs_dict: if key != 'errors' and 'physicalcard' in pcs_dict[key]: pcs.append(pcs_dict[key]['physicalcard']) except Deck.CardsNotFoundException as cnfe: pass #sys.stderr.write("cardlist is '{}'".format(pcs)) context['card_list'] = (a.get_card_name() for a in pcs) context['seeds'] = (a.get_latest_card() for a in pcs) context['recommendations'] = () context['spicy'] = list() if len(pcs): dcr = Recommender() context['recommendations'] = dcr.get_recommended_cards(pcs, context['format'], include_lands=include_lands) # get spicy... basic_supertype = Supertype.objects.filter(supertype='Basic').first() #sys.stderr.write("Basic type is {}\n".format(basic_supertype)) for tcard in context['recommendations']: if basic_supertype in tcard.basecard.types.all(): # Let's not look up similar cards to Basic lands continue sims = tcard.basecard.physicalcard.find_similar_cards(max_results=4) for sim in sims: #sys.stderr.write("%%%% SIM IS {} for {}\n".format(sim, tcard)) if sim.basecard.physicalcard in pcs: #sys.stderr.write("-- skipping {} for spicy because the user already wants it!\n".format(sim)) continue # Let's not consider Basic lands as spicy if basic_supertype in sim.basecard.supertypes.all(): #sys.stderr.write("-- skipping basic land for spicy.\n") continue # Let's only recommend cards in the current format if FormatBasecard.objects.filter(basecard=sim.basecard, format=context['format']).count() == 0: #sys.stderr.write("-- skipping {} for spicy because it isn't in format.\n".format(sim)) continue if sim in context['recommendations']: #sys.stderr.write("-- skipping {} for spicy because it is already recommended.\n".format(sim)) continue if sim in context['spicy']: #sys.stderr.write("-- skipping {} for spicy because it is already spicy!\n".format(sim)) continue #sys.stderr.write("starting with score of {}\n".format(tcard.annotations['match_confidence'])) sim.annotations['spicy_score'] = tcard.annotations['match_confidence'] + (sim.annotations['similarity_score'] * 50.0) context['spicy'].append(sim) break if len(context['spicy']) >= 8: break return render(request, 'decks/recommendations.html', context)
def add(request): error_messages = [] # Must have all info filled out before registering a field user_can_register_decks = request.user.profile.is_complete() # Can't register too many decks max_uploads_in_day = settings.MAX_UPLOADS_PER_DAY twenty_four_hours_ago = datetime.datetime.now() - datetime.timedelta( hours=24) my_uploads_today = DeckRegistration.objects.filter( user=request.user, created_on__gte=twenty_four_hours_ago) user_hit_register_rate_limit = len( my_uploads_today) > max_uploads_in_day - 1 if request.method == 'POST': form = RegiseterNewDeckForm(request.POST, request.FILES) signed_nonce = SignedNonce.from_post(request.POST) if not signed_nonce.is_valid(): error_messages.append( 'This registration code has expired. Please use submit a new registration using the code below.' ) elif form.is_valid(): # Process the form... master_vault_url = form.cleaned_data['master_vault_link'] master_vault_id = Deck.get_id_from_master_vault_url( master_vault_url) deck, created = Deck.objects.get_or_create(id=master_vault_id) if created: r = get(deck.get_master_vault_api_url()) deck.name = r.json()['data']['name'] deck.save() else: # Only allow the user to have one pending registartion per deck old_registrations = DeckRegistration.objects.filter( user=request.user, deck=deck, status=DeckRegistration.Status.PENDING).update( is_archived=True) registration = DeckRegistration() registration.user = request.user registration.deck = deck registration.verification_code = signed_nonce.nonce try: registration.verification_photo_url = save_verification_photo( request, form, deck) registration.save() email = NewDeckRegistrationSubmittedEmail(registration) email.send() return HttpResponseRedirect( reverse('register-detail', kwargs={'pk': registration.id})) except ClientError: error_messages.append("Oops! Let's try that again") else: form = RegiseterNewDeckForm() return render( request, 'register/page-new.html', { 'form': form, 'signed_nonce': SignedNonce.create(), 'user_can_register_decks': user_can_register_decks, 'user_hit_register_rate_limit': user_hit_register_rate_limit, 'error_messages': error_messages })
def handle(self, *args, **options): #logger = logging.getLogger(__name__) # the first (and only) arg should be a filename if len(args) < 1: sys.stderr.write("No directory name given.\n") return directory = args[0] if not os.access(directory, os.R_OK): sys.stderr.write("Cannot read directory '{}'.\n".format(filename)) return onlyfiles = [f for f in listdir(directory) if isfile(join(directory, f))] for filename in onlyfiles: if filename.find('tournament_') > -1: # and False: # REVISIT - commented out for the moment! filehandler = open(join(directory, filename)) jblob = json.load(filehandler) #{"url": "/en/content/2011-great-britain-national-championship", "tournament_format": null, "name": "Great Britain National Championship", "start_date": "2011-08-19"} if jblob['name'].lower().find('test deck') > -1: sys.stdout.write("Tournament: skipped test deck tournament: {}\n".format(jblob['name'])) pass else: turl = jblob['url'] # The StarCityGames tournaments will probably not have a URL at all if turl is None or len(turl) == 0: pass # Some of the Wizards-crawled tournaments will not have a fully-qualified URL elif turl.find('http') < 0: turl = 'http://magic.wizards.com' + turl format_string = jblob['tournament_format'] if format_string is None: format_string = 'Unknown' elif format_string.find('Modern') > -1: format_string = 'Modern' elif format_string.find('Standard') > -1: format_string = 'Standard' elif format_string.find('Commander') > -1: format_string = 'Commander' elif format_string.find('Tiny') > -1: format_string = 'TinyLeaders' db_format = Format.objects.filter( formatname=format_string, start_date__lte=self.isodate(jblob['start_date']), end_date__gte=self.isodate(jblob['end_date'])).first() if db_format is not None: db_tournament = Tournament.objects.filter( format=db_format, name=jblob['name'], start_date=self.isodate(jblob['start_date'])).first() if db_tournament is None: # let's make one! db_tournament = Tournament( format=db_format, name=jblob['name'], start_date=self.isodate(jblob['start_date']), end_date=self.isodate(jblob['end_date']), url=turl) db_tournament.save() sys.stdout.write("Tournament: created {}\n".format(jblob['name'])) else: if turl.find('/node/') < 0: db_tournament.url = turl sys.stdout.write("Tournament: updated {}\n".format(jblob['name'])) db_tournament.save() else: sys.stdout.write("Tournament: skipped updated with node {}\n".format(jblob['name'])) else: sys.stdout.write("Tournament: skipped no format '{}' found in db {}\n".format(format_string, jblob['name'])) tournament_url_re = re.compile('^(.+/coverage/([^/]+))/?') # Process the deck files for filename in onlyfiles: if filename.find('deck_') > -1: ###fqfilename = join(directory, filename) # print "last modified: %s" % time.ctime(getmtime(fqfilename)) # REVISIT - nothing processes because I was working on only processing the mostrecent files... # continue filehandler = open(join(directory, filename)) jblob = json.load(filehandler) # let's test if jblob is a set JSON if 'name' in jblob and 'mainboard_cards' in jblob: tourna = None # let's deal with decks that have valid tournament URLs if 'tournament_url' in jblob and jblob['tournament_url'] is not None and len(jblob['tournament_url']) > 0: # We are going to skip decks and tournaments that look like draft and sealed if jblob['tournament_url'].find('draft') > 0 or jblob['tournament_url'].find('sealed') > 0: # skip sys.stdout.write("Deck: skipped limited {}\n".format(jblob['name'])) continue # now find the tournament tu_match = tournament_url_re.search(jblob['tournament_url']) tournament_url = jblob['tournament_url'] tournament_name = '' if tu_match: tournament_url = tu_match.group(1) tournament_name = tu_match.group(2) # find a real tournament that we match to sys.stdout.write("HERE with '{}' and '{}'\n".format(tournament_url, tournament_name)) tourna = Tournament.objects.filter(url=tournament_url).first() # exclude(format__formatname='Unknown').first() elif 'tournament_name' in jblob and 'deck_format' in jblob: # Let's look for tournaments by name and date instead tourna = Tournament.objects.filter(name=jblob['tournament_name'], format__formatname=jblob['deck_format']).first() else: # we just aren't going to have a tournament. pass # Let's see if we already have a deck for this. deck = None # We are going to look at the "deckid" parameter that StarCityGames decks have and match on just that id. dukey_m = SCG_DECK_URL_KEY_RE.search(jblob['url']) if dukey_m: #sys.stdout.write("** MATCHED: {}\n".format(dukey_m.group(1))) deck = Deck.objects.filter(url__icontains='deckid={}'.format(dukey_m.group(1))).first() #sys.stdout.write("** MATCHED: deck is {}\n".format(str(deck))) else: deck = Deck.objects.filter(url=jblob['url']).first() if deck is None: # no deck, so let's add it! deck = Deck(url=jblob['url'], visibility=Deck.HIDDEN) deck.name = jblob['name'] deck.authorname = jblob['author'] if tourna is not None and tourna.format is not None: deck.format = tourna.format elif 'deck_format' in jblob: try: db_format_q = Format.objects.filter( formatname=jblob['deck_format'], start_date__lte=self.isodate( jblob['tournament_date']), end_date__gte=self.isodate( jblob['tournament_date'])).first() deck.format = db_format except ValueError: # Looks like we cannot find a valid format because we don't have a real # deck_format or a real tournament_date. sys.stdout.write("Deck: skipped '{}' because a valid format cannot be found\n".format(jblob['name'])) deck = None pass if deck is not None: deck.save() sys.stdout.write("Deck: created {}\n".format(jblob['name'])) deck = Deck.objects.filter(url=jblob['url']).first() # reload else: # for kicks, let's update name and authorname, since it could be that the # scrapy crawler gets better at figuring those things out deck.name = jblob['name'] deck.authorname = jblob['author'] deck.url = jblob['url'] deck.save() sys.stdout.write("Deck: updated {}\n".format(jblob['name'])) #sys.stdout.write("Deck: {} (db card count {})\n".format(jblob['name'], deck.get_card_count())) #sys.stdout.write(" URL: {}\n".format(jblob['url'])) if deck is not None: # now we have to add cards to the deck... cardtext = '\n'.join(jblob['mainboard_cards']) cardtext = cardtext + '\nSB:' + '\nSB: '.join(jblob['sideboard_cards']) #sys.stdout.write(cardtext + "\n") # REVISIT - just updating them all for now. Shouldn't hurt since # set_cards_from_text deletes all of the current card associations, right? if deck.get_card_count() == 0 or True: try: deck.set_cards_from_text(cardtext) except Deck.CardsNotFoundException as cnfe: for g in cnfe.cnfes: try: sys.stdout.write("ERROR: Could not find card " + str(g.text) + " in file {}\n".format(filename)) except UnicodeEncodeError: sys.stdout.write( "ERROR: Could not find card BUT I CAN'T TELL YOU ABOUT IT BECAUSE UNICODE IN PYTHON SUCKS in {}\n".format(filename)) if tourna is not None and tourna.name is not None and tourna.name.lower().find('test deck') < 0: # Now we will associate the deck to a tournament td = TournamentDeck.objects.filter(deck=deck, tournament=tourna).first() place = 99999 if 'place' in jblob: place = jblob['place'] if td is None: td = TournamentDeck(deck=deck, tournament=tourna, place=place) td.save() sys.stdout.write("TournamentDeck: created for {}\n".format(jblob['name'])) td = TournamentDeck.objects.filter(deck=deck, tournament=tourna).first() # RELOAD else: td.place = place td.save() sys.stdout.write("TournamentDeck: updated for {}\n".format(jblob['name'])) else: sys.stdout.write("Deck: skipped no valid tournament {}\n".format(jblob['name']))
def handle(self, *args, **options): #logger = logging.getLogger(__name__) # the first (and only) arg should be a filename directory = options['inputdir'] deck_meta_only = options['deck_meta_only'] self.only_newer = options['only_newer'] self.start_time = timezone.now() if not os.access(directory, os.R_OK): sys.stderr.write("Cannot read directory '{}'.\n".format(directory)) return # let's figure out the last time we ran. sema_filename = join(directory, 'last_complete.semaphore') last_start_time = datetime(2000, 1, 1, 0, 0, 0, 0, self.localtime) try: sema_in = open(sema_filename, 'r') lst_str = sema_in.readline() last_start_time = dtparse(lst_str) last_start_time = last_start_time.replace(tzinfo=self.localtime) sema_in.close() except: sys.stderr.write("Cannot read the {} file. Proceeding anyway...\n".format(sema_filename)) onlyfiles = [f for f in listdir(directory) if isfile(join(directory, f))] for filename in onlyfiles: if filename.find('tournament_') > -1: # and False: # REVISIT - commented out for the moment! filehandler = open(join(directory, filename)) filetime = datetime.fromtimestamp(os.path.getmtime(join(directory, filename))) filetime = filetime.replace(tzinfo=self.localtime) if self.only_newer and filetime < last_start_time: continue jblob = json.load(filehandler) #{"url": "/en/content/2011-great-britain-national-championship", "tournament_format": null, "name": "Great Britain National Championship", "start_date": "2011-08-19"} if jblob['name'].lower().find('test deck') > -1: sys.stdout.write("Tournament: skipped test deck tournament: {}\n".format(jblob['name'])) pass else: turl = jblob['url'] # The StarCityGames tournaments will probably not have a URL at all if turl is None or len(turl) == 0: pass # Some of the Wizards-crawled tournaments will not have a fully-qualified URL elif turl.find('http') < 0: turl = 'http://magic.wizards.com' + turl format_string = jblob['tournament_format'] if format_string is None: format_string = 'Unknown' elif format_string.find('Modern') > -1: format_string = 'Modern' elif format_string.find('Standard') > -1: format_string = 'Standard' elif format_string.find('Commander') > -1: format_string = 'Commander' elif format_string.find('Pauper') > -1: format_string = 'Pauper' elif format_string.find('Legacy') > -1: format_string = 'Legacy' elif format_string.find('Tiny') > -1: format_string = 'TinyLeaders' elif format_string == '' and 'legacy' in jblob['name'].lower(): format_string = 'Legacy' db_format = Format.objects.filter( formatname__iexact=format_string, start_date__lte=self.isodate(jblob['start_date']), end_date__gt=self.isodate(jblob['end_date'])).first() if db_format is not None: db_tournament = Tournament.objects.filter( format=db_format, name__iexact=jblob['name'], start_date=self.isodate(jblob['start_date'])).first() if db_tournament is None: # let's make one! db_tournament = Tournament( format=db_format, name=jblob['name'], start_date=self.isodate(jblob['start_date']), end_date=self.isodate(jblob['end_date']), url=turl) db_tournament.save() sys.stdout.write("Tournament: created {}\n".format(jblob['name'])) else: if filetime > db_tournament.updated_at or not self.only_newer: # let's update!! if turl.find('/node/') < 0: db_tournament.url = turl sys.stdout.write("Tournament: updated {}\n".format(jblob['name'])) db_tournament.save() else: sys.stdout.write("Tournament: skipped updated with node {}\n".format(jblob['name'])) else: sys.stdout.write("Tournament: not newer... skipped {}\n".format(jblob['name'])) else: sys.stdout.write("Tournament: skipped no format '{}' found in db {}\n".format(format_string, jblob['name'])) tournament_url_re = re.compile('^(.+/coverage/([^/]+))/?') # Process the deck files for filename in onlyfiles: if filename.find('deck_') > -1: ###fqfilename = join(directory, filename) # print "last modified: %s" % time.ctime(getmtime(fqfilename)) filehandler = open(join(directory, filename)) filetime = datetime.fromtimestamp(os.path.getmtime(join(directory, filename))) filetime = filetime.replace(tzinfo=self.localtime) if self.only_newer and filetime < last_start_time: continue jblob = json.load(filehandler) # let's test if jblob is a set JSON if 'name' in jblob and 'mainboard_cards' in jblob: # TEMP FIX - Legacy decks did not havea format_name for a lot of crawling... if jblob['deck_format'] == '' and jblob['tournament_name'] and 'legacy' in jblob['tournament_name'].lower(): jblob['deck_format'] = 'Legacy' tourna = None # let's deal with decks that have valid tournament URLs if 'tournament_url' in jblob and jblob['tournament_url'] is not None and len(jblob['tournament_url']) > 0: # We are going to skip decks and tournaments that look like draft and sealed if jblob['tournament_url'].find('draft') > 0 or jblob['tournament_url'].find('sealed') > 0: # skip sys.stdout.write("Deck: skipped limited {}\n".format(jblob['name'])) continue # now find the tournament tu_match = tournament_url_re.search(jblob['tournament_url']) tournament_url = jblob['tournament_url'] tournament_name = '' if tu_match: tournament_url = tu_match.group(1) tournament_name = tu_match.group(2) # find a real tournament that we match to #sys.stdout.write("HERE with '{}' and '{}'\n".format(tournament_url, tournament_name)) tourna = Tournament.objects.filter(url=tournament_url).first() # exclude(format__formatname='Unknown').first() elif 'tournament_name' in jblob and 'deck_format' in jblob: # Let's look for tournaments by name and date instead tourna = Tournament.objects.filter(name=jblob['tournament_name'], format__formatname=jblob['deck_format']).first() else: # we just aren't going to have a tournament. pass # Let's see if we already have a deck for this. deck = None sys.stdout.write("Deck: {} - {} by {}\n".format(jblob['url'], jblob['name'], jblob['author'])) is_create = False # Should we skip writing this deck to the database? skip_deck = False # We are going to look at the "deckid" parameter that StarCityGames decks have and match on just that id. dukey_m = SCG_DECK_URL_KEY_RE.search(jblob['url']) if dukey_m: #sys.stdout.write("** MATCHED: {}\n".format(dukey_m.group(1))) deck = Deck.objects.filter(url__icontains='deckid={}'.format(dukey_m.group(1))).first() #sys.stdout.write("** MATCHED: deck is {}\n".format(str(deck))) else: if 'page_part' in jblob: if jblob['page_part'] == '0' or jblob['page_part'] == 0: deck = Deck.objects.filter(url=jblob['url']).first() if deck is None: deck = Deck.objects.filter(url='{}#deck{}'.format(jblob['url'], jblob['page_part'])).first() else: deck = Deck.objects.filter(url='{}#deck{}'.format(jblob['url'], jblob['page_part'])).first() else: deck = Deck.objects.filter(url=jblob['url']).first() if deck is None: # no deck, so let's add it! sys.stdout.write(" creating...\n") is_create = True deck = Deck(url=jblob['url'], visibility=Deck.HIDDEN) if 'page_part' in jblob: deck.url = '{}#deck{}'.format(jblob['url'], jblob['page_part']) deck.name = jblob['name'] deck.authorname = jblob['author'] if tourna is not None and tourna.format is not None: deck.format = tourna.format elif 'deck_format' in jblob: try: sys.stderr.write( "Format find: {} - {}\n".format(jblob['deck_format'], self.isodate(jblob['tournament_date']))) db_format_q = Format.objects.filter( formatname=jblob['deck_format'], start_date__lte=self.isodate( jblob['tournament_date']), end_date__gt=self.isodate( jblob['tournament_date'])).first() deck.format = db_format_q except ValueError: # Looks like we cannot find a valid format because we don't have a real # deck_format or a real tournament_date. sys.stdout.write( " skipped because a valid format cannot be found for '{}' on date '{}'\n".format( jblob['deck_format'], jblob['tournament_date'])) deck = None pass if deck is not None: try: deck.save() sys.stdout.write(" Created deck {}!\n".format(str(deck.id))) deck = Deck.objects.get(pk=deck.id) # reload except IntegrityError as ie: sys.stdout.write(" Could not create deck! Integrity error: {}\n".format(str(ie))) deck = None else: if filetime > deck.updated_at or not self.only_newer: # for kicks, let's update name and authorname, since it could be that the # scrapy crawler gets better at figuring those things out deck.name = jblob['name'] deck.authorname = jblob['author'] deck.url = jblob['url'] if 'page_part' in jblob: deck.url = '{}#deck{}'.format(jblob['url'], jblob['page_part']) deck.format = None try: db_format_q = Format.objects.filter( formatname=jblob['deck_format'], start_date__lte=self.isodate( jblob['tournament_date']), end_date__gt=self.isodate( jblob['tournament_date'])).first() deck.format = db_format_q except ValueError as ve: # Looks like we cannot find a valid format because we don't have a real # deck_format or a real tournament_date. sys.stdout.write( " updating '{}' even though could not find a valid format for '{}' on date {} - {}\n".format( jblob['name'], jblob['deck_format'], jblob['tournament_date'], str(ve))) deck.format = None deck.save() sys.stdout.write(" Updated!\n") else: skip_deck = True sys.stdout.write(" not newer... skipped {}\n".format(jblob['url'])) #sys.stdout.write("Deck: {} (db card count {})\n".format(jblob['name'], deck.get_card_count())) #sys.stdout.write(" URL: {}\n".format(jblob['url'])) if deck is not None and not skip_deck: # now we have to add cards to the deck... if is_create or not deck_meta_only: sys.stdout.write(" creating or updating deck list...\n") cardtext = '\n'.join(jblob['mainboard_cards']) if 'sideboard_cards' in jblob and jblob['sideboard_cards'] is not None and len(jblob['sideboard_cards']) > 0: cardtext = cardtext + '\nSB:' + '\nSB: '.join(jblob['sideboard_cards']) if 'commandzone_cards' in jblob and jblob[ 'commandzone_cards'] is not None and len(jblob['commandzone_cards']) > 0: cardtext = cardtext + '\nCZ:' + '\nCZ: '.join(jblob['commandzone_cards']) #sys.stdout.write(cardtext + "\n") # REVISIT - just updating them all for now. Shouldn't hurt since # set_cards_from_text deletes all of the current card associations, right? if True or deck.get_card_count() == 0: try: deck.set_cards_from_text(cardtext) except Deck.CardsNotFoundException as cnfe: for g in cnfe.cnfes: try: sys.stdout.write(" ERROR: Could not find card " + str(g.text) + " in file {}\n".format(filename)) except UnicodeEncodeError: sys.stdout.write( " ERROR: Could not find card BUT I CAN'T TELL YOU ABOUT IT BECAUSE UNICODE IN PYTHON SUCKS in {}\n".format(filename)) if tourna is not None and tourna.name is not None and tourna.name.lower().find('test deck') < 0: # Now we will associate the deck to a tournament td = TournamentDeck.objects.filter(deck=deck, tournament=tourna).first() place = 99999 if 'place' in jblob: place = jblob['place'] if td is None: td = TournamentDeck(deck=deck, tournament=tourna, place=place) td.save() sys.stdout.write(" TournamentDeck: created for {}\n".format(jblob['name'])) td = TournamentDeck.objects.filter(deck=deck, tournament=tourna).first() # RELOAD else: td.place = place td.save() sys.stdout.write(" TournamentDeck: updated for {}\n".format(jblob['name'])) else: sys.stdout.write(" TournamentDeck: skipped no valid tournament {}\n".format(jblob['name'])) sema = open(join(directory, 'last_complete.semaphore'), 'w') sema.write(str(self.start_time)) sema.write("\n") sema.close()
def test_deck_1xmountain(self): tlh = TestLoadHelper() tlh.basics_loader() tformat = Format.objects.filter(format='Standard_2015-01-23').first() tdeck = Deck() tdeck.name = 'My Deck Name' tdeck.url = 'http://card.ninja/' tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = tformat tdeck.save() decklist = '1x Mountain' tdeck.set_cards_from_text(decklist) self.assertEquals(tdeck.get_card_count(), 1)
def test_deck_badname_nosave(self): tlh = TestLoadHelper() tlh.basics_loader() tformat = Format.objects.filter(format='Standard_2015-01-23').first() tdeck = Deck() tdeck.name = 'My Deck Name' tdeck.url = 'http://card.ninja/' tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = tformat tdeck.save() decklist = '''3 Mountain sb: 4x Island''' tdeck.set_cards_from_text(decklist) self.assertEquals(tdeck.get_card_count(), 7) decklist = '''3 Foo jib Battons''' try: tdeck.set_cards_from_text(decklist) self.assertTrue(False) except Deck.CardsNotFoundException as cnfes: self.assertEquals(cnfes.cnfes[0].text, 'Foo jib Battons'.lower()) self.assertEquals(tdeck.get_card_count(), 7)
def test_empty(self): tlh = TestLoadHelper() tlh.basics_loader() tformat = Format.objects.all().first() tdeck = Deck() tdeck.name = 'My Deck Name' tdeck.url = 'http://card.ninja/' tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = tformat tdeck.save() decklist = '' tdeck.set_cards_from_text(decklist) self.assertEquals(tdeck.get_card_count(), 0)
def test_deck_2cards(self): tlh = TestLoadHelper() tlh.basics_loader() tformat = Format.objects.filter(format='Standard_2015-01-23').first() tdeck = Deck() tdeck.name = 'My Deck Name' tdeck.url = 'http://card.ninja/' tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = tformat tdeck.save() decklist = '''2 Mountain 4x Island''' tdeck.set_cards_from_text(decklist) self.assertEquals(tdeck.get_card_count(), 6) dcs = DeckCard.objects.filter(deck=tdeck).order_by('cardcount') dc = dcs[0] self.assertEquals(dc.cardcount, 2) self.assertEquals(dc.board, DeckCard.MAIN) self.assertEquals(dc.physicalcard.get_card_name(), 'Mountain') dc = dcs[1] self.assertEquals(dc.cardcount, 4) self.assertEquals(dc.board, DeckCard.MAIN) self.assertEquals(dc.physicalcard.get_card_name(), 'Island')
def test_deck_7mountain(self): tlh = TestLoadHelper() tlh.basics_loader() tformat = Format.objects.filter(format='Standard_2015-01-23').first() tdeck = Deck() tdeck.name = 'My Deck Name' tdeck.url = 'http://card.ninja/' tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = tformat tdeck.save() decklist = '7 Mountain' tdeck.set_cards_from_text(decklist) self.assertEquals(tdeck.get_card_count(), 7) dcs = DeckCard.objects.filter(deck=tdeck) for dc in dcs: self.assertEquals(dc.cardcount, 7) self.assertEquals(dc.board, DeckCard.MAIN) self.assertEquals(dc.physicalcard.get_card_name(), 'Mountain')
def test_one_deck_abs_card(self): tlh = TestLoadHelper() tlh.basics_loader() mountain = BaseCard.objects.filter(name='Mountain').first().physicalcard island = BaseCard.objects.filter(name='Island').first().physicalcard myform = Format.objects.filter(formatname='Modern').order_by('-start_date').first() tdeck = Deck() tdeck.name = 'My Deck Name' tdeck.url = 'http://card.ninja/' tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = myform tdeck.save() tdeck = Deck.objects.get(pk=tdeck.id) dc1 = DeckCard() dc1.physicalcard = island dc1.deck = tdeck dc1.cardcount = 60 dc1.board = DeckCard.MAIN dc1.save() self.assertEquals(tdeck.get_card_count(), 60) tourny = Tournament(name='Test', url='http://foo.dog/', format=myform, start_date=myform.start_date, end_date=myform.start_date) tourny.save() #tourny = Tournament.objects.all().first() td = TournamentDeck(tournament=tourny, deck=tdeck, place=1) td.save() #td = TournamentDeck.objects.filter(tournament=tourny, deck=tdeck, place=1).first() FormatStat.calc_all() FormatCardStat.calc_all() fstat = FormatStat.objects.filter(format=myform).first() mstat = FormatCardStat.objects.filter(format=myform, physicalcard=mountain).first() dcount = mstat.deck_count self.assertEquals(dcount, 0) tdcount = fstat.tournamentdeck_count self.assertEquals(tdcount, 1, '1 Tournament Deck in the Format') self.assertEquals(mstat.in_decks_percentage(), 0.0, 'Mountain is in 0% of decks') self.assertEquals(mstat.occurence_count, 0, 'Mountain shows up 0 times in tournament decks') # the number of decks in this format that have this card self.assertEquals(mstat.deck_count, 0, '0 Tournament Decks have Mountain in the them') # the average card count when this card is included in a deck self.assertEquals(mstat.average_card_count_in_deck, 0.0, 'Average count of Mountain in Tournament Decks is 0') # the percentage of all cards in the format that are this card self.assertEquals(mstat.percentage_of_all_cards, 0.0, 'Average count of Tournament Decks with Mountain in it is 0') istat = FormatCardStat.objects.filter(format=myform, physicalcard=island).first() dcount = istat.deck_count self.assertEquals(dcount, 1, '1 Tournament Deck that has Island in it') self.assertEquals(istat.in_decks_percentage(), 100.0, 'Island is in 100% of decks') self.assertEquals(istat.occurence_count, 60, 'Island shows up 0 times in tournament decks') # the number of decks in this format that have this card self.assertEquals(istat.deck_count, 1, '1 Tournament Decks have Island in the them') # the average card count when this card is included in a deck self.assertEquals(istat.average_card_count_in_deck, 60.0, 'Average count of Island in Tournament Decks is 60') # the percentage of all cards in the format that are this card self.assertEquals( istat.percentage_of_all_cards, 1.0, 'Average count of Tournament Decks with Island in it should be 100, not {}'.format( istat.percentage_of_all_cards))
def test_tcbf_5(self): tlh = TestLoadHelper() tlh.basics_loader() mountain = BaseCard.objects.filter(name='Mountain').first().physicalcard island = BaseCard.objects.filter(name='Island').first().physicalcard swamp = BaseCard.objects.filter(name='Swamp').first().physicalcard plains = BaseCard.objects.filter(name='Plains').first().physicalcard formats = Format.objects.filter(formatname='Modern').order_by('-start_date') myform = formats[0] prev_form = formats[1] old_form = formats[2] # current format, all islands tourny = Tournament(name='Test {}'.format(myform.pk), url='http://foo.dog/', format=myform, start_date=myform.start_date, end_date=myform.start_date) tourny.save() for dcc in range(0, 6): tdeck = Deck() tdeck.name = 'My {} Deck Name in {}'.format(dcc, myform.format) tdeck.url = 'http://card.ninja/{}'.format(myform.id) tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = myform tdeck.save() dc1 = DeckCard(physicalcard=island, deck=tdeck, cardcount=31, board=DeckCard.MAIN) dc1.save() dc2 = DeckCard(physicalcard=swamp, deck=tdeck, cardcount=29, board=DeckCard.MAIN) dc2.save() td = TournamentDeck(tournament=tourny, deck=tdeck, place=dcc) td.save() # previous format, 10 islands, 20 swamps, 30 mountains tourny = Tournament(name='Test {}'.format(prev_form.pk), url='http://foo.dog/', format=prev_form, start_date=prev_form.start_date, end_date=prev_form.start_date) tourny.save() for dcc in range(0, 6): tdeck = Deck() tdeck.name = 'My Deck Name in {}'.format(prev_form.format) tdeck.url = 'http://card.ninja/{}'.format(prev_form.id) tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = prev_form tdeck.save() dc1 = DeckCard(physicalcard=island, deck=tdeck, cardcount=10, board=DeckCard.MAIN) dc1.save() dc2 = DeckCard(physicalcard=swamp, deck=tdeck, cardcount=20, board=DeckCard.MAIN) dc2.save() dc3 = DeckCard(physicalcard=mountain, deck=tdeck, cardcount=30, board=DeckCard.MAIN) dc3.save() td = TournamentDeck(tournament=tourny, deck=tdeck, place=dcc) td.save() # older format, 10 islands, 10 swamps, 10 mountains, 30 plains tourny = Tournament(name='Test {}'.format(old_form.pk), url='http://foo.dog/', format=old_form, start_date=old_form.start_date, end_date=old_form.start_date) tourny.save() for dcc in range(0, 3): tdeck = Deck() tdeck.name = 'My {} Deck Name in {}'.format(dcc, old_form.format) tdeck.url = 'http://card.ninja/{}-{}'.format(old_form.id, dcc) tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = old_form tdeck.save() dc1 = DeckCard(physicalcard=island, deck=tdeck, cardcount=10, board=DeckCard.MAIN) dc1.save() dc2 = DeckCard(physicalcard=swamp, deck=tdeck, cardcount=10, board=DeckCard.MAIN) dc2.save() dc3 = DeckCard(physicalcard=mountain, deck=tdeck, cardcount=10, board=DeckCard.MAIN) dc3.save() dc4 = DeckCard(physicalcard=plains, deck=tdeck, cardcount=30, board=DeckCard.MAIN) dc4.save() td = TournamentDeck(tournament=tourny, deck=tdeck, place=dcc) td.save() FormatStat.calc_all() FormatCardStat.calc_all() fstat = FormatStat.objects.filter(format=myform).first() mstat = FormatCardStat.objects.filter(format=myform, physicalcard=mountain).first() istat = FormatCardStat.objects.filter(format=myform, physicalcard=island).first() sstat = FormatCardStat.objects.filter(format=myform, physicalcard=swamp).first() # Try it once with looking back ONLY 1 format, and then again looking back 2 formats for lookback_days in (10,): cc = FormatCardStat.objects.top_cards_by_format(myform, format_lookback_days=lookback_days) first_cc = cc[0] self.assertEquals(first_cc.physicalcard, island, "Top card in this format is Island") self.assertIs( str( prev_form.pk) in first_cc.previous_format_ids, True, "The previous format ids on the FormatCardStat object should be the previous format id. Not {}".format( first_cc.previous_format_ids)) if lookback_days == 40: self.assertIs( str( old_form.pk) in first_cc.previous_format_ids, True, "The old format ids on the FormatCardStat object should be the old format id Not {}".format( first_cc.previous_format_ids)) # in prev_format, 1 out of 6 were Island self.assertAlmostEqual( first_cc.percentage_of_all_cards_previous(), 1.0 / 6.0, msg='Last format was split 1 out of 6 were Islands, so 16.66% is returned') # Now Island is 31/60, so 31/60 - 10/60 = 35% self.assertAlmostEqual(first_cc.percentage_of_all_cards_delta(), (31.0 / 60.0) - (10.0 / 60.0), msg='35.0% points higher, so positive .35 is returned') self.assertAlmostEqual(first_cc.percentage_of_all_cards_perchange(), 0.35 / (1.0 / 6.0), msg='210% change for Island - it is big! Not {}'.format(first_cc.percentage_of_all_cards_perchange())) looked_at_mountain = False looked_at_swamp = False looked_at_plains = False for other_cc in cc: if other_cc.physicalcard_id == mountain.id: looked_at_mountain = True self.assertAlmostEqual(other_cc.percentage_of_all_cards_previous(), 0.5, msg='Last format was split Islands and Mountains, so 50% is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_delta(), -0.5, msg='50% points lower, so negative .5 is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_perchange(), -1.0, msg='100% change for Mountain - big loss! Not {}'.format( other_cc.percentage_of_all_cards_perchange())) if other_cc.physicalcard_id == swamp.id: looked_at_swamp = True self.assertAlmostEqual(other_cc.percentage_of_all_cards_previous(), 1.0 / 3.0, msg='Last format had Swamps, Mountains, and Islands, so 33.3% is returned') # had been a 1/3, and now 29/60th self.assertAlmostEqual(other_cc.percentage_of_all_cards_delta(), (29.0 / 60.0) - (1.0 / 3.0), msg='15% points higher, so negative .15 is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_perchange(), 0.45, msg='45% change for Swamp - big win! Not {}'.format( other_cc.percentage_of_all_cards_perchange())) if other_cc.physicalcard_id == plains.id: looked_at_plains = True self.assertAlmostEqual( other_cc.percentage_of_all_cards_previous(), 0.0, msg='Last format had Swamps, Mountains, and Islands, so 0% Plains should be returned, not {}'.format( other_cc.percentage_of_all_cards_previous())) self.assertAlmostEqual(other_cc.percentage_of_all_cards_delta(), 0.0, msg='No change for plains, so 0.0 is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_perchange(), 0.0, msg='0% change for Plains - oh well! Not {}'.format( other_cc.percentage_of_all_cards_perchange())) self.assertIs(looked_at_mountain, True, 'Why did we not look at Mountain?') self.assertIs(looked_at_swamp, True, 'Why did we not look at Swamp?') self.assertIs(looked_at_plains, True, 'Why did we not look at Plains?') for lookback_days in (40,): # look back 2 formats now!! cc = FormatCardStat.objects.top_cards_by_format(myform, format_lookback_days=lookback_days) first_cc = cc[0] self.assertEquals(first_cc.physicalcard, island, "Top card in this format is Island") self.assertIs( str( prev_form.pk) in first_cc.previous_format_ids, True, "The previous format ids on the FormatCardStat object should be the previous format id. Not {}".format( first_cc.previous_format_ids)) self.assertIs(str(old_form.pk) in first_cc.previous_format_ids, True, "The old format ids on the FormatCardStat object should be the old format id Not {}".format(first_cc.previous_format_ids)) # in prev_format, 1 out of 6 were Island self.assertAlmostEqual( first_cc.percentage_of_all_cards_previous(), 1.0 / 6.0, msg='Last 2 formats summed was split 1 out of 6 were Islands, so 16.66% is returned') # Now Island is 31/60, so 31/60 - 10/60 = 35% self.assertAlmostEqual(first_cc.percentage_of_all_cards_delta(), (31.0 / 60.0) - (10.0 / 60.0), msg='35.0% points higher, so positive .35 is returned') self.assertAlmostEqual(first_cc.percentage_of_all_cards_perchange(), 0.35 / (1.0 / 6.0), msg='210% change for Island - it is big! Not {}'.format(first_cc.percentage_of_all_cards_perchange())) looked_at_mountain = False looked_at_swamp = False looked_at_plains = False for other_cc in cc: if other_cc.physicalcard_id == mountain.id: looked_at_mountain = True self.assertAlmostEqual(other_cc.percentage_of_all_cards_previous(), 21.0 / 54.0, msg='Last formats had 210 Mountains out of 540 cards, so 38.8% is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_delta(), -21.0 / 54.0, msg='38.8% points lower, so negative .388 is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_perchange(), -1.0, msg='100% change for Mountain - big loss! Not {}'.format( other_cc.percentage_of_all_cards_perchange())) if other_cc.physicalcard_id == swamp.id: looked_at_swamp = True self.assertAlmostEqual(other_cc.percentage_of_all_cards_previous(), 5.0 / 18.0, msg='Last formats 5 out of 18 cards as Swamps, so 27.7% is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_delta(), 29.0 / 60.0 - 5.0 / 18.0, msg='20.6% points better, so positive .2066 is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_perchange(), (29.0 / 60.0 - 5.0 / 18.0) / (5.0 / 18.0), msg='74% change for Swamp - big win! Not {}'.format( other_cc.percentage_of_all_cards_perchange())) if other_cc.physicalcard_id == plains.id: looked_at_plains = True self.assertAlmostEqual( other_cc.percentage_of_all_cards_previous(), 1.0 / 6.0, msg='Last formats had some Plains, so 16.6% Plains should be returned, not {}'.format( other_cc.percentage_of_all_cards_previous())) self.assertAlmostEqual(other_cc.percentage_of_all_cards_delta(), -1.0 / 6.0, msg='All Plains are gone, so delta is negative .1666') self.assertAlmostEqual(other_cc.percentage_of_all_cards_perchange(), -1.0, msg='-100% change for Plains - oh well! Not {}'.format( other_cc.percentage_of_all_cards_perchange())) self.assertIs(looked_at_mountain, True, 'Why did we not look at Mountain?') self.assertIs(looked_at_swamp, True, 'Why did we not look at Swamp?') self.assertIs(looked_at_plains, True, 'Why did we not look at Plains?')
def test_tcbf_4(self): tlh = TestLoadHelper() tlh.basics_loader() mountain = BaseCard.objects.filter(name='Mountain').first().physicalcard island = BaseCard.objects.filter(name='Island').first().physicalcard swamp = BaseCard.objects.filter(name='Swamp').first().physicalcard plains = BaseCard.objects.filter(name='Plains').first().physicalcard formats = Format.objects.filter(formatname='Modern').order_by('-start_date') myform = formats[0] prev_form = formats[1] old_form = formats[2] # current format, all islands tourny = Tournament(name='Test {}'.format(myform.pk), url='http://foo.dog/', format=myform, start_date=myform.start_date, end_date=myform.start_date) tourny.save() for dcc in range(0, 3): tdeck = Deck() tdeck.name = 'My {} Deck Name in {}'.format(dcc, myform.format) tdeck.url = 'http://card.ninja/{}'.format(myform.id) tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = myform tdeck.save() dc1 = DeckCard() dc1.physicalcard = island dc1.deck = tdeck dc1.cardcount = 60 dc1.board = DeckCard.MAIN dc1.save() td = TournamentDeck(tournament=tourny, deck=tdeck, place=dcc) td.save() # previous format, 10 islands, 20 swamps, 30 mountains tourny = Tournament(name='Test {}'.format(prev_form.pk), url='http://foo.dog/', format=prev_form, start_date=prev_form.start_date, end_date=prev_form.start_date) tourny.save() for dcc in range(0, 3): tdeck = Deck() tdeck.name = 'My Deck Name in {}'.format(prev_form.format) tdeck.url = 'http://card.ninja/{}'.format(prev_form.id) tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = prev_form tdeck.save() dc1 = DeckCard(physicalcard=island, deck=tdeck, cardcount=10, board=DeckCard.MAIN) dc1.save() dc2 = DeckCard(physicalcard=swamp, deck=tdeck, cardcount=20, board=DeckCard.MAIN) dc2.save() dc3 = DeckCard(physicalcard=mountain, deck=tdeck, cardcount=30, board=DeckCard.MAIN) dc3.save() td = TournamentDeck(tournament=tourny, deck=tdeck, place=dcc) td.save() # older format, 10 islands, 20 swamps, 30 mountains tourny = Tournament(name='Test {}'.format(old_form.pk), url='http://foo.dog/', format=old_form, start_date=old_form.start_date, end_date=old_form.start_date) tourny.save() for dcc in range(0, 3): tdeck = Deck() tdeck.name = 'My {} Deck Name in {}'.format(dcc, old_form.format) tdeck.url = 'http://card.ninja/{}-{}'.format(old_form.id, dcc) tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = old_form tdeck.save() dc1 = DeckCard(physicalcard=island, deck=tdeck, cardcount=10, board=DeckCard.MAIN) dc1.save() dc2 = DeckCard(physicalcard=swamp, deck=tdeck, cardcount=20, board=DeckCard.MAIN) dc2.save() dc3 = DeckCard(physicalcard=mountain, deck=tdeck, cardcount=30, board=DeckCard.MAIN) dc3.save() td = TournamentDeck(tournament=tourny, deck=tdeck, place=dcc) td.save() FormatStat.calc_all() FormatCardStat.calc_all() fstat = FormatStat.objects.filter(format=myform).first() mstat = FormatCardStat.objects.filter(format=myform, physicalcard=mountain).first() istat = FormatCardStat.objects.filter(format=myform, physicalcard=island).first() sstat = FormatCardStat.objects.filter(format=myform, physicalcard=swamp).first() # Try it once with looking back ONLY 1 format, and then again looking back 2 formats for lookback_days in (10, 40): # note the test data has Modern formats ever month cc = FormatCardStat.objects.top_cards_by_format(myform, format_lookback_days=lookback_days) first_cc = cc[0] self.assertEquals(first_cc.physicalcard, island, "Top card in this format is Island") self.assertIs( str( prev_form.pk) in first_cc.previous_format_ids, True, "The previous format ids on the FormatCardStat object should be the previous format id. Not {}".format( first_cc.previous_format_ids)) if lookback_days == 40: self.assertIs( str( old_form.pk) in first_cc.previous_format_ids, True, "The old format ids on the FormatCardStat object should be the old format id Not {}".format( first_cc.previous_format_ids)) self.assertAlmostEqual( first_cc.percentage_of_all_cards_previous(), 1.0 / 6.0, msg='Last format was split Islands and Mountains, so 16.66% is returned') self.assertAlmostEqual(first_cc.percentage_of_all_cards_delta(), 1.0 - (1.0 / 6.0), msg='83.33% points higher, so positive .8333 is returned') self.assertAlmostEqual(first_cc.percentage_of_all_cards_perchange(), 5.0, msg='500% change for Island - it is big! Not {}'.format(first_cc.percentage_of_all_cards_perchange())) looked_at_mountain = False looked_at_swamp = False looked_at_plains = False for other_cc in cc: if other_cc.physicalcard_id == mountain.id: looked_at_mountain = True self.assertAlmostEqual(other_cc.percentage_of_all_cards_previous(), 0.5, msg='Last format was split Islands and Mountains, so 50% is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_delta(), -0.5, msg='50% points lower, so negative .5 is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_perchange(), -1.0, msg='100% change for Mountain - big loss! Not {}'.format( other_cc.percentage_of_all_cards_perchange())) if other_cc.physicalcard_id == swamp.id: looked_at_swamp = True self.assertAlmostEqual(other_cc.percentage_of_all_cards_previous(), 1.0 / 3.0, msg='Last format had Swamps, Mountains, and Islands, so 33.3% is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_delta(), -1.0 / 3.0, msg='33.3% points lower, so negative .333 is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_perchange(), -1.0, msg='100% change for Swamp - big loss! Not {}'.format( other_cc.percentage_of_all_cards_perchange())) if other_cc.physicalcard_id == plains.id: looked_at_plains = True self.assertAlmostEqual( other_cc.percentage_of_all_cards_previous(), 0.0, msg='Last format had Swamps, Mountains, and Islands, so 0% Plains should be returned, not {}'.format( other_cc.percentage_of_all_cards_previous())) self.assertAlmostEqual(other_cc.percentage_of_all_cards_delta(), 0.0, msg='No change for plains, so 0.0 is returned') self.assertAlmostEqual(other_cc.percentage_of_all_cards_perchange(), 0.0, msg='0% change for Plains - oh well! Not {}'.format( other_cc.percentage_of_all_cards_perchange())) self.assertIs(looked_at_mountain, True, 'Why did we not look at Mountain?') self.assertIs(looked_at_swamp, True, 'Why did we not look at Swamp?') self.assertIs(looked_at_plains, True, 'Why did we not look at Plains?')
def test_tcbf_3(self): tlh = TestLoadHelper() tlh.basics_loader() mountain = BaseCard.objects.filter(name='Mountain').first().physicalcard island = BaseCard.objects.filter(name='Island').first().physicalcard formats = Format.objects.filter(formatname='Modern').order_by('-start_date') myform = formats[0] prev_form = formats[1] # current format, all islands tdeck = Deck() tdeck.name = 'My Deck Name in {}'.format(myform.format) tdeck.url = 'http://card.ninja/{}'.format(myform.id) tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = myform tdeck.save() dc1 = DeckCard() dc1.physicalcard = island dc1.deck = tdeck dc1.cardcount = 60 dc1.board = DeckCard.MAIN dc1.save() tourny = Tournament(name='Test {}'.format(myform.pk), url='http://foo.dog/', format=myform, start_date=myform.start_date, end_date=myform.start_date) tourny.save() td = TournamentDeck(tournament=tourny, deck=tdeck, place=1) td.save() # previous format, half islands, hald mountains tdeck = Deck() tdeck.name = 'My Deck Name in {}'.format(prev_form.format) tdeck.url = 'http://card.ninja/{}'.format(prev_form.id) tdeck.visibility = tdeck.VISIBLE tdeck.authorname = 'Test Dude' tdeck.format = prev_form tdeck.save() dc1 = DeckCard() dc1.physicalcard = island dc1.deck = tdeck dc1.cardcount = 30 dc1.board = DeckCard.MAIN dc1.save() dc2 = DeckCard() dc2.physicalcard = mountain dc2.deck = tdeck dc2.cardcount = 30 dc2.board = DeckCard.MAIN dc2.save() tourny = Tournament(name='Test {}'.format(prev_form.pk), url='http://foo.dog/', format=prev_form, start_date=prev_form.start_date, end_date=prev_form.start_date) tourny.save() td = TournamentDeck(tournament=tourny, deck=tdeck, place=1) td.save() FormatStat.calc_all() FormatCardStat.calc_all() fstat = FormatStat.objects.filter(format=myform).first() mstat = FormatCardStat.objects.filter(format=myform, physicalcard=mountain).first() istat = FormatCardStat.objects.filter(format=myform, physicalcard=island).first() cc = FormatCardStat.objects.top_cards_by_format(myform) first_cc = cc[0] self.assertEquals(first_cc.physicalcard, island, "Top card in this format is Island") self.assertEquals(first_cc.previous_format_ids, str(prev_form.pk), "The previous format ids on the FormatCardStat object should be the previous format id") self.assertEquals( first_cc.percentage_of_all_cards_previous(), 0.5, 'Last format was split Islands and Mountains, so 50% is returned') self.assertEquals(first_cc.percentage_of_all_cards_delta(), 0.5, '50% points higher, so positive .5 is returned') self.assertEquals(first_cc.percentage_of_all_cards_perchange(), 1.0, '100% change for Island - it doubled! Not {}'.format(first_cc.percentage_of_all_cards_perchange())) looked_at_mountain = False for other_cc in cc: if other_cc.physicalcard_id == mountain.id: looked_at_mountain = True self.assertEquals(other_cc.previous_format_ids, str(prev_form.pk), "The previous format ids on the FormatCardStat object should be the previous format id") self.assertEquals( other_cc.percentage_of_all_cards_previous(), 0.5, 'Last format was split Islands and Mountains, so 50% is returned') self.assertEquals(other_cc.percentage_of_all_cards_delta(), -0.5, '50% points lower, so negative .5 is returned') self.assertEquals(other_cc.percentage_of_all_cards_perchange(), - 1.0, '100% change for Mountain - big loss! Not {}'.format(other_cc.percentage_of_all_cards_perchange())) self.assertIs(looked_at_mountain, True, 'Why did we not look at Mountain?')