reginafeles's picture
Upload 40 files
d2213a5 verified
"""Генератор задач: выбор предмета из смеси с 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'