def seed_population(my_word, first_words): """ Generates a starting population of poems, using n-grams to generate a word based on a previous sequence of words my_word () first_words (string): a string representing the first n words of the inspiring test, which are used to start the poem generation """ poem_string = first_words old_sequence = first_words population = [] # generates 20 poems for a generation counter = 0 max_poems = 20 while counter < max_poems: poem = Poem() # each poem is 50 words for i in range(50): if len(poem_string) == 0: random_word = old_sequence.split()[0] else: random_word = rand.choice(poem_string.split()) new_word = my_word.get_next_word(old_sequence, random_word) + " " poem_string += new_word line_val = i % 10 if line_val == 0: poem_string += '\n' # for the purposes of crossbreeding, splits the poem in half if len(poem_string.split()) == 25: if i > 25: poem.second_half = poem_string poem_string = "" else: poem.first_half = poem_string poem_string = "" old_word_list = old_sequence.split() old_sequence = "" for k in range(1, len(old_word_list)): old_sequence = old_sequence + old_word_list[k] + " " old_sequence = old_sequence + new_word population.append(poem) counter += 1 return population
def get_poem(poem_link): try: poemhunter_poem_url = 'https://www.poemhunter.com' + poem_link poem_page = requests.get(poemhunter_poem_url) try: if poem_page.status_code != requests.codes.ok: raise Exception( 'The link {} does not exist on poemhunter.com'.format( poem_link)) poem_page_content = BeautifulSoup(poem_page.text, 'lxml') poem_container = poem_page_content.find('div', id='solSiirMetinDV') poem_block = poem_container.find('div', class_='KonaBody') poem_url = poemhunter_poem_url poem_title = '' poem_text = '' if poem_container.find('h1', class_='title') is not None: poem_title = poem_container.find('h1', class_='title').text if poem_block.find('p') is not None: poem_text = replace_double_br_tag_with_pipe(poem_block) return Poem('', poem_url, poem_title, poem_text) except Exception as exz: print(exz) return None except Exception as per: print(per) return None
def find_poem(poem_soup, url): if not poem_soup: return None try: poem_title = poem_soup.find('h1') if poem_title: title = unescape_text(poem_title.text, left=True, right=True) print("⇅ " + title) lines = find_poem_lines(poem_soup) translator = find_span_beginning_remove(poem_soup, 'c-txt_attribution', 'translated by') source = find_span_beginning_remove(poem_soup, 'c-txt_note', 'source:') year = None if source: year = find_poem_year(source) return Poem(title=title, lines=lines, translator=translator, source=source, year=year, url=url) except urllib.error.HTTPError as err: print("Poem not found, error " + str(err)) except urllib.error.URLError as err: print("Poem not found, error " + str(err)) return None
def test_should_be_able_to_echo_for_reveal_day_1(self): poet = Poet(Poem(POEM), EchoFormatter()) actualTale = poet.revealForDay(1) expectedTale = "This is the house that Jack built.\n\tthe house that Jack built." self.assertEqual(actualTale, expectedTale)
def mutate(poem, word_dictionary, n_value, mutation_prob=0.05): """ Handles the mutation functions of the poem by calling helper functions poem(Poem): the given poem to mutate word_dictionary (word_dictionary): the dictionary containing the n-grams information n_value (int): the user inputted n value mutation_prob (float): the probability that an indivudal word would be mutated """ new_poem = Poem() new_poem.first_half = get_words(poem.first_half, word_dictionary, n_value, mutation_prob) new_poem.second_half = get_words(poem.second_half, word_dictionary, n_value, mutation_prob) return new_poem
def test_recite_contains_day( self ): # TODO - hard to understand, what is Tale Day? The initial problem has no such word. poet = Poet(Poem(POEM), NoEchoFormatter()) tale = poet.recite() actualTaleDay = len(poet.poem.getPoem()) # TODO - don't invent words expectedTaleDay = tale.count("Day") self.assertEqual(actualTaleDay, expectedTaleDay)
def randomNumberGenerator(self): poem = Poem() while not thread_stop_event.isSet(): line = poem.get_line(7, [5, 7]) socketio.emit('newnumber', {'number': line}, namespace='/') line = poem.get_line(7, [5, 7]) socketio.emit('newnumber', {'number': line}, namespace='/') line = poem.get_line(7, [5, 7]) socketio.emit('newnumber', {'number': line}, namespace='/') line = poem.get_line(9, [5, 9]) socketio.emit('newnumber', {'number': line}, namespace='/') socketio.emit('newnumber', {'number': "-"*50}, namespace='/') poem.clear()
def main(): parser = argparse.ArgumentParser(prog='Shalk', description='The best poem generator ever!') parser.add_argument('-t', '--type', help='Poem type', choices=['haiku', 'tanka', 'limerick', 'quatrain'], default='haiku') #TODO: add others parser.add_argument('-n', '--quantity', help='Quantity of poems generated', default=10) parser.add_argument('-s', '--smoothing', help='Smoothing algorithm', choices=['linear', 'backoff'], default='backoff') args = parser.parse_args() p = Poem(ptype=args.type, smoothing=args.smoothing) for x in range(0, args.quantity): print '*** HOT NEW POEM COMING RIGHT UP!!! ***' text = p.generate() if not text: print 'Yeah, not this time... Let me try again!' print '======================================' continue print text print '======================================' print '*** That\'s it, folks!!! ***'
def test_reveal_for_day_5( self): # TODO - try to see if you can use multi-line strings poet = Poet(Poem(POEM), NoEchoFormatter()) actualTale = poet.revealForDay(5) expectedTale = "This is the dog that worried\n\t" \ + "the cat that killed\n\t" \ + "the rat that ate\n\t" \ + "the malth that lay in\n\t" \ + "the house that Jack built." \ self.assertEqual(actualTale, expectedTale)
def test_recite_reveal_everyday_tale( self ): # TODO - the test can be more specific, like how many days should exist? What should be the length of the poem? poet = Poet(Poem(POEM), NoEchoFormatter()) tale = poet.recite() actualTaleDay = len(poet.poem.getPoem()) expectedTaleDay = tale.count("Day") for day in range(1, actualTaleDay + 1): dayString = "Day {0} -".format(day) self.assertNotEqual( tale.index(dayString), -1 ) # TODO Complicated way of saying that something should exist. Is there is a simpler method to do that.
def main(): response = get_poem('https://cagibilit.com/wp-json/wp/v2/posts/10555') if response != None: ri = ResponseInspector(response) ri.run() if response != None: # pretty print the JSON response object # json_formatted_str = json.dumps(response.json(), indent=2) # print(json_formatted_str) poem = Poem(response.text) print(poem)
def couplet(hashtag): ''' Generates a Couplet poem given a list of (text, syllable count, rhyme) tuples ''' q = text( '''SELECT * FROM tweet LEFT JOIN tweets ON tweet.id = tweets.tweet_id WHERE tweets.tweet_id IS NULL AND tweet.hashtag = :h''') tweets = engine.connect().execute(q, h=hashtag).fetchall() corpus = [{'line':t.text, 'syllables':t.syllables, 'phone':t.phone, 'id':t.id, 'last_word':t.last_word} \ for t in tweets] def get_lines(phone, word, syllables): return [ line for line in corpus if line != {} and line['phone'] == phone and word.lower() != line['last_word'].lower() and abs(line['syllables'] - syllables) <= 1 ] def get_lines2(): return [ line for line in corpus if line != {} and line['phone'] != None and len(get_lines(line['phone'], line['last_word'], line['syllables'])) > 0 ] try: # Get random sample from 5 or 7 syllable tweets first = sample(get_lines2(), 1) phone = first[0] phone = phone['phone'] second = first word = first[0]['last_word'] syl = first[0]['syllables'] if len(get_lines(phone, word, syl)) > 0: while word == second[0]['last_word']: second = sample(get_lines(phone, word, syl), 1) else: raise ValueError( 'Could not construct couplet - not enough tweets found') except ValueError as e: raise ValueError( 'Could not construct couplet - not enough tweets found') first = first[0] second = second[0] tweets = [first, second] tweets = [db.session.query(Tweet).get(t['id']) for t in tweets] poem = Poem(tweets, hashtag, 'couplet') return poem
def run(): parser = Parser() parser.checkArgs() args = parser.getArgs() poem = Poem(POEM, Main.getRandom(args)) poet = Poet(poem, Main.getEcho(args)) shouldRecite = args[constant.RECITE_DEST] if shouldRecite: tale = poet.recite() print(tale) else: forWhichDay = args[constant.REVEAL_FOR_DAY_DEST][0] tale = poet.revealForDay(forWhichDay) print(tale)
def crossover(population): """ Performs crossover on a given generation of poems, swapping the first and second halves of each poem in a generation population (list): A list representing the breeding pool for the current generation """ new_population = [] for i in range(0, len(population), 2): new_poem1 = Poem() new_poem1.first_half = population[i].first_half new_poem1.second_half = population[i + 1].second_half new_poem2 = Poem() new_poem2.first_half = population[i + 1].first_half new_poem2.second_half = population[i].second_half new_population.append(new_poem1) new_population.append(new_poem2) return new_population
def poems_from(result): results = result.fetchall() if not results: print("query for poem failed") return None poems = [] for result in results: poem_id, title, author_str, translator, source, url, text = result poem = Poem(id=poem_id, title=title, author=author_str, text=text, translator=translator, source=source, url=url) poems.append(poem) print(f'{len(poems)} poems') return poems
def get_random_poem(author=None, max_lines=MAX_LINES, line_length=LINE_LENGTH): """ Returns a random Poem from the DATABASE of max length max_lines and from author if given. Returns None if no poems found """ conn = sqlite3.connect(DATABASE) cursor = conn.cursor() max_characters = max_lines * line_length result = None if author: result = cursor.execute(SELECT_RANDOM_POEM_POET, (max_lines, author, max_characters)) else: result = cursor.execute(SELECT_RANDOM_POEM, (max_lines, max_characters)) poem_array = result.fetchone() if not poem_array: print("query for poem failed") return None poem_id, title, author, translator, year, source, url = poem_array lines = [] for row in cursor.execute(SELECT_POEM_LINES, (poem_id, )): lines.append(row[0]) cursor.close() conn.commit() poem = Poem(title=title, author=author, lines=lines, translator=translator, year=year, source=source, url=url) print(poem.title + "\n") [print(l) for l in poem.lines] return poem
def haiku(hashtag): ''' Generates a Haiku poem given a hashtag ''' def get_lines(sylla_count): ''' Returns all tweets with the given number of syllables ''' q = text('''SELECT * FROM tweet LEFT JOIN tweets ON tweet.id = tweets.tweet_id WHERE tweets.tweet_id IS NULL AND tweet.hashtag = :h AND tweet.syllables = :s''') tweets = engine.connect().execute(q, h=hashtag, s=sylla_count).fetchall() print "Haiku: query", q, ": ", str(len(tweets)) print "hashtag:", hashtag return tweets try: # Get random sample from 5 or 7 syllable tweets five_syllables = sample(get_lines(5), 2) seven_syllables = sample(get_lines(7), 1) except ValueError as e: print 'haiku - not enough tweets...' raise ValueError('Could not construct haiku - not enough tweets') tweets = [five_syllables[0], seven_syllables[0], five_syllables[1]] tweets = [db.session.query(Tweet).get(t.id) for t in tweets] return Poem(tweets, hashtag, 'haiku')
def add_poems(self, poem_strings): for p in poem_strings: self.poems.append(Poem(p))
import pandas as pd from csv_manage import read_csv, write_csv from poem import Poem from tweeter import api as tweeter df = pd.read_csv('poem_list.csv') (author,title,link) = tuple(df.sample(1).iloc[0]) poem = Poem(author,title,link) tweet = poem.get_tweet() tweeter.update_status(tweet) print("Twitter update\n{}".format(tweet))
# -*- coding:utf-8 -*- """ author: Ziyu Chen """ from poem import Poem if __name__ == '__main__': poem = Poem('poetry_simplified.txt') poem.set_stopwords('stopwords.txt') poem.process() poem_set = poem.return_poem_set() poem.generate_word_cloud('poetry_simplified.txt', 'jiubei.jpg', 'jiubei_cw.jpg', userpic_as_backgroud=False) poem.generate_wordcloud_for_poet('李白', 'libai.jpg', 'libai_cw.jpg') poem.generate_wordcloud_for_poet('杜甫', 'dufu.jpg', 'dufu_cw.jpg') poem.draw_top_produced_poet() poem.draw_top_poem_kind() # poem.word_statistics(15)
def get(self): poem = Poem() self.write(poem.generate())
def limerick(hashtag): ''' Generates a limerick given a dictionary of line/syllables/phone ''' q = text( '''SELECT * FROM tweet LEFT JOIN tweets ON tweet.id = tweets.tweet_id WHERE tweets.tweet_id IS NULL AND tweet.hashtag = :h''') tweets = engine.connect().execute(q, h=hashtag).fetchall() corpus = [{'line':t.text, 'syllables':t.syllables, 'phone':t.phone, 'id':t.id, 'last_word':t.last_word} \ for t in tweets] print "-*" * 10 print len(corpus) print "-*" * 10 def get_lines(sylla_min, sylla_max, n): ''' Returns dic of at least n rhyming tweets within the given syllable range ex. {'ha1':['some tweet text', 'some other text']} ''' lines = [ line for line in corpus if line['syllables'] >= sylla_min and line['syllables'] <= sylla_max ] dic = {} # dic is a dictionary of phone strings to line dictionaries for line in lines: phone = line['phone'] if phone is None: continue elif phone in dic: # Avoid repeated last words if line['last_word'] not in [ l['last_word'] for l in dic[phone] ]: dic[phone].append(line) else: dic[phone] = [line] # Pick the least syllabically variant n lines return_lines = '' least_variance = 999 for key in dic: lines = dic[key] if len(lines) >= n: # Check variance, we want lines with similar syllable counts variance = max(lines, key=lambda line:line['syllables'])['syllables'] - \ min(lines, key=lambda line:line['syllables'])['syllables'] if len(return_lines) == 0 or least_variance > variance: return_lines = [line for line in lines] least_variance = variance logging.info("best lines: ") logging.info(return_lines) if len(return_lines) != 0: return return_lines else: raise ValueError ''' Limerick format is as follows: 6-12A 6-12A 3-6B 3-6B 6-10A ''' try: a = get_lines(6, 12, 3) # Get 3 6-12 syllable lines that rhyme b = get_lines(3, 7, 2) # Get 2 3-6 syllable lines that rhyme except ValueError as e: raise ValueError('Could not construct limerick - not enough tweets') tweets = [a[0], a[1], b[0], b[1], a[2]] tweets = [db.session.query(Tweet).get(t['id']) for t in tweets] poem = Poem(tweets, hashtag, 'limerick') return poem
def test_reveal_for_day_1(self): poet = Poet(Poem(POEM), NoEchoFormatter()) actualTale = poet.revealForDay(1) expectedTale = "This is the house that Jack built." self.assertEqual(actualTale, expectedTale)