Example #1
0
def make_medal_payment(request, medal_order):
	amount = medal_order.n_medals * models_klb.MEDAL_PRICE

	if medal_order.with_plate:
		amount += medal_order.n_medals * models_klb.PLATE_PRICE

	# if medal_order.lname == u'Пушкин': # For test purposes
	# 	amount = 15

	payment = models.Payment_moneta.objects.create(
		amount=amount,
		description=u'Оплата за {} медал{} участника КЛБМатча–{}'.format(
			medal_order.n_medals, results_util.plural_ending_new(medal_order.n_medals, 3), medal_order.year),
		user=medal_order.created_by,
		sender=medal_order.created_by.get_full_name() if medal_order.created_by else u'{} {}'.format(medal_order.fname, medal_order.lname),
	)
	payment.refresh_from_db()
	payment.transaction_id = DESCRIPTION_PREFIX + unicode(payment.id)
	payment.signature = get_payment_md5(payment)
	payment.save()

	medal_order.payment = payment
	medal_order.save()

	redirect_url = get_redirect_url(payment)
	# models.write_log('make_medal_payment: Redirecting to {}'.format(redirect_url))
	return redirect(redirect_url)
Example #2
0
def send_update_results(new_races, future_events_created, email):
    body = u"Добрый день!\n\nСвежезагруженные результаты паркранов (всего забегов {}):\n\n".format(
        len(new_races))
    html_body = u"Добрый день!\n"
    html_body += u"<p/>Свежезагруженные результаты паркранов (всего забегов {}):\n".format(
        len(new_races))
    i = 1
    for race, n_results, existed in new_races:
        str_existed = ''
        if not existed:
            str_existed = u' (этого забега не было в календаре!)'
        body += u"{} – {}, {}, {} результатов{}\n".format(
            race.event.start_date, race.event, race.event.url_site, n_results,
            str_existed)
        html_body += u"<p/>{}. {} – <a href='{}'>{}</a>, <a href='{}{}'>{} результат{}</a>{}\n".format(
            i, race.event.start_date, race.event.url_site, race.event,
            models.SITE_URL, race.get_absolute_url(), n_results,
            results_util.plural_ending_new(n_results, 1), str_existed)
        i += 1
    body += u"\n\nСоздано будущих паркранов: {}.".format(future_events_created)
    html_body += u"<p/>Создано будущих паркранов: {}.".format(
        future_events_created)

    for race in get_empty_parkruns():
        s = u'Найден паркран без результатов: {} {} {}{}'.format(
            race.event.name, race.event.start_date, models.SITE_URL,
            race.get_absolute_url())
        body += u"\n\n" + s
        html_body += u"<p/>" + s

    body += u"\n\nНа сегодня это всё. До связи!\nВаш кронтаб."
    html_body += u"<p/>На сегодня это всё. До связи!<p/>Ваш кронтаб."
    return send_mail(u'ПроБЕГ: результаты закачки паркранов',
                     body,
                     models.INFO_MAIL_HEADER, [email],
                     html_message=html_body)
Example #3
0
def klb_team_add_new_participant(request, team_id):
    team = get_object_or_404(models.Klb_team, pk=team_id)
    club = team.club
    context, has_rights, target = check_rights(request, club=club)
    if not has_rights:
        return target
    user = request.user
    if not models.is_active_klb_year(team.year, context['is_admin']):
        messages.warning(
            request,
            u'Вы уже не можете добавлять людей в команду за {} год. Тот матч давно в прошлом.'
            .format(team.year))
        return redirect(team)
    form = None
    to_create_runner = to_create_person = to_create_participant = False

    if 'step1_submit' in request.POST:
        form = RunnerForKlbForm(user=user, year=team.year, data=request.POST)
        if form.is_valid():
            new_runner = form.instance
            runners = models.Runner.objects.filter(
                Q(birthday=None) | Q(birthday__year=new_runner.birthday.year,
                                     birthday_known=False)
                | Q(birthday=new_runner.birthday, birthday_known=True),
                lname=new_runner.lname,
                fname=new_runner.fname,
                # n_starts__gt=0,
            ).select_related('city__region__country',
                             'klb_person').order_by('-n_starts')
            if new_runner.midname:
                runners = runners.filter(midname__in=['', new_runner.midname])
            if runners.exists(
            ):  # We want to ask whether we should create new runner or use some of old ones
                context['runners'] = []
                for runner in runners:
                    runner_dict = {}
                    runner_dict['runner'] = runner
                    info = []
                    if runner.birthday_known:
                        info.append(u'дата рождения {}'.format(
                            runner.birthday.strftime("%d.%m.%Y")))
                    elif runner.birthday:
                        info.append(u'{} год рождения'.format(
                            runner.birthday.year))
                    if runner.city:
                        info.append(runner.city.nameWithCountry())
                    n_starts = runner.n_starts if runner.n_starts else 0
                    info.append(u'{} результат{} в базе данных'.format(
                        n_starts,
                        results_util.plural_ending_new(runner.n_starts, 1)))
                    if runner.klb_person:
                        person = runner.klb_person
                        n_klb_starts = person.klb_result_set.count()
                        if n_klb_starts:
                            info.append(
                                u'{} результат{} в зачёт КЛБМатчей'.format(
                                    n_klb_starts,
                                    results_util.plural_ending_new(
                                        n_klb_starts, 1)))
                        runner_dict[
                            'cur_participant'] = person.klb_participant_set.filter(
                                match_year=team.year).first()
                    runner_dict['info'] = ', '.join(info)
                    context['runners'].append(runner_dict)
            else:  # There are no similar runners, so we can create him
                to_create_runner = True
        else:
            messages.warning(request, u'Пожалуйста, исправьте ошибки в форме')
    elif 'step2_submit' in request.POST:
        form = RunnerForKlbForm(user=user, year=team.year, data=request.POST)
        if form.is_valid():
            new_runner = form.instance
            runner_id = models.int_safe(request.POST.get('runner_id', 0))
            if runner_id == -1:  # This special value means we should create new runner
                to_create_runner = True
            else:  # We should add some existing runner
                cur_year_person_ids = set(
                    models.Klb_participant.objects.filter(
                        match_year=team.year).values_list('klb_person_id',
                                                          flat=True))
                runner = models.Runner.objects.filter(pk=runner_id).first()
                if runner:
                    person = runner.klb_person
                    if person:
                        if person.id in cur_year_person_ids:
                            person_team = person.klb_participant_set.filter(
                                match_year=team.year).first().team
                            if person_team:
                                messages.warning(
                                    request,
                                    u'{} {} (id {}) уже заявлен в КЛБМатч-{} в команду {}'
                                    .format(person.fname, person.lname,
                                            person.id, team.year,
                                            person_team.name))
                            else:
                                messages.warning(
                                    request,
                                    u'{} {} (id {}) уже заявлен в КЛБМатч-{} как индивидуальный участник'
                                    .format(person.fname, person.lname,
                                            person.id, team.year))
                            return redirect(team)
                        else:
                            to_create_participant = True
                    else:  # So we should create new person for this runner. And maybe we can update runner?
                        changed_fields = []
                        if runner.midname.lower() != new_runner.midname.lower(
                        ):
                            runner.midname = new_runner.midname
                            changed_fields.append('midname')
                        if (runner.birthday != new_runner.birthday
                            ) or not runner.birthday_known:
                            runner.birthday = new_runner.birthday
                            changed_fields.append('birthday')
                            if not runner.birthday_known:
                                runner.birthday_known = True
                                changed_fields.append('birthday_known')
                        if runner.city != new_runner.city:
                            runner.city = new_runner.city
                            changed_fields.append('city')
                        if changed_fields:
                            models.log_obj_create(
                                user,
                                runner,
                                models.ACTION_UPDATE,
                                field_list=changed_fields,
                                comment=
                                u'При добавлении отдельного участника в КЛБМатч'
                            )
                        to_create_person = True
                else:
                    messages.warning(
                        request,
                        u'К сожалению, выбранный Вами бегун (id {}) не найден. Попробуйте ещё раз'
                        .format(runner_id))
        else:
            messages.warning(request, u'Пожалуйста, исправьте ошибки в форме')

    if to_create_runner:
        runner = form.save(commit=False)
        runner.birthday_known = True
        runner.created_by = user
        runner.save()
        models.log_obj_create(
            user,
            runner,
            models.ACTION_CREATE,
            comment=u'При добавлении нового участника в КЛБМатч')
        to_create_person = True
    if to_create_person:
        person = runner.create_klb_person(
            user, comment=u'При добавлении нового участника в КЛБМатч')
        to_create_participant = True
    if to_create_participant:
        email = form.cleaned_data.get('email', '')
        phone_number = form.cleaned_data.get('phone_number', '')

        participant, club_member, is_changed = person.create_participant(
            team,
            user,
            email=email,
            phone_number=phone_number,
            comment=u'При добавлении нового участника в КЛБМатч-{}'.format(
                team.year),
            add_to_club=form.cleaned_data.get('and_to_club_members'))
        if is_changed:
            update_runner_stat(club_member=club_member)

        messages.success(
            request, u'{} {} успешно добавлен{} в команду с {}'.format(
                runner.fname, runner.lname,
                u'а' if person.gender == models.GENDER_FEMALE else '',
                participant.date_registered.strftime("%d.%m.%Y")))
        update_team_score(team, to_clean=False, to_calc_sum=True)
        return redirect(team)

    if form is None:
        initial = {}
        if club.city:
            initial['city_id'] = club.city.id
            initial['region'] = club.city.region.id
        form = RunnerForKlbForm(user=user, year=team.year, initial=initial)
    context['form'] = form
    context['page_title'] = u'Команда в КЛБМатче: {}, {} год'.format(
        team.name, team.year)
    context['year'] = team.year
    context = team.update_context_for_team_page(context,
                                                request.user,
                                                ordering=models.ORDERING_NAME)
    if 'runners' in context:
        template = 'klb/team_add_new_participants_step2.html'
    else:
        template = 'klb/team_add_new_participants_step1.html'
    return render(request, template, context)
Example #4
0
def add_club_member(request, club_id):
    club = get_object_or_404(models.Club, pk=club_id)
    context, has_rights, target = check_rights(request, club=club)
    if not has_rights:
        return target
    user = request.user
    form = None
    to_create_runner = to_create_member = False

    if 'step1_submit' in request.POST:
        form = RunnerForClubForm(user=user, data=request.POST)
        if form.is_valid():
            new_runner = form.instance
            runners = models.Runner.objects.filter(
                Q(birthday=None) | Q(birthday__year=new_runner.birthday.year,
                                     birthday_known=False)
                | Q(birthday=new_runner.birthday, birthday_known=True),
                lname=new_runner.lname,
                fname=new_runner.fname,
                # n_starts__gt=0,
            ).select_related('city__region__country').order_by('-n_starts')
            if new_runner.midname:
                runners = runners.filter(midname__in=['', new_runner.midname])
            if runners.exists(
            ):  # We want to ask whether we should create new runner or use some of old ones
                context['runners'] = []
                for runner in runners:
                    runner_dict = {}
                    runner_dict['runner'] = runner
                    info = []
                    if runner.birthday_known:
                        info.append(u'дата рождения {}'.format(
                            runner.birthday.strftime("%d.%m.%Y")))
                    elif runner.birthday:
                        info.append(u'{} год рождения'.format(
                            runner.birthday.year))
                    if runner.city:
                        info.append(runner.city.nameWithCountry())
                    n_starts = runner.n_starts if runner.n_starts else 0
                    info.append(u'{} результат{} в базе данных'.format(
                        n_starts, results_util.plural_ending_new(n_starts, 1)))
                    runner_dict['info'] = ', '.join(info)

                    runner_dict['club_member'] = runner.club_member_set.filter(
                        club=club).first()
                    context['runners'].append(runner_dict)
            else:  # There are no similar runners, so we can create him/her
                to_create_runner = True
        else:
            messages.warning(request, u'Пожалуйста, исправьте ошибки в форме')
    elif 'step2_submit' in request.POST:
        form = RunnerForClubForm(user=user, data=request.POST)
        if form.is_valid():
            new_runner = form.instance
            runner_id = models.int_safe(request.POST.get('runner_id', 0))
            if runner_id == -1:  # This special value means we should create new runner
                to_create_runner = True
            else:  # We should add some existing runner
                runner = models.Runner.objects.filter(pk=runner_id).first()
                if runner:
                    club_member = runner.club_member_set.filter(
                        club=club).first()
                    if club_member:
                        if club_member.is_already_removed():
                            messages.warning(
                                request,
                                u'{} (id {}) уже был членом клуба «{}» до {}'.
                                format(runner.name(), runner.id, club.name,
                                       club_member.date_removed))
                        else:
                            messages.warning(
                                request,
                                u'{} (id {}) уже и так член клуба «{}»'.format(
                                    runner.name(), runner.id, club.name))
                        return redirect(club)
                    else:
                        to_create_member = True
                else:
                    messages.warning(
                        request,
                        u'К сожалению, выбранный Вами бегун (id {}) не найден. Попробуйте ещё раз'
                        .format(runner_id))
        else:
            messages.warning(request, u'Пожалуйста, исправьте ошибки в форме')

    if to_create_runner:
        runner = form.save(commit=False)
        runner.birthday_known = True
        runner.created_by = user
        runner.save()
        models.log_obj_create(
            user,
            runner,
            models.ACTION_CREATE,
            comment=u'При добавлении нового участника в КЛБМатч')
        to_create_member = True
    if to_create_member:
        email = form.cleaned_data.get('email', '')
        phone_number = form.cleaned_data.get('phone_number', '')
        club_member = models.Club_member.objects.create(
            runner=runner,
            club=club,
            email=form.cleaned_data.get('email', ''),
            phone_number=form.cleaned_data.get('phone_number', ''),
            date_registered=form.cleaned_data['date_registered'],
            added_by=user,
        )
        if runner.user and (runner.user != user):
            models.User_added_to_team_or_club.objects.create(
                user=runner.user,
                club=club,
                added_by=user,
            )
        update_runner_stat(club_member=club_member)
        models.log_obj_create(
            user,
            club,
            models.ACTION_CLUB_MEMBER_CREATE,
            child_object=club_member,
            comment=u'При добавлении нового участника в клуб')
        messages.success(
            request, u'{} успешно добавлен{} в команду'.format(
                runner.name(),
                u'а' if runner.gender == models.GENDER_FEMALE else ''))
        return redirect(club)

    if form is None:
        initial = {}
        if club.city:
            initial['city_id'] = club.city.id
            initial['region'] = club.city.region.id
        form = RunnerForClubForm(user=user, initial=initial)
    context['club'] = club
    context['members'] = get_cur_year_members(club)
    context['cur_stat_year'] = models.CUR_RUNNERS_ORDERING_YEAR
    context['form'] = form
    context['page_title'] = u'Добавление участника в клуб «{}»'.format(
        club.name)
    context['cur_klb_teams'] = club.klb_team_set.filter(
        year=models.CUR_KLB_YEAR)
    if 'runners' in context:
        template = 'club/add_club_member_step2.html'
    else:
        template = 'club/add_club_member_step1.html'
    return render(request, template, context)
Example #5
0
def ending(value, word_type):
    return plural_ending_new(value, word_type)
Example #6
0
def klb_make_team_or_club_payment(request, team_id=None, club_id=None):
	team, club, team_or_club, year, context, target, participants = get_team_club_year_context_target(request, team_id, club_id)
	if target:
		return target

	if 'btnPayForTeam' not in request.POST:
		return redirect(team_or_club.get_payment_url())

	good_participant_ids = set(participants.filter(payment=None).values_list('pk', flat=True))
	bad_participant_ids = set(participants.exclude(payment=None).values_list('pk', flat=True))
	good_participants = []
	bad_participants = []

	total_amount = models.int_safe(request.POST.get('total_amount', 0))
	price = get_participation_price(year)
	sum_of_prices = 0

	user = request.user
	for key, val in request.POST.items():
		if key.startswith("amount_"):
			participant_id = models.int_safe(key[len("amount_"):])
			if participant_id in bad_participant_ids:
				bad_participants.append((participant_id, u'Участие уже оплачено'))
			elif participant_id not in good_participant_ids:
				bad_participants.append((participant_id, u'Участник не выступает за нужную команду'))
			else: # So participant_id is in good_participant_ids
				participant = models.Klb_participant.objects.get(pk=participant_id)
				person = participant.klb_person

				participant_price = models.int_safe(val)
				if participant_price not in (0, price):
					bad_participants.append((participant_id, u'Недопустимая цена участия: {}'.format(participant_price)))
				elif (participant_price == 0) and (not participant.is_senior) and (person.disability_group == 0):
					bad_participants.append((participant_id, u'Цена участия — 0, хотя участник молод и здоров'))
				else:
					good_participants.append((participant, participant_price == 0))
					sum_of_prices += participant_price

	problems_desc = ''
	if bad_participants:
		problems_desc = u'\n'.join(u'{}: {}'.format(participant_id, desc) for participant_id, desc in bad_participants)
	elif sum_of_prices != total_amount:
		problems_desc = u'Общая цена — {}, но сумма по отдельным участникам — {}'.format(total_amount, sum_of_prices)

	if problems_desc:
		models.send_panic_email(
			u'Problem when paying for club {} (id {}), team {} (id {})'.format(club.name, club.id,
				team.name if team else '-', team.id if team else '-'),
			u'User {} {}{} was trying to pay for this club. Correct participants: {}. Incorrect participants: {}. Problems:\n\n{}'.format(
				user.get_full_name(), models.SITE_URL, user.user_profile.get_absolute_url(), len(good_participants), len(bad_participants), problems_desc),
			to_all=True
		)
		messages.warning(request, (u'К сожалению, при создании заказа возникла проблема. Администраторы уже знают об этом. '
			+ u'Вы можете попробовать ещё раз или подождать письма от нас о том, что проблема исправлена.'))
		return redirect(team_or_club.get_payment_url())

	if len(good_participants) == 0:
		messages.warning(request, u'Похоже, вы пытались заплатить за 0 человек. Не стоит этого делать :)')
		return redirect(team_or_club)

	if total_amount == 0:
		payment = models.Payment_moneta.objects.create(
			amount=0,
			is_dummy=True,
			is_paid=True,
			user=user,
		)
		payment.transaction_id = models.PAYMENT_DUMMY_PREFIX + unicode(payment.id)
		payment.save()

		for participant, _ in good_participants:
			participant.payment = payment
			participant.paid_status = models.PAID_STATUS_FREE
			participant.save()
			models.log_obj_create(request.user, participant.klb_person, models.ACTION_KLB_PARTICIPANT_UPDATE, child_object=participant,
				field_list=['paid_status', 'payment'], comment=u'Платёж {}'.format(payment.id), verified_by=models.USER_ROBOT_CONNECTOR)
		messages.success(request, u'Вы оплатили участие {} человек на общую сумму 0 рублей. Ура!'.format(len(good_participants)))
		return redirect(team_or_club)

	payment = models.Payment_moneta.objects.create(
		amount=total_amount,
		description=u'Оплата за {} участник{} {} {} в КЛБМатче–{}'.format(
			len(good_participants), results_util.plural_ending_new(len(good_participants), 16), u'команды' if team else u'клуба',
			team_or_club.name, year),
		user=user,
		sender=user.get_full_name(),
	)
	payment.refresh_from_db()
	payment.transaction_id = DESCRIPTION_PREFIX + unicode(payment.id)
	payment.signature = get_payment_md5(payment)
	payment.save()

	for participant, wants_to_pay_zero in good_participants:
		participant.payment = payment
		participant.wants_to_pay_zero = wants_to_pay_zero
		participant.save()
		models.log_obj_create(request.user, participant.klb_person, models.ACTION_KLB_PARTICIPANT_UPDATE, child_object=participant,
			field_list=['wants_to_pay_zero', 'payment'], comment=u'Платёж {}'.format(payment.id), verified_by=models.USER_ROBOT_CONNECTOR)
	redirect_url = get_redirect_url(payment)
	return redirect(redirect_url)
Example #7
0
def event_delete(request, event_id):
	event = get_object_or_404(models.Event, pk=event_id)
	context, has_rights, target = check_rights(request, event=event)
	if not has_rights:
		return target
	has_dependent_objects = event.has_dependent_objects()
	ok_to_delete = False
	if 'frmForEvent_submit' in request.POST:
		form = forms.ForEventForm(request.POST, auto_id='frmForEvent_%s')
		if form.is_valid():
			if has_dependent_objects:
				new_event_id = models.int_safe(request.POST.get('new_event_id', 0))
				if new_event_id:
					if new_event_id != event.id:
						new_event = models.Event.objects.filter(pk=new_event_id).first()
						if new_event:
							ok_to_delete = True
						else:
							messages.warning(request, u'Забег, на который нужно заменить текущий, не найден.')
					else:
						messages.warning(request, u'Нельзя заменить забег на себя же.')
				else:
					messages.warning(request, u'Забег, на который нужно заменить текущий, не указан.')
			else: # There are no races in the event, so we just delete it
				ok_to_delete = True
		else:
			messages.warning(request, u"Забег не удалён. Пожалуйста, исправьте ошибки в форме.")
	else:
		form = None
		messages.warning(request, u"Вы не указали забег для удаления.")
	if ok_to_delete:
		if not has_dependent_objects:
			new_event_id = 0
			new_event = None
		log = logging.getLogger('structure_modification')
		log_prefix = 'event_delete: event {}->{}, by user {}.'.format(event_id, new_event_id, request.user.id)
		log.debug('{} before flock'.format(log_prefix))
		log_exc_info = False
		with Flock_mutex(LOCK_FILE_FOR_RATED_TREE_MODIFICATIONS):
			event_name = event.name
			series = event.series
			log.debug('{} trnsctn start'.format(log_prefix))
			try:
				with transaction.atomic():
					if has_dependent_objects:
						update_event(request, event, new_event)
					log.debug('{} 1'.format(log_prefix))
					transfer_children_before_node_deletion(event, new_event)
					log.debug('{} 2'.format(log_prefix))
					models.log_obj_delete(request.user, event)
					log.debug('{} 3'.format(log_prefix))
					start_date = event.start_date
					event.delete()
					log.debug('{} 4'.format(log_prefix))
					update_events_count()
					log.debug('{} 5'.format(log_prefix))
					update_course_records(series)
					if event.series.is_russian_parkrun():
						log.debug('{} 6'.format(log_prefix))
						prev_event = series.event_set.filter(start_date__lt=start_date).order_by('-start_date').first()
						if prev_event:
							_, n_fixed_parkruns = views_parkrun.fix_parkrun_numbers(correct_event=prev_event)
							messages.success(request, u'Исправлена нумерация у {} паркран{} после удалённого'.format(n_fixed_parkruns,
								results_util.plural_ending_new(n_fixed_parkruns, 1)))
				log.debug('{} trnsctn end'.format(log_prefix))
			except (UpdatedRecordExistsError, AssertionError) as e:
				error_msg = repr(e)
				if isinstance(e, AssertionError):
					log_exc_info = True
			except Exception as e:
				log.error('{} Unexpected error: {}'.format(log_prefix, repr(e)), exc_info=True)
				raise
			else:
				error_msg = None
		if error_msg is None:
			log.info('{} OK'.format(log_prefix))
			messages.success(request, u'Забег «{}» из серии «{}» успешно удалён.'.format(event_name, series))
		else:
			log.error('{} {}'.format(log_prefix, error_msg), exc_info=log_exc_info)
			messages.warning(
				request, u'Не удалось удалить забег «{}» из серии «{}»<br />({}).'.format(
					event_name, series, error_msg
				)
			)
		return redirect(event.series)

	return event_details(request, event_id=event_id, event=event, frmForEvent=form)
Example #8
0
def make_event_news_text(event):
	races = event.race_set.filter(loaded=models.RESULTS_LOADED).select_related('distance').order_by(
		'distance__distance_type', '-distance__length', 'precise_name')
	races_count = races.count()
	if races_count == 0:
		return ''
	if races_count > 1:
		total_participants = races.aggregate(Sum('n_participants'), Sum('n_participants_finished'), Sum('n_participants_finished_men'))
		total = total_participants['n_participants__sum']
		total_finished = total_participants['n_participants_finished__sum']
		total_finished_men = total_participants['n_participants_finished_men__sum']
		total_finished_women = total_participants['n_participants_finished__sum'] - total_finished_men
	else:
		race = races[0]
	res = u'<p>{} в {} прошёл {}'.format(event.dateFull(), event.strCityCountry(), event.name)
	if races_count == 1:
		res += u' на дистанцию {}'.format(race.distance_with_heights())
	res += '.</p>\n'
	if races_count > 1:
		res += u'<p>Всего в нём приняли участие {} человек{}'.format(total, results_util.plural_ending_new(total, 9))
		if 0 < total_finished < total:
			res += u', финишировали {} человек{}'.format(total_finished, results_util.plural_ending_new(total_finished, 9))
		if 0 < total_finished_men < total_finished:
			res += u' ({} мужчин и {} женщин)'.format(total_finished_men, total_finished_women)
		res += u'.</p>\n'
		for race in races:
			if race.n_participants_finished == 1:
				if race.n_participants_finished_men:
					finished_ending = u''
				else:
					finished_ending = u'и'
			else:
				finished_ending = u'о'
			res += u'<p>На дистанции {} (финишировал{} '.format(race.distance_with_heights(), finished_ending)
			if race.n_participants_finished_men:
				res += u'{} мужчин{}'.format(race.n_participants_finished_men, results_util.plural_ending_new(race.n_participants_finished_men, 13))
				if race.n_participants_finished_men < race.n_participants_finished:
					res += u' и {} женщин{}'.format(race.get_n_participants_finished_women(),
						results_util.plural_ending_new(race.get_n_participants_finished_women(), 2))
			else:
				res += u'{} человек{}'.format(race.n_participants_finished, results_util.plural_ending_new(race.n_participants_finished, 9))
			res += u') победил'
			if race.n_participants_finished_men < race.n_participants_finished:
				res += u'и'
			res += u' {} {} '.format(race.winner_male_fname, race.winner_male_lname)
			if race.winner_male_city:
				res += u'({}) '.format(race.winner_male_city)
			res += u'— {}'.format(race.winner_male_result)
			if race.n_participants_finished_men < race.n_participants_finished:
				res += u' и'
				res += u' {} {} '.format(race.winner_female_fname, race.winner_female_lname)
				if race.winner_female_city:
					res += u'({}) '.format(race.winner_female_city)
				res += u'— {}'.format(race.winner_female_result)
			res += u'.</p>\n'
	else:
		res += u'<p>В нём приняли участие {} человек{}'.format(race.n_participants, results_util.plural_ending_new(race.n_participants, 9))
		if 0 < race.n_participants_finished < race.n_participants:
			res += u', финишировали {} человек{}'.format(race.n_participants_finished, results_util.plural_ending_new(race.n_participants_finished, 9))
		if 0 < race.n_participants_finished_men < race.n_participants_finished:
			res += u' ({} мужчин{} и {} женщин{})'.format(race.n_participants_finished_men,
				results_util.plural_ending_new(race.n_participants_finished_men, 13),
				race.get_n_participants_finished_women(), results_util.plural_ending_new(race.get_n_participants_finished_women(), 2))
		res += u'.</p>\n'
		res += u'<p>Победил'
		if race.n_participants_finished_men < race.n_participants_finished:
			res += u'и'
		res += u' {} {} '.format(race.winner_male_fname, race.winner_male_lname)
		if race.winner_male_city:
			res += u'({}) '.format(race.winner_male_city)
		res += u'— {}'.format(race.winner_male_result)
		if race.n_participants_finished_men < race.n_participants_finished:
			res += u' и'
			res += u' {} {} '.format(race.winner_female_fname, race.winner_female_lname)
			if race.winner_female_city:
				res += u'({}) '.format(race.winner_female_city)
			res += u'— {}'.format(race.winner_female_result)
		res += u'.</p>\n'
	return res