Exemple #1
0
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
Exemple #3
0
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
Exemple #4
0
    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)
Exemple #5
0
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
Exemple #6
0
    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)
Exemple #7
0
 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()
Exemple #8
0
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!!! ***'
Exemple #9
0
    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)
Exemple #10
0
    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.
Exemple #11
0
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)
Exemple #12
0
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
Exemple #13
0
    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)
Exemple #14
0
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
Exemple #15
0
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
Exemple #16
0
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
Exemple #17
0
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')
Exemple #18
0
 def add_poems(self, poem_strings):
     for p in poem_strings:
         self.poems.append(Poem(p))
Exemple #19
0
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)
Exemple #21
0
 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
Exemple #23
0
    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)