-
Notifications
You must be signed in to change notification settings - Fork 0
/
wordsExercises.py
332 lines (278 loc) · 14.7 KB
/
wordsExercises.py
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# -*-coding:utf-8 -*
import logging
import random
import time
import kanas
import words
# Exception when it is not correct that a specific romaji follows a っ
class LittleTsuError(SyntaxError):
pass
# Select the translation between both directions
def selectWordsExercise():
selected2 = False
while not selected2:
print(
"# Select mode\n 1- Random French word->Japanese word\n 2- Random Japanese word->French word\n 0- Return\n")
choice1 = input("> ")
selected2 = True
if choice1 == '1':
selected2 = randomFrenchToJapaneseWord()
elif choice1 == '2':
selected2 = randomJapaneseToFrenchWord()
elif choice1 == '0':
return False
else:
selected2 = False
print("Wrong choice\n")
return True
# Exercise: French word to Japanese word
def randomFrenchToJapaneseWord():
select1 = False
score = 0
frenchWordsNumber = len(words.frenchToJapaWordsDict)
incorrectFrenchWords = []
while not select1:
print(
f"# How many words for the game? (1-{frenchWordsNumber}, enter 0 for all)\n")
try:
nbWords = int(input("> "))
# 0 : select every word
if nbWords == 0:
nbWords = frenchWordsNumber
if nbWords >= 1 and nbWords <= frenchWordsNumber:
select1 = True
randFrenchWords = random.sample(
list(words.frenchToJapaWordsDict.keys()), nbWords)
print(
"For each word, enter the correct translation, then press Enter.")
print(
"\nYou can write directly with a Japanese keyboard, OR you can enter Romaji (romanized Japanese kanas) separated with space.\nExample: e mo ji")
for idxExercise in range(0, nbWords):
frenchWord = randFrenchWords[idxExercise]
inputJapaWord = input(
f"\n#{idxExercise+1}/{nbWords}\n {frenchWord}\n ").strip(" ").lower()
correctJapaWordsList = words.frenchToJapaWordsDict[frenchWord]
if inputJapaWord in correctJapaWordsList:
print("CORRECT")
score += 1
else:
decipheredAndCorrect, rebuiltAndCorrectWord = decipherJapaneseWordsFromRomajiTranscription(
inputJapaWord, correctJapaWordsList)
if decipheredAndCorrect:
print(f"{rebuiltAndCorrectWord}\nCORRECT")
score += 1
else:
# Definitely incorrect
incorrectAnswerString = "INCORRECT, it was "
if len(correctJapaWordsList) == 1:
incorrectAnswerString += correctJapaWordsList[0]
elif len(correctJapaWordsList) == 2:
for word in correctJapaWordsList[:-1]:
incorrectAnswerString += word
incorrectAnswerString += " or " + \
correctJapaWordsList[-1]
else:
for word in correctJapaWordsList[:-2]:
incorrectAnswerString += word + ", "
incorrectAnswerString += correctJapaWordsList[-2] + \
" or " + correctJapaWordsList[-1]
print(incorrectAnswerString)
incorrectFrenchWords.append(frenchWord)
# Score
time.sleep(1.0)
print(
f"\nScore: {score}/{nbWords}, {(100.0*score/nbWords):.01f}%\n")
if score < nbWords:
print("List of every incorrect translation:")
for incorrectWord in incorrectFrenchWords:
print(
f" {incorrectWord} - {words.frenchToJapaWordsDict[incorrectWord]}")
print("")
else:
raise ValueError()
except ValueError:
print(f"Wrong choice (must be 1-{frenchWordsNumber})\n")
return True
# Because one romaji may transcript two different kana, the transcripted kana word is a matrix.
# For each character of the word (first level), every possibility (second level) will be explored and compared with the correct list
# This function must be called with the Hiraganas and the Katakana matrix
def compareEveryCombinationWithTheCorrectList(kanaWordMatrix, correctJapaWordsList, rebuiltWord="", matrixIndex=0):
# This list will contain the index where get each kana from each list of kanaWordMatrix.
# If the romaji word is "a ji ju", giving then two possibilities for each two last romaji, kanaWordIndices
# will have these values: 000, 010, 011
# Should not occur
if len(kanaWordMatrix) == 0:
logging.error(
"Something went wrong, no romaji were detected in your input")
return False, None
idxPossibleKana = 0
for possibleKana in kanaWordMatrix[matrixIndex]:
logging.debug(
f'[compareEveryCombinationWithTheCorrectList] #{matrixIndex}#{idxPossibleKana}: {rebuiltWord}+{possibleKana}')
rebuiltWordWithCurrentKana = rebuiltWord+possibleKana
if matrixIndex == len(kanaWordMatrix)-1:
# Check rebuilt word (end condition)
if rebuiltWordWithCurrentKana in correctJapaWordsList:
logging.debug(
'[compareEveryCombinationWithTheCorrectList] SUCCESS')
return True, rebuiltWordWithCurrentKana
else:
logging.debug(
'[compareEveryCombinationWithTheCorrectList] FAILED')
return False, None
else:
# Iterate
returnedStatus, returnedWord = compareEveryCombinationWithTheCorrectList(
kanaWordMatrix, correctJapaWordsList, rebuiltWordWithCurrentKana, matrixIndex+1)
# Stop the search and return True, returnedWord
if returnedStatus:
return returnedStatus, returnedWord
# Else, continue the search
idxPossibleKana += 1
return False, None
# Sometimes, the player can input a Japanese word only using romaji.
# This function tries to decipher it (transcript in into Japanese) and return if it is in the list of correct words for this exercise's step
def decipherJapaneseWordsFromRomajiTranscription(inputJapaWord, correctJapaWordsList):
decipheredAndCorrect = False
rebuiltAndCorrectWord = None
try:
# In inputJapaWord is not readable, return deciphered=False
# If inputJapaWord is made of Kanas, we should not try to decipher it: return False
if inputJapaWord != None and inputJapaWord != "" and inputJapaWord.strip(" ")[0] < "z" and inputJapaWord.strip(" ")[0] > "0":
# Try to decipher romaji inputs
# Romaji splitted by space
romajiList = inputJapaWord.split(" ")
# These 2 variables are not directly strings to support the possibility to have several kana for one romaji (ji, ju).
# The combinatory will be explored below
hiraganaWordMatrix = [None] * len(romajiList)
katakanaWordMatrix = [None] * len(romajiList)
idxLetter = 0
for romaji in romajiList:
if romaji in kanas.AMBIGUOUS_ROMAJI_LIST:
# Ambiguous case when a Romaji can be several hira/katakana
potentialRomajis = kanas.AMBIGUOUS_ROMAJI_DICT[kanas.AMBIGUOUS_ROMAJI_LIST.index(
romaji)][romaji]
else:
# Not ambiguous: the potential romajis are in fact just the only one here
potentialRomajis = [romaji]
# From everyKanasHira, extract the hira translating the potential romaji using the index of everyKanasRoma
potentialHira = [""] * len(potentialRomajis)
idxPotentialRoma = 0
for roma in potentialRomajis:
# Double consonant
if len(roma) > 2 and roma[0] == roma[1]:
logging.debug(
f"[decipherJapaneseWordsFromRomajiTranscription] Hira: double consonant '{roma[0]}'")
potentialHira[idxPotentialRoma] += "っ"
# Checking if the rest of the romaji is authorized to be prefixed by っ
if roma[1] in kanas.ROMAJI_CONSONANTS_AUTHORIZING_LITTLE_TSU_PREFIX_LIST:
consolidatedRoma = roma[1:]
else:
raise LittleTsuError(roma[1:])
else:
consolidatedRoma = roma
potentialHira[idxPotentialRoma] += kanas.rootKanasHira[-1][kanas.rootKanasRoma[-1].index(
consolidatedRoma)]
idxPotentialRoma += 1
hiraganaWordMatrix[idxLetter] = potentialHira
# From everyKanasKata, extract the kata translating the potential romaji using the index of everyKanasRoma
potentialKata = [""] * len(potentialRomajis)
idxPotentialRoma = 0
for roma in potentialRomajis:
# Double consonant
if len(roma) > 2 and roma[0] == roma[1]:
logging.debug(
f"[decipherJapaneseWordsFromRomajiTranscription] Kana: double consonant '{roma[0]}'")
potentialKata[idxPotentialRoma] += "っ"
# Checking if the rest of the romaji is authorized to be prefixed by っ
if roma[1] in kanas.ROMAJI_CONSONANTS_AUTHORIZING_LITTLE_TSU_PREFIX_LIST:
consolidatedRoma = roma[1:]
else:
raise LittleTsuError(roma[1:])
else:
consolidatedRoma = roma
potentialKata[idxPotentialRoma] += kanas.rootKanasKata[-1][kanas.rootKanasRoma[-1].index(
consolidatedRoma)]
idxPotentialRoma += 1
katakanaWordMatrix[idxLetter] = potentialKata
idxLetter += 1
# Compare the Hiragana matrix's combinations with correctJapaWordsList
returnedStatus, returnedWord = compareEveryCombinationWithTheCorrectList(
hiraganaWordMatrix, correctJapaWordsList)
if not returnedStatus:
# If there is no result, compare the Katakana matrix's combinations with correctJapaWordsList
returnedStatus, returnedWord = compareEveryCombinationWithTheCorrectList(
katakanaWordMatrix, correctJapaWordsList)
# Found a word in correctJapaWordsList
if returnedStatus:
decipheredAndCorrect = True
rebuiltAndCorrectWord = returnedWord
# else: return False, None
# Exception when a romaji does not exist
except ValueError as err:
print(
f'There is something wrong with your input: "{romaji}" is NOT a Romaji')
except LittleTsuError as err:
print(
f'There is something wrong with your input: "{err}" cannot follow っ')
return decipheredAndCorrect, rebuiltAndCorrectWord
# Exercise: Japanese word to French word
def randomJapaneseToFrenchWord():
select1 = False
score = 0
japaWordsNumber = len(words.japaToFrenchWordsDict)
incorrectJapaWords = []
while not select1:
print(
f"# How many words for the game? (1-{japaWordsNumber}, enter 0 for all)\n")
try:
nbWords = int(input("> "))
# 0 : select every word
if nbWords == 0:
nbWords = japaWordsNumber
if nbWords >= 1 and nbWords <= japaWordsNumber:
select1 = True
randJapaWords = random.sample(
list(words.japaToFrenchWordsDict.keys()), nbWords)
print(
"For each word, enter the correct translation, then press Enter.")
for idxExercise in range(0, nbWords):
japaWord = randJapaWords[idxExercise]
inputFrenchWord = input(
f"\n#{idxExercise+1}/{nbWords}\n {japaWord}\n ").strip(" ").lower()
correctFrenchWordsList = words.japaToFrenchWordsDict[japaWord]
if inputFrenchWord in correctFrenchWordsList:
print("CORRECT")
score += 1
else:
# Definitely incorrect
incorrectAnswerString = "INCORRECT, it was "
if len(correctFrenchWordsList) == 1:
incorrectAnswerString += correctFrenchWordsList[0]
elif len(correctFrenchWordsList) == 2:
for word in correctFrenchWordsList[:-1]:
incorrectAnswerString += word
incorrectAnswerString += " or " + \
correctFrenchWordsList[-1]
else:
for word in correctFrenchWordsList[:-2]:
incorrectAnswerString += word + ", "
incorrectAnswerString += correctFrenchWordsList[-2] + \
" or " + correctFrenchWordsList[-1]
print(incorrectAnswerString)
incorrectJapaWords.append(japaWord)
# Score
time.sleep(1.0)
print(
f"\nScore: {score}/{nbWords}, {(100.0*score/nbWords):.01f}%\n")
if score < nbWords:
print("List of every incorrect translation:")
for incorrectWord in incorrectJapaWords:
print(
f" {incorrectWord} - {words.japaToFrenchWordsDict[incorrectWord]}")
print("")
else:
raise ValueError()
except ValueError:
print(f"Wrong choice (must be 1-{japaWordsNumber})\n")
return True