<commit_before>#! /usr/bin/env python3
# -*- coding: utf-8 -*-
#
# A Hangman game programmed in Python 3.
#
# Copyright (c) 2013 K Kollmann <code∆k.kollmann·moe>
# License: http://opensource.org/licenses/MIT MIT
#
# You need to have Python 3.x installed to run this game.
# The game's objective is to guess a word, letter by letter.
# 11 incorrect guesses are possible, then hangman dies and the game is over.
#
# Parameters the game can be run with:
# -nosound to turn off text-to-speech
# -en|de to play with English or German words # TODO: (defaults to English)
#
"""Hangman - a word-guessing game.

parameters:
-nosound ... play the game without sound
-en|de ... play the game with English/German words
"""

import random # module for randomisation
import subprocess # enable command line functions
import sys # module for parameters

def stringtogether(thislist):
    """return elements in a list as a string"""
    return ''.join(thislist)

def output(text, blankchar='-', blankcharvoiced='blank', software='say',
    voice=True, outputtext=True, ending='\n', spell=False):
    """Print out text and voice it using text-to-speech software.

    If outputtext is True, print text.
    If voice is True, voice text with text-to-speech.
    """

    maxvoicedblanks = 2
    t2s_errormsg = ("There was a problem with running the text-to-speech "
        "software {}.".format(software))
    # spell out placeholder characters explicitely
    if text:
        print(text,end=ending)
    if voice:
        if spell:
            # don't spell out all placeholder chars
            speaklist = []
            howmanyblanks = 0
            for char in text:
                if char == blankchar:
                    howmanyblanks += 1
                else:
                    if howmanyblanks > 0:
                        # append no. of blank characters
                        if howmanyblanks > maxvoicedblanks:
                            speaklist.append("{} {}s ".format(howmanyblanks,
                                blankcharvoiced))
                        else:
                            for x in range(howmanyblanks):
                                speaklist.append(blankcharvoiced)
                    speaklist.append(char)
                    howmanyblanks = 0

            if char == blankchar: # needed for when last character is a dot
                if howmanyblanks > maxvoicedblanks:
                    speaklist.append("{} {}s ".format(howmanyblanks,
                        blankcharvoiced))
                else:
                    for x in range(howmanyblanks):
                        speaklist.append(blankcharvoiced)

            for element in speaklist:
                try:
                    subprocess.call([software, element])
                except:
                    print(t2s_errormsg)
        else:
            try:
                subprocess.call([software, text])
            except:
                print(t2s_errormsg)

def analysewords(mywords):
    """Analyse mywords and return all used characters.

     The characters are sorted by occurence (descending).
     """
    mydict = {}
    for word in mywords: # create dict with occurence of letters in all words
        for letter in word.lower():
            if letter in mydict:
                mydict[letter] += 1
            else:
                mydict[letter] = 1

    # pairs in mydict dictionary sorted by occurence (descending)
    # http://stackoverflow.com/questions/613183/python-sort-a-dictionary-by-value
    # pairlist looks like this: [('e', 167410), ('n', 100164),...]
    pairlist = sorted(mydict.items(), key=lambda x: x[1], reverse=True)
    occurencestring = ''
    for pair in pairlist:
        occurencestring += pair[0] # use 1st element of each pair
    return list(occurencestring.upper())

def showhint(occurencelist):
    """Returns the first element of occurencelist as string."""
    return str(occurencelist[0])

def game(sound, wordlanguage):
    """the actual Hangman game"""

    # ---- start program
    possibletries = 11 # 11 incorrect guesses allowed
    alphabet = "abcdefghijklmnopqrstuvwxyz"
    mywords = [] # guessable words
    incorrectguesses = '' # string for incorrectly guessed letters
    correctguesses = ''
    tryword = 'tries'
    placeholderchar = '-'
    placeholdercharvoiced = 'blank'

    # determine OS and choose corresponding text-to-speech software
    if sys.platform == 'darwin':
        voicesoftware = 'say'
    elif (sys.platform == 'linux') or (sys.platform == 'win32'):
        voicesoftware = 'espeak'
    else:
        voicesoftware = 'espeak'
    t2s_errormsg = ("There was a problem with running the text-to-speech "
        "software {}.".format(voicesoftware))

    if wordlanguage == '':
        wordlanguage = 'en'
    try: # filter out 5+ letter words from dict file
        myfile = open("de-en.dict")
        for line in myfile:
            myword = line.split()[0]
            for letter in myword.lower():
                if len(myword) < 5:
                    break
                if not letter in alphabet:
                    break
            else:
                mywords.append(myword)

        myfile.close()
    except: # fallback list of words if dict file isn't found
        mywords = ["cherry", "summer", "winter", "programming", "hydrogen",
                "Saturday", "unicorn", "magic", "artichoke", "juice",
                "hacker", "python", "Neverland", "baking", "sherlock",
                "troll", "batman", "japan", "pastries", "Cairo", "Vienna",
                "raindrop", "waves", "diving", "Malta", "cupcake", "ukulele"]

    occurencelist = analysewords(mywords)
    theword = random.choice(mywords)
    placeholderword = list(placeholderchar*len(theword))

    if sound:
        print("Starting soundcheck...")
        # test existence of text-to-speech software
        try:
            output("If you can hear a voice and want to play the game with "
                "text-to-speech output, please type yes and press enter. "
                "Otherwise type no and press enter.", software=voicesoftware,
                outputtext=False)
        except:
            print("Please install the programm '{}' to use text-to-speech "
                "(or have your system administrator install it for you)."
                .format(voicesoftware))
            print("Note that you can still play the text-only version of "
                "Hangman even if you don't have '{}' installed!"
                .format(voicesoftware))
            sound = False
        else:
            print("You have the necessary software installed to play Hangman "
                "with text-to-speech output.".format(voicesoftware))
            print("Could you hear your computer talk and do you want to play "
                "with text-to-speech enabled?")
            answer = input("Please type yes or no (and press enter): ")
            if len(answer) > 0 and answer.lower()[0] == 'y':
                sound = True
            else:
                sound = False
        finally:
            print("Soundcheck completed, you're ready to play.")

    output("Let's play Hangman! You have to guess the word.",
        blankchar=placeholderchar, blankcharvoiced=placeholdercharvoiced,
        software=voicesoftware, voice=sound)
    output("Whenever you want the computer to help you, type in a {}."
        .format("question mark"), blankchar=placeholderchar,
        blankcharvoiced=placeholdercharvoiced, software=voicesoftware,
        voice=sound)
    output(stringtogether(placeholderword), blankchar=placeholderchar,
        blankcharvoiced=placeholdercharvoiced, software=voicesoftware,
        voice=False) # show blank word
    if sound:
        output("The word you're looking for has {} letters"
            .format(len(theword)), software=voicesoftware, outputtext=False)

    while possibletries > 0:
        output("Please pick a letter: ", blankchar=placeholderchar,
            blankcharvoiced=placeholdercharvoiced, software=voicesoftware,
            voice=sound, ending='')
        pickedletter = input().upper()

        if pickedletter == '???':
            occurencestringpretty = ''
            for char in str(occurencelist):
                if char not in "'[]":
                    occurencestringpretty += char
            output("Clever you! The most common letters are: {}"
                .format(occurencestringpretty), blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            continue

        if len(pickedletter) > 0:
            pickedletter = pickedletter[0]
        if pickedletter == '?':
            output("You could try guessing the letter '{}'."
                .format(showhint(occurencelist)), blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            continue
        if not pickedletter.isalpha() : # disallow digits, special chars
            output("Sorry, but you didn't type a letter! Try again."
                .format(pickedletter), blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            continue
        if pickedletter in incorrectguesses: # letter was already guessed
            output("You already guessed the letter '{}'!"
                .format(pickedletter), blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            continue
        if pickedletter in correctguesses:
            output("You already successfully picked '{}'!"
                .format(pickedletter.upper()), blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            continue

        if pickedletter in theword.upper(): # correct guess
            letterposition = 0
            for letterexists in theword.upper():
                if letterexists == pickedletter:
                    placeholderword[letterposition] = (
                        theword.upper()[letterposition])
                letterposition += 1
            output("You guessed correctly, well done!",
                blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware,
                voice=sound)
            correctguesses += pickedletter
        else: # incorrect guess
            incorrectguesses += pickedletter
            possibletries -= 1
            output("Sorry, '{}' is an incorrect guess!"
                .format(pickedletter.upper()), blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)

            if (incorrectguesses != '') and (possibletries > 0):
                if possibletries == 1:
                    tryword = 'try'
                output("You have {} {} left."
                    .format(possibletries,tryword),
                    blankchar=placeholderchar,
                    blankcharvoiced=placeholdercharvoiced,
                    software=voicesoftware, voice=sound)
                output("Incorrectly guessed letters so far: ",
                    blankchar=placeholderchar,
                    blankcharvoiced=placeholdercharvoiced,
                    software=voicesoftware,
                    voice=sound,  ending='')
                output(incorrectguesses, ending='', spell=True,
                    blankchar=placeholderchar,
                    blankcharvoiced=placeholdercharvoiced,
                    software=voicesoftware,
                    voice=sound)
                print('.')
        # ----- end guessing

        # remove pickedletter from hint list
        if pickedletter in occurencelist:
            occurencelist.remove(pickedletter)
        if not placeholderchar in placeholderword:
            output("We have a winner! Thanks for playing. :)",
                blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            break
        if placeholderword == list(placeholderchar*len(theword)):
            output(stringtogether(placeholderword),
                blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=False) # show whole blank word
            if sound:
                try:
                    output("The word you're looking for has {} letters"
                        .format(len(theword)), software=voicesoftware,
                        outputtext=False)
                except:
                    print(t2s_errormsg)
        else:
            output("The word is: ", ending='', blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            output(stringtogether(placeholderword), spell=True,
                blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware,
                voice=sound)
    else:
        output("\nGame over. :( ", blankchar=placeholderchar,
            blankcharvoiced=placeholdercharvoiced,
            software=voicesoftware, voice=sound)
    output("The word you were looking for was: " +theword+ '.',
        blankchar=placeholderchar, blankcharvoiced=placeholdercharvoiced,
        software=voicesoftware, voice=sound)

# ------- variable not part of functions -------
sound = True
wordlanguage = ''
voicesoftware = ''

# call game() function when file is opened
if __name__ == "__main__":
    if len(sys.argv) > 1:   # check for parameter input
        # begin loop
        argumentlist = sys.argv[1:] # all args but filename (= 1st arg)
        for argument in argumentlist:
            thisargument = argument.lower()
            if (thisargument == "-nosound") or (thisargument == "nosound"):
                sound = False
                continue
            if ((thisargument == "en") or (thisargument == "-en") or
             (thisargument == "de") or (thisargument == "-de")):
                if "en" in thisargument:
                    if wordlanguage != '':
                        print("You entered more than one parameter for "
                            "language - Hangman will now default to English.")
                    wordlanguage = "en"
                else:
                    if wordlanguage != '':
                        print("You entered more than one parameter for "
                            "language - Hangman will now default to German.")
                    wordlanguage = "de"
    game(sound, wordlanguage)<commit_msg>added TODOs for making game playable with py2<commit_after>#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# A Hangman game programmed in Python 3.
#
# Copyright (c) 2013 K Kollmann <code∆k.kollmann·moe>
# License: http://opensource.org/licenses/MIT MIT
#
# You need to have Python 3.x installed to run this game.
# The game's objective is to guess a word, letter by letter.
# 11 incorrect guesses are possible, then hangman dies and the game is over.
#
# Parameters the game can be run with:
# -nosound to turn off text-to-speech
# -en|de to play with English or German words # TODO: (defaults to English)
#
"""Hangman - a word-guessing game.

parameters:
-nosound ... play the game without sound
-en|de ... play the game with English/German words
"""

from __future__ import print_function # for python2.x
import random # module for randomisation
import subprocess # enable command line functions
import sys # module for parameters

def stringtogether(thislist):
    """return elements in a list as a string"""
    return ''.join(thislist)

def output(text, blankchar='-', blankcharvoiced='blank', software='say',
    voice=True, outputtext=True, ending='\n', spell=False):
    """Print out text and voice it using text-to-speech software.

    If outputtext is True, print text.
    If voice is True, voice text with text-to-speech.
    """

    maxvoicedblanks = 2
    t2s_errormsg = ("There was a problem with running the text-to-speech "
        "software {}.".format(software))
    # spell out placeholder characters explicitely
    if text:
        print(text,end=ending)
    if voice:
        if spell:
            # don't spell out all placeholder chars
            speaklist = []
            howmanyblanks = 0
            for char in text:
                if char == blankchar:
                    howmanyblanks += 1
                else:
                    if howmanyblanks > 0:
                        # append no. of blank characters
                        if howmanyblanks > maxvoicedblanks:
                            speaklist.append("{} {}s ".format(howmanyblanks,
                                blankcharvoiced))
                        else:
                            for x in range(howmanyblanks):
                                speaklist.append(blankcharvoiced)
                    speaklist.append(char)
                    howmanyblanks = 0

            if char == blankchar: # needed for when last character is a dot
                if howmanyblanks > maxvoicedblanks:
                    speaklist.append("{} {}s ".format(howmanyblanks,
                        blankcharvoiced))
                else:
                    for x in range(howmanyblanks):
                        speaklist.append(blankcharvoiced)

            for element in speaklist:
                try:
                    subprocess.call([software, element])
                except:
                    print(t2s_errormsg)
        else:
            try:
                subprocess.call([software, text])
            except:
                print(t2s_errormsg)

def analysewords(mywords):
    """Analyse mywords and return all used characters.

     The characters are sorted by occurence (descending).
     """
    mydict = {}
    for word in mywords: # create dict with occurence of letters in all words
        for letter in word.lower():
            if letter in mydict:
                mydict[letter] += 1
            else:
                mydict[letter] = 1

    # pairs in mydict dictionary sorted by occurence (descending)
    # http://stackoverflow.com/questions/613183/python-sort-a-dictionary-by-value
    # pairlist looks like this: [('e', 167410), ('n', 100164),...]
    pairlist = sorted(mydict.items(), key=lambda x: x[1], reverse=True)
    occurencestring = ''
    for pair in pairlist:
        occurencestring += pair[0] # use 1st element of each pair
    return list(occurencestring.upper())

def showhint(occurencelist):
    """Returns the first element of occurencelist as string."""
    return str(occurencelist[0])

def game(sound, wordlanguage):
    """the actual Hangman game"""

    # ---- start program
    possibletries = 11 # 11 incorrect guesses allowed
    alphabet = "abcdefghijklmnopqrstuvwxyz"
    mywords = [] # guessable words
    incorrectguesses = '' # string for incorrectly guessed letters
    correctguesses = ''
    tryword = 'tries'
    placeholderchar = '-'
    placeholdercharvoiced = 'blank'

    # determine OS and choose corresponding text-to-speech software
    if sys.platform == 'darwin':
        voicesoftware = 'say'
    elif (sys.platform == 'linux') or (sys.platform == 'win32'):
        voicesoftware = 'espeak'
    else:
        voicesoftware = 'espeak'
    t2s_errormsg = ("There was a problem with running the text-to-speech "
        "software {}.".format(voicesoftware))

    if wordlanguage == '':
        wordlanguage = 'en'
    try: # filter out 5+ letter words from dict file
        myfile = open("de-en.dict")
        for line in myfile:
            myword = line.split()[0]
            for letter in myword.lower():
                if len(myword) < 5:
                    break
                if not letter in alphabet:
                    break
            else:
                mywords.append(myword)

        myfile.close()
    except: # fallback list of words if dict file isn't found
        mywords = ["cherry", "summer", "winter", "programming", "hydrogen",
                "Saturday", "unicorn", "magic", "artichoke", "juice",
                "hacker", "python", "Neverland", "baking", "sherlock",
                "troll", "batman", "japan", "pastries", "Cairo", "Vienna",
                "raindrop", "waves", "diving", "Malta", "cupcake", "ukulele"]

    occurencelist = analysewords(mywords)
    theword = random.choice(mywords)
    placeholderword = list(placeholderchar*len(theword))

    if sound:
        print("Starting soundcheck...")
        # test existence of text-to-speech software
        try:
            output("If you can hear a voice and want to play the game with "
                "text-to-speech output, please type yes and press enter. "
                "Otherwise type no and press enter.", software=voicesoftware,
                outputtext=False)
        except:
            print("Please install the programm '{}' to use text-to-speech "
                "(or have your system administrator install it for you)."
                .format(voicesoftware))
            print("Note that you can still play the text-only version of "
                "Hangman even if you don't have '{}' installed!"
                .format(voicesoftware))
            sound = False
        else:
            print("You have the necessary software installed to play Hangman "
                "with text-to-speech output.".format(voicesoftware))
            print("Could you hear your computer talk and do you want to play "
                "with text-to-speech enabled?")
            answer = input("Please type yes or no (and press enter): ")
            # TODO use raw_input() for py2
            # answer = raw_input("Please type yes or no (and press enter): ")
            if len(answer) > 0 and answer.lower()[0] == 'y':
                sound = True
            else:
                sound = False
        finally:
            print("Soundcheck completed, you're ready to play.")

    output("Let's play Hangman! You have to guess the word.",
        blankchar=placeholderchar, blankcharvoiced=placeholdercharvoiced,
        software=voicesoftware, voice=sound)
    output("Whenever you want the computer to help you, type in a {}."
        .format("question mark"), blankchar=placeholderchar,
        blankcharvoiced=placeholdercharvoiced, software=voicesoftware,
        voice=sound)
    output(stringtogether(placeholderword), blankchar=placeholderchar,
        blankcharvoiced=placeholdercharvoiced, software=voicesoftware,
        voice=False) # show blank word
    if sound:
        output("The word you're looking for has {} letters"
            .format(len(theword)), software=voicesoftware, outputtext=False)

    while possibletries > 0:
        output("Please pick a letter: ", blankchar=placeholderchar,
            blankcharvoiced=placeholdercharvoiced, software=voicesoftware,
            voice=sound, ending='')
        pickedletter = input().upper()
        # TODO use raw_input().upper() for py2
        # pickedletter = input().upper()

        if pickedletter == '???':
            occurencestringpretty = ''
            for char in str(occurencelist):
                if char not in "'[]":
                    occurencestringpretty += char
            output("Clever you! The most common letters are: {}"
                .format(occurencestringpretty), blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            continue

        if len(pickedletter) > 0:
            pickedletter = pickedletter[0]
        if pickedletter == '?':
            output("You could try guessing the letter '{}'."
                .format(showhint(occurencelist)), blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            continue
        if not pickedletter.isalpha() : # disallow digits, special chars
            output("Sorry, but you didn't type a letter! Try again."
                .format(pickedletter), blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            continue
        if pickedletter in incorrectguesses: # letter was already guessed
            output("You already guessed the letter '{}'!"
                .format(pickedletter), blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            continue
        if pickedletter in correctguesses:
            output("You already successfully picked '{}'!"
                .format(pickedletter.upper()), blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            continue

        if pickedletter in theword.upper(): # correct guess
            letterposition = 0
            for letterexists in theword.upper():
                if letterexists == pickedletter:
                    placeholderword[letterposition] = (
                        theword.upper()[letterposition])
                letterposition += 1
            output("You guessed correctly, well done!",
                blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware,
                voice=sound)
            correctguesses += pickedletter
        else: # incorrect guess
            incorrectguesses += pickedletter
            possibletries -= 1
            output("Sorry, '{}' is an incorrect guess!"
                .format(pickedletter.upper()), blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)

            if (incorrectguesses != '') and (possibletries > 0):
                if possibletries == 1:
                    tryword = 'try'
                output("You have {} {} left."
                    .format(possibletries,tryword),
                    blankchar=placeholderchar,
                    blankcharvoiced=placeholdercharvoiced,
                    software=voicesoftware, voice=sound)
                output("Incorrectly guessed letters so far: ",
                    blankchar=placeholderchar,
                    blankcharvoiced=placeholdercharvoiced,
                    software=voicesoftware,
                    voice=sound,  ending='')
                output(incorrectguesses, ending='', spell=True,
                    blankchar=placeholderchar,
                    blankcharvoiced=placeholdercharvoiced,
                    software=voicesoftware,
                    voice=sound)
                print('.')
        # ----- end guessing

        # remove pickedletter from hint list
        if pickedletter in occurencelist:
            occurencelist.remove(pickedletter)
        if not placeholderchar in placeholderword:
            output("We have a winner! Thanks for playing. :)",
                blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            break
        if placeholderword == list(placeholderchar*len(theword)):
            output(stringtogether(placeholderword),
                blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=False) # show whole blank word
            if sound:
                try:
                    output("The word you're looking for has {} letters"
                        .format(len(theword)), software=voicesoftware,
                        outputtext=False)
                except:
                    print(t2s_errormsg)
        else:
            output("The word is: ", ending='', blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware, voice=sound)
            output(stringtogether(placeholderword), spell=True,
                blankchar=placeholderchar,
                blankcharvoiced=placeholdercharvoiced,
                software=voicesoftware,
                voice=sound)
    else:
        output("\nGame over. :( ", blankchar=placeholderchar,
            blankcharvoiced=placeholdercharvoiced,
            software=voicesoftware, voice=sound)
    output("The word you were looking for was: " +theword+ '.',
        blankchar=placeholderchar, blankcharvoiced=placeholdercharvoiced,
        software=voicesoftware, voice=sound)

# ------- variable not part of functions -------
sound = True
wordlanguage = ''
voicesoftware = ''

# call game() function when file is opened
if __name__ == "__main__":
    if len(sys.argv) > 1:   # check for parameter input
        # begin loop
        argumentlist = sys.argv[1:] # all args but filename (= 1st arg)
        for argument in argumentlist:
            thisargument = argument.lower()
            if (thisargument == "-nosound") or (thisargument == "nosound"):
                sound = False
                continue
            if ((thisargument == "en") or (thisargument == "-en") or
             (thisargument == "de") or (thisargument == "-de")):
                if "en" in thisargument:
                    if wordlanguage != '':
                        print("You entered more than one parameter for "
                            "language - Hangman will now default to English.")
                    wordlanguage = "en"
                else:
                    if wordlanguage != '':
                        print("You entered more than one parameter for "
                            "language - Hangman will now default to German.")
                    wordlanguage = "de"
    game(sound, wordlanguage)<|endoftext|>


<commit_before>import random
import string
import os
import platform

# Defining the text file containing the list of words
WORDLIST_FILENAME = "words.txt"
MAX_GUESSES = 8

def loadWords():
    # Returns a list of valid words. Words are taken from the file words.txt

    print "Loading word list from file..."
    # Open file for reading with no buffering
    inFile = open(WORDLIST_FILENAME, 'r', 0)
    # Read the file in single line
    line = inFile.readline()
    # Split all the words separated by whitespaces
    wordlist = string.split(line)
    print "  ", len(wordlist), "words loaded."
    return wordlist

def chooseWord(wordlist):
    # Choose a word at random which the user have to guess
    return random.choice(wordlist)

def isWordGuessed(secretWord, lettersGuessed):
    # Separating out each character from the secretWord
    # Each character is stored only once
    secretLetters = {};
    for letter in secretWord:
        secretLetters[letter] = True;

    # Checking for the non-existence of any character from the secretWord
    # The result is stored as True of False
    result = True;
    for sl in secretLetters:
        if not sl in lettersGuessed:
            result = False;
            break;
    return result;

def getGuessedWord(secretWord, lettersGuessed):
    # Returns the guessed word in a specific format
    # Example - the word 'apple' with the guessed characters ['a', 'b','l','s','e']
    # would look like this 'a_ _ l _ '
    result = "'";
    for letter in secretWord:
        if letter in lettersGuessed:
            result += letter;
        else:
            result += '_ ';
    result += "'";
    return result;

def getAvailableLetters(lettersGuessed):
    # Return the list of letters that are available to be used
    # The letters returned are in lowercase
    availableLetters = string.ascii_lowercase;
    for letter in lettersGuessed:
        availableLetters = availableLetters.replace(letter, '');
    return availableLetters;

def clearTerminal():
    # Clears the terminal on which the output is being displayed.
    # Works at least on Windows and Linux, I haven't tested it on Mac OS
    if platform.system() == 'Windows':
        os.system('cls')
    else:
        os.system('clear')

def hangman(secretWord):
    # Total number of wrong guesses allowed is 8
    numberOfGuesses = MAX_GUESSES
    # The letters guessed by the user
    lettersGuessed = {}
    # Welcome message
    print 'Welcome to the game, Hangman!'
    print 'I am thinking of a word that is %s letters long.' %(str(len(secretWord)))
    # Infinite loop which breaks from inside the loop's conditions
    while True:
        print '-------------'
        if not isWordGuessed(secretWord, lettersGuessed):
            # Word not guessed
            if numberOfGuesses == 0:
                # All guesses exhausted, end the game
                print 'Sorry, you ran out of guesses. The word was %s.' %(secretWord)
                break
            else:
                # Guesses left, Display guesses left and available letters
                print 'You have %s guesses left.' %(str(numberOfGuesses))
                print 'Available letters: %s' %(getAvailableLetters(lettersGuessed))
                # Take input from the user
                guessedLetter = raw_input('Please guess a letter: ')
                # Clearing the terminal
                # Can use and cannot use depending on the preference
                clearTerminal()
                if guessedLetter in lettersGuessed:
                    #  Already guessed letter, display guessed word
                    print 'Oops! You\'ve already guessed that letter:%s' %(getGuessedWord(secretWord, lettersGuessed))
                else:
                    # New guess, add to lettersGuessed
                    lettersGuessed[guessedLetter] = True
                    if guessedLetter not in secretWord:
                        # Wrong Guess, decrement number of guesses
                        print 'Oops! That letter is not in my word:%s' %(getGuessedWord(secretWord, lettersGuessed))
                        numberOfGuesses -= 1
                    else:
                        # Correct guess
                        print 'Good guess:%s' %(getGuessedWord(secretWord, lettersGuessed))
        else:
            # Word guessed
            print 'Congratulations, you won!'
            break

# Execution sequence of the game
# Load the words from file
wordlist = loadWords()
# Choose a secret word for the user to guess
secretWord = chooseWord(wordlist).lower()
# Start the game for user
hangman(secretWord)<commit_msg>Optimizing isWordGuessed<commit_after>import random
import string
import os
import platform

# Defining the text file containing the list of words
WORDLIST_FILENAME = "words.txt"
MAX_GUESSES = 8

def loadWords():
    # Returns a list of valid words. Words are taken from the file words.txt

    print "Loading word list from file..."
    # Open file for reading with no buffering
    inFile = open(WORDLIST_FILENAME, 'r', 0)
    # Read the file in single line
    line = inFile.readline()
    # Split all the words separated by whitespaces
    wordlist = string.split(line)
    print "  ", len(wordlist), "words loaded."
    return wordlist

def chooseWord(wordlist):
    # Choose a word at random which the user have to guess
    return random.choice(wordlist)

def isWordGuessed(secretWord, lettersGuessed):
    # Checking for the non-existence of any character from the secretWord
    # The result is stored as True of False
    result = True;
    for secretLetter in secretWord:
        if not secretLetter in lettersGuessed:
            result = False;
            break;
    return result;

def getGuessedWord(secretWord, lettersGuessed):
    # Returns the guessed word in a specific format
    # Example - the word 'apple' with the guessed characters ['a', 'b','l','s','e']
    # would look like this 'a_ _ l _ '
    result = "'";
    for letter in secretWord:
        if letter in lettersGuessed:
            result += letter;
        else:
            result += '_ ';
    result += "'";
    return result;

def getAvailableLetters(lettersGuessed):
    # Return the list of letters that are available to be used
    # The letters returned are in lowercase
    availableLetters = string.ascii_lowercase;
    for letter in lettersGuessed:
        availableLetters = availableLetters.replace(letter, '');
    return availableLetters;

def clearTerminal():
    # Clears the terminal on which the output is being displayed.
    # Works at least on Windows and Linux, I haven't tested it on Mac OS
    if platform.system() == 'Windows':
        os.system('cls')
    else:
        os.system('clear')

def hangman(secretWord):
    # Total number of wrong guesses allowed is 8
    numberOfGuesses = MAX_GUESSES
    # The letters guessed by the user
    lettersGuessed = {}
    # Welcome message
    print 'Welcome to the game, Hangman!'
    print 'I am thinking of a word that is %s letters long.' %(str(len(secretWord)))
    # Infinite loop which breaks from inside the loop's conditions
    while True:
        print '-------------'
        if not isWordGuessed(secretWord, lettersGuessed):
            # Word not guessed
            if numberOfGuesses == 0:
                # All guesses exhausted, end the game
                print 'Sorry, you ran out of guesses. The word was %s.' %(secretWord)
                break
            else:
                # Guesses left, Display guesses left and available letters
                print 'You have %s guesses left.' %(str(numberOfGuesses))
                print 'Available letters: %s' %(getAvailableLetters(lettersGuessed))
                # Take input from the user
                guessedLetter = raw_input('Please guess a letter: ')
                # Clearing the terminal
                # Can use and cannot use depending on the preference
                clearTerminal()
                if guessedLetter in lettersGuessed:
                    #  Already guessed letter, display guessed word
                    print 'Oops! You\'ve already guessed that letter:%s' %(getGuessedWord(secretWord, lettersGuessed))
                else:
                    # New guess, add to lettersGuessed
                    lettersGuessed[guessedLetter] = True
                    if guessedLetter not in secretWord:
                        # Wrong Guess, decrement number of guesses
                        print 'Oops! That letter is not in my word:%s' %(getGuessedWord(secretWord, lettersGuessed))
                        numberOfGuesses -= 1
                    else:
                        # Correct guess
                        print 'Good guess:%s' %(getGuessedWord(secretWord, lettersGuessed))
        else:
            # Word guessed
            print 'Congratulations, you won!'
            break

# Execution sequence of the game
# Load the words from file
wordlist = loadWords()
# Choose a secret word for the user to guess
secretWord = chooseWord(wordlist).lower()
# Start the game for user
hangman(secretWord)<|endoftext|>


<commit_before>#!/usr/bin/env python
import logging
import os
import time
import string
import subprocess
import sys
import re
import socket
from collections import OrderedDict

import requests

logger = logging.getLogger(__name__)

# Config ENV
PORT = os.getenv("PORT", "80")
MODE = os.getenv("MODE", "http")
BALANCE = os.getenv("BALANCE", "roundrobin")
MAXCONN = os.getenv("MAXCONN", "4096")
SSL = os.getenv("SSL", "")
SESSION_COOKIE = os.getenv("SESSION_COOKIE")
OPTION = os.getenv("OPTION", "redispatch, httplog, dontlognull, forwardfor").split(",")
TIMEOUT = os.getenv("TIMEOUT", "connect 5000, client 50000, server 50000").split(",")
VIRTUAL_HOST = os.getenv("VIRTUAL_HOST", None)
TUTUM_CONTAINER_API_URL = os.getenv("TUTUM_CONTAINER_API_URL", None)
POLLING_PERIOD = int(os.getenv("POLLING_PERIOD", 30))

TUTUM_AUTH = os.getenv("TUTUM_AUTH")
DEBUG = os.getenv("DEBUG", False)

# Const var
CONFIG_FILE = '/etc/haproxy/haproxy.cfg'
HAPROXY_CMD = ['/usr/sbin/haproxy', '-f', CONFIG_FILE, '-db']
LINK_ENV_PATTERN = "_PORT_%s_TCP" % PORT
LINK_ADDR_SUFFIX = LINK_ENV_PATTERN + "_ADDR"
LINK_PORT_SUFFIX = LINK_ENV_PATTERN + "_PORT"
TUTUM_URL_SUFFIX = "_TUTUM_API_URL"
VIRTUAL_HOST_SUFFIX = "_ENV_VIRTUAL_HOST"

# Global Var
HAPROXY_CURRENT_SUBPROCESS = None

endpoint_match = re.compile(r"(?P<proto>tcp|udp):\/\/(?P<addr>[^:]*):(?P<port>.*)")

def get_cfg_text(cfg):
    text = ""
    for section, contents in cfg.items():
        text += "%s\n" % section
        for content in contents:
            text += "  %s\n" % content
    return text.strip()

def create_default_cfg(maxconn, mode):
    cfg = OrderedDict({
        "global": ["log 127.0.0.1 local0",
                   "log 127.0.0.1 local1 notice",
                   "maxconn %s" % maxconn,
                   "pidfile /var/run/haproxy.pid",
                   "user haproxy",
                   "group haproxy",
                   "daemon",
                   "stats socket /var/run/haproxy.stats level admin"],
        "defaults": ["log global",
                     "mode %s" % mode]})
    for option in OPTION:
        if option:
            cfg["defaults"].append("option %s" % option.strip())
    for timeout in TIMEOUT:
        if timeout:
            cfg["defaults"].append("timeout %s" % timeout.strip())

    return cfg

def get_backend_routes(dict_var):
    # Return sth like: {'HELLO_WORLD_1': {'addr': '172.17.0.103', 'port': '80'},
    # 'HELLO_WORLD_2': {'addr': '172.17.0.95', 'port': '80'}}
    addr_port_dict = {}
    for name, value in dict_var.iteritems():
        position = string.find(name, LINK_ENV_PATTERN)
        if position != -1:
            container_name = name[:position]
            add_port = addr_port_dict.get(container_name, {'addr': "", 'port': ""})
            try:
                add_port['addr'] = socket.gethostbyname(container_name.lower())
            except socket.gaierror:
                add_port['addr'] = socket.gethostbyname(container_name.lower().replace("_", "-"))
            if name.endswith(LINK_PORT_SUFFIX):
                add_port['port'] = value
            addr_port_dict[container_name] = add_port

    return addr_port_dict

def update_cfg(cfg, backend_routes, vhost):
    logger.debug("Updating cfg: \n old cfg: %s\n backend_routes: %s\n vhost: %s", cfg, backend_routes, vhost)
    # Set frontend
    frontend = []
    frontend.append("bind 0.0.0.0:80")
    if SSL:
        frontend.append("redirect scheme https code 301 if !{ ssl_fc }"),
        frontend.append("bind 0.0.0.0:443 %s" % SSL)
        frontend.append("reqadd X-Forwarded-Proto:\ https")
    if vhost:
        added_vhost = {}
        for _, domain_name in vhost.iteritems():
            if not added_vhost.has_key(domain_name):
                domain_str = domain_name.upper().replace(".", "_")
                frontend.append("acl host_%s hdr(host) -i %s" % (domain_str, domain_name))
                frontend.append("use_backend %s_cluster if host_%s" % (domain_str, domain_str))
                added_vhost[domain_name] = domain_str
    else:
        frontend.append("default_backend default_service")
    cfg["frontend default_frontend"] = frontend

    # Set backend
    if vhost:
        added_vhost = {}
        for service_name, domain_name in vhost.iteritems():
            domain_str = domain_name.upper().replace(".", "_")
            service_name = service_name.upper()
            if added_vhost.has_key(domain_name):
                backend = cfg.get("backend %s_cluster" % domain_str, [])
                for container_name, addr_port in backend_routes.iteritems():
                    if container_name.startswith(service_name):
                        server_string = "server %s %s:%s" % (container_name, addr_port["addr"], addr_port["port"])
                        if SESSION_COOKIE:
                            server_string += " cookie check"

                        # Do not add duplicate backend routes
                        duplicated = False
                        for server_str in backend:
                            if "%s:%s" % (addr_port["addr"], addr_port["port"]) in server_str:
                                duplicated = True
                                break
                        if not duplicated:
                            backend.append(server_string)
                cfg["backend %s_cluster" % domain_str] = sorted(backend)
            else:
                backend = []
                if SESSION_COOKIE:
                    backend.append("appsession %s len 64 timeout 3h request-learn prefix" % (SESSION_COOKIE, ))

                backend.append("balance %s" % BALANCE)
                for container_name, addr_port in backend_routes.iteritems():
                    if container_name.startswith(service_name):
                        server_string = "server %s %s:%s" % (container_name, addr_port["addr"], addr_port["port"])
                        if SESSION_COOKIE:
                            server_string += " cookie check"

                        # Do not add duplicate backend routes
                        duplicated = False
                        for server_str in backend:
                            if "%s:%s" % (addr_port["addr"], addr_port["port"]) in server_str:
                                duplicated = True
                                break
                        if not duplicated:
                            backend.append(server_string)
            if backend:
                cfg["backend %s_cluster" % domain_name.upper().replace(".", "_")] = sorted(backend)
                added_vhost[domain_name] = domain_name.upper().replace(".", "_")

    else:
        backend = []
        if SESSION_COOKIE:
            backend.append("appsession %s len 64 timeout 3h request-learn prefix" % (SESSION_COOKIE, ))

        backend.append("balance %s" % BALANCE)
        for container_name, addr_port in backend_routes.iteritems():
            server_string = "server %s %s:%s" % (container_name, addr_port["addr"], addr_port["port"])
            if SESSION_COOKIE:
                server_string += " cookie check"

            # Do not add duplicate backend routes
            duplicated = False
            for server_str in backend:
                if "%s:%s" % (addr_port["addr"], addr_port["port"]) in server_str:
                    duplicated = True
                    break
            if not duplicated:
                backend.append(server_string)

        cfg["backend default_service"] = sorted(backend)

    logger.debug("New cfg: %s", cfg)

def save_config_file(cfg_text, config_file):
    try:
        directory = os.path.dirname(config_file)
        if not os.path.exists(directory):
            os.makedirs(directory)
        f = open(config_file, 'w')
    except Exception as e:
        logger.error(e)
    else:
        f.write(cfg_text)
        logger.info("Config file is updated")
        f.close()

def reload_haproxy():
    global HAPROXY_CURRENT_SUBPROCESS
    if HAPROXY_CURRENT_SUBPROCESS:
        # Reload haproxy
        logger.info("Reloading haproxy")
        process = subprocess.Popen(HAPROXY_CMD + ["-sf", str(HAPROXY_CURRENT_SUBPROCESS.pid)])
        HAPROXY_CURRENT_SUBPROCESS.wait()
        HAPROXY_CURRENT_SUBPROCESS = process
    else:
        # Launch haproxy
        logger.info("Lauching haproxy")
        HAPROXY_CURRENT_SUBPROCESS = subprocess.Popen(HAPROXY_CMD)

def update_virtualhost(vhost):
    if VIRTUAL_HOST:
        # vhost specified using environment variables
        for host in VIRTUAL_HOST.split(","):
            tmp = host.split("=", 2)
            if len(tmp) == 2:
                vhost[tmp[0].strip()] = tmp[1].strip()
    else:
        # vhost specified in the linked containers
        for name, value in os.environ.iteritems():
            position = string.find(name, VIRTUAL_HOST_SUFFIX)
            if position != -1 and value != "**None**":
                hostname = name[:position]
                vhost[hostname] = value

if __name__ == "__main__":
    logging.basicConfig(stream=sys.stdout)
    logging.getLogger(__name__).setLevel(logging.DEBUG if DEBUG else logging.INFO)

    cfg = create_default_cfg(MAXCONN, MODE)
    vhost = {}

    # Tell the user the mode of autoupdate we are using, if any
    if TUTUM_CONTAINER_API_URL:
        if TUTUM_AUTH:
            logger.info("HAproxy has access to Tutum API - will reload list of backends every %d seconds",
                        POLLING_PERIOD)
        else:
            logger.warning(
                "HAproxy doesn't have access to Tutum API and it's running in Tutum - you might want to give "
                "an API role to this service for automatic backend reconfiguration")
    else:
        logger.info("HAproxy is not running in Tutum")
    session = requests.Session()
    headers = {"Authorization": TUTUM_AUTH}

    # Main loop
    old_text = ""
    while True:
        try:
            if TUTUM_CONTAINER_API_URL and TUTUM_AUTH:
                # Running on Tutum with API access - fetch updated list of environment variables
                r = session.get(TUTUM_CONTAINER_API_URL, headers=headers)
                r.raise_for_status()
                container_details = r.json()

                backend_routes = {}
                for link in container_details.get("linked_to_container", []):
                    for port, endpoint in link.get("endpoints", {}).iteritems():
                        if port == "%s/tcp" % PORT:
                            backend_routes[link["name"]] = endpoint_match.match(endpoint).groupdict()
            else:
                # No Tutum API access - configuring backends based on static environment variables
                backend_routes = get_backend_routes(os.environ)

            # Update backend routes
            update_virtualhost(vhost)
            update_cfg(cfg, backend_routes, vhost)
            cfg_text = get_cfg_text(cfg)

            # If cfg changes, write to file
            if old_text != cfg_text:
                logger.info("HAProxy configuration has been changed:\n%s" % cfg_text)
                save_config_file(cfg_text, CONFIG_FILE)
                reload_haproxy()
                old_text = cfg_text
        except Exception as e:
            logger.exception("Error: %s" % e)

        time.sleep(POLLING_PERIOD)
<commit_msg>set min POLLING_PERIOD to 5 sec<commit_after>#!/usr/bin/env python
import logging
import os
import time
import string
import subprocess
import sys
import re
import socket
from collections import OrderedDict

import requests

logger = logging.getLogger(__name__)

# Config ENV
PORT = os.getenv("PORT", "80")
MODE = os.getenv("MODE", "http")
BALANCE = os.getenv("BALANCE", "roundrobin")
MAXCONN = os.getenv("MAXCONN", "4096")
SSL = os.getenv("SSL", "")
SESSION_COOKIE = os.getenv("SESSION_COOKIE")
OPTION = os.getenv("OPTION", "redispatch, httplog, dontlognull, forwardfor").split(",")
TIMEOUT = os.getenv("TIMEOUT", "connect 5000, client 50000, server 50000").split(",")
VIRTUAL_HOST = os.getenv("VIRTUAL_HOST", None)
TUTUM_CONTAINER_API_URL = os.getenv("TUTUM_CONTAINER_API_URL", None)
POLLING_PERIOD = max(int(os.getenv("POLLING_PERIOD", 30)), 5)

TUTUM_AUTH = os.getenv("TUTUM_AUTH")
DEBUG = os.getenv("DEBUG", False)

# Const var
CONFIG_FILE = '/etc/haproxy/haproxy.cfg'
HAPROXY_CMD = ['/usr/sbin/haproxy', '-f', CONFIG_FILE, '-db']
LINK_ENV_PATTERN = "_PORT_%s_TCP" % PORT
LINK_ADDR_SUFFIX = LINK_ENV_PATTERN + "_ADDR"
LINK_PORT_SUFFIX = LINK_ENV_PATTERN + "_PORT"
TUTUM_URL_SUFFIX = "_TUTUM_API_URL"
VIRTUAL_HOST_SUFFIX = "_ENV_VIRTUAL_HOST"

# Global Var
HAPROXY_CURRENT_SUBPROCESS = None

endpoint_match = re.compile(r"(?P<proto>tcp|udp):\/\/(?P<addr>[^:]*):(?P<port>.*)")

def get_cfg_text(cfg):
    text = ""
    for section, contents in cfg.items():
        text += "%s\n" % section
        for content in contents:
            text += "  %s\n" % content
    return text.strip()

def create_default_cfg(maxconn, mode):
    cfg = OrderedDict({
        "global": ["log 127.0.0.1 local0",
                   "log 127.0.0.1 local1 notice",
                   "maxconn %s" % maxconn,
                   "pidfile /var/run/haproxy.pid",
                   "user haproxy",
                   "group haproxy",
                   "daemon",
                   "stats socket /var/run/haproxy.stats level admin"],
        "defaults": ["log global",
                     "mode %s" % mode]})
    for option in OPTION:
        if option:
            cfg["defaults"].append("option %s" % option.strip())
    for timeout in TIMEOUT:
        if timeout:
            cfg["defaults"].append("timeout %s" % timeout.strip())

    return cfg

def get_backend_routes(dict_var):
    # Return sth like: {'HELLO_WORLD_1': {'addr': '172.17.0.103', 'port': '80'},
    # 'HELLO_WORLD_2': {'addr': '172.17.0.95', 'port': '80'}}
    addr_port_dict = {}
    for name, value in dict_var.iteritems():
        position = string.find(name, LINK_ENV_PATTERN)
        if position != -1:
            container_name = name[:position]
            add_port = addr_port_dict.get(container_name, {'addr': "", 'port': ""})
            try:
                add_port['addr'] = socket.gethostbyname(container_name.lower())
            except socket.gaierror:
                add_port['addr'] = socket.gethostbyname(container_name.lower().replace("_", "-"))
            if name.endswith(LINK_PORT_SUFFIX):
                add_port['port'] = value
            addr_port_dict[container_name] = add_port

    return addr_port_dict

def update_cfg(cfg, backend_routes, vhost):
    logger.debug("Updating cfg: \n old cfg: %s\n backend_routes: %s\n vhost: %s", cfg, backend_routes, vhost)
    # Set frontend
    frontend = []
    frontend.append("bind 0.0.0.0:80")
    if SSL:
        frontend.append("redirect scheme https code 301 if !{ ssl_fc }"),
        frontend.append("bind 0.0.0.0:443 %s" % SSL)
        frontend.append("reqadd X-Forwarded-Proto:\ https")
    if vhost:
        added_vhost = {}
        for _, domain_name in vhost.iteritems():
            if not added_vhost.has_key(domain_name):
                domain_str = domain_name.upper().replace(".", "_")
                frontend.append("acl host_%s hdr(host) -i %s" % (domain_str, domain_name))
                frontend.append("use_backend %s_cluster if host_%s" % (domain_str, domain_str))
                added_vhost[domain_name] = domain_str
    else:
        frontend.append("default_backend default_service")
    cfg["frontend default_frontend"] = frontend

    # Set backend
    if vhost:
        added_vhost = {}
        for service_name, domain_name in vhost.iteritems():
            domain_str = domain_name.upper().replace(".", "_")
            service_name = service_name.upper()
            if added_vhost.has_key(domain_name):
                backend = cfg.get("backend %s_cluster" % domain_str, [])
                for container_name, addr_port in backend_routes.iteritems():
                    if container_name.startswith(service_name):
                        server_string = "server %s %s:%s" % (container_name, addr_port["addr"], addr_port["port"])
                        if SESSION_COOKIE:
                            server_string += " cookie check"

                        # Do not add duplicate backend routes
                        duplicated = False
                        for server_str in backend:
                            if "%s:%s" % (addr_port["addr"], addr_port["port"]) in server_str:
                                duplicated = True
                                break
                        if not duplicated:
                            backend.append(server_string)
                cfg["backend %s_cluster" % domain_str] = sorted(backend)
            else:
                backend = []
                if SESSION_COOKIE:
                    backend.append("appsession %s len 64 timeout 3h request-learn prefix" % (SESSION_COOKIE, ))

                backend.append("balance %s" % BALANCE)
                for container_name, addr_port in backend_routes.iteritems():
                    if container_name.startswith(service_name):
                        server_string = "server %s %s:%s" % (container_name, addr_port["addr"], addr_port["port"])
                        if SESSION_COOKIE:
                            server_string += " cookie check"

                        # Do not add duplicate backend routes
                        duplicated = False
                        for server_str in backend:
                            if "%s:%s" % (addr_port["addr"], addr_port["port"]) in server_str:
                                duplicated = True
                                break
                        if not duplicated:
                            backend.append(server_string)
            if backend:
                cfg["backend %s_cluster" % domain_name.upper().replace(".", "_")] = sorted(backend)
                added_vhost[domain_name] = domain_name.upper().replace(".", "_")

    else:
        backend = []
        if SESSION_COOKIE:
            backend.append("appsession %s len 64 timeout 3h request-learn prefix" % (SESSION_COOKIE, ))

        backend.append("balance %s" % BALANCE)
        for container_name, addr_port in backend_routes.iteritems():
            server_string = "server %s %s:%s" % (container_name, addr_port["addr"], addr_port["port"])
            if SESSION_COOKIE:
                server_string += " cookie check"

            # Do not add duplicate backend routes
            duplicated = False
            for server_str in backend:
                if "%s:%s" % (addr_port["addr"], addr_port["port"]) in server_str:
                    duplicated = True
                    break
            if not duplicated:
                backend.append(server_string)

        cfg["backend default_service"] = sorted(backend)

    logger.debug("New cfg: %s", cfg)

def save_config_file(cfg_text, config_file):
    try:
        directory = os.path.dirname(config_file)
        if not os.path.exists(directory):
            os.makedirs(directory)
        f = open(config_file, 'w')
    except Exception as e:
        logger.error(e)
    else:
        f.write(cfg_text)
        logger.info("Config file is updated")
        f.close()

def reload_haproxy():
    global HAPROXY_CURRENT_SUBPROCESS
    if HAPROXY_CURRENT_SUBPROCESS:
        # Reload haproxy
        logger.info("Reloading haproxy")
        process = subprocess.Popen(HAPROXY_CMD + ["-sf", str(HAPROXY_CURRENT_SUBPROCESS.pid)])
        HAPROXY_CURRENT_SUBPROCESS.wait()
        HAPROXY_CURRENT_SUBPROCESS = process
    else:
        # Launch haproxy
        logger.info("Lauching haproxy")
        HAPROXY_CURRENT_SUBPROCESS = subprocess.Popen(HAPROXY_CMD)

def update_virtualhost(vhost):
    if VIRTUAL_HOST:
        # vhost specified using environment variables
        for host in VIRTUAL_HOST.split(","):
            tmp = host.split("=", 2)
            if len(tmp) == 2:
                vhost[tmp[0].strip()] = tmp[1].strip()
    else:
        # vhost specified in the linked containers
        for name, value in os.environ.iteritems():
            position = string.find(name, VIRTUAL_HOST_SUFFIX)
            if position != -1 and value != "**None**":
                hostname = name[:position]
                vhost[hostname] = value

if __name__ == "__main__":
    logging.basicConfig(stream=sys.stdout)
    logging.getLogger(__name__).setLevel(logging.DEBUG if DEBUG else logging.INFO)

    cfg = create_default_cfg(MAXCONN, MODE)
    vhost = {}

    # Tell the user the mode of autoupdate we are using, if any
    if TUTUM_CONTAINER_API_URL:
        if TUTUM_AUTH:
            logger.info("HAproxy has access to Tutum API - will reload list of backends every %d seconds",
                        POLLING_PERIOD)
        else:
            logger.warning(
                "HAproxy doesn't have access to Tutum API and it's running in Tutum - you might want to give "
                "an API role to this service for automatic backend reconfiguration")
    else:
        logger.info("HAproxy is not running in Tutum")
    session = requests.Session()
    headers = {"Authorization": TUTUM_AUTH}

    # Main loop
    old_text = ""
    while True:
        try:
            if TUTUM_CONTAINER_API_URL and TUTUM_AUTH:
                # Running on Tutum with API access - fetch updated list of environment variables
                r = session.get(TUTUM_CONTAINER_API_URL, headers=headers)
                r.raise_for_status()
                container_details = r.json()

                backend_routes = {}
                for link in container_details.get("linked_to_container", []):
                    for port, endpoint in link.get("endpoints", {}).iteritems():
                        if port == "%s/tcp" % PORT:
                            backend_routes[link["name"]] = endpoint_match.match(endpoint).groupdict()
            else:
                # No Tutum API access - configuring backends based on static environment variables
                backend_routes = get_backend_routes(os.environ)

            # Update backend routes
            update_virtualhost(vhost)
            update_cfg(cfg, backend_routes, vhost)
            cfg_text = get_cfg_text(cfg)

            # If cfg changes, write to file
            if old_text != cfg_text:
                logger.info("HAProxy configuration has been changed:\n%s" % cfg_text)
                save_config_file(cfg_text, CONFIG_FILE)
                reload_haproxy()
                old_text = cfg_text
        except Exception as e:
            logger.exception("Error: %s" % e)

        time.sleep(POLLING_PERIOD)
<|endoftext|>


<commit_before>import json
import errno
from dateutil import parser
import calendar

def convert_to_unix(timestamp):
    '''Used to convert any timestamp format to unix time'''
    return calendar.timegm(parser.parse(timestamp).utctimetuple())

def save_data(json_data, location):
    '''Saves json data to a specific file location'''
    try:
        os.makedirs(os.path.dirname(location))
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise

    json.dump(json_data, open(location, 'w'))

<commit_msg>Added missing import<commit_after>import json
import errno
from dateutil import parser
import calendar
import os

def convert_to_unix(timestamp):
    '''Used to convert any timestamp format to unix time'''
    return calendar.timegm(parser.parse(timestamp).utctimetuple())

def save_data(json_data, location):
    '''Saves json data to a specific file location'''
    try:
        os.makedirs(os.path.dirname(location))
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise

    json.dump(json_data, open(location, 'w'))

<|endoftext|>


<commit_before>"""A file of all helper functions"""
import json
import textwrap
import urllib.parse
import urllib.request
import xml.etree.ElementTree as ET
from codecs import open as copen
from datetime import date, timedelta
from os import listdir
from os.path import isfile, join
import requests
import shutil

def fopen_generic(filepath, filemode='rU', coding='utf8', buffering=-1):
    """
    Reads files using system seperators with friendly encodings
    :param filepath: file path
    :type filepath: str
    :param filemode: file mode (default 'rU')
    :type filemode: str
    :param coding: encoding for file (default 'utf8')
    :type coding: str
    :param buffering: buffer mode,
    see https://docs.python.org/2/library/functions.html#open (default -1)
    :type buffering: int
    :return file pointer
    :rtype file
    """
    if isfile(filepath):
        return copen(filepath, filemode, coding, 'replace', buffering)
    return None

def freadlines(fp, keep_open=False):
    """
    Splits file lines
    :param fp: file pointer
    :param keep_open: keep fp open (default false)
    :type fp: file
    :type keep_open: bool | int
    :return: file lines
    :rtype: list
    """
    if fp is not None:
        lines = fp.readlines()
        if not keep_open:
            fp.close()
        return lines
    return []

def split_text(text, i):
    """
    Splits text into a list
    :param text: The text to be splitted
    :type text: str | list
    :param i: the number of sections the text needs to be split into
    :type i: int
    :return: The split up text
    :rtype: list
    """
    if isinstance(text, list):
        text = ''.join(text)
    return textwrap.wrap(text, int(len(text) / i))

def format_eq(term1, term2):
    """
    checks if the value of term1 and term2 are equal,
    and return the range between them
    :param term1: the first term
    :type term1: object
    :param term2: the second term
    :type term2: object
    :return: the range between them
    :rtype: str
    """
    return str(term1) if term1 == term2 else str(min(term1, term2)) + '-' + str(
        max(term1, term2))

async def try_say(bot, text, i=1):
    """
    Try to say the block of text until the bot succeeds
    :param bot: The bot
    :type bot: discord.ext.commands.Bot
    :param text: The block of text
    :type text: str | list
    :param i: how many sections the text needs to be split into
    :type i: int
    :return: nothing
    :rtype: None
    """
    try:
        if isinstance(text, list):
            for txt in text:
                await bot.say('```markdown\n' + txt + '```')
        elif isinstance(text, str):
            await bot.say('```markdown\n' + text + '```')
    except Exception:
        i += 1
        await try_say(bot, split_text(text, i), i)

def read_kana_files():
    """
    Reads the kanna pictures
    :return: All path of kanna pics
    :rtype: list
    """
    root = join('data', 'kanna_is_cute_af')
    return [join(root, f) for
            f in listdir(root) if isfile(join(root, f))]

def is_admin(ctx, id_):
    """
    Check if an user is an admin
    :return: True if the user is an admin
    :rtype: bool
    """
    try:
        return ctx.message.server.get_member(
            id_).server_permissions.administrator
    except AttributeError:
        return False

def generate_image_online(url, fn):
    """
    Generates an image file from a image hot link
    :param url: The url
    :param fn: the file name
    :type url: str
    :return: The generated image path
    :rtype: str
    """
    response = requests.get(url, stream=True)
    if response.status_code == 200:
        with open(fn, 'wb') as f:
            response.raw.decode_content = True
            shutil.copyfileobj(response.raw, f)
    return fn

def generate_latex_online(latex):
    """
    Generate latex image from latex website
    :param latex: the latex equation to be rendered
    :type latex: str
    :return: The path to rendered latex image
    :rtype: str
    """
    url = 'http://frog.isima.fr/cgi-bin/bruno/tex2png--10.cgi?'
    url += urllib.parse.quote(latex, safe='')
    fn = join('data', 'latex.png')
    urllib.request.urlretrieve(url, fn)
    return fn

def read_json(fp, keep_open=False):
    """
    Read a json file into a dictionary
    :param fp: the file pointer
    :type fp: file
    :param keep_open: keep file open (default False)
    :type keep_open: bool | int
    :return: the dictionary
    :rtype: dict
    """
    if fp is not None:
        data = json.load(fp)
        if not keep_open:
            fp.close()
        return data
    return {}

def write_json(fp, data, keep_open=False):
    """
    Write a dictionary into a json file
    :param fp: The json file
    :type fp: ffile
    :param data: The dictionary
    :type data: dict
    :param keep_open: keep file open (default False)
    :type keep_open: bool | int
    :return: nothing
    :rtype: None
    """
    if fp is not None:
        json.dump(data, fp)
        if not keep_open:
            fp.close()

def update_command_blacklist(add, command, id_):
    """
    Update the command blacklist for the server
    :param add: The mode, true for add, false for del
    :type add: bool
    :param command: the command
    :type command: str
    :param id_: the server id
    :type id_: str
    :return: nothing
    :rtype: None
    """
    my_dict = read_json(fopen_generic(join('data', 'command_blacklist.json')))
    if id_ not in my_dict:
        my_dict[id_] = []
    if add is False:
        if command in my_dict[id_]:
            my_dict[id_].remove(command)
    else:
        if command not in my_dict[id_]:
            my_dict[id_].append(command)
    write_json(fopen_generic(join('data', 'command_blacklist.json'), 'w'),
               my_dict)

def is_banned(command, id_):
    """
    Check if a command in banned in this server
    :param command: the command
    :type command: str
    :param id_: the server id
    :type id_: str
    :return: True if it's banned
    :rtype: bool
    """
    data = read_json(fopen_generic(join('data', 'command_blacklist.json')))
    try:
        return True if id_ in data and \
                       command in data[id_] else False
    except AttributeError:
        return False

def get_server_id(ctx):
    """
    Get the server id of a context
    :param ctx: the context
    :type ctx: context
    :return: the server id
    :rtype: str
    """
    try:
        return ctx.message.server.id
    except AttributeError:
        return None

def convert_currency(base, amount, target):
    """
    Conver currency to another
    :param base: str
    :param amount: str
    :param target: str
    :return: str
    """
    key = read_json(fopen_generic(join('data', 'api_keys.json')))['Currency']
    request_url = 'http://www.apilayer.net/api/live?access_key={}& currencies' \
                  '=USD,{}{}&format=1'.format(key, base, target)
    response = requests.get(request_url).text
    try:
        parsed_data = json.loads(response)['quotes']
    except KeyError:
        raise KeyError
    try:
        rate = float(parsed_data['USD{}'.format(target)]) / float(
            parsed_data['USD{}'.format(base)])
        return "{0:.2f}".format(float(amount) * rate)
    except KeyError:
        raise KeyError

def safebooru(tag):
    """
    Get a list of pictures from safebooru based on tag
    :param tag: the tag to search for
    :return: a list of picture links based on the tag
    """
    url = "https://safebooru.org//index.php?page=dapi&s=post&q=index&tags={}"\
        .format(tag)
    result = requests.get(url).content
    root = ET.fromstring(result)
    return ['https:' + child.attrib['file_url'] for child in root]

def get_distro():
    """
    Name of your Linux distro (in lowercase).
    """
    with open("/etc/issue") as f:
        return f.read().lower().split()[:3]

def split_list(lst, max_length):
    """
    Split a list into sublists
    :param lst: the list to be split
    :param max_length: the max allowed length of the result
    :return: a list of split up lists
    """
    return [lst[i:i + max_length] for i in range(0, len(lst), max_length)]

def get_date(diff):
    """
    Return yesterday's date in YYYYMMDD format
    :return: yesterday's date in YYYYMMDD format
    """
    yesterday = date.today() - timedelta(diff)
    return yesterday.strftime('%Y%m%d')

def comma(val):
    """
    Return a comma seprated number
    :param val: the number
    :return: the comma seprated number
    """
    return "{:,}".format(int(val))
<commit_msg>fixed currency <commit_after>"""A file of all helper functions"""
import json
import textwrap
import urllib.parse
import urllib.request
import xml.etree.ElementTree as ET
from codecs import open as copen
from datetime import date, timedelta
from os import listdir
from os.path import isfile, join
import requests
import shutil

def fopen_generic(filepath, filemode='rU', coding='utf8', buffering=-1):
    """
    Reads files using system seperators with friendly encodings
    :param filepath: file path
    :type filepath: str
    :param filemode: file mode (default 'rU')
    :type filemode: str
    :param coding: encoding for file (default 'utf8')
    :type coding: str
    :param buffering: buffer mode,
    see https://docs.python.org/2/library/functions.html#open (default -1)
    :type buffering: int
    :return file pointer
    :rtype file
    """
    if isfile(filepath):
        return copen(filepath, filemode, coding, 'replace', buffering)
    return None

def freadlines(fp, keep_open=False):
    """
    Splits file lines
    :param fp: file pointer
    :param keep_open: keep fp open (default false)
    :type fp: file
    :type keep_open: bool | int
    :return: file lines
    :rtype: list
    """
    if fp is not None:
        lines = fp.readlines()
        if not keep_open:
            fp.close()
        return lines
    return []

def split_text(text, i):
    """
    Splits text into a list
    :param text: The text to be splitted
    :type text: str | list
    :param i: the number of sections the text needs to be split into
    :type i: int
    :return: The split up text
    :rtype: list
    """
    if isinstance(text, list):
        text = ''.join(text)
    return textwrap.wrap(text, int(len(text) / i))

def format_eq(term1, term2):
    """
    checks if the value of term1 and term2 are equal,
    and return the range between them
    :param term1: the first term
    :type term1: object
    :param term2: the second term
    :type term2: object
    :return: the range between them
    :rtype: str
    """
    return str(term1) if term1 == term2 else str(min(term1, term2)) + '-' + str(
        max(term1, term2))

async def try_say(bot, text, i=1):
    """
    Try to say the block of text until the bot succeeds
    :param bot: The bot
    :type bot: discord.ext.commands.Bot
    :param text: The block of text
    :type text: str | list
    :param i: how many sections the text needs to be split into
    :type i: int
    :return: nothing
    :rtype: None
    """
    try:
        if isinstance(text, list):
            for txt in text:
                await bot.say('```markdown\n' + txt + '```')
        elif isinstance(text, str):
            await bot.say('```markdown\n' + text + '```')
    except Exception:
        i += 1
        await try_say(bot, split_text(text, i), i)

def read_kana_files():
    """
    Reads the kanna pictures
    :return: All path of kanna pics
    :rtype: list
    """
    root = join('data', 'kanna_is_cute_af')
    return [join(root, f) for
            f in listdir(root) if isfile(join(root, f))]

def is_admin(ctx, id_):
    """
    Check if an user is an admin
    :return: True if the user is an admin
    :rtype: bool
    """
    try:
        return ctx.message.server.get_member(
            id_).server_permissions.administrator
    except AttributeError:
        return False

def generate_image_online(url, fn):
    """
    Generates an image file from a image hot link
    :param url: The url
    :param fn: the file name
    :type url: str
    :return: The generated image path
    :rtype: str
    """
    response = requests.get(url, stream=True)
    if response.status_code == 200:
        with open(fn, 'wb') as f:
            response.raw.decode_content = True
            shutil.copyfileobj(response.raw, f)
    return fn

def generate_latex_online(latex):
    """
    Generate latex image from latex website
    :param latex: the latex equation to be rendered
    :type latex: str
    :return: The path to rendered latex image
    :rtype: str
    """
    url = 'http://frog.isima.fr/cgi-bin/bruno/tex2png--10.cgi?'
    url += urllib.parse.quote(latex, safe='')
    fn = join('data', 'latex.png')
    urllib.request.urlretrieve(url, fn)
    return fn

def read_json(fp, keep_open=False):
    """
    Read a json file into a dictionary
    :param fp: the file pointer
    :type fp: file
    :param keep_open: keep file open (default False)
    :type keep_open: bool | int
    :return: the dictionary
    :rtype: dict
    """
    if fp is not None:
        data = json.load(fp)
        if not keep_open:
            fp.close()
        return data
    return {}

def write_json(fp, data, keep_open=False):
    """
    Write a dictionary into a json file
    :param fp: The json file
    :type fp: ffile
    :param data: The dictionary
    :type data: dict
    :param keep_open: keep file open (default False)
    :type keep_open: bool | int
    :return: nothing
    :rtype: None
    """
    if fp is not None:
        json.dump(data, fp)
        if not keep_open:
            fp.close()

def update_command_blacklist(add, command, id_):
    """
    Update the command blacklist for the server
    :param add: The mode, true for add, false for del
    :type add: bool
    :param command: the command
    :type command: str
    :param id_: the server id
    :type id_: str
    :return: nothing
    :rtype: None
    """
    my_dict = read_json(fopen_generic(join('data', 'command_blacklist.json')))
    if id_ not in my_dict:
        my_dict[id_] = []
    if add is False:
        if command in my_dict[id_]:
            my_dict[id_].remove(command)
    else:
        if command not in my_dict[id_]:
            my_dict[id_].append(command)
    write_json(fopen_generic(join('data', 'command_blacklist.json'), 'w'),
               my_dict)

def is_banned(command, id_):
    """
    Check if a command in banned in this server
    :param command: the command
    :type command: str
    :param id_: the server id
    :type id_: str
    :return: True if it's banned
    :rtype: bool
    """
    data = read_json(fopen_generic(join('data', 'command_blacklist.json')))
    try:
        return True if id_ in data and \
                       command in data[id_] else False
    except AttributeError:
        return False

def get_server_id(ctx):
    """
    Get the server id of a context
    :param ctx: the context
    :type ctx: context
    :return: the server id
    :rtype: str
    """
    try:
        return ctx.message.server.id
    except AttributeError:
        return None

def convert_currency(base, amount, target):
    """
    Conver currency to another
    :param base: str
    :param amount: str
    :param target: str
    :return: str
    """
    key = read_json(fopen_generic(join('data', 'api_keys.json')))['Currency']
    request_url = \
        'http://www.apilayer.net/api/live?access_key={}' \
        '&currencies={},{}&source=USD&format=1'.format(key, base, target)
    response = requests.get(request_url).content
    try:
        parsed_data = json.loads(response)['quotes']
    except KeyError:
        raise KeyError
    try:
        rate = float(parsed_data['USD{}'.format(target)]) \
               / float(parsed_data['USD{}'.format(base)])
        return "{0:.2f}".format(float(amount) * rate)
    except KeyError:
        raise KeyError

def safebooru(tag):
    """
    Get a list of pictures from safebooru based on tag
    :param tag: the tag to search for
    :return: a list of picture links based on the tag
    """
    url = "https://safebooru.org//index.php?page=dapi&s=post&q=index&tags={}"\
        .format(tag)
    result = requests.get(url).content
    root = ET.fromstring(result)
    return ['https:' + child.attrib['file_url'] for child in root]

def get_distro():
    """
    Name of your Linux distro (in lowercase).
    """
    with open("/etc/issue") as f:
        return f.read().lower().split()[:3]

def split_list(lst, max_length):
    """
    Split a list into sublists
    :param lst: the list to be split
    :param max_length: the max allowed length of the result
    :return: a list of split up lists
    """
    return [lst[i:i + max_length] for i in range(0, len(lst), max_length)]

def get_date(diff):
    """
    Return yesterday's date in YYYYMMDD format
    :return: yesterday's date in YYYYMMDD format
    """
    yesterday = date.today() - timedelta(diff)
    return yesterday.strftime('%Y%m%d')

def comma(val):
    """
    Return a comma seprated number
    :param val: the number
    :return: the comma seprated number
    """
    return "{:,}".format(int(val))
<|endoftext|>


<commit_before>from math import sin, cos, sqrt, floor
import matplotlib.pyplot as plt
import numpy.random as rnd
import numpy as np
import random
import png

PI = 3.1415926535

Xdim = 1000
Ydim = 1000

BGR = 20
BGG = 75
BGB = 150

bitmap = [[[BGR, BGG, BGB] for _ in range(Ydim)] for _ in range(Xdim)]

def GaussianArray(radius, stddev):
    arr = [0 for _ in range(radius)]
    for i in range(radius):
        arr[i] = np.exp(-(float(i)**2)/(2.0*(stddev**2)))
    return arr

def blur(radius, stddev):
    global bitmap
    newmap = [[[c for c in pix] for pix in row] for row in bitmap]
    arr = GaussianArray(radius*2, stddev)
    for x in range(Xdim):
        for y in range(Ydim):
            left = max(x - radius, 0)
            right = min(x + radius, Xdim)
            top = max(y - radius, 0)
            bottom = min(y + radius, Ydim)
            total = [0, 0, 0]
            for px in range(left, right):
                for py in range(top, bottom):
                    val = bitmap[px][py]
                    # calculate x and y parameters for gaussian
                    gradius = sqrt((px - x)**2 + (y - py)**2)
                    total = [total[i] + val[i]*arr[int(abs(gradius))] for i in
                            range(3)]
            newmap[x][y] = [min(int(c), 255) for c in total]
        print("Row {0} done out of {1}\n".format(x, Xdim))
    bitmap = newmap

class Coordinate:
    def __init__(self, x=0, y=0, z=0):
        self.x = x
        self.y = y
        self.z = z
    def rotateZ(self, deg):
        rads = deg*PI/180.0
        newZ = self.z
        newY = self.x*sin(rads) + self.y*cos(rads)
        newX = self.x*cos(rads) - self.y*sin(rads)
        return Coordinate(newX, newY, newZ)
    def dot(self, other):
        return self.x*other.x + self.y*other.y + self.z*other.z
    def mag(self):
        return sqrt(self.x**2 + self.y**2 + self.z**2)
    def mult(self, c):
        return Coordinate(self.x*c, self.y*c, self.z*c)
    def div(self, c):
        return self.mult(1.0/c)
    def norm(self):
        magnitude = self.mag()
        if (magnitude == 0):
            return Coordinate(self.x, self.y, self.z)
        return self.div(magnitude)
    def __add__(self, other):
        newx = self.x + other.x
        newy = self.y + other.y
        newz = self.z + other.z
        return Coordinate(newx, newy, newz)
    def proj(self, other):
        dp = self.dot(other.norm())
        return other.norm().mult(dp)
    def __repr__(self):
        return "(" + str(self.x) + ", " + str(self.y) + ")"

center = Coordinate(Xdim/2.0, Ydim/2.0, 0)

def switchToOctantZeroFrom(octant, x, y):
    return [(x, y), (y, x), (y, -x),
            (-x, y), (-x, -y), (-y, -x), (-y, x),
            (x, -y)][octant]

def switchToOctantFromZero(octant, x, y):
    return [(x, y), (y, x), (-y, x),
            (-x, y), (-x, -y), (-y, -x), (y, -x),
            (x, -y)][octant]

def sign(x):
    if (x >= 0):
        return 1
    else:
        return -1

def octant(x, y):
    qd = {
            (-1, -1) : 4 if (y > x) else 5,
            (-1, 1)  : 2 if (y > abs(x)) else 3,
            (1, -1)  : 6 if (abs(y) > x) else 7,
            (1, 1)   : 1 if (y > x) else 0,
        }
    ret = qd[(sign(x), sign(y))]
    return ret

def zeroLine(zero, xp, yp):
    # convert to octant zero for Bresenham's line algorithm
    (xo, yo) = (xp - zero[0], yp - zero[1])
    o = octant(xo, yo)
    (x, y) = switchToOctantZeroFrom(o, xo, yo)
    dx = float(x)
    dy = float(y)
    error = float(0)
    derr = abs(float(dy/dx))
    y = int(0)
    for xi in range(0, int(x)):
        (px, py) = switchToOctantFromZero(o, xi, y)
        bitmap[int(zero[0] + px)][int(zero[1] + py)] = [255, 255, 255]
        error += derr
        while (error >= 0.5):
            (px, py) = switchToOctantFromZero(o, xi, y)
            bitmap[int(zero[0] + px)][int(zero[1] + py)] = [255, 255, 255]
            y += sign(dy)
            error -= 1.0

def ipart(x):
    return int(x)

def round(x):
    return ipart(x + 0.5)

def fpart(x):
    if x < 0:
        return 1 - (x - floor(x))
    return x - floor(x)

def rfpart(x):
    return 1 - fpart(x)

def plot(x, y, c):
    current = bitmap[x][y]
    remaining = [(255 - v) for v in current]
    increments = [int(c*float(remain)) for remain in remaining]
    bitmap[x][y] = [cur + incr for (cur, incr) in zip(current, increments)]

def constrain(x, minimum, maximum):
    if (x < minimum):
        return minimum
    if (x > maximum):
        return maximum
    return x

def zeroPlotInOct(zero, octant, x, y, c):
    (xo, yo) = switchToOctantFromZero(octant, x, y)
    (xb, yb) = (constrain(xo + zero[0], 0, Xdim-1), constrain(yo + zero[1], 0,
        Ydim-1))
    plot(int(xb), int(yb), c)

def xiaolinZeroLine(zero, xp, yp):
    (xo, yo) = (xp - zero[0], yp - zero[1])
    o = octant(xo, yo)
    (x, y) = switchToOctantZeroFrom(o, xo, yo)
    dy = (y)
    dx = (x)
    gradient = float(dy)/float(dx)
    # first endpoint
    xend  = 0
    yend  = 0
    xgap  = rfpart(0.5)
    xpx11 = xend
    ypx11 = ipart(yend)
    zeroPlotInOct(zero, o, xpx11, ypx11, rfpart(yend) * xgap)
    zeroPlotInOct(zero, o, xpx11, ypx11+1, fpart(yend) * xgap)
    intery = yend + gradient
    # second endpoint
    xend  = round(x)
    yend  = y + gradient * (xend - x)
    xgap  = fpart(x + 0.5)
    xpx12 = xend
    ypx12 = ipart(yend)
    zeroPlotInOct(zero, o, xpx12, ypx12, rfpart(yend) * xgap)
    zeroPlotInOct(zero, o, xpx12, ypx12 + 1, fpart(yend) * xgap)
    for x in range(xpx11 + 1, xpx12):
        zeroPlotInOct(zero, o, x, ipart(intery), rfpart(intery))
        zeroPlotInOct(zero, o, x, ipart(intery) + 1, fpart(intery))
        intery += gradient

def line(x0, y0, x1, y1):
    xiaolinZeroLine((y0, x0), y1, x1)

def draw(p1, p2):
    line(p1.x + center.x, p1.y + center.y, p2.x + center.x, p2.y + center.y)

def line_center(x0, y0, x1, y1):
    line(x0 + center.x, y0 + center.y, x1 + center.x, y1 + center.y)

def render():
    resized = [[0 for _ in range(3*Ydim)] for _ in range(Xdim)]
    for i in range(Xdim):
        for j in range(Ydim):
            resized[i][j*3 + 0] = bitmap[i][j][0]
            resized[i][j*3 + 1] = bitmap[i][j][1]
            resized[i][j*3 + 2] = bitmap[i][j][2]
    pic = png.from_array(resized, mode='RGB;8')
    return pic

class Cube:
    Directions = {
        'RU' : Coordinate(-1, 0, 1),
        'LU' : Coordinate(0, -1, 1),
        'R': Coordinate(-1, 1, 0),
        'L': Coordinate(1, -1, 0),
        'RD' : Coordinate(0, 1, -1),
        'LD' : Coordinate(1, 0, -1),
    }
    def __init__(self, coord, grid=1):
        self.loc = Coordinate(coord.x, coord.y, coord.z)
        self.loc.z = -(self.loc.x + self.loc.y)
        self.gridSize = grid
    def getNeighbor(self, direction):
        center = self.loc + Cube.Directions[direction]
        return Cube(center, self.gridSize)
    def hexagon(self):
        height = 2.0*self.gridSize
        basisr = Coordinate(sqrt(3.0)/2.0, 0, 0).mult(height)
        basisq = Coordinate(sqrt(3.0)/4.0, -0.75, 0).mult(height)
        center = basisr.mult(self.loc.y) + basisq.mult(self.loc.z)
        edge = self.gridSize
        return Hexagon(center.x, center.y, edge)

class Hexagon:
    def __init__(self, x=0, y=0, edge=1):
        self.center = Coordinate(x, y, 0)
        self.edge = edge
    # corner #0 is at the top, counts up CW
    def getCorner(self, i):
        d = Coordinate(0, 1, 0).norm().mult(self.edge)
        d = d.rotateZ(60*i)
        return d + self.center
    def draw(self):
        for i in range(6):
            p1 = self.getCorner(i)
            p2 = self.getCorner(i + 1)
            draw(p1, p2)
    def cube(self):
        self.center.z = -(self.center.x + self.center.y)
        a = sqrt(3.0)/2.0
        b = sqrt(3.0)/4.0
        c = 0
        d = -0.75
        multiplier = 1/(a*d - b*c)
        y = multiplier*(self.center.x * d + self.center.y * -b)/(self.edge*2)
        z = multiplier*(-c * self.center.x +self.center.y * a)/(self.edge*2)
        x = -(y + z)
        return Cube(Coordinate(x, y), self.edge)

def Column(x, edge):
    nHexagons = int(Ydim/(1.5*edge)) - 1
    Top = Hexagon(x, -Ydim/2 + edge, edge)
    Top.draw()
    chain = Top.cube().getNeighbor('RD')
    for _ in range(nHexagons/2):
        chain.hexagon().draw()
        chain = chain.getNeighbor('LD')
        chain.hexagon().draw()
        chain = chain.getNeighbor('RD')

# To create an image with hexagons, add your code here!
# For examples of how to use my library (the code in this file), see the code in
# the examples/ folder. Just paste any of those samples here and run to generate
# the file (output.png)
Column(-300, 50)
Column(-170, 50)
Column(-160, 50)
Column(-150, 50)
Column(-20, 50)
Column(-10, 50)
Column(0, 50)
Column(10, 50)
Column(20, 50)
Column(150, 50)
Column(160, 50)
Column(170, 50)
Column(300, 50)

pic = render()
pic.save('output.png')

<commit_msg>Fixed rendering problem with non-square window sizes<commit_after>from math import sin, cos, sqrt, floor
import matplotlib.pyplot as plt
import numpy.random as rnd
import numpy as np
import random
import png
import pdb

PI = 3.1415926535

Xdim = 1080
Ydim = 1920

BGR = 20
BGG = 75
BGB = 150

bitmap = [[[BGR, BGG, BGB] for _ in range(Ydim)] for _ in range(Xdim)]

def GaussianArray(radius, stddev):
    arr = [0 for _ in range(radius)]
    for i in range(radius):
        arr[i] = np.exp(-(float(i)**2)/(2.0*(stddev**2)))
    return arr

def blur(radius, stddev):
    global bitmap
    newmap = [[[c for c in pix] for pix in row] for row in bitmap]
    arr = GaussianArray(radius*2, stddev)
    for x in range(Xdim):
        for y in range(Ydim):
            left = max(x - radius, 0)
            right = min(x + radius, Xdim)
            top = max(y - radius, 0)
            bottom = min(y + radius, Ydim)
            total = [0, 0, 0]
            for px in range(left, right):
                for py in range(top, bottom):
                    val = bitmap[px][py]
                    # calculate x and y parameters for gaussian
                    gradius = sqrt((px - x)**2 + (y - py)**2)
                    total = [total[i] + val[i]*arr[int(abs(gradius))] for i in
                            range(3)]
            newmap[x][y] = [min(int(c), 255) for c in total]
        print("Row {0} done out of {1}\n".format(x, Xdim))
    bitmap = newmap

class Coordinate:
    def __init__(self, x=0, y=0, z=0):
        self.x = x
        self.y = y
        self.z = z
    def rotateZ(self, deg):
        rads = deg*PI/180.0
        newZ = self.z
        newY = self.x*sin(rads) + self.y*cos(rads)
        newX = self.x*cos(rads) - self.y*sin(rads)
        return Coordinate(newX, newY, newZ)
    def dot(self, other):
        return self.x*other.x + self.y*other.y + self.z*other.z
    def mag(self):
        return sqrt(self.x**2 + self.y**2 + self.z**2)
    def mult(self, c):
        return Coordinate(self.x*c, self.y*c, self.z*c)
    def div(self, c):
        return self.mult(1.0/c)
    def norm(self):
        magnitude = self.mag()
        if (magnitude == 0):
            return Coordinate(self.x, self.y, self.z)
        return self.div(magnitude)
    def __add__(self, other):
        newx = self.x + other.x
        newy = self.y + other.y
        newz = self.z + other.z
        return Coordinate(newx, newy, newz)
    def proj(self, other):
        dp = self.dot(other.norm())
        return other.norm().mult(dp)
    def __repr__(self):
        return "(" + str(self.x) + ", " + str(self.y) + ")"

center = Coordinate(Xdim/2.0, Ydim/2.0, 0)

def switchToOctantZeroFrom(octant, x, y):
    return [(x, y), (y, x), (y, -x),
            (-x, y), (-x, -y), (-y, -x), (-y, x),
            (x, -y)][octant]

def switchToOctantFromZero(octant, x, y):
    return [(x, y), (y, x), (-y, x),
            (-x, y), (-x, -y), (-y, -x), (y, -x),
            (x, -y)][octant]

def sign(x):
    if (x >= 0):
        return 1
    else:
        return -1

def octant(x, y):
    qd = {
            (-1, -1) : 4 if (y > x) else 5,
            (-1, 1)  : 2 if (y > abs(x)) else 3,
            (1, -1)  : 6 if (abs(y) > x) else 7,
            (1, 1)   : 1 if (y > x) else 0,
        }
    ret = qd[(sign(x), sign(y))]
    return ret

def zeroLine(zero, xp, yp):
    # convert to octant zero for Bresenham's line algorithm
    (xo, yo) = (xp - zero[0], yp - zero[1])
    o = octant(xo, yo)
    (x, y) = switchToOctantZeroFrom(o, xo, yo)
    dx = float(x)
    dy = float(y)
    error = float(0)
    derr = abs(float(dy/dx))
    y = int(0)
    for xi in range(0, int(x)):
        (px, py) = switchToOctantFromZero(o, xi, y)
        bitmap[int(zero[0] + px)][int(zero[1] + py)] = [255, 255, 255]
        error += derr
        while (error >= 0.5):
            (px, py) = switchToOctantFromZero(o, xi, y)
            bitmap[int(zero[0] + px)][int(zero[1] + py)] = [255, 255, 255]
            y += sign(dy)
            error -= 1.0

def ipart(x):
    return int(x)

def round(x):
    return ipart(x + 0.5)

def fpart(x):
    if x < 0:
        return 1 - (x - floor(x))
    return x - floor(x)

def rfpart(x):
    return 1 - fpart(x)

def plot(x, y, c):
    current = bitmap[x][y]
    remaining = [(255 - v) for v in current]
    increments = [int(c*float(remain)) for remain in remaining]
    bitmap[x][y] = [cur + incr for (cur, incr) in zip(current, increments)]

def inRange(x, minimum, maximum):
    if (x < minimum):
        return False
    if (x >= maximum):
        return False
    return True

def zeroPlotInOct(zero, octant, x, y, c):
    (xo, yo) = switchToOctantFromZero(octant, x, y)
    if (inRange(xo + zero[0], 0, Xdim-1)):
        if (inRange(yo + zero[1], 0, Ydim-1)):
            plot(int(zero[0] + xo), int(zero[1] + yo), c)

def xiaolinZeroLine(zero, xp, yp):
    (xo, yo) = (xp - zero[0], yp - zero[1])
    o = octant(xo, yo)
    (x, y) = switchToOctantZeroFrom(o, xo, yo)
    dy = (y)
    dx = (x)
    gradient = float(dy)/float(dx)
    # first endpoint
    xend  = 0
    yend  = 0
    xgap  = rfpart(0.5)
    xpx11 = xend
    ypx11 = ipart(yend)
    zeroPlotInOct(zero, o, xpx11, ypx11, rfpart(yend) * xgap)
    zeroPlotInOct(zero, o, xpx11, ypx11+1, fpart(yend) * xgap)
    intery = yend + gradient
    # second endpoint
    xend  = round(x)
    yend  = y + gradient * (xend - x)
    xgap  = fpart(x + 0.5)
    xpx12 = xend
    ypx12 = ipart(yend)
    zeroPlotInOct(zero, o, xpx12, ypx12, rfpart(yend) * xgap)
    zeroPlotInOct(zero, o, xpx12, ypx12 + 1, fpart(yend) * xgap)
    for x in range(xpx11 + 1, xpx12):
        zeroPlotInOct(zero, o, x, ipart(intery), rfpart(intery))
        zeroPlotInOct(zero, o, x, ipart(intery) + 1, fpart(intery))
        intery += gradient

def line(x0, y0, x1, y1):
    xiaolinZeroLine((x0, y0), x1, y1)

def draw(p1, p2):
    global center
    line(p1.x + center.x, p1.y + center.y, p2.x + center.x, p2.y + center.y)

def line_center(x0, y0, x1, y1):
    global center
    line(x0 + center.x, y0 + center.y, x1 + center.x, y1 + center.y)

def render():
    global bitmap
    resized = [[0 for _ in range(3*Xdim)] for _ in range(Ydim)]
    for i in range(Xdim):
        for j in range(Ydim):
            resized[j][i*3 + 0] = bitmap[i][j][0]
            resized[j][i*3 + 1] = bitmap[i][j][1]
            resized[j][i*3 + 2] = bitmap[i][j][2]
    pic = png.from_array(resized, mode='RGB;8')
    return pic

class Cube:
    Directions = {
        'RU' : Coordinate(-1, 0, 1),
        'LU' : Coordinate(0, -1, 1),
        'R': Coordinate(-1, 1, 0),
        'L': Coordinate(1, -1, 0),
        'RD' : Coordinate(0, 1, -1),
        'LD' : Coordinate(1, 0, -1),
    }
    def __init__(self, coord, grid=1):
        self.loc = Coordinate(coord.x, coord.y, coord.z)
        self.loc.z = -(self.loc.x + self.loc.y)
        self.gridSize = grid
    def getNeighbor(self, direction):
        lcenter = self.loc + Cube.Directions[direction]
        return Cube(lcenter, self.gridSize)
    def hexagon(self):
        height = 2.0*self.gridSize
        basisr = Coordinate(sqrt(3.0)/2.0, 0, 0).mult(height)
        basisq = Coordinate(sqrt(3.0)/4.0, -0.75, 0).mult(height)
        center = basisr.mult(self.loc.y) + basisq.mult(self.loc.z)
        edge = self.gridSize
        return Hexagon(center.x, center.y, edge)

class Hexagon:
    def __init__(self, x=0, y=0, edge=1):
        self.center = Coordinate(x, y, 0)
        self.edge = edge
    # corner #0 is at the top, counts up CW
    def getCorner(self, i):
        d = Coordinate(0, 1, 0).norm().mult(self.edge)
        d = d.rotateZ(60*i)
        return d + self.center
    def draw(self):
        for i in range(6):
            p1 = self.getCorner(i)
            p2 = self.getCorner(i + 1)
            draw(p1, p2)
    def cube(self):
        self.center.z = -(self.center.x + self.center.y)
        a = sqrt(3.0)/2.0
        b = sqrt(3.0)/4.0
        c = 0
        d = -0.75
        multiplier = 1/(a*d - b*c)
        y = multiplier*(self.center.x * d + self.center.y * -b)/(self.edge*2)
        z = multiplier*(-c * self.center.x +self.center.y * a)/(self.edge*2)
        x = -(y + z)
        return Cube(Coordinate(x, y), self.edge)

def Column(x, edge):
    x -= 0.25*sqrt(3)*edge
    nHexagons = int(Ydim/(1.5*edge)) - 1
    Top = Hexagon(x, -Ydim/2 + edge, edge)
    Top.draw()
    chain = Top.cube().getNeighbor('RD')
    for _ in range(nHexagons):
        chain.hexagon().draw()
        chain = chain.getNeighbor('LD')
        chain.hexagon().draw()
        chain = chain.getNeighbor('RD')

# To create an image with hexagons, add your code here!
# For examples of how to use my library (the code in this file), see the code in
# the examples/ folder. Just paste any of those samples here and run to generate
# the file (output.png)
size = 50
Column(-300, size)
Column(-170, size)
Column(-160, size)
Column(-150, size)
Column(-20, size)
Column(-10, size)
Column(0, size)
Column(10, size)
Column(20, size)
Column(150, size)
Column(160, size)
Column(170, size)
Column(300, size)

line_center(0, 0, 10, 10)

pic = render()
pic.save('output.png')

<|endoftext|>


<commit_before>
s = None
t = None
r = None
h = None

def isOdd(num):
    return bool(num & 0x1)
def isEven(num):
    return not (num & 0x1)

class HexagonMetricError(Exception): pass

def setMetric(name, value):
    globals()[name.lower()] = value

def getMetric(name):
    value = globals()[name.lower()]
    if value != None:
        return value
    else:
        raise HexagonMetricError("Hexagon metrics not set")

def gridToPixels(xgrid, ygrid):
    xcoord = xgrid * (getMetric('t') + getMetric('s'))
<commit_msg>Finished hexmech<commit_after>
s = None
t = None
r = None
h = None

def isOdd(num):
    return bool(num & 0x1)
def isEven(num):
    return not (num & 0x1)

class HexagonMetricError(Exception): pass

def setMetric(name, value):
    globals()[name.lower()] = value

def getMetric(name):
    value = globals()[name.lower()]
    if value != None:
        return value
    else:
        raise HexagonMetricError("Hexagon metrics not set")

def coordToPixels(xgrid, ygrid, xpixeloffset=0, ypixeloffset=0):
    """
    Convert the grid coordinate location of a hexagon
    to pixel a position on the screen.
    """

    t = getMetric('t')
    s = getMetric('s')
    h = getMetric('h')
    r = getMetric('r')

    xcoord = xgrid * (t + s)
    ycoord = ygrid * h

    if isOdd(xgrid):
        ycoord += r

    xcoord += xpixeloffset
    ycoord += ypixeloffset

    return (xcoord, ycoord)

def pixelsToCoord(x, y):
    """
    Convert the pixel coordinates of a mouse cursor to find
    which hexagon on the coordinate grid it lies on.
    """

    pass
<|endoftext|>