diff --git a/NYTimesClueGenerator/demo.py b/NYTimesClueGenerator/demo.py index f9f0129..105b89e 100644 --- a/NYTimesClueGenerator/demo.py +++ b/NYTimesClueGenerator/demo.py @@ -5,20 +5,37 @@ import tkinter as tk from tkinter import ttk +print("\n\n--Available resources for clue generation:") +print("\t-Wordnet") +print("\t-Merriam Dictionary") +print("\t-Oxford Dictionary") +print("\t-Urban Dictionary") +print("\t-Google Dictionary") +print("\t-Wikipedia") +print('---------------------------------\n\n') + ''' Getting files from 'data' directory ''' def get_old_puzzles(): files = os.listdir('data') + print('---------------------------------') + print('Old puzzles are loading...\n') + names = {} for file in files: - name = re.findall('[A-Z][^A-Z]*', file)[1].replace('.json', '') - names[str(name)] = file + if file != '.DS_Store': + name = re.findall('[A-Z][^A-Z]*', file)[1].replace('.json', '') + print("Puzzle: " + name + " has been loaded.") + names[str(name)] = file # Sorting dates names = sorted(names.items(), key = lambda x: datetime.datetime.strptime(x[0], '%B%d,%Y')) + print('\nAll old puzzles have been loaded') + print('---------------------------------') + return names @@ -85,3 +102,5 @@ def display_old_puzzle(filename): # Loop root.resizable(False, False) root.mainloop() + +print("\n\nBye") \ No newline at end of file diff --git a/NYTimesClueGenerator/src/clue_gen/clueChanger.py b/NYTimesClueGenerator/src/clue_gen/clueChanger.py index 7408e4f..f6e64e8 100644 --- a/NYTimesClueGenerator/src/clue_gen/clueChanger.py +++ b/NYTimesClueGenerator/src/clue_gen/clueChanger.py @@ -10,13 +10,15 @@ from clue_gen.urbanParser import getWordFromUrban from clue_gen.didyoumean import did_you_mean from clue_gen.wikipediaParser import search_wikipedia +from clue_gen.googleDictionary import getWordFromGoogleDictionary # All resources to be searched RESOURCES = [{'name': 'Wikipedia', 'func': search_wikipedia}, {'name': 'Wordnet', 'func': search_wordnet}, {'name': 'Merriam', 'func': getWordFromMerriam}, {'name': 'Oxford', 'func': getWordFromOxford}, - {'name': 'Urban', 'func': getWordFromUrban}] + {'name': 'Urban', 'func': getWordFromUrban}, + {'name': 'Google Dict', 'func': getWordFromGoogleDictionary}] # For finding the stem (root) of the word ps = PorterStemmer() @@ -36,10 +38,10 @@ ''' -def changeClue(word, clue, replace_policy): +def changeClue(word, clue, replace_policy, trace = False): # Checking the word in Google's 'Did You Mean' - did_you_mean_result = did_you_mean(word) + did_you_mean_result = did_you_mean(word, trace) if did_you_mean_result is not None: word = did_you_mean_result @@ -63,7 +65,7 @@ def changeClue(word, clue, replace_policy): # Checking the resources for resource in RESOURCES: - results = resource['func'](word)[replaced] + results = resource['func'](word, trace)[replaced] if results is not None and len(results) != 0: # If the original clue returned as a new clue @@ -82,7 +84,7 @@ def changeClue(word, clue, replace_policy): if word.lower() not in result.lower(): continue else: - new_clue = result.lower().replace(word.lower(), '...').strip() + new_clue = result.lower().replace(word.lower(), '___').strip() is_found = True break else: diff --git a/NYTimesClueGenerator/src/clue_gen/clueGenerator.py b/NYTimesClueGenerator/src/clue_gen/clueGenerator.py index 20c5c5d..8cdbc1c 100644 --- a/NYTimesClueGenerator/src/clue_gen/clueGenerator.py +++ b/NYTimesClueGenerator/src/clue_gen/clueGenerator.py @@ -7,7 +7,7 @@ ''' -def changePuzzle(clues): +def changePuzzle(clues, trace = False): across_clues = clues['across'] down_clues = clues['down'] @@ -18,19 +18,27 @@ def changePuzzle(clues): word = ac_clue['answer'] num = ac_clue['number'] - print("Searching clue for \"" + str(word) + "\"") + print("\n----------------------------------") + print("*** Searching clue for \"" + str(word) + "\" ***\n") found = False for i in range(4): - new_clue = changeClue(word, clue, i) + if i == 0: print("\t---Looking for definitions---\n") + elif i == 1: print("\t---Looking for synonyms---\n") + elif i == 2: print("\t---Looking for antonyms---\n") + elif i == 3: print("\t---Looking for examples---\n") + + new_clue = changeClue(word, clue, i, trace) if new_clue['new_clue'] is not None: - print("New clue for \"" + str(word) + "\" is found from " + str(new_clue['source']) + "\n") + print("\n*** New clue for \"" + str(word) + "\" is found from " + str(new_clue['source']) + " ***") changed_across_clues.append({'clue': new_clue['new_clue'], 'answer': word, 'number': num}) + print("----------------------------------\n") found = True break # No new clue cannot be found if found is False: - print("No new clue cannot be found for \"" + str(word) + "\"\n") + print("\n*** No new clue can be found for \"" + str(word) + "\" ***") + print("----------------------------------\n") changed_across_clues.append(ac_clue) print("\n----Generating down clues----\n") @@ -40,19 +48,27 @@ def changePuzzle(clues): word = down_clue['answer'] num = down_clue['number'] - print("Searching clue for \"" + str(word) + "\"") + print("\n----------------------------------") + print("*** Searching clue for \"" + str(word) + "\" ***\n") found = False for i in range(4): - new_clue = changeClue(word, clue, i) + if i == 0: print("\t---Looking for definitions---\n") + elif i == 1: print("\t---Looking for synonyms---\n") + elif i == 2: print("\t---Looking for antonyms---\n") + elif i == 3: print("\t---Looking for examples---\n") + + new_clue = changeClue(word, clue, i, trace) if new_clue['new_clue'] is not None: - print("New clue for \"" + str(word) + "\" is found from " + str(new_clue['source']) + "\n") + print("\n*** New clue for \"" + str(word) + "\" is found from " + str(new_clue['source']) + " ***") + print("----------------------------------\n") changed_down_clues.append({'clue': new_clue['new_clue'], 'answer': word, 'number': num}) found = True break # No new clue cannot be found if found is False: - print("No new clue cannot be found for \"" + str(word) + "\"\n") + print("\n*** No new clue can be found for \"" + str(word) + "\" ***") + print("----------------------------------\n") changed_down_clues.append(down_clue) # Returning diff --git a/NYTimesClueGenerator/src/clue_gen/didyoumean.py b/NYTimesClueGenerator/src/clue_gen/didyoumean.py index b26c635..265266b 100644 --- a/NYTimesClueGenerator/src/clue_gen/didyoumean.py +++ b/NYTimesClueGenerator/src/clue_gen/didyoumean.py @@ -10,8 +10,12 @@ ''' -def did_you_mean(query): +def did_you_mean(query, trace = False): try: + # Trace + if trace is True: + print("\t\t\"Did You Mean (from Google) check\" for the query: \"" + query + "\"") + # query = str(query).strip() html = get_page('http://www.google.com/search?q=' + query) soup = BeautifulSoup(html, 'html.parser') @@ -21,8 +25,18 @@ def did_you_mean(query): result = answer.find('i') if answer is not None else None result = result.text if result is not None else None + # Trace + if trace is True and result is None: + print("\t\tNo correction from \"Did You Mean check\" for the query: \"" + query + "\"\n") + else: + print("\t\t\"" + query + "\" is replaced with \"" + result +"\"\n") + return result except Exception as e: - raise + pass + + # Trace + if trace is True: + print("\t\tPassed \"Did You Mean check\" for the query: \"" + query + "\"\n") return None diff --git a/NYTimesClueGenerator/src/clue_gen/googleDictionary.py b/NYTimesClueGenerator/src/clue_gen/googleDictionary.py new file mode 100644 index 0000000..c33f9ea --- /dev/null +++ b/NYTimesClueGenerator/src/clue_gen/googleDictionary.py @@ -0,0 +1,60 @@ +import urllib.request +import json +import unicodedata + +URL = 'https://googledictionaryapi.eu-gb.mybluemix.net/' + +''' + Searching the word in Google Dictionary API (unofficial) + + :param word - the given word +''' + + +def getWordFromGoogleDictionary(word, trace = False): + # Trace + if trace is True: + print("\t\tChecking Google dictionary for the word: \"" + word + "\"") + + # Replacing non-eng chars + word = unicodedata.normalize('NFKD', word).encode('ascii', 'ignore').decode('utf8') + + url = URL + '?define=' + word + '&lang=en' + + meanings = [] + + try: + request = urllib.request.Request(url) + response = urllib.request.urlopen(request) + content = response.read().decode('utf-8') + contentJson = json.loads(content) + + for res in contentJson: + meaning = res['meaning'] + + for key in meaning.keys(): + for definition in meaning[key]: + meanings.append(definition['definition']) + + except Exception as e: + pass + + # Trace + if trace is True and len(meanings) == 0: + print("\t\tNo results from Google dictionary for the word: \"" + word + "\"\n") + + # Returning word + word = { + "word": word, + "syn": [], + "ant": [], + "def": meanings, + "examples": [] + } + + return word + + +# TEST +# print(getWordFromGoogleDictionary('İSN\'T')) + diff --git a/NYTimesClueGenerator/src/clue_gen/merriamParser.py b/NYTimesClueGenerator/src/clue_gen/merriamParser.py index bda98ed..8a5963c 100644 --- a/NYTimesClueGenerator/src/clue_gen/merriamParser.py +++ b/NYTimesClueGenerator/src/clue_gen/merriamParser.py @@ -10,7 +10,11 @@ ''' -def getWordFromMerriam(word): +def getWordFromMerriam(word, trace = False): + # Trace + if trace is True: + print("\t\tChecking Merriam dictionary for the word: \"" + word + "\"") + url = "https://dictionaryapi.com/api/v3/references/thesaurus/json/"+word+"?key="+merriam_app_key synsMixed = [] antsMixed = [] @@ -48,6 +52,10 @@ def getWordFromMerriam(word): exMixed = [] defsMixed = [] + # Trace + if trace is True and len(synsMixed) == 0 and len(antsMixed) == 0 and len(defsMixed) == 0 and len(exMixed) == 0: + print("\t\tNo results from Merriam dictionary for the word: \"" + word + "\"\n") + # Returning word word = { "word": word, diff --git a/NYTimesClueGenerator/src/clue_gen/oxford.py b/NYTimesClueGenerator/src/clue_gen/oxford.py index 3c35e69..5f55755 100644 --- a/NYTimesClueGenerator/src/clue_gen/oxford.py +++ b/NYTimesClueGenerator/src/clue_gen/oxford.py @@ -9,7 +9,11 @@ URL = 'https://od-api.oxforddictionaries.com:443/api/v2/entries/' + LANGUAGE + '/' -def getWordFromOxford(word): +def getWordFromOxford(word, trace = False): + # Trace + if trace is True: + print("\t\tChecking Oxford dictionary for the word: \"" + word + "\"") + url = URL + word.lower() synsMixed = [] @@ -41,6 +45,10 @@ def getWordFromOxford(word): exMixed = [] defsMixed = [] + # Trace + if trace is True and len(defsMixed) == 0 and len(exMixed) == 0: + print("\t\tNo results from Oxford dictionary for the word: \"" + word + "\"\n") + # Returning word word = { "word": word, diff --git a/NYTimesClueGenerator/src/clue_gen/urbanParser.py b/NYTimesClueGenerator/src/clue_gen/urbanParser.py index cd4e1b2..7e972a4 100644 --- a/NYTimesClueGenerator/src/clue_gen/urbanParser.py +++ b/NYTimesClueGenerator/src/clue_gen/urbanParser.py @@ -10,7 +10,11 @@ ''' -def getWordFromUrban(word): +def getWordFromUrban(word, trace = False): + # Trace + if trace is True: + print("\t\tChecking Urban dictionary for the word: \"" + word + "\"") + url = URL + word defsMixed = [] @@ -36,6 +40,10 @@ def getWordFromUrban(word): except Exception as e: pass + # Trace + if trace is True and len(defsMixed) == 0 and len(exMixed) == 0: + print("\t\tNo results from Urban dictionary for the word: \"" + word + "\"\n") + word = { "word": word, "syn": [], diff --git a/NYTimesClueGenerator/src/clue_gen/wikipediaParser.py b/NYTimesClueGenerator/src/clue_gen/wikipediaParser.py index f96ec83..58b9b77 100644 --- a/NYTimesClueGenerator/src/clue_gen/wikipediaParser.py +++ b/NYTimesClueGenerator/src/clue_gen/wikipediaParser.py @@ -10,10 +10,14 @@ ''' -def search_wikipedia(word): +def search_wikipedia(word, trace = False): # To ignore module warnings warnings.filterwarnings('ignore') + # Trace + if trace is True: + print("\t\tChecking Wikipedia for the word: \"" + word + "\"") + # Example sentences sentences = [] @@ -29,6 +33,10 @@ def search_wikipedia(word): except Exception as e: pass + # Trace + if trace is True and len(sentences) == 0: + print("\t\tNo results from Wikipedia for the word: \"" + word + "\"\n") + return { "word": word, "syn": [], diff --git a/NYTimesClueGenerator/src/clue_gen/wordnet.py b/NYTimesClueGenerator/src/clue_gen/wordnet.py index 74a75bb..1c502e2 100644 --- a/NYTimesClueGenerator/src/clue_gen/wordnet.py +++ b/NYTimesClueGenerator/src/clue_gen/wordnet.py @@ -12,7 +12,11 @@ ''' -def search_wordnet(word): +def search_wordnet(word, trace = False): + # Trace + if trace is True: + print("\t\tChecking Wordnet for the word: \"" + word + "\"") + # Synonym set of the word) synset = wordnet.synsets(str(word)) @@ -33,6 +37,10 @@ def search_wordnet(word): if len(synonyms) != 0 and word.lower() in synonyms: synonyms.remove(word.lower()) + # Trace + if trace is True and len(synonyms) == 0 and len(antonyms) == 0 and len(definitions) == 0 and len(examples) == 0: + print("\t\tNo results from Wordnet for the word: \"" + word + "\"\n") + return { "word": word, "syn": synonyms, diff --git a/NYTimesClueGenerator/src/puzzle/gui.py b/NYTimesClueGenerator/src/puzzle/gui.py index 73b2704..93c5c2e 100644 --- a/NYTimesClueGenerator/src/puzzle/gui.py +++ b/NYTimesClueGenerator/src/puzzle/gui.py @@ -33,7 +33,7 @@ def __render_title(self, date): # LOG self.log_gen.write_to_file('Title is rendered') - print('Title is rendered') + print('\tTitle is rendered') ''' @@ -80,7 +80,7 @@ def __render_grid(self, puzzle): # LOG self.log_gen.write_to_file('Grids are rendered') - print('Grids are rendered') + print('\tGrids are rendered') ''' @@ -121,7 +121,7 @@ def __render_clues(self, clues, title): # LOG self.log_gen.write_to_file('Clues are rendered') - print('Clues are rendered') + print('\tClues are rendered') ''' @@ -135,8 +135,9 @@ def render(self, data): # self.__root.geometry('1000x1000') # LOG + print("---Showing the puzzle----\n") self.log_gen.write_to_file('Window is constructed') - print('Window is constructed') + print('\tWindow is constructed') if data is None or data['date'] is None or data['puzzle'] is None or data['clues'] is None: print("ERROR: Data is not in proper format!") diff --git a/NYTimesClueGenerator/src/puzzle/main.py b/NYTimesClueGenerator/src/puzzle/main.py index 755b5e8..b8871a6 100644 --- a/NYTimesClueGenerator/src/puzzle/main.py +++ b/NYTimesClueGenerator/src/puzzle/main.py @@ -27,8 +27,14 @@ sys.exit() # NEW CLUES -data['generated_clues'] = changePuzzle(data['clues']) +print("Generating clues for puzzle of ", data['date']) +data['generated_clues'] = changePuzzle(data['clues'], trace=True) + +print("\nClue generation for puzzle of " + data['date'] + " has been finished!") +print('---------------------------------\n') + + # GUI with data gui = GUI(l_gen) -gui.render(data) +gui.render(data) \ No newline at end of file diff --git a/NYTimesClueGenerator/src/puzzle/scraper.py b/NYTimesClueGenerator/src/puzzle/scraper.py index c0387aa..cdd3d15 100644 --- a/NYTimesClueGenerator/src/puzzle/scraper.py +++ b/NYTimesClueGenerator/src/puzzle/scraper.py @@ -69,8 +69,8 @@ def fetch_puzzle(self): outfile.write(w_data) # LOG - self.log_gen.write_to_file('Puzzle data is written to the JSON file') - print('Puzzle data is written to the JSON file') + self.log_gen.write_to_file('\tPuzzle data is written to the JSON file') + print('\tPuzzle data is written to the JSON file\n\n') return data @@ -86,10 +86,11 @@ def __reveal_answer(self): driver = webdriver.Chrome() # LOG - self.log_gen.write_to_file('Browser is opened and request is sent to the URL') - self.log_gen.write_to_file('Page is loading') - print('Browser is opened and request is sent to the URL') - print('Page is loading') + print("---Getting today's puzzle---\n") + self.log_gen.write_to_file('\tBrowser is opened and request is sent to the URL') + self.log_gen.write_to_file('\tPage is loading') + print('\tBrowser is opened and request is sent to the URL') + print('\tPage is loading') driver.get(self.URL) @@ -99,8 +100,8 @@ def __reveal_answer(self): WebDriverWait(driver, timeout).until(modal) # LOG - self.log_gen.write_to_file('Page is loaded') - print('Page is loaded') + self.log_gen.write_to_file('\tPage is loaded') + print('\tPage is loaded') # CLicking to start btn start_btn = driver.find_element_by_css_selector(".buttons-modalButton--1REsR") @@ -119,8 +120,8 @@ def __reveal_answer(self): puzzle_btn.click() # LOG - self.log_gen.write_to_file('Reveal Puzzle is clicked!') - print('Reveal Puzzle is clicked!') + self.log_gen.write_to_file('\tReveal Puzzle is clicked!') + print('\tReveal Puzzle is clicked!') except TimeoutException: print("TIMEOUT") @@ -137,8 +138,8 @@ def __reveal_answer(self): driver.close() # LOG - self.log_gen.write_to_file('Browser is closed and content of the page is returned') - print('Browser is closed and content of the page is returned') + self.log_gen.write_to_file('\tBrowser is closed and content of the page is returned') + print('\tBrowser is closed and content of the page is returned') except Exception as e: p_source = None @@ -172,8 +173,8 @@ def __fetch_clues(self, clues): }) # LOG - self.log_gen.write_to_file('Across clues are parsed from the page content') - print('Across clues are parsed from the page content') + self.log_gen.write_to_file('\tAcross clues are parsed from the page content') + print('\tAcross clues are parsed from the page content') # Down down = divs[1].find('ol').find_all('li') @@ -185,8 +186,8 @@ def __fetch_clues(self, clues): }) # LOG - self.log_gen.write_to_file('Down clues are parsed from the page content') - print('Down clues are parsed from the page content') + self.log_gen.write_to_file('\tDown clues are parsed from the page content') + print('\tDown clues are parsed from the page content') # Returning whole data return { @@ -229,8 +230,8 @@ def __fetch_cells(self, puzzle): j += 1 # LOG - self.log_gen.write_to_file('Puzzle cells are parsed from the page content') - print('Puzzle cells are parsed from the page content') + self.log_gen.write_to_file('\tPuzzle cells are parsed from the page content') + print('\tPuzzle cells are parsed from the page content') return puzzle_data