<commit_before>#!/usr/bin/env python2.5
#encoding:utf-8
#author:dbr/Ben
#contributors: by ccjensen/Chris
#project:themoviedb
#http://github.com/dbr/themoviedb

"""An interface to the themoviedb.org API
"""

__author__ = "dbr/Ben"
__version__ = "0.2b"

config = {}
config['apikey'] = "a8b9f96dde091408a03cb4c78477bd14"

config['urls'] = {}
config['urls']['movie.search'] = "http://api.themoviedb.org/2.1/Movie.search/en/xml/%(apikey)s/%%s" % (config)
config['urls']['movie.getInfo'] = "http://api.themoviedb.org/2.1/Movie.getInfo/en/xml/%(apikey)s/%%s" % (config)
config['urls']['hash.getInfo'] = "http://api.themoviedb.org/2.1/Hash.getInfo/en/xml/%(apikey)s/%%s" % (config)

import os
import struct
import urllib

import xml.etree.cElementTree as ElementTree

class TmdBaseError(Exception):
    pass

class TmdNoResults(TmdBaseError):
    pass

class TmdHttpError(TmdBaseError):
    pass

class TmdXmlError(TmdBaseError):
    pass

def opensubtitleHashFile(name):
    """Hashes a file using OpenSubtitle's method.

    > In natural language it calculates: size + 64bit chksum of the first and
    > last 64k (even if they overlap because the file is smaller than 128k).

    A slightly more Pythonic version of the Python solution on..
    http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes
    """
    longlongformat = 'q'
    bytesize = struct.calcsize(longlongformat)

    f = open(name, "rb")

    filesize = os.path.getsize(name)
    fhash = filesize

    if filesize < 65536 * 2:
       raise ValueError("File size must be larger than %s bytes (is %s)" % (65536*2, filesize))

    for x in range(65536/bytesize):
        buf = f.read(bytesize)
        (l_value,)= struct.unpack(longlongformat, buf)
        fhash += l_value
        fhash = fhash & 0xFFFFFFFFFFFFFFFF # to remain as 64bit number

    f.seek(max(0,filesize-65536),0)
    for x in range(65536/bytesize):
        buf = f.read(bytesize)
        (l_value,)= struct.unpack(longlongformat, buf)
        fhash += l_value
        fhash = fhash & 0xFFFFFFFFFFFFFFFF

    f.close()
    return  "%016x" % fhash

class XmlHandler:
    """Deals with retrieval of XML files from API
    """

    def __init__(self, url):
        self.url = url

    def _grabUrl(self, url):
        try:
            urlhandle = urllib.urlopen(url)
        except IOError, errormsg:
            raise TmdHttpError(errormsg)
        return urlhandle.read()

    def getEt(self):
        xml = self._grabUrl(self.url)
        try:
            et = ElementTree.fromstring(xml)
        except SyntaxError, errormsg:
            raise TmdXmlError(errormsg)
        return et

class SearchResults(list):
    """Stores a list of Movie's that matched the search
    """

    def __repr__(self):
        return "<Search results: %s>" % (list.__repr__(self))

class MovieResult(dict):
    """A dict containing the information about a specific search result
    """

    def __repr__(self):
        return "<MovieResult: %s (%s)>" % (self.get("name"), self.get("released"))

    def info(self):
        """Performs a MovieDb.getMovieInfo search on the current id, returns
        a Movie object
        """
        cur_id = self['id']
        info = MovieDb().getMovieInfo(cur_id)
        return info

class Movie(dict):
    """A dict containing the information about the film
    """

    def __repr__(self):
        return "<MovieResult: %s (%s)>" % (self.get("name"), self.get("released"))

class Categories(dict):
    """Stores category information
    """

    def set(self, category_et):
        """Takes an elementtree Element ('category') and stores the url,
        using the type and name as the dict key.

        For example:
       <category type="genre" url="http://themoviedb.org/encyclopedia/category/80" name="Crime"/>

        ..becomes:
        categories['genre']['Crime'] = 'http://themoviedb.org/encyclopedia/category/80'
        """
        _type = category_et.get("type")
        name = category_et.get("name")
        url = category_et.get("url")
        self.setdefault(_type, {})[name] = url
        self[_type][name] = url

class Studios(dict):
    """Stores category information
    """

    def set(self, studio_et):
        """Takes an elementtree Element ('studio') and stores the url,
        using the name as the dict key.

        For example:
       <studio url="http://www.themoviedb.org/encyclopedia/company/20" name="Miramax Films"/>

        ..becomes:
        studios['name'] = 'http://www.themoviedb.org/encyclopedia/company/20'
        """
        name = studio_et.get("name")
        url = studio_et.get("url")
        self[name] = url

class Countries(dict):
    """Stores country information
    """

    def set(self, country_et):
        """Takes an elementtree Element ('country') and stores the url,
        using the name and code as the dict key.

        For example:
       <country url="http://www.themoviedb.org/encyclopedia/country/223" name="United States of America" code="US"/>

        ..becomes:
        countries['code']['name'] = 'http://www.themoviedb.org/encyclopedia/country/223'
        """
        code = country_et.get("code")
        name = country_et.get("name")
        url = country_et.get("url")
        self.setdefault(code, {})[name] = url

class Image(dict):
    """Stores image information for a single poster/backdrop (includes
    multiple sizes)
    """

    def __init__(self, _id, _type, size, url):
        self['id'] = _id
        self['type'] = _type

    def largest(self):
        for csize in ["original", "mid", "cover", "thumb"]:
            if csize in self:
                return csize

    def __repr__(self):
        return "<Image (%s for ID %s)>" % (self['type'], self['id'])

class ImagesList(list):
    """Stores a list of Images, and functions to filter "only posters" etc
    """

    def set(self, image_et):
        """Takes an elementtree Element ('image') and stores the url,
        along with the type, id and size.

        Is a list containing each image as a dictionary (which includes the
        various sizes)

        For example:
        <image type="poster" size="original" url="http://images.themoviedb.org/posters/4181/67926_sin-city-02-color_122_207lo.jpg" id="4181"/>

        ..becomes:
        images[0] = {'id':4181', 'type': 'poster', 'original': 'http://images.themov...'}
        """
        _type = image_et.get("type")
        _id = image_et.get("id")
        size = image_et.get("size")
        url = image_et.get("url")

        cur = self.find_by('id', _id)
        if len(cur) == 0:
            nimg = Image(_id = _id, _type = _type, size = size, url = url)
            self.append(nimg)
        elif len(cur) == 1:
            cur[0][size] = url
        else:
            raise ValueError("Found more than one poster with id %s, this should never happen" % (_id))

    def find_by(self, key, value):
        ret = []
        for cur in self:
            if cur[key] == value:
                ret.append(cur)
        return ret

    @property
    def posters(self):
        return self.find_by('type', 'poster')

    @property
    def backdrops(self):
        return self.find_by('type', 'backdrop')

class CrewRoleList(dict):
    """Stores a list of roles, such as director, actor etc

    >>> import tmdb
    >>> tmdb.getMovieInfo(550)['cast'].keys()[:5]
    ['casting', 'producer', 'author', 'sound editor', 'actor']
    """
    pass

class CrewList(list):
    """Stores list of crew in specific role

    >>> import tmdb
    >>> tmdb.getMovieInfo(550)['cast']['author']
    [<author (id 7468): Chuck Palahniuk>, <author (id 7469): Jim Uhls>]
    """
    pass

class Person(dict):
    """Stores information about a specific member of cast
    """

    def __init__(self, job, _id, name, character, url):
        self['job'] = job
        self['id'] = _id
        self['name'] = name
        self['character'] = character
        self['url'] = url

    def __repr__(self):
        if self['character'] is None or self['character'] == "":
            return "<%(job)s (id %(id)s): %(name)s>" % self
        else:
            return "<%(job)s (id %(id)s): %(name)s (as %(character)s)>" % self

class MovieDb:
    """Main interface to www.themoviedb.com

    The search() method searches for the film by title.
    The getMovieInfo() method retrieves information about a specific movie using themoviedb id.
    """

    def _parseSearchResults(self, movie_element):
        cur_movie = MovieResult()
        cur_images = ImagesList()
        for item in movie_element.getchildren():
                if item.tag.lower() == "images":
                    for subitem in item.getchildren():
                        cur_images.set(subitem)
                else:
                    cur_movie[item.tag] = item.text
        cur_movie['images'] = cur_images
        return cur_movie

    def _parseMovie(self, movie_element):
        cur_movie = Movie()
        cur_categories = Categories()
        cur_studios = Studios()
        cur_countries = Countries()
        cur_images = ImagesList()
        cur_cast = CrewRoleList()
        for item in movie_element.getchildren():
            if item.tag.lower() == "categories":
                for subitem in item.getchildren():
                    cur_categories.set(subitem)
            elif item.tag.lower() == "studios":
                for subitem in item.getchildren():
                    cur_studios.set(subitem)
            elif item.tag.lower() == "countries":
                for subitem in item.getchildren():
                    cur_countries.set(subitem)
            elif item.tag.lower() == "images":
                for subitem in item.getchildren():
                    cur_images.set(subitem)
            elif item.tag.lower() == "cast":
                for subitem in item.getchildren():
                    job = subitem.get("job").lower()
                    p = Person(
                        job = job,
                        _id = subitem.get("id"),
                        name = subitem.get("name"),
                        character = subitem.get("character"),
                        url = subitem.get("url"),
                    )
                    cur_cast.setdefault(job, CrewList()).append(p)
            else:
                cur_movie[item.tag] = item.text

        cur_movie['categories'] = cur_categories
        cur_movie['studios'] = cur_studios
        cur_movie['countries'] = cur_countries
        cur_movie['images'] = cur_images
        cur_movie['cast'] = cur_cast
        return cur_movie

    def search(self, title):
        """Searches for a film by its title.
        Returns SearchResults (a list) containing all matches (Movie instances)
        """
        title = urllib.quote(title.encode("utf-8"))
        url = config['urls']['movie.search'] % (title)
        etree = XmlHandler(url).getEt()
        search_results = SearchResults()
        for cur_result in etree.find("movies").findall("movie"):
            cur_movie = self._parseSearchResults(cur_result)
            search_results.append(cur_movie)
        return search_results

    def getMovieInfo(self, id):
        """Returns movie info by it's TheMovieDb ID.
        Returns a Movie instance
        """
        url = config['urls']['movie.getInfo'] % (id)
        etree = XmlHandler(url).getEt()
        moviesTree = etree.find("movies").findall("movie")

        if len(moviesTree) == 0:
            raise TmdNoResults("No results for id %s" % id)

        return self._parseMovie(moviesTree[0])

    def hashGetInfo(self, hash):
        """Returns movie info by it's OpenSubtitle-format hash.
        http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes

        Example hash of "Willow (1988).avi": 00277ff46533b155
        """
        url = config['urls']['hash.getInfo'] % (hash)
        etree = XmlHandler(url).getEt()
        moviesTree = etree.find("movies").findall("movie")

        if len(moviesTree) == 0:
            raise TmdNoResults("No results for hash %s" % hash)

        return self._parseMovie(moviesTree[0])

def search(name):
    """Convenience wrapper for MovieDb.search - so you can do..

    >>> import tmdb
    >>> tmdb.search("Fight Club")
    <Search results: [<MovieResult: Fight Club (1999-09-16)>]>
    """
    mdb = MovieDb()
    return mdb.search(name)

def getMovieInfo(id):
    """Convenience wrapper for MovieDb.search - so you can do..

    >>> import tmdb
    >>> tmdb.getMovieInfo(187)
    <MovieResult: Sin City (2005-04-01)>
    """
    mdb = MovieDb()
    return mdb.getMovieInfo(id)

def hashGetInfo(hash):
    """Convenience wrapper for MovieDb.hashGetInfo - so you can do..

    >>> import tmdb
    >>> tmdb.hashGetInfo('00277ff46533b155')
    <MovieResult: Willow (1988-05-20)>
    """
    mdb = MovieDb()
    return mdb.hashGetInfo(hash)

def searchByHashingFile(filename):
    """Searches for the specified file using the OpenSubtitle hashing method
    """
    return hashGetInfo(opensubtitleHashFile(filename))

def main():
    results = search("Fight Club")
    searchResult = results[0]
    movie = getMovieInfo(searchResult['id'])
    print movie['name']

    print "Producers:"
    for prodr in movie['cast']['producer']:
        print " " * 4, prodr['name']
    print movie['images']
    for genreName in movie['categories']['genre']:
        print "%s (%s)" % (genreName, movie['categories']['genre'][genreName])

if __name__ == '__main__':
    main()
<commit_msg>Update docstring for hashGetInfo method<commit_after>#!/usr/bin/env python2.5
#encoding:utf-8
#author:dbr/Ben
#contributors: by ccjensen/Chris
#project:themoviedb
#http://github.com/dbr/themoviedb

"""An interface to the themoviedb.org API
"""

__author__ = "dbr/Ben"
__version__ = "0.2b"

config = {}
config['apikey'] = "a8b9f96dde091408a03cb4c78477bd14"

config['urls'] = {}
config['urls']['movie.search'] = "http://api.themoviedb.org/2.1/Movie.search/en/xml/%(apikey)s/%%s" % (config)
config['urls']['movie.getInfo'] = "http://api.themoviedb.org/2.1/Movie.getInfo/en/xml/%(apikey)s/%%s" % (config)
config['urls']['hash.getInfo'] = "http://api.themoviedb.org/2.1/Hash.getInfo/en/xml/%(apikey)s/%%s" % (config)

import os
import struct
import urllib

import xml.etree.cElementTree as ElementTree

class TmdBaseError(Exception):
    pass

class TmdNoResults(TmdBaseError):
    pass

class TmdHttpError(TmdBaseError):
    pass

class TmdXmlError(TmdBaseError):
    pass

def opensubtitleHashFile(name):
    """Hashes a file using OpenSubtitle's method.

    > In natural language it calculates: size + 64bit chksum of the first and
    > last 64k (even if they overlap because the file is smaller than 128k).

    A slightly more Pythonic version of the Python solution on..
    http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes
    """
    longlongformat = 'q'
    bytesize = struct.calcsize(longlongformat)

    f = open(name, "rb")

    filesize = os.path.getsize(name)
    fhash = filesize

    if filesize < 65536 * 2:
       raise ValueError("File size must be larger than %s bytes (is %s)" % (65536*2, filesize))

    for x in range(65536/bytesize):
        buf = f.read(bytesize)
        (l_value,)= struct.unpack(longlongformat, buf)
        fhash += l_value
        fhash = fhash & 0xFFFFFFFFFFFFFFFF # to remain as 64bit number

    f.seek(max(0,filesize-65536),0)
    for x in range(65536/bytesize):
        buf = f.read(bytesize)
        (l_value,)= struct.unpack(longlongformat, buf)
        fhash += l_value
        fhash = fhash & 0xFFFFFFFFFFFFFFFF

    f.close()
    return  "%016x" % fhash

class XmlHandler:
    """Deals with retrieval of XML files from API
    """

    def __init__(self, url):
        self.url = url

    def _grabUrl(self, url):
        try:
            urlhandle = urllib.urlopen(url)
        except IOError, errormsg:
            raise TmdHttpError(errormsg)
        return urlhandle.read()

    def getEt(self):
        xml = self._grabUrl(self.url)
        try:
            et = ElementTree.fromstring(xml)
        except SyntaxError, errormsg:
            raise TmdXmlError(errormsg)
        return et

class SearchResults(list):
    """Stores a list of Movie's that matched the search
    """

    def __repr__(self):
        return "<Search results: %s>" % (list.__repr__(self))

class MovieResult(dict):
    """A dict containing the information about a specific search result
    """

    def __repr__(self):
        return "<MovieResult: %s (%s)>" % (self.get("name"), self.get("released"))

    def info(self):
        """Performs a MovieDb.getMovieInfo search on the current id, returns
        a Movie object
        """
        cur_id = self['id']
        info = MovieDb().getMovieInfo(cur_id)
        return info

class Movie(dict):
    """A dict containing the information about the film
    """

    def __repr__(self):
        return "<MovieResult: %s (%s)>" % (self.get("name"), self.get("released"))

class Categories(dict):
    """Stores category information
    """

    def set(self, category_et):
        """Takes an elementtree Element ('category') and stores the url,
        using the type and name as the dict key.

        For example:
       <category type="genre" url="http://themoviedb.org/encyclopedia/category/80" name="Crime"/>

        ..becomes:
        categories['genre']['Crime'] = 'http://themoviedb.org/encyclopedia/category/80'
        """
        _type = category_et.get("type")
        name = category_et.get("name")
        url = category_et.get("url")
        self.setdefault(_type, {})[name] = url
        self[_type][name] = url

class Studios(dict):
    """Stores category information
    """

    def set(self, studio_et):
        """Takes an elementtree Element ('studio') and stores the url,
        using the name as the dict key.

        For example:
       <studio url="http://www.themoviedb.org/encyclopedia/company/20" name="Miramax Films"/>

        ..becomes:
        studios['name'] = 'http://www.themoviedb.org/encyclopedia/company/20'
        """
        name = studio_et.get("name")
        url = studio_et.get("url")
        self[name] = url

class Countries(dict):
    """Stores country information
    """

    def set(self, country_et):
        """Takes an elementtree Element ('country') and stores the url,
        using the name and code as the dict key.

        For example:
       <country url="http://www.themoviedb.org/encyclopedia/country/223" name="United States of America" code="US"/>

        ..becomes:
        countries['code']['name'] = 'http://www.themoviedb.org/encyclopedia/country/223'
        """
        code = country_et.get("code")
        name = country_et.get("name")
        url = country_et.get("url")
        self.setdefault(code, {})[name] = url

class Image(dict):
    """Stores image information for a single poster/backdrop (includes
    multiple sizes)
    """

    def __init__(self, _id, _type, size, url):
        self['id'] = _id
        self['type'] = _type

    def largest(self):
        for csize in ["original", "mid", "cover", "thumb"]:
            if csize in self:
                return csize

    def __repr__(self):
        return "<Image (%s for ID %s)>" % (self['type'], self['id'])

class ImagesList(list):
    """Stores a list of Images, and functions to filter "only posters" etc
    """

    def set(self, image_et):
        """Takes an elementtree Element ('image') and stores the url,
        along with the type, id and size.

        Is a list containing each image as a dictionary (which includes the
        various sizes)

        For example:
        <image type="poster" size="original" url="http://images.themoviedb.org/posters/4181/67926_sin-city-02-color_122_207lo.jpg" id="4181"/>

        ..becomes:
        images[0] = {'id':4181', 'type': 'poster', 'original': 'http://images.themov...'}
        """
        _type = image_et.get("type")
        _id = image_et.get("id")
        size = image_et.get("size")
        url = image_et.get("url")

        cur = self.find_by('id', _id)
        if len(cur) == 0:
            nimg = Image(_id = _id, _type = _type, size = size, url = url)
            self.append(nimg)
        elif len(cur) == 1:
            cur[0][size] = url
        else:
            raise ValueError("Found more than one poster with id %s, this should never happen" % (_id))

    def find_by(self, key, value):
        ret = []
        for cur in self:
            if cur[key] == value:
                ret.append(cur)
        return ret

    @property
    def posters(self):
        return self.find_by('type', 'poster')

    @property
    def backdrops(self):
        return self.find_by('type', 'backdrop')

class CrewRoleList(dict):
    """Stores a list of roles, such as director, actor etc

    >>> import tmdb
    >>> tmdb.getMovieInfo(550)['cast'].keys()[:5]
    ['casting', 'producer', 'author', 'sound editor', 'actor']
    """
    pass

class CrewList(list):
    """Stores list of crew in specific role

    >>> import tmdb
    >>> tmdb.getMovieInfo(550)['cast']['author']
    [<author (id 7468): Chuck Palahniuk>, <author (id 7469): Jim Uhls>]
    """
    pass

class Person(dict):
    """Stores information about a specific member of cast
    """

    def __init__(self, job, _id, name, character, url):
        self['job'] = job
        self['id'] = _id
        self['name'] = name
        self['character'] = character
        self['url'] = url

    def __repr__(self):
        if self['character'] is None or self['character'] == "":
            return "<%(job)s (id %(id)s): %(name)s>" % self
        else:
            return "<%(job)s (id %(id)s): %(name)s (as %(character)s)>" % self

class MovieDb:
    """Main interface to www.themoviedb.com

    The search() method searches for the film by title.
    The getMovieInfo() method retrieves information about a specific movie using themoviedb id.
    """

    def _parseSearchResults(self, movie_element):
        cur_movie = MovieResult()
        cur_images = ImagesList()
        for item in movie_element.getchildren():
                if item.tag.lower() == "images":
                    for subitem in item.getchildren():
                        cur_images.set(subitem)
                else:
                    cur_movie[item.tag] = item.text
        cur_movie['images'] = cur_images
        return cur_movie

    def _parseMovie(self, movie_element):
        cur_movie = Movie()
        cur_categories = Categories()
        cur_studios = Studios()
        cur_countries = Countries()
        cur_images = ImagesList()
        cur_cast = CrewRoleList()
        for item in movie_element.getchildren():
            if item.tag.lower() == "categories":
                for subitem in item.getchildren():
                    cur_categories.set(subitem)
            elif item.tag.lower() == "studios":
                for subitem in item.getchildren():
                    cur_studios.set(subitem)
            elif item.tag.lower() == "countries":
                for subitem in item.getchildren():
                    cur_countries.set(subitem)
            elif item.tag.lower() == "images":
                for subitem in item.getchildren():
                    cur_images.set(subitem)
            elif item.tag.lower() == "cast":
                for subitem in item.getchildren():
                    job = subitem.get("job").lower()
                    p = Person(
                        job = job,
                        _id = subitem.get("id"),
                        name = subitem.get("name"),
                        character = subitem.get("character"),
                        url = subitem.get("url"),
                    )
                    cur_cast.setdefault(job, CrewList()).append(p)
            else:
                cur_movie[item.tag] = item.text

        cur_movie['categories'] = cur_categories
        cur_movie['studios'] = cur_studios
        cur_movie['countries'] = cur_countries
        cur_movie['images'] = cur_images
        cur_movie['cast'] = cur_cast
        return cur_movie

    def search(self, title):
        """Searches for a film by its title.
        Returns SearchResults (a list) containing all matches (Movie instances)
        """
        title = urllib.quote(title.encode("utf-8"))
        url = config['urls']['movie.search'] % (title)
        etree = XmlHandler(url).getEt()
        search_results = SearchResults()
        for cur_result in etree.find("movies").findall("movie"):
            cur_movie = self._parseSearchResults(cur_result)
            search_results.append(cur_movie)
        return search_results

    def getMovieInfo(self, id):
        """Returns movie info by it's TheMovieDb ID.
        Returns a Movie instance
        """
        url = config['urls']['movie.getInfo'] % (id)
        etree = XmlHandler(url).getEt()
        moviesTree = etree.find("movies").findall("movie")

        if len(moviesTree) == 0:
            raise TmdNoResults("No results for id %s" % id)

        return self._parseMovie(moviesTree[0])

    def hashGetInfo(self, hash):
        """Returns movie info by it's OpenSubtitle-format hash.
        http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes

        Example hash of "Underworld (2003).avi": 00277ff46533b155
        """
        url = config['urls']['hash.getInfo'] % (hash)
        etree = XmlHandler(url).getEt()
        moviesTree = etree.find("movies").findall("movie")

        if len(moviesTree) == 0:
            raise TmdNoResults("No results for hash %s" % hash)

        return self._parseMovie(moviesTree[0])

def search(name):
    """Convenience wrapper for MovieDb.search - so you can do..

    >>> import tmdb
    >>> tmdb.search("Fight Club")
    <Search results: [<MovieResult: Fight Club (1999-09-16)>]>
    """
    mdb = MovieDb()
    return mdb.search(name)

def getMovieInfo(id):
    """Convenience wrapper for MovieDb.search - so you can do..

    >>> import tmdb
    >>> tmdb.getMovieInfo(187)
    <MovieResult: Sin City (2005-04-01)>
    """
    mdb = MovieDb()
    return mdb.getMovieInfo(id)

def hashGetInfo(hash):
    """Convenience wrapper for MovieDb.hashGetInfo - so you can do..

    >>> import tmdb
    >>> tmdb.hashGetInfo('00277ff46533b155')
    <MovieResult: Underworld (2003-09-19)>
    """
    mdb = MovieDb()
    return mdb.hashGetInfo(hash)

def searchByHashingFile(filename):
    """Searches for the specified file using the OpenSubtitle hashing method
    """
    return hashGetInfo(opensubtitleHashFile(filename))

def main():
    results = search("Fight Club")
    searchResult = results[0]
    movie = getMovieInfo(searchResult['id'])
    print movie['name']

    print "Producers:"
    for prodr in movie['cast']['producer']:
        print " " * 4, prodr['name']
    print movie['images']
    for genreName in movie['categories']['genre']:
        print "%s (%s)" % (genreName, movie['categories']['genre'][genreName])

if __name__ == '__main__':
    main()
<|endoftext|>


<commit_before>from collections import namedtuple
import itertools
import math

_Vector = namedtuple("_Vector", ("x", "y", "z"))

class Vector(_Vector):

    __slots__ = ()

    def __add__(self, other):
        return Vector(self[0] + other[0], self[1] + other[1], self[2] + other[2])

    def __sub__(self, other):
        return Vector(self[0] - other[0], self[1] - other[1], self[2] - other[2])

    def __mul__(self, other):
        if isinstance(other, (int, float)):
            return Vector(self[0] * other, self[1] * other, self[2] * other)

        return Vector(self[0] * other[0], self[1] * other[1], self[2] * other[2])

    def __truediv__(self, other):
        if isinstance(other, (int, float)):
            return Vector(self[0] / other, self[1] / other, self[2] / other)

        return Vector(self[0] / other[0], self[1] / other[1], self[2] / other[2])

    __div__ = __truediv__

    def length(self):
        return math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2])

class BoundingBox (object):
    type = int

    def __init__(self, origin=(0, 0, 0), size=(0, 0, 0)):
        if isinstance(origin, BoundingBox):
            self._origin = origin._origin
            self._size = origin._size
        else:
            self._origin, self._size = Vector(*(self.type(a) for a in origin)), Vector(*(self.type(a) for a in size))

    def __repr__(self):
        return "BoundingBox({0}, {1})".format(self.origin, self.size)

    @property
    def origin(self):
        "The smallest position in the box"
        return self._origin

    @property
    def size(self):
        "The size of the box"
        return self._size

    @property
    def width(self):
        "The dimension along the X axis"
        return self._size.x

    @property
    def height(self):
        "The dimension along the Y axis"
        return self._size.y

    @property
    def length(self):
        "The dimension along the Z axis"
        return self._size.z

    @property
    def minx(self):
        return self.origin.x

    @property
    def miny(self):
        return self.origin.y

    @property
    def minz(self):
        return self.origin.z

    @property
    def maxx(self):
        return self.origin.x + self.size.x

    @property
    def maxy(self):
        return self.origin.y + self.size.y

    @property
    def maxz(self):
        return self.origin.z + self.size.z

    @property
    def maximum(self):
        "The largest point of the box; origin plus size."
        return self._origin + self._size

    @property
    def volume(self):
        "The volume of the box in blocks"
        return self.size.x * self.size.y * self.size.z

    @property
    def positions(self):
        """iterate through all of the positions within this selection box"""
        return itertools.product(
            xrange(self.minx, self.maxx),
            xrange(self.miny, self.maxy),
            xrange(self.minz, self.maxz)
        )

    def intersect(self, box):
        """
        Return a box containing the area self and box have in common. Box will have zero volume
         if there is no common area.
        """
        if (self.minx > box.maxx or self.maxx < box.minx or
            self.miny > box.maxy or self.maxy < box.miny or
            self.minz > box.maxz or self.maxz < box.minz):
            #Zero size intersection.
            return BoundingBox()

        origin = Vector(
            max(self.minx, box.minx),
            max(self.miny, box.miny),
            max(self.minz, box.minz),
        )
        maximum = Vector(
            min(self.maxx, box.maxx),
            min(self.maxy, box.maxy),
            min(self.maxz, box.maxz),
        )

        #print "Intersect of {0} and {1}: {2}".format(self, box, newbox)
        return BoundingBox(origin, maximum - origin)

    def union(self, box):
        """
        Return a box large enough to contain both self and box.
        """
        origin = Vector(
            min(self.minx, box.minx),
            min(self.miny, box.miny),
            min(self.minz, box.minz),
        )
        maximum = Vector(
            max(self.maxx, box.maxx),
            max(self.maxy, box.maxy),
            max(self.maxz, box.maxz),
        )
        return BoundingBox(origin, maximum - origin)

    def expand(self, dx, dy=None, dz=None):
        """
        Return a new box with boundaries expanded by dx, dy, dz.
        If only dx is passed, expands by dx in all dimensions.
        """
        if dz is None:
            dz = dx
        if dy is None:
            dy = dx

        origin = self.origin - (dx, dy, dz)
        size = self.size + (dx * 2, dy * 2, dz * 2)

        return BoundingBox(origin, size)

    def __contains__(self, pos):
        x, y, z = pos
        if x < self.minx or x >= self.maxx:
            return False
        if y < self.miny or y >= self.maxy:
            return False
        if z < self.minz or z >= self.maxz:
            return False

        return True

    def __cmp__(self, b):
        return cmp((self.origin, self.size), (b.origin, b.size))

    # --- Chunk positions ---

    @property
    def mincx(self):
        "The smallest chunk position contained in this box"
        return self.origin.x >> 4

    @property
    def mincz(self):
        "The smallest chunk position contained in this box"
        return self.origin.z >> 4

    @property
    def maxcx(self):
        "The largest chunk position contained in this box"
        return ((self.origin.x + self.size.x - 1) >> 4) + 1

    @property
    def maxcz(self):
        "The largest chunk position contained in this box"
        return ((self.origin.z + self.size.z - 1) >> 4) + 1

    def chunkBox(self, level):
        """Returns this box extended to the chunk boundaries of the given level"""
        box = self
        return BoundingBox((box.mincx << 4, 0, box.mincz << 4),
                           (box.maxcx - box.mincx << 4, level.Height, box.maxcz - box.mincz << 4))

    @property
    def chunkPositions(self):
        #iterate through all of the chunk positions within this selection box
        return itertools.product(xrange(self.mincx, self.maxcx), xrange(self.mincz, self.maxcz))

    @property
    def chunkCount(self):
        return (self.maxcx - self.mincx) * (self.maxcz - self.mincz)

    @property
    def isChunkAligned(self):
        return (self.origin.x & 0xf == 0) and (self.origin.z & 0xf == 0)

class FloatBox (BoundingBox):
    type = float
<commit_msg>Add Vector.normalize<commit_after>from collections import namedtuple
import itertools
import math

_Vector = namedtuple("_Vector", ("x", "y", "z"))

class Vector(_Vector):

    __slots__ = ()

    def __add__(self, other):
        return Vector(self[0] + other[0], self[1] + other[1], self[2] + other[2])

    def __sub__(self, other):
        return Vector(self[0] - other[0], self[1] - other[1], self[2] - other[2])

    def __mul__(self, other):
        if isinstance(other, (int, float)):
            return Vector(self[0] * other, self[1] * other, self[2] * other)

        return Vector(self[0] * other[0], self[1] * other[1], self[2] * other[2])

    def __truediv__(self, other):
        if isinstance(other, (int, float)):
            return Vector(self[0] / other, self[1] / other, self[2] / other)

        return Vector(self[0] / other[0], self[1] / other[1], self[2] / other[2])

    __div__ = __truediv__

    def length(self):
        return math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2])

    def normalize(self):
        l = self.length()
        if l == 0: return self
        return self / l

class BoundingBox (object):
    type = int

    def __init__(self, origin=(0, 0, 0), size=(0, 0, 0)):
        if isinstance(origin, BoundingBox):
            self._origin = origin._origin
            self._size = origin._size
        else:
            self._origin, self._size = Vector(*(self.type(a) for a in origin)), Vector(*(self.type(a) for a in size))

    def __repr__(self):
        return "BoundingBox({0}, {1})".format(self.origin, self.size)

    @property
    def origin(self):
        "The smallest position in the box"
        return self._origin

    @property
    def size(self):
        "The size of the box"
        return self._size

    @property
    def width(self):
        "The dimension along the X axis"
        return self._size.x

    @property
    def height(self):
        "The dimension along the Y axis"
        return self._size.y

    @property
    def length(self):
        "The dimension along the Z axis"
        return self._size.z

    @property
    def minx(self):
        return self.origin.x

    @property
    def miny(self):
        return self.origin.y

    @property
    def minz(self):
        return self.origin.z

    @property
    def maxx(self):
        return self.origin.x + self.size.x

    @property
    def maxy(self):
        return self.origin.y + self.size.y

    @property
    def maxz(self):
        return self.origin.z + self.size.z

    @property
    def maximum(self):
        "The largest point of the box; origin plus size."
        return self._origin + self._size

    @property
    def volume(self):
        "The volume of the box in blocks"
        return self.size.x * self.size.y * self.size.z

    @property
    def positions(self):
        """iterate through all of the positions within this selection box"""
        return itertools.product(
            xrange(self.minx, self.maxx),
            xrange(self.miny, self.maxy),
            xrange(self.minz, self.maxz)
        )

    def intersect(self, box):
        """
        Return a box containing the area self and box have in common. Box will have zero volume
         if there is no common area.
        """
        if (self.minx > box.maxx or self.maxx < box.minx or
            self.miny > box.maxy or self.maxy < box.miny or
            self.minz > box.maxz or self.maxz < box.minz):
            #Zero size intersection.
            return BoundingBox()

        origin = Vector(
            max(self.minx, box.minx),
            max(self.miny, box.miny),
            max(self.minz, box.minz),
        )
        maximum = Vector(
            min(self.maxx, box.maxx),
            min(self.maxy, box.maxy),
            min(self.maxz, box.maxz),
        )

        #print "Intersect of {0} and {1}: {2}".format(self, box, newbox)
        return BoundingBox(origin, maximum - origin)

    def union(self, box):
        """
        Return a box large enough to contain both self and box.
        """
        origin = Vector(
            min(self.minx, box.minx),
            min(self.miny, box.miny),
            min(self.minz, box.minz),
        )
        maximum = Vector(
            max(self.maxx, box.maxx),
            max(self.maxy, box.maxy),
            max(self.maxz, box.maxz),
        )
        return BoundingBox(origin, maximum - origin)

    def expand(self, dx, dy=None, dz=None):
        """
        Return a new box with boundaries expanded by dx, dy, dz.
        If only dx is passed, expands by dx in all dimensions.
        """
        if dz is None:
            dz = dx
        if dy is None:
            dy = dx

        origin = self.origin - (dx, dy, dz)
        size = self.size + (dx * 2, dy * 2, dz * 2)

        return BoundingBox(origin, size)

    def __contains__(self, pos):
        x, y, z = pos
        if x < self.minx or x >= self.maxx:
            return False
        if y < self.miny or y >= self.maxy:
            return False
        if z < self.minz or z >= self.maxz:
            return False

        return True

    def __cmp__(self, b):
        return cmp((self.origin, self.size), (b.origin, b.size))

    # --- Chunk positions ---

    @property
    def mincx(self):
        "The smallest chunk position contained in this box"
        return self.origin.x >> 4

    @property
    def mincz(self):
        "The smallest chunk position contained in this box"
        return self.origin.z >> 4

    @property
    def maxcx(self):
        "The largest chunk position contained in this box"
        return ((self.origin.x + self.size.x - 1) >> 4) + 1

    @property
    def maxcz(self):
        "The largest chunk position contained in this box"
        return ((self.origin.z + self.size.z - 1) >> 4) + 1

    def chunkBox(self, level):
        """Returns this box extended to the chunk boundaries of the given level"""
        box = self
        return BoundingBox((box.mincx << 4, 0, box.mincz << 4),
                           (box.maxcx - box.mincx << 4, level.Height, box.maxcz - box.mincz << 4))

    @property
    def chunkPositions(self):
        #iterate through all of the chunk positions within this selection box
        return itertools.product(xrange(self.mincx, self.maxcx), xrange(self.mincz, self.maxcz))

    @property
    def chunkCount(self):
        return (self.maxcx - self.mincx) * (self.maxcz - self.mincz)

    @property
    def isChunkAligned(self):
        return (self.origin.x & 0xf == 0) and (self.origin.z & 0xf == 0)

class FloatBox (BoundingBox):
    type = float
<|endoftext|>


<commit_before>from helpers import *
import org.bukkit.Material as Material

"""
remake of dicodes blockplacemods
"""

togPerm = "utils.toggle"

@hook.event("block.BlockPlaceEvent", "low")
def block_place(event):
    block     = event.getBlockPlaced()
    material  = block.getType()
    sender    = event.getPlayer()
    py_player = get_py_player(sender)
    if (material in (Material.WOOD_STEP, Material.STEP)) and py_player.slab_toggle and block.getData() < 8:
        block.setData(block.getData() + 8)
    elif (material == Material.CAULDRON) and py_player.cauldron_toggle:
        block.setData(block.getData() + 3)

def help(sender):
    msg(sender, "&a-=[&6BPM&a]=-")
    msg(sender, "&6Aliases for /toggle: \n &e/set, /setting and /config\n")
    msg(sender, "&6Available settings: \n &eSlab and Cauldron\n")
    msg(sender, "&6Slab: \n&eThe slab setting flips slabs to the top half \nof the block on placing them.\n")
    msg(sender, "&6Cauldron: \n&eThe cauldron setting fills cauldrons on placing them.\n")

@hook.command("toggle")
def toggle_command(sender, cmd, label, args):
    py_player = get_py_player(sender)
    if sender.hasPermission(togPerm) and sender.getWorld().getName() == "creative":
        if len(args) > 0:
            if str(args[0]) == "slab":
                if py_player.slab_toggle == True:
                    msg(sender, "&a Disabled automatically flipping slabs.")
                    py_player.slab_toggle = False
                else:
                    msg(sender, "&a Enabled automatically flipping slabs.")
                    py_player.slab_toggle = True
            elif str(args[0]) == "cauldron":
                if py_player.cauldron_toggle == True:
                    msg(sender, "&a Disabled automatically filling cauldrons.")
                    py_player.cauldron_toggle = False
                else:
                    msg(sender, "&a Enabled automatically filling cauldrons.")
                    py_player.cauldron_toggle = True
            else:
                    help(sender)
        else:
                help(sender)
    elif sender.getWorld() != "creative":
        msg(sender, "&aBPM doesn't work in this world.")
    else:
        msg(sender, "&aNo permission.")<commit_msg>added emptying water from cauldrons<commit_after>from helpers import *
import org.bukkit.Material as Material

"""
remake of dicodes blockplacemods
"""

togPerm = "utils.toggle"

@hook.event("block.BlockPlaceEvent", "low")
def block_place(event):
    block     = event.getBlockPlaced()
    material  = block.getType()
    sender    = event.getPlayer()
    py_player = get_py_player(sender)
    if (material in (Material.WOOD_STEP, Material.STEP)) and py_player.slab_toggle and block.getData() < 8:
        block.setData(block.getData() + 8)
    elif (material == Material.CAULDRON) and py_player.cauldron_toggle:
        block.setData(block.getData() + 3)

@hook.event("player.PlayerInteractEvent", "high")
def on_interact(event):
    block  = event.getClickedBlock()
    sender = event.getPlayer()
    py_player = get_py_player(sender)
    if str(event.getAction()) != "RIGHT_CLICK_BLOCK":
        return
    if block.getType() == Material.CAULDRON and py_player.cauldron_toggle:
        block.setData(block.getData() - 1 if block.getData() > 0 else 3)
    else:
        return

def help(sender):
    msg(sender, "&a-=[&6BPM&a]=-")
    msg(sender, "&6Aliases for /toggle: \n &e/set, /setting and /config\n")
    msg(sender, "&6Available settings: \n &eSlab and Cauldron\n")
    msg(sender, "&6Slab: \n&eThe slab setting flips slabs to the top half \nof the block on placing them.\n")
    msg(sender, "&6Cauldron: \n&eThe cauldron setting fills cauldrons on placing them.\n")

@hook.command("toggle")
def toggle_command(sender, cmd, label, args):
    py_player = get_py_player(sender)
    if sender.hasPermission(togPerm) and sender.getWorld().getName() == "creative":
        if len(args) > 0:
            if str(args[0]) == "slab":
                if py_player.slab_toggle == True:
                    msg(sender, "&a Disabled automatically flipping slabs.")
                    py_player.slab_toggle = False
                else:
                    msg(sender, "&a Enabled automatically flipping slabs.")
                    py_player.slab_toggle = True
            elif str(args[0]) == "cauldron":
                if py_player.cauldron_toggle == True:
                    msg(sender, "&a Disabled automatically filling cauldrons.")
                    py_player.cauldron_toggle = False
                else:
                    msg(sender, "&a Enabled automatically filling cauldrons.")
                    py_player.cauldron_toggle = True
            else:
                    help(sender)
        else:
                help(sender)
    elif sender.getWorld() != "creative":
        msg(sender, "&aBPM doesn't work in this world.")
    else:
        msg(sender, "&aNo permission.")

<|endoftext|>


<commit_before>"""Contains a Node class which implements an AVL binary search tree.

Each node can be considered a binary search tree and has the usual
methods to insert, delete, and check membership of nodes. By default,
the insert and delete methods will perform self-balancing consistent
with an AVL tree. This behavior can be suppressed by passing the optional
'balanced=False' keyword argument to the insert or delete methods.

The class also supports four traversal methods which return generators:

- in_order
- pre_order
- post_order
- breadth_first.

Additionally, methods are included to help visualize the tree structure.
get_dot returns DOT source code, suitable for use with programs such as
Graphviz (http://graphviz.readthedocs.org/en/stable/index.html), and
save_render saves a rendering of the tree structure to the file system.
Passing the optional 'render=True' keyword argument to the insert and
delete methods will automatically save a render to disk upon execution.

Finally, the helper methods 'create_best_case' and 'create_worst_case'
facilitate creation of tree composeds of _n_ integers.

This module was completed with reference to the following:

'Binary Search Tree libary in Python'
(http://www.laurentluce.com/posts/binary-search-tree-library-in-python/)
by Laurent Luce.

'How to Balance your Binary Search Trees - AVL Trees'
(https://triangleinequality.wordpress.com/2014/07/15/how-to-balance-your-binary-search-trees-avl-trees/)

'The AVL Tree Rotations Tutorial'
(http://pages.cs.wisc.edu/~paton/readings/liblitVersion/AVL-Tree-Rotations.pdf)
by John Hargrove

"""
from __future__ import print_function
from __future__ import unicode_literals
import random

from queue import Queue

class Node(object):
    """A class for a binary search tree node."""
    def __init__(self, val=None, parent=None):
        self.val = val
        self.parent = parent
        self.left = None
        self.right = None

    def __repr__(self):
        return '<BST: ({})>'.format(self.val)

    def __str__(self):
        return '{}'.format(self.val)

    def __len__(self):
        return self.size()

    def __iter__(self):
        return self.in_order()

    def __add__(self, other):
        for item in other:
            self.insert(item)

    def __sub__(self, other):
        for item in other:
            self.delete(item)

    def insert(self, val, balanced=True, render=False):
        """Insert a node with a value into the tree.

        If val is already present, it will be ignored.

        args:
            val: the value to insert
            balanced: performs AVL self-balancing if set to True
            render: automatically saves a render to disk if set to True
        """
        if self.val is not None:
            if val == self.val:
                return None
            if val < self.val:
                if self.left is None:
                    self.left = Node(val, self)
                    if balanced:
                        self.left._self_balance()
                else:
                    self.left.insert(val, balanced, render)
            elif val > self.val:
                if self.right is None:
                    self.right = Node(val, self)
                    if balanced:
                        self.right._self_balance()
                else:
                    self.right.insert(val, balanced, render)
        else:
            self.val = val
        if render and self.parent is None:
            self.save_render()

    def delete(self, val, balanced=True, render=False):
        """Delete a node matching value and reorganize tree as needed.

        If the matched node is the only node in the tree, only its value
        will be deleted.

        args:
            val: the value of the node to delete
            balanced: performs AVL self-balancing if set to True
            render: automatically saves a render to disk if set to True
        """
        node = self.lookup(val)
        parent = node.parent
        if node is not None:
            children_count = node._children_count()
            if children_count == 0:
                if parent:
                    if parent.left is node:
                        parent.left = None
                    else:
                        parent.right = None
                    if balanced:
                        parent._self_balance()
                else:
                    self.val = None
            elif children_count == 1:
                if node.left:
                    child = node.left
                else:
                    child = node.right
                if parent:
                    if parent.left is node:
                        parent.left = child
                    else:
                        parent.right = child
                    child.parent = parent
                    if balanced:
                        child._self_balance()
                else:
                    self.left = child.left
                    self.right = child.right
                    try:
                        self.right.parent = self
                        self.left.parent = self
                    except AttributeError:
                        pass
                    self.val = child.val
                    if balanced:
                        self._self_balance()
            else:
                parent = node
                successor = node.right
                while successor.left:
                    parent = successor
                    successor = successor.left
                node.val = successor.val
                if parent.left == successor:
                    parent.left = successor.right
                    try:
                        parent.left.parent = parent
                    except AttributeError:
                        pass
                    parent._self_balance()
                else:
                    parent.right = successor.right
                    try:
                        parent.right.parent = parent
                    except AttributeError:
                        pass
                    if balanced:
                        parent._self_balance()
        if render and self.parent is None:
            self.save_render()

    def contains(self, val):
        """Check tree for node with given value.

        args:
            val: the value to check for

        returns: True if val is in the tree, False if not.
        """
        if val == self.val:
            return True
        elif val < self.val:
            if self.left is None:
                return False
            return self.left.contains(val)
        elif val > self.val:
            if self.right is None:
                return False
            return self.right.contains(val)

    def lookup(self, val):
        """Find a node by value and return that node.

        args:
            val: the value to search by

        returns: a node
        """
        if val < self.val:
            if self.left is None:
                return None, None
            return self.left.lookup(val)
        elif val > self.val:
            if self.right is None:
                return None, None
            return self.right.lookup(val)
        else:
            return self

    def size(self):
        """Return the total number of nodes in the tree.

        returns: integer of total node; 0 if empty
        """
        if self.val is None:
            return 0
        left_size = self.left.size() if self.left is not None else 0
        right_size = self.right.size() if self.right is not None else 0
        return left_size + right_size + 1

    def depth(self):
        """Return an the total number of levels in the tree.

        If there is one value, the depth should be 1, if two values it'll be 2,
        if three values it may be 2 or three, depending, etc.

        returns: integer of level number
        """
        left_depth = self.left.depth() if self.left is not None else 0
        right_depth = self.right.depth() if self.right is not None else 0
        return max(left_depth, right_depth) + 1

    def balance(self):
        """Return a positive or negative number representing tree balance.

        Trees higher on the left than the right should return a positive value,
        trees higher on the right than the left should return a negative value.
        An ideally-balanced tree should return 0.

        returns: integer
        """
        left_depth = self.left.depth() if self.left is not None else 0
        right_depth = self.right.depth() if self.right is not None else 0
        return left_depth - right_depth

    def _is_left(self):
        """Check nodes relationship to parent.

        returns:
            - True if node is left child of parent
            - False if node is right childe of parent
            - None if node has no parent
        """
        if self.parent is None:
            return None
        else:
            return self is self.parent.left

    def _rotate_right(self):
        """Perform a single right tree rotation."""
        pivot = self.left
        if pivot is None:
            return
        self.val, pivot.val = pivot.val, self.val
        self.left = pivot.left
        if self.left is not None:
            self.left.parent = self
        pivot.left = pivot.right
        if pivot.left is not None:
            pivot.left.parent = pivot
        pivot.right = self.right
        if pivot.right is not None:
            pivot.right.parent = pivot
        self.right, pivot.parent = pivot, self

    def _rotate_left(self):
        """Perform a single left tree rotation."""
        pivot = self.right
        if pivot is None:
            return
        self.val, pivot.val = pivot.val, self.val
        self.right = pivot.right
        if self.right is not None:
            self.right.parent = self
        pivot.right = pivot.left
        if pivot.right is not None:
            pivot.right.parent = pivot
        pivot.left = self.left
        if pivot.left is not None:
            pivot.left.parent = pivot
        self.left, pivot.parent = pivot, self

    def _self_balance(self):
        """Balance the subtree from given node."""
        balance = self.balance()
        # Tree is left heavy
        if balance == 2:
            if self.left.balance() <= -1:
                # Double Right
                self.left._rotate_left()
            # Single Right
            self._rotate_right()
            if self.parent is not None:
                self.parent._self_balance()

        # Tree is right heavy
        elif balance == -2:
            if self.right.balance() >= 1:
                # Double Left
                self.right._rotate_right()
            # Single Left
            self._rotate_left()
            if self.parent is not None:
                self.parent._self_balance()
        else:
            if self.parent is not None:
                self.parent._self_balance()

    def in_order(self):
        """Return a generator with tree values from in-order traversal"""
        stack = []
        node = self
        while stack or node:
            if node:
                stack.append(node)
                node = node.left
            else:
                node = stack.pop()
                yield node.val
                node = node.right

    def pre_order(self):
        """Return a generator with tree values from pre-order traversal"""
        stack = []
        node = self
        while stack or node:
            if node:
                yield node.val
                stack.append(node)
                node = node.left
            else:
                node = stack.pop()
                node = node.right

    def post_order(self):
        """Return a generator with tree values from post-order traversal"""
        stack = []
        node = self
        last = None
        while stack or node:
            if node:
                stack.append(node)
                node = node.left
            else:
                peek = stack[-1]
                if peek.right is not None and last != peek.right:
                    node = peek.right
                else:
                    yield peek.val
                    last = stack.pop()
                    node = None

    def breadth_first(self):
        """Return a generator with tree values from breadth first traversal"""
        q = Queue()
        q.enqueue(self)
        while q.size() > 0:
            node = q.dequeue()
            yield node.val
            if node.left:
                q.enqueue(node.left)
            if node.right:
                q.enqueue(node.right)

    def _children_count(self):
        """Return a node's number of children."""
        cnt = 0
        if self.left:
            cnt += 1
        if self.right:
            cnt += 1
        return cnt

    def get_dot(self):
        """Return the tree with root as a dot graph for visualization."""
        return "digraph G{\n%s}" % ("" if self.val is None else (
            "\t%s;\n%s\n" % (
                self.val,
                "\n".join(self._get_dot())
            )
        ))

    def _get_dot(self):
        """recursively prepare a dot graph entry for this node."""
        if self.left is not None:
            yield "\t%s -> %s;" % (self.val, self.left.val)
            for i in self.left._get_dot():
                yield i
        elif self.right is not None:
            r = random.randint(0, 1e9)
            yield "\tnull%s [shape=point];" % r
            yield "\t%s -> null%s;" % (self.val, r)
        if self.right is not None:
            yield "\t%s -> %s;" % (self.val, self.right.val)
            for i in self.right._get_dot():
                yield i
        elif self.left is not None:
            r = random.randint(0, 1e9)
            yield "\tnull%s [shape=point];" % r
            yield "\t%s -> null%s;" % (self.val, r)

    def save_render(self, savefile="tree.gv"):
        """Render and save a represntation of the tree.

        args:
            savefile: the optional filename
        """
        from graphviz import Source
        src = Source(self.get_dot())
        path = 'graphviz/{}'.format(savefile)
        src.render(path)

    @classmethod
    def _sorted_list_to_bst(cls, items=[], start=None, end=None, parent=None):
        """Create a balanced binary search tree from sorted list.

        args:
            items: the sorted list of items to insert into tree
            start: the start of the list
            end: the end of the list

        returns: a balanced binary search tree (node)
        """
        if start > end:
            return None
        mid = start + (end - start) // 2
        node = Node(items[mid], parent)
        node.left = cls._sorted_list_to_bst(items, start, mid - 1, node)
        node.right = cls._sorted_list_to_bst(items, mid + 1, end, node)
        return node

    @classmethod
    def create_best_case(cls, n):
        """Create a balanced binary search tree from a given range.

        args:
            n: the range of integers to insert into the tree

        returns: a balanced binary search tree (node)
        """
        return cls._sorted_list_to_bst(range(n), 0, n - 1)

    @classmethod
    def create_worst_case(cls, n):
        """Create an unbalanced binary search tree from a given range.

        The tree will be one long linear branch to the right.

        args:
            n: the range of integers to add to the tree

        returns: a (very) unbalanced binary search tree (node)
        """
        node = Node(0)
        parent = node
        for i in range(1, n):
            parent.right = Node(i, parent)
            parent = parent.right
        return node

if __name__ == '__main__':
    from timeit import Timer

    """Document the best and worst cases for searching for a value in the tree.
        The worst case consists of a tree with one long linear branch.
        The best case is a perfectly balanced tree.
    """

    SIZE = 900
    LOOKUP = 900

    worst = Node.create_worst_case(SIZE)
    best = Node.create_best_case(SIZE)

    worst_case = Timer(
        'worst.contains({})'.format(LOOKUP, SIZE), 'from __main__ import worst'
    ).timeit(1000)

    best_case = Timer(
        'best.contains({})'.format(LOOKUP), 'from __main__ import best'
    ).timeit(1000)

    print(
        "\nLookup Time Comparison: Best and Worst Case\n"
        "\nGiven a tree of {n} items, find a node with value of {l}.\n"
        .format(n=SIZE, l=LOOKUP)
    )

    print(
        "Worst case, with tree balanced at {b}.\n"
        "Time: {t}\n"
        .format(b=worst.balance(), t=worst_case)
    )
    print(
        "Best case,  with tree balanced at {b}.\n"
        "Time: {t}\n"
        .format(b=best.balance(), t=best_case)
    )
<commit_msg>Simplify bst.py rotation algorithms<commit_after>"""Contains a Node class which implements an AVL binary search tree.

Each node can be considered a binary search tree and has the usual
methods to insert, delete, and check membership of nodes. By default,
the insert and delete methods will perform self-balancing consistent
with an AVL tree. This behavior can be suppressed by passing the optional
'balanced=False' keyword argument to the insert or delete methods.

The class also supports four traversal methods which return generators:

- in_order
- pre_order
- post_order
- breadth_first.

Additionally, methods are included to help visualize the tree structure.
get_dot returns DOT source code, suitable for use with programs such as
Graphviz (http://graphviz.readthedocs.org/en/stable/index.html), and
save_render saves a rendering of the tree structure to the file system.
Passing the optional 'render=True' keyword argument to the insert and
delete methods will automatically save a render to disk upon execution.

Finally, the helper methods 'create_best_case' and 'create_worst_case'
facilitate creation of tree composeds of _n_ integers.

This module was completed with reference to the following:

'Binary Search Tree libary in Python'
(http://www.laurentluce.com/posts/binary-search-tree-library-in-python/)
by Laurent Luce.

'How to Balance your Binary Search Trees - AVL Trees'
(https://triangleinequality.wordpress.com/2014/07/15/how-to-balance-your-binary-search-trees-avl-trees/)

'The AVL Tree Rotations Tutorial'
(http://pages.cs.wisc.edu/~paton/readings/liblitVersion/AVL-Tree-Rotations.pdf)
by John Hargrove

"""
from __future__ import print_function
from __future__ import unicode_literals
import random

from queue import Queue

class Node(object):
    """A class for a binary search tree node."""
    def __init__(self, val=None, parent=None):
        self.val = val
        self.parent = parent
        self.left = None
        self.right = None

    def __repr__(self):
        return '<BST: ({})>'.format(self.val)

    def __str__(self):
        return '{}'.format(self.val)

    def __len__(self):
        return self.size()

    def __iter__(self):
        return self.in_order()

    def __add__(self, other):
        for item in other:
            self.insert(item)

    def __sub__(self, other):
        for item in other:
            self.delete(item)

    def insert(self, val, balanced=True, render=False):
        """Insert a node with a value into the tree.

        If val is already present, it will be ignored.

        args:
            val: the value to insert
            balanced: performs AVL self-balancing if set to True
            render: automatically saves a render to disk if set to True
        """
        if self.val is not None:
            if val == self.val:
                return None
            if val < self.val:
                if self.left is None:
                    self.left = Node(val, self)
                    if balanced:
                        self.left._self_balance()
                else:
                    self.left.insert(val, balanced, render)
            elif val > self.val:
                if self.right is None:
                    self.right = Node(val, self)
                    if balanced:
                        self.right._self_balance()
                else:
                    self.right.insert(val, balanced, render)
        else:
            self.val = val
        if render and self.parent is None:
            self.save_render()

    def delete(self, val, balanced=True, render=False):
        """Delete a node matching value and reorganize tree as needed.

        If the matched node is the only node in the tree, only its value
        will be deleted.

        args:
            val: the value of the node to delete
            balanced: performs AVL self-balancing if set to True
            render: automatically saves a render to disk if set to True
        """
        node = self.lookup(val)
        parent = node.parent
        if node is not None:
            children_count = node._children_count()
            if children_count == 0:
                if parent:
                    if parent.left is node:
                        parent.left = None
                    else:
                        parent.right = None
                    if balanced:
                        parent._self_balance()
                else:
                    self.val = None
            elif children_count == 1:
                if node.left:
                    child = node.left
                else:
                    child = node.right
                if parent:
                    if parent.left is node:
                        parent.left = child
                    else:
                        parent.right = child
                    child.parent = parent
                    if balanced:
                        child._self_balance()
                else:
                    self.left = child.left
                    self.right = child.right
                    try:
                        self.right.parent = self
                        self.left.parent = self
                    except AttributeError:
                        pass
                    self.val = child.val
                    if balanced:
                        self._self_balance()
            else:
                parent = node
                successor = node.right
                while successor.left:
                    parent = successor
                    successor = successor.left
                node.val = successor.val
                if parent.left == successor:
                    parent.left = successor.right
                    try:
                        parent.left.parent = parent
                    except AttributeError:
                        pass
                    parent._self_balance()
                else:
                    parent.right = successor.right
                    try:
                        parent.right.parent = parent
                    except AttributeError:
                        pass
                    if balanced:
                        parent._self_balance()
        if render and self.parent is None:
            self.save_render()

    def contains(self, val):
        """Check tree for node with given value.

        args:
            val: the value to check for

        returns: True if val is in the tree, False if not.
        """
        if val == self.val:
            return True
        elif val < self.val:
            if self.left is None:
                return False
            return self.left.contains(val)
        elif val > self.val:
            if self.right is None:
                return False
            return self.right.contains(val)

    def lookup(self, val):
        """Find a node by value and return that node.

        args:
            val: the value to search by

        returns: a node
        """
        if val < self.val:
            if self.left is None:
                return None, None
            return self.left.lookup(val)
        elif val > self.val:
            if self.right is None:
                return None, None
            return self.right.lookup(val)
        else:
            return self

    def size(self):
        """Return the total number of nodes in the tree.

        returns: integer of total node; 0 if empty
        """
        if self.val is None:
            return 0
        left_size = self.left.size() if self.left is not None else 0
        right_size = self.right.size() if self.right is not None else 0
        return left_size + right_size + 1

    def depth(self):
        """Return an the total number of levels in the tree.

        If there is one value, the depth should be 1, if two values it'll be 2,
        if three values it may be 2 or three, depending, etc.

        returns: integer of level number
        """
        left_depth = self.left.depth() if self.left is not None else 0
        right_depth = self.right.depth() if self.right is not None else 0
        return max(left_depth, right_depth) + 1

    def balance(self):
        """Return a positive or negative number representing tree balance.

        Trees higher on the left than the right should return a positive value,
        trees higher on the right than the left should return a negative value.
        An ideally-balanced tree should return 0.

        returns: integer
        """
        left_depth = self.left.depth() if self.left is not None else 0
        right_depth = self.right.depth() if self.right is not None else 0
        return left_depth - right_depth

    def _is_left(self):
        """Check nodes relationship to parent.

        returns:
            - True if node is left child of parent
            - False if node is right childe of parent
            - None if node has no parent
        """
        if self.parent is None:
            return None
        else:
            return self is self.parent.left

    def _rotate_right(self):
        """Perform a single right tree rotation."""
        pivot = self.left
        if pivot is None:
            return
        self.val, pivot.val = pivot.val, self.val
        self.left = pivot.left
        if self.left is not None:
            self.left.parent = self
        pivot.left = pivot.right
        pivot.right = self.right
        if pivot.right is not None:
            pivot.right.parent = pivot
        self.right = pivot

    def _rotate_left(self):
        """Perform a single left tree rotation."""
        pivot = self.right
        if pivot is None:
            return
        self.val, pivot.val = pivot.val, self.val
        self.right = pivot.right
        if self.right is not None:
            self.right.parent = self
        pivot.right = pivot.left
        pivot.left = self.left
        if pivot.left is not None:
            pivot.left.parent = pivot
        self.left = pivot

    def _self_balance(self):
        """Balance the subtree from given node."""
        balance = self.balance()
        # Tree is left heavy
        if balance == 2:
            if self.left.balance() <= -1:
                # Double Right
                self.left._rotate_left()
            # Single Right
            self._rotate_right()
            if self.parent is not None:
                self.parent._self_balance()

        # Tree is right heavy
        elif balance == -2:
            if self.right.balance() >= 1:
                # Double Left
                self.right._rotate_right()
            # Single Left
            self._rotate_left()
            if self.parent is not None:
                self.parent._self_balance()
        else:
            if self.parent is not None:
                self.parent._self_balance()

    def in_order(self):
        """Return a generator with tree values from in-order traversal"""
        stack = []
        node = self
        while stack or node:
            if node:
                stack.append(node)
                node = node.left
            else:
                node = stack.pop()
                yield node.val
                node = node.right

    def pre_order(self):
        """Return a generator with tree values from pre-order traversal"""
        stack = []
        node = self
        while stack or node:
            if node:
                yield node.val
                stack.append(node)
                node = node.left
            else:
                node = stack.pop()
                node = node.right

    def post_order(self):
        """Return a generator with tree values from post-order traversal"""
        stack = []
        node = self
        last = None
        while stack or node:
            if node:
                stack.append(node)
                node = node.left
            else:
                peek = stack[-1]
                if peek.right is not None and last != peek.right:
                    node = peek.right
                else:
                    yield peek.val
                    last = stack.pop()
                    node = None

    def breadth_first(self):
        """Return a generator with tree values from breadth first traversal"""
        q = Queue()
        q.enqueue(self)
        while q.size() > 0:
            node = q.dequeue()
            yield node.val
            if node.left:
                q.enqueue(node.left)
            if node.right:
                q.enqueue(node.right)

    def _children_count(self):
        """Return a node's number of children."""
        cnt = 0
        if self.left:
            cnt += 1
        if self.right:
            cnt += 1
        return cnt

    def get_dot(self):
        """Return the tree with root as a dot graph for visualization."""
        return "digraph G{\n%s}" % ("" if self.val is None else (
            "\t%s;\n%s\n" % (
                self.val,
                "\n".join(self._get_dot())
            )
        ))

    def _get_dot(self):
        """recursively prepare a dot graph entry for this node."""
        if self.left is not None:
            yield "\t%s -> %s;" % (self.val, self.left.val)
            for i in self.left._get_dot():
                yield i
        elif self.right is not None:
            r = random.randint(0, 1e9)
            yield "\tnull%s [shape=point];" % r
            yield "\t%s -> null%s;" % (self.val, r)
        if self.right is not None:
            yield "\t%s -> %s;" % (self.val, self.right.val)
            for i in self.right._get_dot():
                yield i
        elif self.left is not None:
            r = random.randint(0, 1e9)
            yield "\tnull%s [shape=point];" % r
            yield "\t%s -> null%s;" % (self.val, r)

    def save_render(self, savefile="tree.gv"):
        """Render and save a represntation of the tree.

        args:
            savefile: the optional filename
        """
        from graphviz import Source
        src = Source(self.get_dot())
        path = 'graphviz/{}'.format(savefile)
        src.render(path)

    @classmethod
    def _sorted_list_to_bst(cls, items=[], start=None, end=None, parent=None):
        """Create a balanced binary search tree from sorted list.

        args:
            items: the sorted list of items to insert into tree
            start: the start of the list
            end: the end of the list

        returns: a balanced binary search tree (node)
        """
        if start > end:
            return None
        mid = start + (end - start) // 2
        node = Node(items[mid], parent)
        node.left = cls._sorted_list_to_bst(items, start, mid - 1, node)
        node.right = cls._sorted_list_to_bst(items, mid + 1, end, node)
        return node

    @classmethod
    def create_best_case(cls, n):
        """Create a balanced binary search tree from a given range.

        args:
            n: the range of integers to insert into the tree

        returns: a balanced binary search tree (node)
        """
        return cls._sorted_list_to_bst(range(n), 0, n - 1)

    @classmethod
    def create_worst_case(cls, n):
        """Create an unbalanced binary search tree from a given range.

        The tree will be one long linear branch to the right.

        args:
            n: the range of integers to add to the tree

        returns: a (very) unbalanced binary search tree (node)
        """
        node = Node(0)
        parent = node
        for i in range(1, n):
            parent.right = Node(i, parent)
            parent = parent.right
        return node

if __name__ == '__main__':
    from timeit import Timer

    """Document the best and worst cases for searching for a value in the tree.
        The worst case consists of a tree with one long linear branch.
        The best case is a perfectly balanced tree.
    """

    SIZE = 900
    LOOKUP = 900

    worst = Node.create_worst_case(SIZE)
    best = Node.create_best_case(SIZE)

    worst_case = Timer(
        'worst.contains({})'.format(LOOKUP, SIZE), 'from __main__ import worst'
    ).timeit(1000)

    best_case = Timer(
        'best.contains({})'.format(LOOKUP), 'from __main__ import best'
    ).timeit(1000)

    print(
        "\nLookup Time Comparison: Best and Worst Case\n"
        "\nGiven a tree of {n} items, find a node with value of {l}.\n"
        .format(n=SIZE, l=LOOKUP)
    )

    print(
        "Worst case, with tree balanced at {b}.\n"
        "Time: {t}\n"
        .format(b=worst.balance(), t=worst_case)
    )
    print(
        "Best case,  with tree balanced at {b}.\n"
        "Time: {t}\n"
        .format(b=best.balance(), t=best_case)
    )
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Car class for the DriveIt Gym environment.
@author: Jean-Claude Manoli
"""

import math
import numpy as np
from numpy import cos, sin, pi
from utils import *
from part import *
from gym.envs.classic_control import rendering

steer_actions =    [ 0.,  1., -1.,  0.,  1., -1.,  0.,  1., -1.]
throttle_actions = [ 0.,  0.,  0.,  1.,  1.,  1., -1., -1., -1.]

class CarSpecifications():
    car_width = 0.12
    car_length = 0.24
    steer_step = 0.1
    throttle_step = 0.1
    K_max = 4.5
    max_accel = 10.0

    def __init__(self, v_max=2.5):
        self.v_max = v_max

class Car(RectangularPart):

    breadcrumb = None

    def __init__(self, color=Color.black, specs=CarSpecifications(), trail_length=180, *args, **kwargs):
        RectangularPart.__init__(self, specs.car_length, specs.car_width)
        self.specs = specs
        self.color = color
        self.trail_length = trail_length
        self.dist_sensors = []
        self.reset(*args, **kwargs)

    def add_dist_sensor(self, sensor, x, y, theta):
        self.dist_sensors.append(sensor)
        self.add_part(sensor, x, y, theta)

    def reset(self, x=0.0, y=0.0, theta=0.0, steer=0.0, throttle=0.0, odometer=0.0, v=None):
        if v is None:
            v = self.specs.v_max * throttle
        K = self.specs.K_max * steer

        self.set_position(x, y, theta)
        self.state = (steer, throttle, odometer, v, K)
        if self.breadcrumb != None:
            self.breadcrumb.v.clear()

        return x, y, theta, steer, throttle, odometer, v, K

    def _dsdt(s, t, a, K_dot):
        '''
        Computes derivatives of state parameters.
        '''
        x, y, theta, v, K, d = s
        x_dot = v * cos(theta)
        y_dot = v * sin(theta)
        theta_dot = v * K
        return x_dot, y_dot, theta_dot, a, K_dot, v

    def _move(x, y, theta, v, K, d, a, K_dot, dt):
        s = x, y, theta, v, K, d
        I = rk4(Car._dsdt, s, [0.0, dt], a, K_dot)
        x, y, theta, v, K, d = I[1]
        theta = canonical_angle(theta)
        return x, y, theta, v, K, d

    def reset_odometer(self, value):
        steer, throttle, d, v, K = self.state
        self.state = (steer, throttle, value, v, K)

    def step(self, action, dt):
        '''
        Executes the specified action and computes the new state.
        '''

        # initial state
        x_, y_, theta_ = self.get_position()
        steer_, throttle_, d_, v_, K_ = self.state

        # action
        ds = steer_actions[action] * self.specs.steer_step
        steer = max(-1.0, min(1.0, steer_ + ds))
        K = self.specs.K_max * steer

        dp = throttle_actions[action] * self.specs.throttle_step
        throttle = Car._safe_throttle_move(steer, throttle_, dp)

        deltav = self.specs.v_max * throttle - v_
        dvmax = self.specs.max_accel * dt
        if abs(deltav) > dvmax:
            deltav = math.copysign(dvmax, deltav)
        v = v_ + deltav

        a = (v - v_) / dt
        K_dot = (K - K_) / dt

        # get new state
        x, y, theta, _, _, d = Car._move(x_, y_, theta_, v_, K_, d_, a, K_dot, dt)

        self.set_position(x, y, theta)
        self.state = (steer, throttle, d, v, K)

        return x, y, theta, steer, throttle, d, v, K

    def detect_collision(self, cars):
        for car in cars:
            if car != self:

                if car.is_collided(self.front_left) \
                or car.is_collided(self.front_right):
                    return car

                if self.is_collided(car.back_left) \
                or self.is_collided(car.back_right):
                    return car

        return None

    def get_velocity(self):
        v = self.state[3]
        th = self._position[2]
        return v, th

    def set_velocity(self, v):
        steer, throttle, d, _, K = self.state
        self.state = steer, throttle, d, v, K

    def _safe_throttle_move(steer, throttle, desired_change):
        '''
        Moves the throttle by the desired amout or according to the safe speed limit.
        '''
        safe = Car._safe_throttle(steer)
        if throttle + desired_change > safe:
            return safe
        else:
            return max(0.0, min(1.0, throttle + desired_change))

    def _safe_throttle(steer):
        '''
        Gets the safe throttle value based on the specified steering.
        '''
        return min(1.0, 1.0 - abs(steer) / 2.0)

    def init_rendering(self, viewer):

        self.steering_wheel = SteeringWheel()
        self.add_part(self.steering_wheel, 0.065, 0.0, 0.0)
        self.breadcrumb = rendering.PolyLine([], close=False)
        self.breadcrumb._color.vec4 = Color.set_alpha(self.color, 0.5);
        viewer.add_geom(self.breadcrumb)

    def get_geometry(self):

        l = -self.length / 2.0
        r = self.length / 2.0
        t = self.width / 2.0
        b = -self.width / 2.0

        body = rendering.FilledPolygon([(l, b), (l, t), (r, t), (r, b)])
        body.set_color(1, 1, 1)

        d = 0.015
        sensor = rendering.FilledPolygon([(-d, -d), (-d, +d), (+d, +d), (+d, -d)])
        sensor.set_color(1, 0, 0)

        bumpers = rendering.PolyLine([(l, b), (l, t), (r, t), (r, b)], close=True)
        bumpers.set_linewidth(3)
        bumpers._color.vec4 = self.color

        return [body, sensor, bumpers]

    def render(self, viewer):

        self.steering_wheel.set_rotation(self.state[0] * right_angle)
        x, y, theta = self.get_position()
        self.breadcrumb.v.append((x, y))
        if len(self.breadcrumb.v) > self.trail_length:
            self.breadcrumb.v.pop(0)

        Part.render(self, viewer)

class SteeringWheel(Part):
    def get_geometry(self):
        steer = rendering.PolyLine([(-0.035, 0.0), (0.035, 0.0)], close=False)
        steer.set_linewidth(3)
        steer.set_color(0, 0, 255)
        return [steer]

<commit_msg>Make it harder to control the car.<commit_after># -*- coding: utf-8 -*-
"""
Car class for the DriveIt Gym environment.
@author: Jean-Claude Manoli
"""

import math
import numpy as np
from numpy import cos, sin, pi
from utils import *
from part import *
from gym.envs.classic_control import rendering

steer_actions =    [ 0.,  1., -1.,  0.,  1., -1.,  0.,  1., -1.]
throttle_actions = [ 0.,  0.,  0.,  1.,  1.,  1., -1., -1., -1.]

class CarSpecifications():
    car_width = 0.12
    car_length = 0.24
    steer_step = 0.05
    throttle_step = 0.05
    K_max = 4.5
    max_accel = 10.0

    def __init__(self, v_max=2.5):
        self.v_max = v_max

class Car(RectangularPart):

    breadcrumb = None

    def __init__(self, color=Color.black, specs=CarSpecifications(), trail_length=180, *args, **kwargs):
        RectangularPart.__init__(self, specs.car_length, specs.car_width)
        self.specs = specs
        self.color = color
        self.trail_length = trail_length
        self.dist_sensors = []
        self.reset(*args, **kwargs)

    def add_dist_sensor(self, sensor, x, y, theta):
        self.dist_sensors.append(sensor)
        self.add_part(sensor, x, y, theta)

    def reset(self, x=0.0, y=0.0, theta=0.0, steer=0.0, throttle=0.0, odometer=0.0, v=None):
        if v is None:
            v = self.specs.v_max * throttle
        K = self.specs.K_max * steer

        self.set_position(x, y, theta)
        self.state = (steer, throttle, odometer, v, K)
        if self.breadcrumb != None:
            self.breadcrumb.v.clear()

        return x, y, theta, steer, throttle, odometer, v, K

    def _dsdt(s, t, a, K_dot):
        '''
        Computes derivatives of state parameters.
        '''
        x, y, theta, v, K, d = s
        x_dot = v * cos(theta)
        y_dot = v * sin(theta)
        theta_dot = v * K
        return x_dot, y_dot, theta_dot, a, K_dot, v

    def _move(x, y, theta, v, K, d, a, K_dot, dt):
        s = x, y, theta, v, K, d
        I = rk4(Car._dsdt, s, [0.0, dt], a, K_dot)
        x, y, theta, v, K, d = I[1]
        theta = canonical_angle(theta)
        return x, y, theta, v, K, d

    def reset_odometer(self, value):
        steer, throttle, d, v, K = self.state
        self.state = (steer, throttle, value, v, K)

    def step(self, action, dt):
        '''
        Executes the specified action and computes the new state.
        '''

        # initial state
        x_, y_, theta_ = self.get_position()
        steer_, throttle_, d_, v_, K_ = self.state

        # action
        ds = steer_actions[action] * self.specs.steer_step
        steer = max(-1.0, min(1.0, steer_ + ds))
        K = self.specs.K_max * steer

        dp = throttle_actions[action] * self.specs.throttle_step
        throttle = Car._safe_throttle_move(steer, throttle_, dp)

        deltav = self.specs.v_max * throttle - v_
        dvmax = self.specs.max_accel * dt
        if abs(deltav) > dvmax:
            deltav = math.copysign(dvmax, deltav)
        v = v_ + deltav

        a = (v - v_) / dt
        K_dot = (K - K_) / dt

        # get new state
        x, y, theta, _, _, d = Car._move(x_, y_, theta_, v_, K_, d_, a, K_dot, dt)

        self.set_position(x, y, theta)
        self.state = (steer, throttle, d, v, K)

        return x, y, theta, steer, throttle, d, v, K

    def detect_collision(self, cars):
        for car in cars:
            if car != self:

                if car.is_collided(self.front_left) \
                or car.is_collided(self.front_right):
                    return car

                if self.is_collided(car.back_left) \
                or self.is_collided(car.back_right):
                    return car

        return None

    def get_velocity(self):
        v = self.state[3]
        th = self._position[2]
        return v, th

    def set_velocity(self, v):
        steer, throttle, d, _, K = self.state
        self.state = steer, throttle, d, v, K

    def _safe_throttle_move(steer, throttle, desired_change):
        '''
        Moves the throttle by the desired amout or according to the safe speed limit.
        '''
        safe = Car._safe_throttle(steer)
        if throttle + desired_change > safe:
            return safe
        else:
            return max(0.0, min(1.0, throttle + desired_change))

    def _safe_throttle(steer):
        '''
        Gets the safe throttle value based on the specified steering.
        '''
        return min(1.0, 1.0 - abs(steer) / 2.0)

    def init_rendering(self, viewer):

        self.steering_wheel = SteeringWheel()
        self.add_part(self.steering_wheel, 0.065, 0.0, 0.0)
        self.breadcrumb = rendering.PolyLine([], close=False)
        self.breadcrumb._color.vec4 = Color.set_alpha(self.color, 0.5);
        viewer.add_geom(self.breadcrumb)

    def get_geometry(self):

        l = -self.length / 2.0
        r = self.length / 2.0
        t = self.width / 2.0
        b = -self.width / 2.0

        body = rendering.FilledPolygon([(l, b), (l, t), (r, t), (r, b)])
        body.set_color(1, 1, 1)

        d = 0.015
        sensor = rendering.FilledPolygon([(-d, -d), (-d, +d), (+d, +d), (+d, -d)])
        sensor.set_color(1, 0, 0)

        bumpers = rendering.PolyLine([(l, b), (l, t), (r, t), (r, b)], close=True)
        bumpers.set_linewidth(3)
        bumpers._color.vec4 = self.color

        return [body, sensor, bumpers]

    def render(self, viewer):

        self.steering_wheel.set_rotation(self.state[0] * right_angle)
        x, y, theta = self.get_position()
        self.breadcrumb.v.append((x, y))
        if len(self.breadcrumb.v) > self.trail_length:
            self.breadcrumb.v.pop(0)

        Part.render(self, viewer)

class SteeringWheel(Part):
    def get_geometry(self):
        steer = rendering.PolyLine([(-0.035, 0.0), (0.035, 0.0)], close=False)
        steer.set_linewidth(3)
        steer.set_color(0, 0, 255)
        return [steer]

<|endoftext|>


<commit_before>import time, os, sys, threading, picamera
import wiringpi

class motorClass(object):
    def __init__(self):
        self.pwmPin = 18
        self.directionPin = 17
        self.enablePin = 4
        self.speed = 20
        wiringpi.pinMode(self.enablePin,1)
        wiringpi.pinMode(self.directionPin,1)
        wiringpi.pinMode(self.pwmPin,1)
        wiringpi.softPwmCreate(self.pwmPin,0,100)

    def forward(self):
        wiringpi.softPwmWrite(self.pwmPin,self.speed)
        wiringpi.digitalWrite(self.enablePin,1)
        wiringpi.digitalWrite(self.directionPin,1)

    def stop(self):
        wiringpi.digitalWrite(self.enablePin,0)

class cameraClass(object):
    def __init__(self):
        #initialise camera
        self.camera = picamera.PiCamera()
        self.camera.resolution = (1024, 768)
        self.camera.start_preview()

    def picture(self):
        self.camera.capture('image.jpg')

class crashSensor(object):
    def __init__(self):
        self.pin = 16
        self.alive = True
        wiringpi.pinMode(self.pin,0)
        wiringpi.pullUpDnControl(self.pin,2)

    def crashWorker(self):
        while self.alive:
            state = wiringpi.digitalRead(self.pin)
            if state == 0:
                self.crash()
                self.alive = False

    def check(self):
        t = threading.Thread(name='crash',target=self.crashWorker)
        t.start()

    def crash(self):
        c.lightFL.blink(2)
        c.lightFR.blink(2)

class light(object):
    def __init__(self, pin):
        #make pins into output
        wiringpi.pinMode(pin,1)
        #set output low
        wiringpi.digitalWrite(pin,0)
        #set variables
        self.status = 0
        self.pin = pin

    def on(self):
        #turn light on
        wiringpi.digitalWrite(self.pin,1)
        self.status = 1

    def off(self):
        #turn light off
        wiringpi.digitalWrite(self.pin,0)
        self.status = 0

    def blinkWorker(self,pause):
        #frits: ik ben er vrij zeker van dat dit met minder code kan.
        if (self.status == 0):
            self.on()
            time.sleep(pause)
            self.off()
            time.sleep(pause)
        else:
            self.off()
            time.sleep(pause)
            self.on()
            time.sleep(pause)

    def blinkThread(self):
        for _ in range(self.times):
            self.blinkWorker(0.5)

    def blink(self,times):
        self.times = times
        #Dit is een example voor threading omdat ik deze functie async wil laten lopen misschien moet het wat schoon gemaakt worden
        #meer info over threading: https://pymotw.com/2/threading/
        t = threading.Thread(name='light',target=self.blinkThread)
        t.start()

def cameraTest():
    camera.picture()

def lightTest():
    lightFL.on()
    lightFR.on()
    time.sleep(2)
    lightFL.off()
    lightFR.off()

def crashTest():
    crashS.check()

def motorTest():
    motor.forward()
    time.sleep(2)
    motor.stop()

lightFL = light(26)
lightFR = light(20)
crashS = crashSensor()
camera = cameraClass()
motor = motorClass()

test = input('What do you want to test:(light,camera,crash)')
if (test == "light"):
    lightTest()
if (test == "camera"):
    cameraTest()
if (test == "crash"):
    crashTest()
if (test == "motor"):
    motorTest()
<commit_msg>Motor<commit_after>import time, os, sys, threading, picamera
import wiringpi

class motorClass(object):
    def __init__(self):
        self.pwmPin = 18
        self.forwardPin = 17
        self.backwardPin = 4
        self.speed = 20
        wiringpi.pinMode(self.fowardPin,1)
        wiringpi.pinMode(self.backwardPin,1)
        wiringpi.pinMode(self.pwmPin,1)
        wiringpi.softPwmCreate(self.pwmPin,0,100)

    def forward(self):
        wiringpi.softPwmWrite(self.pwmPin,self.speed)
        wiringpi.digitalWrite(self.forwardPin,1)
        wiringpi.digitalWrite(self.backwardPin,0)

    def stop(self):
        wiringpi.digitalWrite(self.forwardPin,0)
        wiringpi.digitalWrite(self.backwardPin,0)

class cameraClass(object):
    def __init__(self):
        #initialise camera
        self.camera = picamera.PiCamera()
        self.camera.resolution = (1024, 768)
        self.camera.start_preview()

    def picture(self):
        self.camera.capture('image.jpg')

class crashSensor(object):
    def __init__(self):
        self.pin = 16
        self.alive = True
        wiringpi.pinMode(self.pin,0)
        wiringpi.pullUpDnControl(self.pin,2)

    def crashWorker(self):
        while self.alive:
            state = wiringpi.digitalRead(self.pin)
            if state == 0:
                self.crash()
                self.alive = False

    def check(self):
        t = threading.Thread(name='crash',target=self.crashWorker)
        t.start()

    def crash(self):
        c.lightFL.blink(2)
        c.lightFR.blink(2)

class light(object):
    def __init__(self, pin):
        #make pins into output
        wiringpi.pinMode(pin,1)
        #set output low
        wiringpi.digitalWrite(pin,0)
        #set variables
        self.status = 0
        self.pin = pin

    def on(self):
        #turn light on
        wiringpi.digitalWrite(self.pin,1)
        self.status = 1

    def off(self):
        #turn light off
        wiringpi.digitalWrite(self.pin,0)
        self.status = 0

    def blinkWorker(self,pause):
        #frits: ik ben er vrij zeker van dat dit met minder code kan.
        if (self.status == 0):
            self.on()
            time.sleep(pause)
            self.off()
            time.sleep(pause)
        else:
            self.off()
            time.sleep(pause)
            self.on()
            time.sleep(pause)

    def blinkThread(self):
        for _ in range(self.times):
            self.blinkWorker(0.5)

    def blink(self,times):
        self.times = times
        #Dit is een example voor threading omdat ik deze functie async wil laten lopen misschien moet het wat schoon gemaakt worden
        #meer info over threading: https://pymotw.com/2/threading/
        t = threading.Thread(name='light',target=self.blinkThread)
        t.start()

def cameraTest():
    camera.picture()

def lightTest():
    lightFL.on()
    lightFR.on()
    time.sleep(2)
    lightFL.off()
    lightFR.off()

def crashTest():
    crashS.check()

def motorTest():
    motor.forward()
    time.sleep(2)
    motor.stop()

lightFL = light(26)
lightFR = light(20)
crashS = crashSensor()
camera = cameraClass()
motor = motorClass()

test = input('What do you want to test:(light,camera,crash)')
if (test == "light"):
    lightTest()
if (test == "camera"):
    cameraTest()
if (test == "crash"):
    crashTest()
if (test == "motor"):
    motorTest()
<|endoftext|>


<commit_before>import urllib2
import simplejson
import datetime

from django.conf import settings

def get_object_list(container):
    container = "%s%s/%s" % (settings.OBJECT_STORE_URL, settings.TENANT_ID, container)
    print container
    req = urllib2.Request(container)
    req.add_header("Content-type", "application/json")
    req.add_header("X-Auth-Token", get_auth_token())
    response = urllib2.urlopen(req)
    return response.read().split('\n')

def _get_cdn_enabled_containers():
    path = "%s%s" % (settings.CDN_URL, settings.TENANT_ID)
    return path
CDN_ENABLED_CONTAINERS = _get_cdn_enabled_containers()

<commit_msg>Remove the cdn.py file.<commit_after><|endoftext|>