File size: 5,077 Bytes
d2213a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
"""Генератор задач: выбор предмета из смеси с 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'