"""Генератор задач: выбор предмета из смеси с pymorphy3""" from core.base_generator import BaseTaskGenerator from models.task import Task from fractions import Fraction from config import COMPLEXITY_CONFIG import random import pymorphy3 morph = pymorphy3.MorphAnalyzer() class MixedItemsGenerator(BaseTaskGenerator): """Генератор задач про выбор предмета из смеси с корректной морфологией""" ITEM_WEIGHTS = { 'пирожок': 1.0, 'конфета': 1.0, 'шар': 1.0, 'пазл': 1.0, 'ручка': 1.0, # ручки реже } def generate(self) -> Task: config = COMPLEXITY_CONFIG[self.complexity] item_variants = [ ('тарелке', 'лежат', 'пирожок', 'муж', 'с', [('с мясом', 'с мясом'), ('с капустой', 'с капустой'), ('с вишней', 'с вишней')]), ('коробке', 'лежат', 'конфета', 'жен', 'прил', [('шоколадных', 'шоколадная'), ('карамельных', 'карамельная'), ('фруктовых', 'фруктовая')]), ('ящике', 'лежат', 'шар', 'муж', 'прил', [('красных', 'красный'), ('синих', 'синий'), ('зелёных', 'зелёный')]), ('стакане', 'лежат', 'ручка', 'жен', 'прил', [('чёрных', 'чёрная'), ('синих', 'синяя'), ('красных', 'красная')]), ('коробке', 'находятся', 'пазл', 'муж', 'прил', [('с животными', 'с животными'), ('с картинами', 'с картинами'), ('с пейзажами', 'с пейзажами')]), ] weights = [self.ITEM_WEIGHTS.get(v[2], 1.0) for v in item_variants] ( container, verb, item_singular, gender, desc_type, categories ) = random.choices(item_variants, weights=weights, k=1)[0] count_options = { 'easy': [(4, 8, 3), (5, 7, 3), (6, 10, 4)], 'medium': [(4, 8, 3), (5, 7, 3), (6, 10, 4), (7, 13, 5)], 'hard': [(4, 8, 3), (5, 7, 3), (6, 10, 4), (7, 13, 5), (9, 15, 6)], } counts = random.choice(count_options[self.complexity]) total = sum(counts) target_idx = random.randint(0, 2) items_desc = [] for num, (adj, _) in zip(counts, categories): noun_parsed = morph.parse(item_singular)[0].make_agree_with_number(num) noun_form = noun_parsed.word if noun_parsed is not None else item_singular items_desc.append(f"{num} {adj}") items_description = ', '.join(items_desc[:-1]) + ' и ' + items_desc[-1] if desc_type == 'с': verb_form = f"окажется {categories[target_idx][1]}" else: adj = categories[target_idx][1] adj_parsed = morph.parse(adj)[0].inflect({'sing', 'masc' if gender=='муж' else 'femn', 'ablt'}) adj_instr = adj_parsed.word if adj_parsed is not None else adj verb_form = f"окажется {adj_instr}" selected_form = "выбранный" if gender == 'муж' else "выбранная" preposition = 'На' if container == 'тарелке' else 'В' noun_total_parsed = morph.parse(item_singular)[0].make_agree_with_number(total) noun_total = noun_total_parsed.word if noun_total_parsed is not None else item_singular question = ( f"{preposition} {container} {verb} {total} {noun_total}: " f"{items_description}. Найдите вероятность того, что случайно {selected_form} {item_singular} {verb_form}." ) favorable = counts[target_idx] fraction = Fraction(favorable, total) noun_fav_parsed = morph.parse(item_singular)[0].make_agree_with_number(favorable) noun_fav = noun_fav_parsed.word if noun_fav_parsed is not None else item_singular if desc_type != 'с': step2 = f"{categories[target_idx][0].capitalize()} {noun_fav}: {favorable}" else: step2 = f"{noun_fav.capitalize()} {categories[target_idx][0]}: {favorable}" steps = [ f"1. Общее число {noun_total}: {total}", f"2. {step2}", f"3. Вероятность = {favorable}/{total} = {fraction}", ] return Task( type='mixed_items', question=question, answer=float(fraction), answer_fraction=str(fraction), solution=f"Вероятность = {favorable}/{total} = {fraction}", steps=steps, complexity=self.complexity, ) def get_type(self) -> str: return 'mixed_items'