Files
  • main.py
  • datamuse.py
  • datamuseAPI.pickle
  • fileHandler.py
  • input.txt
  • pseudocode.txt
  • textReader.pickle
  • textReader.py
main.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
from datamuse import DatamuseAPI
from fileHandler import FileHandler
from textReader import TextReader
import random

class SonnetMaker:
	def __init__(self, datamuseFilepath=None, textReaderFilepath=None):
		self.datamuseFilepath = datamuseFilepath
		self.textReaderFilepath = textReaderFilepath

		if datamuseFilepath:
			self.datamuseAPI = FileHandler.loadData(datamuseFilepath)
		else:
			self.datamuseAPI = DatamuseAPI()
			self.datamuseFilepath = "datamuseAPI.pickle"
		
		if textReaderFilepath:
			self.textReader = FileHandler.loadData(textReaderFilepath)
		else:
			self.textReader = TextReader()
			self.textReaderFilepath = "textReader.pickle"
	
	def __nextWord(self, word, mode, variation):
		possibleWords = self.textReader.nextWords(word, mode, variation)
		random.shuffle(possibleWords)
		for eachWord in possibleWords:
			if self.datamuseAPI.isWordRecognized(eachWord):
				return eachWord
		return None

	def __genLineBackwards(self, lastWord, syllables=10, variation=10):
		currentSyllables = 0
		while currentSyllables != syllables:
			currentSyllables = self.datamuseAPI.getSyllables(lastWord)
			words = [lastWord]
			while currentSyllables < syllables:
				newWord = self.__nextWord(words[0], "preceding", variation)
				currentSyllables += self.datamuseAPI.getSyllables(newWord)
				words.insert(0, newWord)
		words[0] = words[0][0].upper() + words[0][1:]
		return words
	
	def __filterToRecognized(self, wordList):
		recognizedWords = []
		for word in wordList:
			if self.textReader.isWordRecognized(word) and self.datamuseAPI.getRhyme(word, self.textReader) != None:
				recognizedWords.append(word)
		return recognizedWords

	def __getTopicWords(self, topic, neededWords, maxIterations=10):
		endWords = self.datamuseAPI.getTopicWords(topic)
		for i in range(maxIterations):
			newEndWords = list(set(endWords))
			for endWord in endWords:
				newEndWords.extend(self.datamuseAPI.getTopicWords(endWord))
				recognizedEndWords = self.__filterToRecognized(newEndWords)
				if len(recognizedEndWords) >= neededWords:
					random.shuffle(recognizedEndWords)
					return recognizedEndWords[:neededWords]
			endWords = newEndWords
 

	def genSonnet(self, topic, rhymeScheme="shakespearean"):
		if rhymeScheme == "shakespearean":
			topicWords = self.__getTopicWords(topic, 7)
			endWords = [topicWords[0], topicWords[1], self.datamuseAPI.getRhyme(topicWords[0], self.textReader, topic), self.datamuseAPI.getRhyme(topicWords[1], self.textReader, topic), None,
						topicWords[2], topicWords[3], self.datamuseAPI.getRhyme(topicWords[2], self.textReader, topic), self.datamuseAPI.getRhyme(topicWords[3], self.textReader, topic), None,
						topicWords[4], topicWords[5], self.datamuseAPI.getRhyme(topicWords[4], self.textReader, topic), self.datamuseAPI.getRhyme(topicWords[5], self.textReader, topic), None,
						topicWords[6], self.datamuseAPI.getRhyme(topicWords[6], self.textReader, topic)]
		sonnetString = ""
		for endWord in endWords:
			if endWord:
				sonnetString += " ".join(str(x) for x in self.__genLineBackwards(endWord))
			sonnetString += "\n   "
		return "   " + sonnetString[:-4]

	def topicRecognized(self, topic):
		if not topic.isalpha():
			return False
		if self.datamuseAPI.isWordRecognized(topic):
			return True
		return False

	def getApiCalls(self):
		return self.datamuseAPI.getApiCalls()
	
	def learnData(self, filepath):
		self.textReader.learnFile(filepath)

	def save(self, text=True, datamuse=True):
		if datamuse:
			FileHandler.saveData(self.datamuseAPI, self.datamuseFilepath)
		if text:
			FileHandler.saveData(self.textReader, self.textReaderFilepath)

running = True
mSonnetMaker = SonnetMaker("datamuseAPI.pickle")
print("\n===========")
print("Hello, I'm Poe. I write poetry.")
print("Upon starting, I read the file 'input.txt'. I use the data I read when writing poems.")
print("Try pasting a very large text documents into the 'input.txt' file. Different text documents can make different styles of poetry")
print("Large text documents (ie books in plain text) can be found at 'https://www.gutenberg.org/'.")
print("A collection of Edgar Allen Poe's writing is stored in input.txt by default.")
print("===========")
print(" - Reading 'input.txt'...")
mSonnetMaker.learnData("input.txt")
print(" - Data has been read.")
print("===========")
while running:
	topicRecognized = False
	while not topicRecognized:
		print("What would you like your sonnet to be about? (ie 'darkness', 'sports, 'programming')")
		topic = input(": ").lower()
		topicRecognized = mSonnetMaker.topicRecognized(topic)
		if topic == "/exit":
			running = False
			topicRecognized = True
		elif topic == "/api":
			print(" - The Datamuse API has been called {} times.".format(mSonnetMaker.getApiCalls()))
		if not topicRecognized and topic != "/api":
			print(" - Your topic must be one word (ie 'darkness', 'sports', 'programming')")
	print("===========")
	if running:
		print(" - Generating sonnet (this will take a minute)...")
		mySonnet = mSonnetMaker.genSonnet(topic)
		print(" - Sonnet generated")
		print("===========")
		print("Sonnet:")
		print("-------")
		print(mySonnet)
		print("===========")
		print("Type '/exit' to exit the program and save what has been learned. Type /api to see how many times you have called the Datamuse API.")
mSonnetMaker.save()