Пример #1
0
def get_tour(date):
    """
    :type date: datetime
    """
    if NEW_TOUR_BY_MONTH:
        try:
            tour = Tour.objects.get(date_start__year=date.year,
                                    date_start__month=date.month,
                                    is_ended=False)
        except Tour.DoesNotExist:
            tour = Tour.objects.create(date_start=date)
            logger.info('started a new tour by month')
            Tour.objects.exclude(id=tour.id).filter(is_ended=False).update(
                is_ended=True, date_end=date)
    else:
        try:
            tour = Tour.objects.get(is_ended=False)
        except Tour.DoesNotExist:
            tour = Tour.objects.create(title='Tour name')
            logger.warning('open tour was not found - started a new tour')
        except Tour.MultipleObjectsReturned:
            logger.error('multiple not ended tours - should be only one')
            input()
            sys.exit()
    return tour
Пример #2
0
def __run_background_job(job, tour_cutoff):
    if not job.work_left and not job.unlimited_work:
        return False

    global LOG_COUNTER

    backfill_sorties = job.query_find_sorties(tour_cutoff)
    nr_left = backfill_sorties.count()
    if nr_left == 0:
        job.work_left = False
        return False

    if LOG_COUNTER == 0 and job.log_update(nr_left):
        logger.info(job.log_update(nr_left))
    LOG_COUNTER = (LOG_COUNTER + 1) % LOGGING_INTERVAL

    for sortie in backfill_sorties[0:SORTIES_PER_BATCH]:
        job.compute_for_sortie(sortie)

    if nr_left <= SORTIES_PER_BATCH:
        if job.log_done():
            logger.info(job.log_done())
        job.work_left = False
        LOG_COUNTER = 0

    return True
Пример #3
0
def main():
    logger.info('IL2 stats {stats}, Python {python}, Django {django}'.format(
        stats=__version__,
        python=sys.version[0:5],
        django=django.get_version()))

    # TODO переделать на проверку по времени создания файлов
    processed_reports = []

    waiting_new_report = False
    online_timestamp = 0

    while True:
        new_reports = []
        for m_report_file in MISSION_REPORT_PATH.glob(
                'missionReport*[[]0[]].txt'):
            if m_report_file.name not in processed_reports:
                new_reports.append(m_report_file)

        if len(new_reports) > 1:
            waiting_new_report = False
            # обрабатываем все логи кроме последней миссии
            for m_report_file in new_reports[:-1]:
                stats_whore(m_report_file=m_report_file)
                cleanup(m_report_file=m_report_file)
                processed_reports.append(m_report_file.name)
            continue
        elif len(new_reports) == 1:
            m_report_file = new_reports[0]
            m_report_files = collect_mission_reports(
                m_report_file=m_report_file)
            online_timestamp = update_online(m_report_files=m_report_files,
                                             online_timestamp=online_timestamp)
            # если последний файл был создан более 2х минут назад - обрабатываем его
            if time.time() - m_report_files[-1].stat().st_mtime > 120:
                waiting_new_report = False
                stats_whore(m_report_file=m_report_file)
                cleanup(m_report_file=m_report_file)
                processed_reports.append(m_report_file.name)
                continue

        if not waiting_new_report:
            logger.info('waiting new report...')
        waiting_new_report = True

        # удаляем юзеров которые не активировали свои регистрации в течении определенного времени
        cleanup_registration()

        # в идеале новые логи появляются как минимум раз в 30 секунд
        time.sleep(30)
Пример #4
0
def stats_whore(m_report_file):
    """
    :type m_report_file: Path
    """
    mission_timestamp = int(
        time.mktime(
            time.strptime(m_report_file.name[14:-8], '%Y-%m-%d_%H-%M-%S')))

    if Mission.objects.filter(timestamp=mission_timestamp).exists():
        logger.info(
            '{mission} - exists in the DB'.format(mission=m_report_file.stem))
        return
    logger.info(
        '{mission} - processing new report'.format(mission=m_report_file.stem))

    m_report_files = collect_mission_reports(m_report_file=m_report_file)

    real_date = TIME_ZONE.localize(datetime.fromtimestamp(mission_timestamp))
    real_date = real_date.astimezone(pytz.UTC)

    objects = MappingProxyType(
        {obj['log_name']: obj
         for obj in Object.objects.values()})
    # classes = MappingProxyType({obj['cls']: obj['cls_base'] for obj in objects.values()})
    score_dict = MappingProxyType(
        {s.key: s.get_value()
         for s in Score.objects.all()})

    m_report = MissionReport(objects=objects)
    m_report.processing(files=m_report_files)

    backup_log(name=m_report_file.name, lines=m_report.lines, date=real_date)

    if not m_report.is_correctly_completed:
        logger.info(
            '{mission} - mission has not been completed correctly'.format(
                mission=m_report_file.stem))

    tour = get_tour(date=real_date)

    mission = Mission.objects.create(
        tour_id=tour.id,
        name=m_report.file_path.replace('\\',
                                        '/').split('/')[-1].split('.')[0],
        path=m_report.file_path,
        date_start=real_date,
        date_end=real_date + timedelta(seconds=m_report.tik_last // 50),
        duration=m_report.tik_last // 50,
        timestamp=mission_timestamp,
        preset=m_report.preset_id,
        settings=m_report.settings,
        is_correctly_completed=m_report.is_correctly_completed,
        score_dict=dict(score_dict),
    )
    if m_report.winning_coal_id:
        mission.winning_coalition = m_report.winning_coal_id
        mission.win_reason = 'task'
        mission.save()

    # собираем/создаем профили игроков и сквадов
    profiles, players_pilots, players_gunners, players_tankmans, squads = create_profiles(
        tour=tour, sorties=m_report.sorties)

    players_aircraft = defaultdict(dict)
    players_mission = {}
    players_killboard = {}

    coalition_score = {1: 0, 2: 0}
    new_sorties = []
    for sortie in m_report.sorties:
        sortie_aircraft_id = objects[sortie.aircraft_name]['id']
        profile = profiles[sortie.account_id]
        if sortie.cls_base == 'aircraft':
            player = players_pilots[sortie.account_id]
        elif sortie.cls == 'aircraft_turret':
            player = players_gunners[sortie.account_id]
        elif sortie.cls in ('tank_light', 'tank_heavy', 'tank_medium',
                            'tank_turret'):
            player = players_tankmans[sortie.account_id]
        else:
            continue

        squad = squads[profile.squad_id] if profile.squad else None
        player.squad = squad

        new_sortie = create_new_sortie(mission=mission,
                                       sortie=sortie,
                                       profile=profile,
                                       player=player,
                                       sortie_aircraft_id=sortie_aircraft_id)
        update_fairplay(new_sortie=new_sortie)
        update_bonus_score(new_sortie=new_sortie)

        # не добавляем очки в сумму если было диско
        if not new_sortie.is_disco:
            coalition_score[new_sortie.coalition] += new_sortie.score

        new_sorties.append(new_sortie)
        # добавляем ссылку на запись в базе к объекту вылета, чтобы использовать в добавлении событий вылета
        sortie.sortie_db = new_sortie

    if not mission.winning_coalition and WIN_BY_SCORE:
        _coalition = sorted(coalition_score.items(),
                            key=operator.itemgetter(1),
                            reverse=True)
        max_coal, max_score = _coalition[0]
        min_coal, min_score = _coalition[1]
        # минимальное кол-во очков = 1
        min_score = min_score or 1
        if max_score >= WIN_SCORE_MIN and max_score / min_score >= WIN_SCORE_RATIO:
            mission.winning_coalition = max_coal
            mission.win_reason = 'score'
            mission.save()

    for new_sortie in new_sorties:
        _player_id = new_sortie.player.id
        _profile_id = new_sortie.profile.id

        player_mission = players_mission.setdefault(
            _player_id,
            PlayerMission.objects.get_or_create(profile_id=_profile_id,
                                                player_id=_player_id,
                                                mission_id=mission.id)[0])

        player_aircraft = players_aircraft[_player_id].setdefault(
            new_sortie.aircraft.id,
            PlayerAircraft.objects.get_or_create(
                profile_id=_profile_id,
                player_id=_player_id,
                aircraft_id=new_sortie.aircraft.id)[0])

        vlife = VLife.objects.get_or_create(profile_id=_profile_id,
                                            player_id=_player_id,
                                            tour_id=tour.id,
                                            relive=0)[0]

        # если случилась победа по очкам - требуется обновить бонусы
        if mission.win_reason == 'score':
            update_bonus_score(new_sortie=new_sortie)

        update_sortie(new_sortie=new_sortie,
                      player_mission=player_mission,
                      player_aircraft=player_aircraft,
                      vlife=vlife)
        reward_sortie(sortie=new_sortie)

        vlife.save()
        reward_vlife(vlife)

        new_sortie.vlife_id = vlife.id
        new_sortie.save()

    # ===============================================================================
    mission.players_total = len(profiles)
    mission.pilots_total = len(players_pilots)
    mission.gunners_total = len(players_gunners)
    mission.save()

    for p in profiles.values():
        p.save()

    for p in players_pilots.values():
        p.save()
        reward_tour(player=p)

    for p in players_gunners.values():
        p.save()

    for p in players_tankmans.values():
        p.save()

    for aircrafts in players_aircraft.values():
        for a in aircrafts.values():
            a.save()

    for p in players_mission.values():
        p.save()
        reward_mission(player_mission=p)

    for s in squads.values():
        s.save()

    tour.save()

    for event in m_report.log_entries:
        params = {
            'mission_id': mission.id,
            'date': real_date + timedelta(seconds=event['tik'] // 50),
            'tik': event['tik'],
            'extra_data': {
                'pos': event.get('pos'),
            },
        }
        if event['type'] == 'respawn':
            params['type'] = 'respawn'
            params['act_object_id'] = event['sortie'].sortie_db.aircraft.id
            params['act_sortie_id'] = event['sortie'].sortie_db.id
        elif event['type'] == 'end':
            params['type'] = 'end'
            params['act_object_id'] = event['sortie'].sortie_db.aircraft.id
            params['act_sortie_id'] = event['sortie'].sortie_db.id
        elif event['type'] == 'takeoff':
            params['type'] = 'takeoff'
            params['act_object_id'] = event[
                'aircraft'].sortie.sortie_db.aircraft.id
            params['act_sortie_id'] = event['aircraft'].sortie.sortie_db.id
        elif event['type'] == 'landed':
            params['act_object_id'] = event[
                'aircraft'].sortie.sortie_db.aircraft.id
            params['act_sortie_id'] = event['aircraft'].sortie.sortie_db.id
            if event['is_rtb'] and not event['is_killed']:
                params['type'] = 'landed'
            else:
                if event['status'] == LifeStatus.destroyed:
                    params['type'] = 'crashed'
                else:
                    params['type'] = 'ditched'
        elif event['type'] == 'bailout':
            params['type'] = 'bailout'
            params['act_object_id'] = event['bot'].sortie.sortie_db.aircraft.id
            params['act_sortie_id'] = event['bot'].sortie.sortie_db.id
        elif event['type'] == 'damage':
            params['extra_data']['damage'] = event['damage']
            params['extra_data']['is_friendly_fire'] = event[
                'is_friendly_fire']
            if event['target'].cls_base == 'crew':
                params['type'] = 'wounded'
            else:
                params['type'] = 'damaged'
            if event['attacker']:
                if event['attacker'].sortie:
                    params['act_object_id'] = event[
                        'attacker'].sortie.sortie_db.aircraft.id
                    params['act_sortie_id'] = event[
                        'attacker'].sortie.sortie_db.id
                else:
                    params['act_object_id'] = objects[
                        event['attacker'].log_name]['id']
            if event['target'].sortie:
                params['cact_object_id'] = event[
                    'target'].sortie.sortie_db.aircraft.id
                params['cact_sortie_id'] = event['target'].sortie.sortie_db.id
            else:
                params['cact_object_id'] = objects[
                    event['target'].log_name]['id']
        elif event['type'] == 'kill':
            params['extra_data']['is_friendly_fire'] = event[
                'is_friendly_fire']
            if event['target'].cls_base == 'crew':
                params['type'] = 'killed'
            elif event['target'].cls_base == 'aircraft':
                params['type'] = 'shotdown'
            else:
                params['type'] = 'destroyed'
            if event['attacker']:
                if event['attacker'].sortie:
                    params['act_object_id'] = event[
                        'attacker'].sortie.sortie_db.aircraft.id
                    params['act_sortie_id'] = event[
                        'attacker'].sortie.sortie_db.id
                else:
                    params['act_object_id'] = objects[
                        event['attacker'].log_name]['id']
            if event['target'].sortie:
                params['cact_object_id'] = event[
                    'target'].sortie.sortie_db.aircraft.id
                params['cact_sortie_id'] = event['target'].sortie.sortie_db.id
            else:
                params['cact_object_id'] = objects[
                    event['target'].log_name]['id']

        l = LogEntry.objects.create(**params)
        if l.type == 'shotdown' and l.act_sortie and l.cact_sortie and not l.act_sortie.is_disco and not l.extra_data.get(
                'is_friendly_fire'):
            update_killboard_pvp(player=l.act_sortie.player,
                                 opponent=l.cact_sortie.player,
                                 players_killboard=players_killboard)

    for p in players_killboard.values():
        p.save()

    logger.info(
        '{mission} - processing finished'.format(mission=m_report_file.stem))