File size: 8,378 Bytes
2ccf6b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import regex
from num2words import num2words
import unicodedata

simple_replacements = {
    '№' : 'номер',
    '§': 'номер'
}

masc_replacments_dict = {
    '%':['відсоток', 'відсотки', 'відсотків'],
    'мм': ['міліметр', 'міліметри', 'міліметрів'],
    'см': ['сантиметр', 'сантиметри', 'сантиметрів'],
    'мм': ['міліметр', 'міліметри', 'міліметрів'],
    # 'м': ['метр', 'метри', 'метрів'],
    'км': ['кілометр', 'кілометри', 'кілометрів'],
    'гц': ['герц', 'герци', 'герців'],
    'кгц': ['кілогерц', 'кілогерци', 'кілогерців'],
    'мгц': ['мегагерц', 'мегагерци', 'мегагерців'],
    'ггц': ['гігагерц', 'гігагерци', 'гігагерців'],
    'вт': ['ват', 'вати', 'ватів'],
    'квт': ['кіловат', 'кіловати', 'кіловатів'],
    'мвт': ['мегават', 'мегавати', 'мегаватів'],
    'гвт': ['гігават', 'гігавати', 'гігаватів'],
    'дж': ['джоуль', 'джоулі', 'джоулів'],
    'кдж': ['кілоджоуль', 'кілоджоулі', 'кілоджоулів'],
    'мдж': ['мегаджоуль', 'мегаджоулі', 'мегаджоулів'],
    'см2': ['сантиметр квадратний', 'сантиметри квадратні', 'сантиметрів квадратних'],
    'м2': ['метр квадратний', 'метри квадратні', 'метрів квадратних'],
    'м2': ['кілометр квадратний', 'кілометри квадратні', 'кілометрів квадратних'],
    '$': ['долар', 'долари', 'доларів'],
    '€': ['євро', 'євро', 'євро'],
}

fem_replacments_dict = {
    'кал': ['калорія', 'калорії', 'калорій'],
    'ккал': ['кілокалорія', 'кілокалорії', 'кілокалорій'],
    'грн': ['гривня', 'гривні', 'гривень'],
    'грв': ['гривня', 'гривні', 'гривень'],
    '₴': ['гривня', 'гривні', 'гривень'],
}

neu_replacments_dict = {
     '€': ['євро', 'євро', 'євро'],
}

all_replacments_keys = list(masc_replacments_dict.keys()) + list(fem_replacments_dict.keys()) + list(neu_replacments_dict.keys())

#Ordinal types
#Називний
ordinal_nominative_masculine_cases = ('й','ий')
ordinal_nominative_feminine_cases = ('a','ша', 'я')
ordinal_nominative_neuter_cases = ('е',)

#Родовий
ordinal_genitive_masculine_case = ('го','о',)
ordinal_genitive_feminine_case = ('ї', 'ої')


#Давальний
ordinal_dative_masculine_case = ('му',)
ordinal_dative_feminine_case = ('й','ій')

#Знахідний
ordinal_accusative_masculine_case = ordinal_genitive_masculine_case
ordinal_accusative_feminine_case = ('у',)

#Орудний
ordinal_instrumental_masculine_case = ('им', 'ім')
ordinal_instrumental_feminine_case = ('ю')


#Місцевий
# ordinal_locative_masculine_case = ordinal_dative_masculine_case
# ordinal_locative_feminine_case = ordinal_dative_feminine_case

numcases_r = regex.compile(rf'((?:^|\s)(\d+)\s*(\-?)(([^\d,]*?)|(\-\.+))(?:\.|,|:|-)?)(\s+[^,.:\-]|$)', regex.IGNORECASE, regex.UNICODE)

print(numcases_r)
cardinal_genitive_endings = ('а', 'e', 'є', 'й')
ordinal_genitive_cases = ('року',)

def number_form(number):
    if number[-1] == "1":
        return 0
    elif number[-1] in ("2", "3", "4"):
        return 1
    else:
        return 2

def replace_cases(number, dash, case='', next_word=''):
    print(f'{number}, {dash}, {case}, {next_word}')
    gender = 'masculine'
    m_case = 'nominative'
    to = 'ordinal'
    repl = ''
    if not dash:
        if case in all_replacments_keys:
            if case in masc_replacments_dict.keys():
                repl = masc_replacments_dict.get(case)[number_form(number)]
                gender = 'masculine'
            elif case in fem_replacments_dict.keys():
                repl = fem_replacments_dict.get(case)[number_form(number)]
                gender = 'feminine'
            elif case in neu_replacments_dict.keys():
                repl = neu_replacments_dict.get(case)[number_form(number)]
                gender = 'neuter'
            to = 'cardinal'
        else:
            if len(case) < 3 and case and case[-1] in cardinal_genitive_endings:
                m_case = 'genitive'
                gender='masculine'
                to = 'cardinal'
            elif case in ordinal_genitive_cases:
                to = 'ordinal'
                m_case = 'genitive'
                repl = case
            else:
                to = 'cardinal'
                repl = case
                
    else:    
        if case in ordinal_nominative_masculine_cases:
            m_case = 'nominative'
            gender = 'masculine'
        elif case in ordinal_nominative_feminine_cases:
            m_case = 'nominative'
            gender = 'feminine'
        elif case in ordinal_nominative_neuter_cases:
            m_case = 'nominative'
            gender = 'neuter'
        elif case in ordinal_genitive_masculine_case:
            m_case = 'genitive'
            gender = 'masculine'
        elif case in ordinal_genitive_feminine_case:
            m_case = 'genitive'
            gender = 'feminine'
        elif case in ordinal_dative_masculine_case:
            m_case = 'dative'
            gender = 'masculine'
        elif case in ordinal_dative_feminine_case:
            m_case = 'dative'
            gender = 'feminine'
        elif case in ordinal_accusative_feminine_case:
            m_case = 'accusative'
            gender = 'feminine'
        elif case in ordinal_instrumental_masculine_case:
            m_case = 'instrumental'
            gender = 'masculine'
        elif case in ordinal_instrumental_feminine_case:
            m_case = 'instrumental'
            gender = 'feminine'
        else:
            if case and case[-1] in cardinal_genitive_endings:
                m_case = 'genitive'
                gender='masculine'
                to = 'cardinal'
                repl = case
            else:
                print(f'UNKNOWN CASE {number}-{case}')

    return_str = num2words(number, to=to, lang='uk', case=m_case, gender=gender)
    if repl:
        return_str +=  ' ' + repl
    if not next_word or (next_word and  next_word.strip().isupper()):
        return_str += '.'
    return return_str

def norm(text):
    text = regex.sub(r'[\t\n]', ' ', text)
    text = regex.sub(rf"[{''.join(simple_replacements.keys())}]", lambda x: f' {simple_replacements[x.group()]} ', text)
    text = regex.sub(r"(\d)\s+(\d)", r"\1\2", text)
    text = regex.sub(r'\s+', ' ', text)
    text = unicodedata.normalize('NFC', text)
    matches = numcases_r.finditer(text)
    pos = 0
    new_text = ''
    for m in matches:
        repl = replace_cases(m.group(2), m.group(3), m.group(4), m.group(7))
        new_text += text[pos:m.start(0)]+ ' ' + repl
        pos = m.end(1)
    new_text += text[pos:]
    return new_text.strip()

    

#1-го квітня, на 1-му поверсі Яринка загубила 2грн але знайшла 5€. Але її 4-річна сестричка забрала 50% її знахідки.
#Також 2003 року щось там сталося і 40-річний чоловік помер. Його знайшли через 3 години.

#01:51:37.250 -> 01:51:44.650:  Серед міленіалів цей показник становить 39%, серед покоління X – 30%,
#39
#30
#MATCHED: серед міленіалів цей показник становить тридцять девять , серед покоління Х - тридцять ,
#Skipped because contains inapropirate characters

#05:28:52.350 -> 05:29:00.000:  2016 рік завершився з чистими збитками 1,2 мільярди доларів США.
#2016
#MATCHED: дві тисячі шістнадцять рік завершився з чистими збитками 1,2 млрд доларів США.