def __init__(self): self.fave_ep = None self.fave_char = None self.prev_quote = None self.no_response_count = 0 self.context_count = 0 try: from seinfeld import Seinfeld except ImportError: import pip print('Crazy Joe: Installing necessary dependency: \'seinfeld\'...') pip.main(['install', 'seinfeld']) finally: from seinfeld import Seinfeld if not os.path.isfile(self.db_name): #looking in current dir only. import urllib.request as rq print('Crazy Joe: Downloading Seinfeld Database...') rq.urlretrieve(self.db_loc, self.db_name) self.seinfeld = Seinfeld(self.db_name) self.eps = {v.title.lower() : k for k, v in self.seinfeld.episode().items()} self.chars = ['jerry', 'elaine', 'george', 'kramer', 'leo', 'newman', 'maestro', 'puddy', 'peterman',] self.def_subjects = ['keys', 'tips', 'tipping', 'kavorka', 'tv', 'parents', 'sex', 'comedy', 'nothing',] self.new_subjects = [] self.jerry = False self.larry = False
def setUp(self): self.seinfeld = Seinfeld() self.seinfeld.open()
class TestDatabase(unittest.TestCase): def setUp(self): self.seinfeld = Seinfeld() self.seinfeld.open() def tearDown(self): self.seinfeld.close() def test_db_counts(self): self.assertEqual(len(self.seinfeld.episode()), 173) self.assertEqual(len(self.seinfeld.season()), 9) self.assertEqual(len(self.seinfeld.speaker()), 726) c = self.seinfeld.cursor() c.execute('select id from utterance order by id desc limit 1') count, = c.fetchone() self.assertEqual(count, 52206) self.assertEqual(self.seinfeld.MAX_QUOTE_ID, 52206) def test_data(self): season = self.seinfeld.season(2) self.assertEqual(season.number, 2) self.assertIsInstance(season.episodes, dict) self.assertEqual(len(season.episodes), 12) episode = season.episodes[3] self.assertEqual(episode.season, 2) self.assertEqual(episode.number, 3) self.assertEqual(episode.title, 'The Jacket') self.assertIsInstance(episode.date, dt.date) self.assertEqual(episode.date, dt.date(1991, 2, 6)) self.assertIsInstance(episode.writers, set) self.assertIn('Larry David', episode.writers) self.assertIn('Jerry Seinfeld', episode.writers) self.assertEqual(episode.director, 'Tom Cherones') def test_quote(self): speaker = self.seinfeld.speaker('GEORGE') episode = self.seinfeld.season(4).episodes[3] quote = self.seinfeld.quote(34663) self.assertEqual(quote.id, 34663) self.assertEqual(quote.episode, episode) self.assertEqual(quote.number, 250) self.assertEqual(quote.speaker, speaker) self.assertEqual(quote.text, '(Smiling) Nothing.') def test_search_single_quote(self): speaker = self.seinfeld.speaker('CUSTOMER') episode = self.seinfeld.season(2).episodes[3] quotes = self.seinfeld.search(speaker=speaker, subject='Alton Benes') self.assertEquals(len(quotes), 1) quote = quotes[0] self.assertEqual(quote.id, 1442) self.assertEqual(quote.episode, episode) self.assertEqual(quote.number, 6) self.assertEqual(quote.speaker, speaker) self.assertEqual(quote.text, 'Alton Benes is your father?') def test_search_multi_quote(self): speaker = self.seinfeld.speaker('ELAINE') episode = self.seinfeld.season(3).episodes[14] # test default limit quotes = self.seinfeld.search(episode=episode, speaker=speaker) self.assertEquals(len(quotes), 10) # test custom limit quotes = self.seinfeld.search(episode=episode, speaker=speaker, limit=5) self.assertEquals(len(quotes), 5) # test no limit quotes = self.seinfeld.search(episode=episode, speaker=speaker, limit=None) self.assertEquals(len(quotes), 37) last_number = 0 for quote in quotes: self.assertEqual(quote.episode, episode) self.assertGreater(quote.number, last_number) self.assertEqual(quote.speaker, speaker) self.assertTrue(quote.text) last_number = quote.number def test_passage(self): speaker = self.seinfeld.speaker('GEORGE') episode = self.seinfeld.season(4).episodes[3] quote = self.seinfeld.quote(34663) # custom length passage = self.seinfeld.passage(quote, length=10) self.assertEqual(len(passage.quotes), 10) # default length passage = self.seinfeld.passage(quote) self.assertEqual(len(passage.quotes), 5) self.assertTrue(passage) self.assertEqual(passage.id, 34663) self.assertEqual(passage.episode, episode) # passage beginning quote = passage.quotes[0] self.assertEqual(quote.id, 34661) self.assertEqual(quote.episode, episode) self.assertEqual(quote.number, 248) self.assertEqual(quote.speaker, speaker) self.assertTrue(quote.text.startswith('I think I can sum up the show')) # passage ending quote = passage.quotes[-1] self.assertEqual(quote.id, 34665) self.assertEqual(quote.episode, episode) self.assertEqual(quote.number, 252) self.assertEqual(quote.speaker, speaker) self.assertEqual(quote.text, 'The show is about nothing.')
class CrazyJoe(object): db_name = 'seinfeld.db' db_loc = 'https://noswap.com/pub/seinfeld.db' agent_name = 'Crazy Joe' def __init__(self): self.fave_ep = None self.fave_char = None self.prev_quote = None self.no_response_count = 0 self.context_count = 0 try: from seinfeld import Seinfeld except ImportError: import pip print('Crazy Joe: Installing necessary dependency: \'seinfeld\'...') pip.main(['install', 'seinfeld']) finally: from seinfeld import Seinfeld if not os.path.isfile(self.db_name): #looking in current dir only. import urllib.request as rq print('Crazy Joe: Downloading Seinfeld Database...') rq.urlretrieve(self.db_loc, self.db_name) self.seinfeld = Seinfeld(self.db_name) self.eps = {v.title.lower() : k for k, v in self.seinfeld.episode().items()} self.chars = ['jerry', 'elaine', 'george', 'kramer', 'leo', 'newman', 'maestro', 'puddy', 'peterman',] self.def_subjects = ['keys', 'tips', 'tipping', 'kavorka', 'tv', 'parents', 'sex', 'comedy', 'nothing',] self.new_subjects = [] self.jerry = False self.larry = False @classmethod def kmp(self, text, pattern): '''returns index of first subsequence in text matching pattern. -1 if DNE''' shifts = [1] * (len(pattern) + 1) shift = 1 for pos in range(len(pattern)): while shift <= pos and pattern[pos] != pattern[pos-shift]: shift += shifts[pos-shift] shifts[pos + 1] = shift start = 0 match_len = 0 for c in text: while match_len == len(pattern) or match_len >= 0 and not match(pattern[match_len], c): start += shifts[match_len] match_len -= shifts[match_len] match_len += 1 if match_len == len(pattern): return start return -1 def introduce(self): return ''' Good evening ladies and gentlemen, how are you doing tonight? Good? Good. I'm Crazy Joe Devola, I used to write for acclaimed sitcom 'Seinfeld.' I have a hard time differentiating between myself and my characters so WATCH OUT. I can only respond in 'Seinfeld' quotes, so bear with me. If anything I say or do offends you, too bad!...Although you could try contacting my creator Graham Kelly at [email protected]. What do you want to hear, quotes? Do you have a favorite episode? A favorite character? You can read my manual too if you need direction. (type 'help')''' def respond(self, the_input): '''Returns a response based on the passed input.''' if not the_input.strip(): # rule 0, respond to no input self.prev_quote = None if self.no_response_count >= len(no_response): self.no_response_count = 0 return self._get_good_quote() # default to just saying quote if no_responses exhausted. else: self.no_response_count += 1 return no_response[self.no_response_count - 1] clean_input = remove_punctuation(the_input) # filtered_input = sw_pattern.sub('', clean_input) # filter stop words wordlist = split(' ', clean_input) wordlist[0] = wordlist[0].lower() sub_wordlist = [w for w in wordlist if w not in stop_words] return self.make_response(wordlist, sub_wordlist) def make_response(self, wordlist, sub_wordlist): '''generates a response to the passed wordlist based on several rules''' if wordlist[0] == 'help': #rule 1: HELP ME! self.prev_quote = None return '\n\t'.join(commands) if wordlist[0] == 'random': #rule 2: random quote. return self._get_random_quote() if wordlist == ['i', 'am', 'the', 'master', 'of', 'my', 'domain']: # rule 11: master of my domain self.fave_ep = self.seinfeld.episode(id=self.eps['the contest']) return self._get_good_quote(episode=self.fave_ep) if wordlist[0:2] == ['who', 'is']: self.prev_quote = None if wordlist[2:4] == ['jerry', 'seinfeld']: #rule 13: learn about jerry seinfeld if not self.jerry: return 'Jerome Allen "Jerry" Seinfeld (born April 29, 1954) is an American comedian, actor, writer, producer, and director. He is known for playing a semifictional version of himself in the sitcom Seinfeld, which he created and wrote with Larry David. Seinfeld was heavily involved in the Bee Movie, in which he voiced its protagonist. In 2010, he premiered a reality series called The Marriage Ref. He directed Colin Quinn in the Broadway show Long Story Short at the Helen Hayes Theater, which ran until January 2011. He is the creator and host of the web series Comedians in Cars Getting Coffee. In his stand-up comedy career, Seinfeld is known for specializing in observational comedy, often ranting about relationships and embarrassing social situations.' else: return 'I already told you about him!' if wordlist[2:4] == ['larry', 'david']: #rule 14: learn about larry david if not self.larry: return 'Lawrence Gene "Larry" David (born July 2, 1947) is an American comedian, writer, actor, playwright, and television producer. He and Jerry Seinfeld created the television series Seinfeld, where he served as its head writer and executive producer from 1989 to 1996. David has subsequently gained further recognition for the HBO series Curb Your Enthusiasm, which he also created, in which he stars as a semi-fictionalized version of himself. He is worth an estimated $900 million US dollars. David\'s work won him a Primetime Emmy Award for Outstanding Comedy Series in 1993. Formerly a stand-up comedian, David went into television comedy, writing and starring in ABC\'s Fridays, as well as writing briefly for Saturday Night Live. He has won two Primetime Emmy Awards, and was voted by fellow comedians and comedy insiders as the 23rd greatest comedy star ever in a 2004 British poll to select "The Comedian\'s Comedian."' else: return 'I already told you about him!' if 'opera' in sub_wordlist: #rule 6: opera house self.fave_char = self.seinfeld.speaker(name='Devola') self.fave_ep = self.seinfeld.episode(id=self.eps['the opera']) lines = ['You have entered the opera house and unleashed my true persona: Crazy Joe Devola.', 'Muahahaha, I have changed your favorite episode and character settings.'] lines.append(self._get_good_quote()) return '\n'.join(lines) if self.kmp(wordlist, ['from', 'my', 'favorite', 'episode']) >= 0: #rule 12: quote from favorite episode if self.fave_ep: return self._get_good_quote(episode=self.fave_ep) if self.kmp(wordlist, ['my', 'favorite']) >= 0: if 'episode' in sub_wordlist: #rule 3: set fave ep try: try: e_loc = wordlist.index('episode') i_loc = wordlist.index('is') if i_loc < e_loc: ep_name = ' '.join(wordlist[0: i_loc]).lower() #pattern: XYZ is my favorite episode... else: ep_name = ' '.join(wordlist[i_loc + 1:]).lower() #pattern: ...my favorite episode is XYZ self.fave_ep = self.seinfeld.episode(id=self.eps[ep_name]) except KeyError: for k in self.eps.keys(): if SequenceMatcher(None, k, ep_name).ratio() >= .75: self.fave_ep = self.seinfeld.episode(id=self.eps[k]) if not self.fave_ep: raise NoEpisodeException except (IndexError, NoEpisodeException): return '\n'.join(['I can\'t seem to figure out what episode you meant.', # 'This is what I got: "' + ep_name + '."', self._get_random_quote(subject='stupid'),]) else: return ' '.join(['Oh yeah,', self.fave_ep.title, 'is a great episode.', 'Here\'s a quote:', self._get_good_quote() ]) if 'character' in sub_wordlist: #rule 4: set fave character try: try: c_loc = wordlist.index('character') i_loc = wordlist.index('is') if i_loc < c_loc: c_name = ' '.join(wordlist[0: i_loc]).lower() #pattern: XYZ is my favorite char... else: c_name = ' '.join(wordlist[i_loc + 1:]).lower() #pattern: ...my favorite char is XYZ self.fave_char = self.seinfeld.speaker(name=c_name.capitalize()) except KeyError: for c in self.chars: if SequenceMatcher(None, c, c_name).ratio() >= .75: self.fave_char = self.seinfeld.character(name=c) if not self.fave_char: raise NoCharacterException except (IndexError, NoCharacterException): return '\n'.join(['I can\'t seem to figure out what character you meant.', # 'This is what I got: "' + ep_name + '."', self._get_random_quote(subject='character'),]) else: return ' '.join(['Oh yeah,', self.fave_char.name, 'is funny.', 'Here\'s a quote: \n', self._get_good_quote() ]) if self.kmp(wordlist, ['add', 'subject']) >= 0: # rule 8: add subject self.prev_quote = None try: subject = wordlist[wordlist.index('subject') + 1] self.new_subjects.append(subject) return 'I will remember that one for later.' except (IndexError, ValueError): return 'Unable to remember that one...' if self.kmp(wordlist, ['show', r'\w*', 'subjects']) >= 0 or self.kmp(wordlist, ['show', 'subjects']) >= 0: # rule 9: show subjects self.prev_quote = None index = max(self.kmp(wordlist, ['show', r'\w*', 'subjects']), self.kmp(wordlist, ['show', 'subjects'])) try: if 'default' in wordlist[index : index + 2]: return 'Here are the default subjects: ' + ', '.join(self.def_subjects) + '.' elif 'my' in wordlist[index : index + 2]: return 'Here are the subjects I remember: ' + ', '.join(self.new_subjects) + '.' elif len(wordlist[index:index+2]) == 2: return 'These are all the subjects I know: ' + ', '.join(self.def_subjects + self.new_subjects) + '.' else: return 'I\'m not quite sure what subjects you want.' except (IndexError, ValueError): return 'I\'m not quite sure what subjects you want.' if self.kmp(wordlist, ['show', 'preferences']) >= 0: # rule 10: show current user prefs. self.prev_quote = None lines = ['Here are the preferences I know:', 'Favorite character: ' + (self.fave_char.name if self.fave_char else 'NONE'), 'Favorite episode: ' + (self.fave_ep.title if self.fave_ep else 'NONE')] return '\n\t'.join(lines) if self.prev_quote and 'context' in sub_wordlist or self.kmp(wordlist, ['i', 'don\'t', 'understand']) >= 0: #rule 5 give context with cycle if self.context_count < 5: #CYCLE p = self.seinfeld.passage(self.prev_quote, length=self.context_count * 3 + 8) lines = ['Perhaps this will help:'] for q in p.quotes: lines.append(q.speaker.name + ': ' + q.text) self.context_count += 1 return '\n\t'.join(lines) else: self.context_count = 0 return 'Seems like you\'re just not going to understand this one...\n' + self._get_random_quote(subject='understand') if self.kmp(wordlist, ['remove', 'preferences']) >= 0: #rule 7: remove preferences self.fave_char = None self.fave_ep = None self.prev_quote = None return '\n'.join(['I\'ve forgotten everything you told me.', self._get_random_quote(subject='forgot')]) try: #default response return self._get_good_quote(subject=choice(sub_wordlist) if sub_wordlist else None) except IndexError: return self._get_good_quote() def _get_good_quote(self, subject=None, episode=None): q = None qtext = '' while len(split(' ', qtext)) < 8: if episode: q = choice(self.seinfeld.search(episode=episode, random=True, limit=10)) elif any([self.fave_char, subject]): q = choice(self.seinfeld.search(speaker=self.fave_char, random=True, limit=10, subject=subject)) else: q = choice(self.seinfeld.search(subject=choice(self.def_subjects + self.new_subjects), random=True, limit=10)) #essentially random quote qtext = q.text self.prev_quote = q self.context_count = 0 return q.speaker.name.strip() + ': ' + qtext def _get_random_quote(self, subject=None): q = None qtext = '' while len(split(' ', qtext)) < 8: q = self.seinfeld.random(subject=subject, speaker=choice(self.chars) if not subject else None) qtext = q.text self.prev_quote = q self.context_count = 0 return q.speaker.name.strip() + ': ' + qtext def agentName(self): return self.agent_name
""" Mock app to test building """ from seinfeld import Seinfeld # pylint: disable=import-error SEINFELD = Seinfeld('mock.db') if __name__ == "__main__": print(SEINFELD.season(1).episodes[1].title)