Пример #1
0
def postinit(request):
    if request.method != 'POST' or 'name' not in request.POST:
        return HttpResponseBadRequest()

    cookie = base64.b64encode(os.urandom(12)).decode()
    player = Player(name=request.POST['name'], cookie=cookie)
    player.save()

    with transaction.atomic():
        game, _ = Game.objects.select_for_update() \
            .filter(status=Game.PENDING, player_count__lt=GAME_THRESHOLD) \
            .order_by('create_time')[:1].get_or_create()
        logger.debug('Game updating.')
        game.player_count = F('player_count') + 1
        game.save()

    logger.debug('Game update success.{}'.format(game.player_count))

    player.game = game
    player.save()
    logger.debug('Player update success.')
    gid = game.id

    msg, evt = noticenter_init.listen(gid)

    if game.players.count() >= GAME_THRESHOLD:
        game.status = Game.READY
        game.save()

    evt.wait()
    msg = msg[0]

    return HttpResponse(
        json.dumps({
            'pid': player.id,
            'cookie': cookie,
            'local_id': sorted(msg['players']).index(player.id) + 1,
            'map': msg['map'],
        }))
Пример #2
0
 def read_csv_text(self, text, session):
     objects = list()
     lines = text.splitlines()
     for line in lines:
         if line == u''\
         or line == u'player, date, time, item, itemID, itemString, response,' \
                     u' votes, class, instance, boss, gear1, gear2, responseID,' \
                     u' isAwardReason':
             continue
         entry = line.split(",")
         if entry[0] == u'':
             entry.pop(0)
         player_name = entry[0].split("-")[0]
         player_realm = entry[0].split("-")[1]
         date = entry[1]
         time = entry[2]
         itemname = entry[3]
         item = entry[5]
         response = entry[6]
         votes = int(entry[7])
         wow_class = entry[8]
         instance = entry[9]
         boss = entry[10]
         gear1 = entry[11]
         gear2 = entry[12]
         responseID = entry[13]
         is_award_reason = entry[14]
         instance_id = instance.split("-")[0]
         instance_id = Codes.instance_codes[instance_id.lower()]
         existing_player = session.query(Player)\
                         .filter(Player.name == player_name, Player.realm == player_realm).all()
         player = None
         if (len(existing_player) == 1):
             player = existing_player[0]
         elif (len(existing_player) > 1):
             raise Exception(
                 "Multiple existing player_rel "
                 "with name {0} and realm {1} found in DB.".format(
                     player_name, player_realm))
         else:
             player = Player(name=player_name, realm=player_realm)
             session.add(player)
         iteminfo = self.unpack_item_string("Hitem:" + item.split("|")[2])
         #RCLC output does not match the actual Wow item string format in that it removes the starting 'hitem'.
         existing_loot = session.query(Loot)\
                         .filter(Loot.item_id == int(iteminfo["itemID"])).all()
         new_time = datetime.strptime(date, "%d/%m/%y")
         new_loot = LootAward(reason=response,
                              player_rel=player,
                              award_date=new_time)
         session.add(new_loot)
         if len(existing_loot) == 1:
             new_loot.item_rel = existing_loot[0]
         elif len(existing_loot) > 1:
             raise Exception(
                 "Multiple loot instances of item {0} found.".format(
                     existing_loot[0].item_id))
         else:
             _loot = Loot(item_id=int(iteminfo["itemID"]),
                          instance=instance_id,
                          name=itemname)
             session.add(_loot)
             new_loot.item_rel = _loot
         if gear1 != "nil":
             gear1info = self.unpack_item_string("Hitem:" +
                                                 gear1.split("|")[2])
             gear1name = gear1.split("|")[3]
             gear1name = gear1name[2:-1]
             existing_gear1 = session.query(Loot).filter(
                 Loot.item_id == int(gear1info["itemID"])).all()
             if len(existing_gear1) == 1:
                 new_loot.replacement1_rel = existing_gear1[0]
             elif len(existing_gear1) > 1:
                 raise Exception(
                     "Multiple loot instances of item {0} found.".format(
                         existing_gear1[0].item_id))
             else:
                 _replacement1 = Loot(item_id=int(gear1info["itemID"]),
                                      instance=-1,
                                      name=gear1name)
                 session.add(_replacement1)
                 new_loot.replacement1_rel = _replacement1
         else:
             new_loot.replacement1_rel = None
         if gear2 != "nil":
             gear2info = self.unpack_item_string("Hitem" +
                                                 gear2.split("|")[2])
             gear2name = gear2.split("|")[3]
             gear2name = gear2name[2:-1]
             existing_gear2 = session.query(Loot) \
                 .filter(Loot.item_id == int(gear2info["itemID"])).all()
             if len(existing_gear2) == 1:
                 new_loot.replacement2_rel = existing_gear2[0]
             elif len(existing_gear2) > 1:
                 raise Exception(
                     "Multiple loot instances of item {0} found.".format(
                         existing_gear2[0].item_id))
             else:
                 _replacement2 = Loot(item_id=int(gear2info["itemID"]),
                                      instance=-1,
                                      name=gear2name)
                 session.add(_replacement2)
                 new_loot.replacement2_rel = _replacement2
         else:
             new_loot.replacement2_rel = None
         objects.append(new_loot)
     return objects
Пример #3
0
    def read_tsv_text(self, text, session):
        """

        :param text: Lines of TSV text representing loot council data. Lines should match
        player	date	time	item	itemID	itemString	response	votes	class	instance	boss	gear1	gear2	responseID	isAwardReason
        format.
        :param session: Database session new loot awards should be added to.
        :return: The LootAward objects created and added to the session.
        """
        objects = list()
        failed_lines = list()
        lines = text.splitlines()
        for line in lines:
            try:
                if line == u''\
                    or line == u'player	date	time	item	itemID	itemString	response' \
                               u'	votes	class	instance	boss	gear1	gear2' \
                               u'	responseID	isAwardReason':
                    continue
                data = line.split("\t")
                player_name = data[0].split("-")[0]
                player_realm = data[0].split("-")[1]
                date = datetime.strptime(data[1], "%d/%m/%y")
                time = data[2]
                itemHL = data[3]
                itemID = int(data[4])
                itemString = data[5]
                response = data[6]
                votes = data[7]
                wow_class = data[8]
                instance = data[9]
                boss = data[10]
                gear1HL = data[11]
                gear2HL = data[12]
                responseID = data[13]
                isAwardReason = data[14]

                item_name = itemHL.split(",")[1]
                item_name = item_name[1:-2]

                gearIDregex = "wowhead.com/item=([0-9]+)"
                gearBonusRegex = "&bonus=([0-9-:]+)"
                gear1_name = gear1HL.split("\",")[1]
                gear1_name = gear1_name[1:-2]
                if gear1_name != u"nil":
                    gear1IDgroups = re.search(gearIDregex, gear1HL)
                    gear1ID = int(gear1IDgroups.group(1))
                    gear1BonusGroups = re.search(gearBonusRegex, gear1HL)
                    if gear1BonusGroups is not None:
                        gear1_bonus_IDs = gear1BonusGroups.group(1).split(":")
                        gear1_bonus_IDs = [int(i) for i in gear1_bonus_IDs]
                    else:
                        gear1_bonus_IDs = list()

                gear2_name = gear2HL.split("\",")[1]
                gear2_name = gear2_name[1:-2]
                if gear2_name != u"nil":
                    gear2IDgroups = re.search(gearIDregex, gear2HL)
                    gear2ID = int(gear2IDgroups.group(1))
                    gear2BonusGroups = re.search(gearBonusRegex, gear2HL)
                    if gear2BonusGroups is not None:
                        gear2_bonus_IDs = gear2BonusGroups.group(1).split(":")
                        gear2_bonus_IDs = [int(i) for i in gear2_bonus_IDs]
                    else:
                        gear2_bonus_IDs = list()

                instance_id = Codes.instance_codes[instance.split("-")
                                                   [0].lower()]
                player = None
                existing_player = session.query(Player)\
                    .filter(Player.name == player_name, Player.realm == player_realm).all()
                if len(existing_player) == 1:
                    player = existing_player[0]
                elif len(existing_player) > 1:
                    raise Exception(
                        "Multiple existing players with name {0} and realm {1} found."
                        .format(player_name, player_realm))
                else:
                    bnet = BNet()
                    player_info = bnet.create_character_profile(
                        session, name=player_name, realm=player_realm)
                    player = Player(name=player_name,
                                    realm=player_realm,
                                    wow_class=player_info["class"])
                    session.add(player)
                item_info = self.unpack_item_string("Hitem:" + itemString)
                #RCLC output does not match the actual WoW item string format, it removes the starting "hitem",
                #we add it here to preserve the purity of unpack_item_string

                new_award = LootAward(reason=response,
                                      player_rel=player,
                                      award_date=date)
                ##session.add(new_award)

                existing_items = session.query(Loot).filter(
                    Loot.item_id == itemID).all()
                item_info["bonusIDs"] = [int(i) for i in item_info["bonusIDs"]]
                matching = list()
                for item in existing_items:
                    all_matching = True
                    if len(item.bonus_ids) != len(item_info["bonusIDs"]):
                        all_matching = False
                    for id in item.bonus_ids:
                        if id.bonus_id not in item_info["bonusIDs"]:
                            all_matching = False
                            break
                    if all_matching:
                        matching.append(item)
                if len(matching) == 1:
                    new_award.item_rel = matching[0]
                elif len(matching) > 1:
                    raise Exception(
                        "Multiple loot instances of item {0} with bonus IDs {1} found."
                        .format(matching[0].item_id, item_info["bonusIDs"]))
                else:
                    new_item = Loot(item_id=itemID,
                                    instance=instance_id,
                                    name=item_name)
                    session.add(new_item)
                    new_award.item_rel = new_item
                    for id in item_info["bonusIDs"]:
                        new_item.bonus_ids.append(BonusID(bonus_id=id))

                #We just get wowhead hyperlinks instead of item strings for the gear replacement, so itemID
                #and bonus IDs extraction is different than how we do it with the awarded item.

                if gear1_name != u"nil":
                    existing_gear1 = session.query(Loot).filter(
                        Loot.item_id == gear1ID).all()
                    matching = list()
                    for item in existing_gear1:
                        all_matching = True
                        if len(item.bonus_ids) != len(gear1_bonus_IDs):
                            all_matching = False
                        for id in item.bonus_ids:
                            if id.bonus_id not in gear1_bonus_IDs:
                                all_matching = False
                                break
                        if all_matching:
                            matching.append(item)
                    if len(matching) == 1:
                        new_award.replacement1_rel = matching[0]
                    elif len(matching) > 1:
                        raise Exception(
                            "Multiple loot instances of item {0} with bonus IDs {1} found."
                            .format(matching[0].item_id, gear1_bonus_IDs))
                    else:
                        new_gear1 = Loot(item_id=gear1ID,
                                         instance=-1,
                                         name=gear1_name)
                        session.add(new_gear1)
                        new_award.replacement1_rel = new_gear1
                        for id in gear1_bonus_IDs:
                            new_gear1.bonus_ids.append(BonusID(bonus_id=id))

                if gear2_name != u"nil":
                    existing_gear2 = session.query(Loot).filter(
                        Loot.item_id == gear2ID).all()
                    matching = list()
                    for item in existing_gear2:
                        all_matching = True
                        if len(item.bonus_ids) != len(gear2_bonus_IDs):
                            all_matching = False
                        for id in item.bonus_ids:
                            if id.bonus_id not in gear2_bonus_IDs:
                                all_matching = False
                                break
                        if all_matching:
                            matching.append(item)
                    if len(matching) == 1:
                        new_award.replacement2_rel = matching[0]
                    elif len(matching) > 1:
                        raise Exception(
                            "Multiple loot instances of item {0} with bonus IDs {1} found."
                            .format(matching[0].item_id, gear2_bonus_IDs))
                    else:
                        new_gear2 = Loot(item_id=gear2ID,
                                         instance=-1,
                                         name=gear2_name)
                        session.add(new_gear2)
                        new_award.replacement2_rel = new_gear2
                        for id in gear2_bonus_IDs:
                            new_gear2.bonus_ids.append(BonusID(bonus_id=id))
                #Check if the exact same award has already been made.
                existing_awards = session.query(LootAward).filter(
                    LootAward.item_rel == new_award.item_rel,
                    LootAward.replacement1_rel == new_award.replacement1_rel,
                    LootAward.replacement2_rel == new_award.replacement2_rel,
                    LootAward.player_rel == new_award.player_rel).all()
                if len(existing_awards) == 0:
                    objects.append(new_award)
                    session.add(new_award)
            except Exception as e:
                ex_type, ex, tb = sys.exc_info()
                traceback.print_tb(tb)
                failed_lines.append("Line: {0}\nError: {1}\n".format(
                    line,
                    str(e) + e.message))
        return objects, failed_lines
Пример #4
0
def run(args):
    """
    Runs the data scraper. Calls various apis and saves data out to the
    database.

    :param args: argparse Namespace containing command-line arguments
    :return None
    """
    init_logging(args.verbose)
    logger = logging.getLogger(__name__)
    logger.info('Starting...')

    conf = read_config(args.config)

    repo = get_database(args.database)

    matches = replays.get_replays(7100)

    for match in matches:
        from db.models import Match, Player, Team

        players = match['player_set']

        if len(players) is not 6:
            continue

        players_stats = stats.get_player_stats(players, conf['apis']['stats']['key'])

        team_0 = []
        team_1 = []
        players_to_save = []

        missing_player_stats = False
        for player in players:
            new_player = Player(player)

            if new_player.team == 0:
                team_0.append(new_player)
            else:
                team_1.append(new_player)

            if player['platform'] == '1':
                new_player_stats = [s for s in players_stats if s['uniqueId'] == player['online_id']]
            else:
                new_player_stats = [s for s in players_stats if s['displayName'] == player['player_name']]

            if len(new_player_stats) == 0:
                missing_player_stats = True
                break
            else:
                new_player.update_stats(new_player_stats[0]['stats'])
                players_to_save.append(new_player)

        if missing_player_stats:
            continue
        else:
            for p in players_to_save:
                repo.save_player(p)

        db_team_0 = Team(team_0)
        db_team_1 = Team(team_1)

        repo.save_team(db_team_0)
        repo.save_team(db_team_1)
        time.sleep(conf['apis']['stats']['delay'])
Пример #5
0
 def create_player(cls, attrs):
     """Create a new player in database
     attrs are the attributes collected by the view"""
     id = Tournament.set_player_id()
     attrs["id"] = id
     Player.create(attrs)
Пример #6
0
def add_player(idx, name, password=None, session=None):
    """ Creates a new Player in DB.
    """
    new_player = Player(id=idx, name=name, password=password)
    session.add(new_player)
Пример #7
0
def make_scrape_round(tournament, round_no, date, url):
    print "round ", round_no, "at", date

    r = requests.get(url, verify=False)
    soup = BeautifulSoup(r.content, "html.parser")

    matches = soup.findAll("a", {"id": "match-link"})

    for match in matches:

        rounds = match.find("div", {
            "class": "round_time"
        }).find("div", {
            "class": "round"
        }).contents[0].strip().split("-")

        gametype = rounds[0].strip().lower()

        if not (gametype in ["ms", "mens singles", "men's singles"]
                or 'ms' in gametype):
            # only men's single
            continue

        details = match.find("div", {
            "class": "score"
        }).contents[0].strip().lower()
        no_match = "no match" in details or "retirement" in details or "walkover" in details

        if no_match:
            continue

        try:
            player1_name = match.find("div", {
                "class": "player1"
            }).contents[0].strip().lower()
            player2_name = match.find("div", {
                "class": "player3"
            }).contents[0].strip().lower()
        except:
            # no first/second player; walk over
            continue

        if player1_name == '' or player2_name == '':
            continue

        # rm digigts
        player1_name = ''.join([i for i in player1_name if not i.isdigit()])
        player2_name = ''.join([i for i in player2_name if not i.isdigit()])

        # rm brackets
        player1_name = ''.join([i for i in player1_name
                                if not i in '[]']).strip()
        player2_name = ''.join([i for i in player2_name
                                if not i in '[]']).strip()

        try:
            player1 = get_player_name(player1_name)
        except:
            player1 = Player()
            player1.name = player1_name
            db.add(player1)

        try:
            player2 = get_player_name(player2_name)
        except:
            player2 = Player()
            player2.name = player2_name
            db.add(player2)

        match_link = match.attrs['href']
        match_link = match_link.replace("&stab=result", "&stab=match")

        r = requests.get(match_link, verify=False)
        soup = BeautifulSoup(r.content, "html.parser")

        duration = soup.find("h3", {
            "class": "match-duration"
        }).contents[0].strip()
        try:
            duration = int(re.findall('\d+', duration)[0])
        except:
            duration = 0

        try:
            m = Match()

            m.tournament = tournament
            m.player1 = player1
            m.player2 = player2
            m.round_no = round_no
            m.duration = duration

            data = soup.find("div", {
                "class": "live-profile-row"
            }).findAll("tr")

            ms1 = MatchStats()
            ms1.max_consecutive_points = getint(
                data[0].findChildren()[0].contents[0].strip())
            ms1.game_points = getint(
                data[1].findChildren()[0].contents[0].strip())
            ms1.rallies_played = getint(
                data[2].findChildren()[0].contents[0].strip())
            ms1.rallies_won = getint(
                data[3].findChildren()[0].contents[0].strip())
            ms1.smash_winners = getint(
                data[4].findChildren()[0].contents[0].strip())
            ms1.net_winners = getint(
                data[5].findChildren()[0].contents[0].strip())
            ms1.clear_winners = getint(
                data[6].findChildren()[0].contents[0].strip())
            ms1.total_points_played = getint(
                data[7].findChildren()[0].contents[0].strip())
            ms1.total_points_won = getint(
                data[8].findChildren()[0].contents[0].strip())

            db.add(ms1)

            ms2 = MatchStats()
            ms2.max_consecutive_points = getint(
                data[0].findChildren()[-1].contents[0].strip())
            ms2.game_points = getint(
                data[1].findChildren()[-1].contents[0].strip())
            ms2.rallies_played = getint(
                data[2].findChildren()[-1].contents[0].strip())
            ms2.rallies_won = getint(
                data[3].findChildren()[-1].contents[0].strip())
            ms2.smash_winners = getint(
                data[4].findChildren()[-1].contents[0].strip())
            ms2.net_winners = getint(
                data[5].findChildren()[-1].contents[0].strip())
            ms2.clear_winners = getint(
                data[6].findChildren()[-1].contents[0].strip())
            ms2.total_points_played = getint(
                data[7].findChildren()[-1].contents[0].strip())
            ms2.total_points_won = getint(
                data[8].findChildren()[-1].contents[0].strip())

            db.add(ms2)

            m.stat1 = ms1
            m.stat2 = ms2

            print "> added match ", m.player1.name, "vs", m.player2.name

            db.add(m)

            sets = match.find("div", {
                "class": "score"
            }).contents[0].strip().split(",")

            for i, game_set in enumerate(sets):
                scores = game_set.split("-")
                s = Set()
                s.match = m
                s.index = i
                s.score_1 = scores[0]
                s.score_2 = scores[1]

                db.add(s)
        except:
            # no match
            continue