<commit_before># This is a Python Class established as a Data Loader for Graphistry

# This Loader support four types of data : Json (eg. '{"xxx":"xxx"}'),
# Json Pointer (eg. './xxx/xxx.json'), Pandas (eg. csv table),
# Pandas Pointer (eg. './xxx/xxx.csv')

# Class Load has the following public methods:

# settings(url, frameheight)
# This function does the work of setting proper server for user.
# url = 'proxy'/'localhost', the default value is 'proxy'.
# 'localhost' would let user connect to the local server, 'proxy'
# would let user connect with server from Graphistry
# frameheight = integer, the default value is 500.
# frameheight is used to set the size of returned figures
#
#...............................................................................

# loadpandassync (edge, node, graphname, sourcefield, destfield, nodefield,
#         edgetitle, edgelabel, edgeweight, pointtitle , pointlabel,
#         pointcolor, pointsize)
# loadpandassync is the primary method. it parses the data with pandas format
# or with pandas pointer and load it to proper Graphistry server, and send back
# the concerned graph. It is a wrapper for loadpandas().

# edge(compulsory) = dataset for edge, the format includes Pandas pointer/Pandas
# node(compulsory) = dataset for node, the format includes Pandas pointer/Pandas
# sourcefield(optional) = name of the column in edge for sourcePointers
#                         (eg. 'source'), the default value is 'src'.
# destfield(optional) = name of the column in edge for destinationPointers
#                      (eg. 'des'), the default value is 'dst'.
# nodefield(optional) = name of the column in node for all pointers,
#                       the default value is 'node'
# graphname(optional) = a name string the user prefer (eg. 'myGraph'), the
#                       default value is a random generagted ten-characters
#                       string with numbers and capital letters.
# edgetitle(optional) = name of the column in edge for edges' titles, the
#                       default value is 'edgeTitle'
# edgelabel(optional) = name of the column in edge for edges' labels, the
#                       default value is 'edgeLabel'
# edgeweight(optional) = name of the column in edge for edges' Weights, the
#                        default value is 'edgeWeight'
# pointtitle(optional) = name of the column in node for nodes' titles, the
#                        default value is 'pointTitle'
# pointlabel(optional) = name of the column in node for nodes' labels, the
#                        default value is 'pointLabel'
# pointColor(optional) = name of the column in node for nodes' colors, the
#                        default value is 'pointColor'
# pointSize(optional) = name of the column in node for nodes' sizes, the
#                       default value is 'pointSize'
#
#...............................................................................

# loadjsonsync (document)
# loadjsonsync is the primary method. it parses the data with Json format
# or with Json pointer and load it to proper Graphistry server, and send back
# the concerned graph. It is a wrapper for isjsonpointer(), loadjsonpointer().

# document(compulsory) = complete dataset for edge and node,
#                        the format includes Json pointer / Json
#
#...............................................................................

# loadjsonpointer(filedir)
# This function load Json file from give directory and returns it with
# Json format (Decoding)
#...............................................................................

# loadpandas(edge, node, graphname, sourcefield, destfield, nodefield,
#            edgeTitle, edgeLabel, edgeWeight, pointTitle, pointLabel,
#            pointColor, pointSize)
# This function load data with pandas format as edge and node seperately
# and returns it with Json format (Decoding)
#...............................................................................

# isjsonpointer(document)
# This function checks whether the input document is Json pointer
#...............................................................................

def settings():
    print "TODO"
    # Return Graphistry object

def plot():
    # Call settings with default values
    # Call loadpandassync
    print "TODO"

class Graphistry (object):

    def __init__ (self):
        self.height = 500
        self.url = 'http://proxy-staging.graphistry.com/etl'
        self.hostname = 'proxy-staging.graphistry.com'

    def settings(self, url='proxy', frameheight=500):

        self.height = frameheight
        print 'Setting server...'
        if url is 'localhost':
            self.hostname = 'localhost:3000'
            self.url = 'http://localhost:3000/etl'
        elif url is 'proxy':
            self.hostname = 'proxy-staging.graphistry.com'
            self.url = 'http://proxy-staging.graphistry.com/etl'
        else:
            self.url = '-1'
            raise ValueError("Can not find this server")
        return self

    def loadpandassync(self, edge, node, graphname=None,
                       sourcefield=None, destfield=None,
                       nodefield=None, edgetitle=None,
                       edgelabel=None, edgeweight=None,
                       pointtitle=None, pointlabel=None,
                       pointcolor=None, pointsize=None):

        import random
        import string
        import requests
        import json
        import yaml

        doc = self.loadpandas(edge, node, graphname,
                              sourcefield, destfield, nodefield, edgetitle,
                              edgelabel, edgeweight, pointtitle,
                              pointlabel, pointcolor, pointsize)

        docj = json.dumps(doc)

        headers = {'content type': 'json', 'content-Encoding': 'gzip',
                   'Accept-Encoding': 'gzip', 'Accept': 'application/json',
                   'Content-Type': 'application/json'}
        try:
            r = requests.post(self.url, docj, headers=headers)
        except requests.exceptions.ConnectionError as e:
            raise ValueError("Connection Error")
        except requests.exceptions.HTTPError as e:
            raise ValueError("HTTPError:", e.message)

        else:
            name = yaml.safe_load(doc['name'])
            print 'Loading Finished!'
            print 'Getting iframe...'
            from IPython.core.display import HTML
            l = "http://" + self.hostname + "/graph/graph.html?dataset=%s"%name
            print "url: ", l
            return HTML('<iframe src="' + l + '" style="width:100%; height:' +
                        str(self.height) + 'px; border: 1px solid #DDD">')

    def loadjsonsync(self, document):

        import requests
        import json
        import yaml

        print 'Loading Json...'

        if self.isjsonpointer(document):
            doc = self.loadjsonpointer(document)
            name = yaml.safe_load(doc['name'])
            doc = json.dumps(doc)

        else:
            doc = document
            name = yaml.safe_load(doc['name'])

        headers = {'content type': 'json', 'content-Encoding': 'gzip',
                   'Accept-Encoding': 'gzip', 'Accept': 'application/json',
                   'Content-Type': 'application/json'}
        try:
            r = requests.post(self.url, doc, headers=headers)
        except requests.exceptions.ConnectionError as e:
            raise ValueError("Connection Error")
        except requests.exceptions.HTTPError as e:
            raise ValueError("HTTPError:", e.message)

        else:
            print 'Loading Finished!'
            print 'Getting iframe...'
            from IPython.core.display import HTML
            l = "http://" + self.hostname + "/graph/graph.html?dataset=%s"%name
            print "url:", l
            return HTML('<iframe src="' + l + '" style="width:100%; height:' + str(self.height) + 'px; border: 1px solid #DDD">')

    def isjsonpointer(self, document):
        if isinstance(document, str):
            if document[-4:] == 'json':
                return True
            else:
                raise ValueError(" This Json Pointer is Invalid!")
        else:
            return False

    def loadjsonpointer(self, filedir):
        import json
        print 'Loading Json...'
        with open(filedir) as data_file:
            files = json.load(data_file)
        return files

    def loadpandas(self, edge, node, graphname=None,
                   sourcefield=None, destfield=None, nodefield=None,
                   edgetitle=None, edgelabel=None, edgeweight=None,
                   pointtitle=None, pointlabel=None,
                   pointcolor=None, pointsize=None,):

        import pandas as pd
        import json
        import random
        import string

        print 'Loading Pandas...'

        if isinstance(edge, str):
            if (edge[-4:] == '.csv'):
                edge = pd.read_csv(edge, na_values=['-'], low_memory=False)
                edge.dropna(how='all', axis=1, inplace=True)
            else:
                raise ValueError("This Pandas Pointer is Invalid")

        if isinstance(node, str):
            if (node[-4:] == '.csv'):
                node = pd.read_csv(node, na_values=['-'], low_memory=False)
                node.dropna(how='all', axis=1, inplace=True)
            else:
                raise ValueError("This Pandas Pointer is Invalid")

        if graphname is None:
            graphname = ''.join(random.choice(string.ascii_uppercase +
                                string.digits)for _ in range(10))

        files = {'name': graphname}
        files['bindings'] = {'idField': 'node', 'destinationField': 'dst',
                             'sourceField': 'src'}
        files['type'] = 'edgelist'

        # for Edge
        edge = edge.reset_index()
        del edge['index']
        edgejson = edge.to_json(orient='records')
        edgej = json.loads(edgejson)
        u_edgej = json.dumps(edgej)
        if sourcefield is None:
            for i in range(0, len(edgej)):
                edgej[i]['src'] = edge['src'][i]
        else:
            for i in range(0, len(edgej)):
                edgej[i]['src'] = edge[sourcefield][i]

        if destfield is None:
            for i in range(0, len(edgej)):
                edgej[i]['dst'] = edge['dst'][i]
        else:
            for i in range(0, len(edgej)):
                edgej[i]['dst'] = edge[destfield][i]

        # set edgelabel
        if edgelabel is None:
            if 'edgeLabel' in u_edgej:
                for i in range(0, len(edgej)):
                    edgej[i]['edgeLabel'] = edge['edgeLabel'][i]
        else:
            for i in range(0, len(edgej)):
                    edgej[i]['edgeLabel'] = edge[edgelabel][i]

        # Set edgeWeight
        if edgeweight is None:
            if 'edgeWeight' in u_edgej:
                for i in range(0, len(edgej)):
                    edgej[i]['edgeWeight'] = edge['edgeWeight'][i]
        else:
            for i in range(0, len(edgej)):
                    edgej[i]['edgeWeight'] = edge[edgeweight][i]

        # Set edgeTitle
        if edgetitle is None:
            if 'edgeTitle' in u_edgej:
                for i in range(0, len(edgej)):
                    edgej[i]['edgeTitle'] = edge['edgeTitle'][i]
        else:
            for i in range(0, len(edgej)):
                    edgej[i]['edgeTitle'] = edge[edgetitle][i]

        files['graph'] = edgej

        # for Label
        node = node.reset_index()
        del node['index']
        nodejson = node.to_json(orient='records')
        nodej = json.loads(nodejson)
        u_nodej = json.dumps(nodej)
        if nodefield is None:
            nodej = {each['node']: each for each in nodej}.values()
            for i in range(0, len(nodej)):
                nodej[i]['node'] = node['node'][i]
        else:
            nodej = {each[nodefield]: each for each in nodej}.values()
            for i in range(0, len(nodej)):
                nodej[i]['node'] = node[nodefield][i]

        # u_nodej = json.dumps(nodej)
        # Set Point Title
        if pointtitle is None:
            if 'pointTitle' in u_nodej:
                for i in range(0, len(nodej)):
                    nodej[i]['pointTitle'] = node['pointTitle'][i]
        else:
            for i in range(0, len(nodej)):
                    nodej[i]['pointTitle'] = node[pointtitle][i]
        # Set Point Label
        if pointlabel is None:
            if 'pointLabel' in u_nodej:
                for i in range(0, len(nodej)):
                    nodej[i]['pointLabel'] = node['pointLabel'][i]
        else:
            for i in range(0, len(nodej)):
                    nodej[i]['pointLabel'] = node[pointlabel][i]
        # Set the point size
        if pointsize is None:
            if 'pointSize' in u_nodej:
                for i in range(0, len(nodej)):
                    nodej[i]['pointSize'] = node['pointSize'][i]
        else:
            for i in range(0, len(nodej)):
                    nodej[i]['pointSize'] = node[pointsize][i]
        # Set the point Color
        if pointcolor is None:
            if 'pointColor' in u_nodej:
                for i in range(0, len(nodej)):
                    nodej[i]['pointColor'] = node['pointColor'][i]
        else:
            for i in range(0, len(nodej)):
                    nodej[i]['pointColor'] = node[pointcolor][i]

        files['labels'] = nodej

        return files
<commit_msg>update plot & settings<commit_after># This is a Python Class established as a Data Loader for Graphistry

# This Loader support four types of data : Json (eg. '{"xxx":"xxx"}'),
# Json Pointer (eg. './xxx/xxx.json'), Pandas (eg. csv table),
# Pandas Pointer (eg. './xxx/xxx.csv')

# Class Load has the following public methods:

# settings(url, frameheight)
# This function does the work of setting proper server for user.
# url = 'proxy'/'localhost', the default value is 'proxy'.
# 'localhost' would let user connect to the local server, 'proxy'
# would let user connect with server from Graphistry
# frameheight = integer, the default value is 500.
# frameheight is used to set the size of returned figures
#
#...............................................................................

# loadpandassync (edge, node, graphname, sourcefield, destfield, nodefield,
#         edgetitle, edgelabel, edgeweight, pointtitle , pointlabel,
#         pointcolor, pointsize)
# loadpandassync is the primary method. it parses the data with pandas format
# or with pandas pointer and load it to proper Graphistry server, and send back
# the concerned graph. It is a wrapper for loadpandas().

# edge(compulsory) = dataset for edge, the format includes Pandas pointer/Pandas
# node(compulsory) = dataset for node, the format includes Pandas pointer/Pandas
# sourcefield(optional) = name of the column in edge for sourcePointers
#                         (eg. 'source'), the default value is 'src'.
# destfield(optional) = name of the column in edge for destinationPointers
#                      (eg. 'des'), the default value is 'dst'.
# nodefield(optional) = name of the column in node for all pointers,
#                       the default value is 'node'
# graphname(optional) = a name string the user prefer (eg. 'myGraph'), the
#                       default value is a random generagted ten-characters
#                       string with numbers and capital letters.
# edgetitle(optional) = name of the column in edge for edges' titles, the
#                       default value is 'edgeTitle'
# edgelabel(optional) = name of the column in edge for edges' labels, the
#                       default value is 'edgeLabel'
# edgeweight(optional) = name of the column in edge for edges' Weights, the
#                        default value is 'edgeWeight'
# pointtitle(optional) = name of the column in node for nodes' titles, the
#                        default value is 'pointTitle'
# pointlabel(optional) = name of the column in node for nodes' labels, the
#                        default value is 'pointLabel'
# pointColor(optional) = name of the column in node for nodes' colors, the
#                        default value is 'pointColor'
# pointSize(optional) = name of the column in node for nodes' sizes, the
#                       default value is 'pointSize'
#
#...............................................................................

# loadjsonsync (document)
# loadjsonsync is the primary method. it parses the data with Json format
# or with Json pointer and load it to proper Graphistry server, and send back
# the concerned graph. It is a wrapper for isjsonpointer(), loadjsonpointer().

# document(compulsory) = complete dataset for edge and node,
#                        the format includes Json pointer / Json
#
#...............................................................................

# loadjsonpointer(filedir)
# This function load Json file from give directory and returns it with
# Json format (Decoding)
#...............................................................................

# loadpandas(edge, node, graphname, sourcefield, destfield, nodefield,
#            edgeTitle, edgeLabel, edgeWeight, pointTitle, pointLabel,
#            pointColor, pointSize)
# This function load data with pandas format as edge and node seperately
# and returns it with Json format (Decoding)
#...............................................................................

# isjsonpointer(document)
# This function checks whether the input document is Json pointer
#...............................................................................

def settings(url='proxy', frameheight=500):
    height = frameheight
    print 'Setting server...'
    if url is 'localhost':
        hostname = 'localhost:3000'
        url = 'http://localhost:3000/etl'
    elif url is 'proxy':
        hostname = 'proxy-staging.graphistry.com'
        url = 'http://proxy-staging.graphistry.com/etl'
    else:
        url = '-1'
        raise ValueError("Can not find this server")
    g = Graphistry (height, url, hostname)
    return g
    # Return Graphistry object

def plot(url='proxy', frameheight=500, edge=None, node=None, graphname=None,
         sourcefield=None, destfield=None, nodefield=None,
         edgetitle=None, edgelabel=None, edgeweight=None,
         pointtitle=None, pointlabel=None, pointcolor=None,
         pointsize=None):

    import pandas as pd
    height = frameheight
    print 'Setting server...'
    if url is 'localhost':
        hostname = 'localhost:3000'
        url = 'http://localhost:3000/etl'
    elif url is 'proxy':
        hostname = 'proxy-staging.graphistry.com'
        url = 'http://proxy-staging.graphistry.com/etl'
    else:
        url = '-1'
        raise ValueError("Can not find this server")
    g = Graphistry (height, url, hostname)

    if node is not None:
        #setting = settings(url=url, frameheight=frameheight)
        return g.loadpandassync(edge, node, graphname, sourcefield,
                               destfield, nodefield, edgetitle, edgelabel,
                               edgeweight, pointtitle, pointlabel, pointcolor,
                               pointsize)
    else:
        #setting = settings(url='proxy', frameheight=500)
        return g.loadjsonsync(edge)

    # Call settings with default values
    # Call loadpandassync

class Graphistry (object):

    def __init__ (self,height,url,hostname):
        self.height = 500
        self.url = url
        self.hostname = hostname

    def settings(self, url='proxy', frameheight=500):

        self.height = frameheight
        print 'Setting server...'
        if url is 'localhost':
            self.hostname = 'localhost:3000'
            self.url = 'http://localhost:3000/etl'
        elif url is 'proxy':
            self.hostname = 'proxy-staging.graphistry.com'
            self.url = 'http://proxy-staging.graphistry.com/etl'
        else:
            self.url = '-1'
            raise ValueError("Can not find this server")
        return self

    def loadpandassync(self, edge, node, graphname=None,
                       sourcefield=None, destfield=None,
                       nodefield=None, edgetitle=None,
                       edgelabel=None, edgeweight=None,
                       pointtitle=None, pointlabel=None,
                       pointcolor=None, pointsize=None):

        import random
        import string
        import requests
        import json
        import yaml

        doc = self.loadpandas(edge, node, graphname,
                              sourcefield, destfield, nodefield, edgetitle,
                              edgelabel, edgeweight, pointtitle,
                              pointlabel, pointcolor, pointsize)

        docj = json.dumps(doc)

        headers = {'content type': 'json', 'content-Encoding': 'gzip',
                   'Accept-Encoding': 'gzip', 'Accept': 'application/json',
                   'Content-Type': 'application/json'}
        try:
            r = requests.post(self.url, docj, headers=headers)
        except requests.exceptions.ConnectionError as e:
            raise ValueError("Connection Error")
        except requests.exceptions.HTTPError as e:
            raise ValueError("HTTPError:", e.message)

        else:
            name = yaml.safe_load(doc['name'])
            print 'Loading Finished!'
            print 'Getting iframe...'
            from IPython.core.display import HTML
            l = "http://" + self.hostname + "/graph/graph.html?dataset=%s"%name
            print "url: ", l
            return HTML('<iframe src="' + l + '" style="width:100%; height:' +
                        str(self.height) + 'px; border: 1px solid #DDD">')

    def loadjsonsync(self, document):

        import requests
        import json
        import yaml

        print 'Loading Json...'

        if self.isjsonpointer(document):
            doc = self.loadjsonpointer(document)
            name = yaml.safe_load(doc['name'])
            doc = json.dumps(doc)

        else:
            doc = document
            name = yaml.safe_load(doc['name'])

        headers = {'content type': 'json', 'content-Encoding': 'gzip',
                   'Accept-Encoding': 'gzip', 'Accept': 'application/json',
                   'Content-Type': 'application/json'}
        try:
            r = requests.post(self.url, doc, headers=headers)
        except requests.exceptions.ConnectionError as e:
            raise ValueError("Connection Error")
        except requests.exceptions.HTTPError as e:
            raise ValueError("HTTPError:", e.message)

        else:
            print 'Loading Finished!'
            print 'Getting iframe...'
            from IPython.core.display import HTML
            l = "http://" + self.hostname + "/graph/graph.html?dataset=%s"%name
            print "url:", l
            return HTML('<iframe src="' + l + '" style="width:100%; height:' + str(self.height) + 'px; border: 1px solid #DDD">')

    def isjsonpointer(self, document):
        if isinstance(document, str):
            if document[-4:] == 'json':
                return True
            else:
                raise ValueError(" This Json Pointer is Invalid!")
        else:
            return False

    def loadjsonpointer(self, filedir):
        import json
        print 'Loading Json...'
        with open(filedir) as data_file:
            files = json.load(data_file)
        return files

    def loadpandas(self, edge, node, graphname=None,
                   sourcefield=None, destfield=None, nodefield=None,
                   edgetitle=None, edgelabel=None, edgeweight=None,
                   pointtitle=None, pointlabel=None,
                   pointcolor=None, pointsize=None,):

        import pandas as pd
        import json
        import random
        import string

        print 'Loading Pandas...'

        if isinstance(edge, str):
            if (edge[-4:] == '.csv'):
                edge = pd.read_csv(edge, na_values=['-'], low_memory=False)
                edge.dropna(how='all', axis=1, inplace=True)
            else:
                raise ValueError("This Pandas Pointer is Invalid")

        if isinstance(node, str):
            if (node[-4:] == '.csv'):
                node = pd.read_csv(node, na_values=['-'], low_memory=False)
                node.dropna(how='all', axis=1, inplace=True)
            else:
                raise ValueError("This Pandas Pointer is Invalid")

        if graphname is None:
            graphname = ''.join(random.choice(string.ascii_uppercase +
                                string.digits)for _ in range(10))

        files = {'name': graphname}
        files['bindings'] = {'idField': 'node', 'destinationField': 'dst',
                             'sourceField': 'src'}
        files['type'] = 'edgelist'

        # for Edge
        edge = edge.reset_index()
        del edge['index']
        edgejson = edge.to_json(orient='records')
        edgej = json.loads(edgejson)
        u_edgej = json.dumps(edgej)
        if sourcefield is None:
            for i in range(0, len(edgej)):
                edgej[i]['src'] = edge['src'][i]
        else:
            for i in range(0, len(edgej)):
                edgej[i]['src'] = edge[sourcefield][i]

        if destfield is None:
            for i in range(0, len(edgej)):
                edgej[i]['dst'] = edge['dst'][i]
        else:
            for i in range(0, len(edgej)):
                edgej[i]['dst'] = edge[destfield][i]

        # set edgelabel
        if edgelabel is None:
            if 'edgeLabel' in u_edgej:
                for i in range(0, len(edgej)):
                    edgej[i]['edgeLabel'] = edge['edgeLabel'][i]
        else:
            for i in range(0, len(edgej)):
                    edgej[i]['edgeLabel'] = edge[edgelabel][i]

        # Set edgeWeight
        if edgeweight is None:
            if 'edgeWeight' in u_edgej:
                for i in range(0, len(edgej)):
                    edgej[i]['edgeWeight'] = edge['edgeWeight'][i]
        else:
            for i in range(0, len(edgej)):
                    edgej[i]['edgeWeight'] = edge[edgeweight][i]

        # Set edgeTitle
        if edgetitle is None:
            if 'edgeTitle' in u_edgej:
                for i in range(0, len(edgej)):
                    edgej[i]['edgeTitle'] = edge['edgeTitle'][i]
        else:
            for i in range(0, len(edgej)):
                    edgej[i]['edgeTitle'] = edge[edgetitle][i]

        files['graph'] = edgej

        # for Label
        node = node.reset_index()
        del node['index']
        nodejson = node.to_json(orient='records')
        nodej = json.loads(nodejson)
        u_nodej = json.dumps(nodej)
        if nodefield is None:
            nodej = {each['node']: each for each in nodej}.values()
            for i in range(0, len(nodej)):
                nodej[i]['node'] = node['node'][i]
        else:
            nodej = {each[nodefield]: each for each in nodej}.values()
            for i in range(0, len(nodej)):
                nodej[i]['node'] = node[nodefield][i]

        # u_nodej = json.dumps(nodej)
        # Set Point Title
        if pointtitle is None:
            if 'pointTitle' in u_nodej:
                for i in range(0, len(nodej)):
                    nodej[i]['pointTitle'] = node['pointTitle'][i]
        else:
            for i in range(0, len(nodej)):
                    nodej[i]['pointTitle'] = node[pointtitle][i]
        # Set Point Label
        if pointlabel is None:
            if 'pointLabel' in u_nodej:
                for i in range(0, len(nodej)):
                    nodej[i]['pointLabel'] = node['pointLabel'][i]
        else:
            for i in range(0, len(nodej)):
                    nodej[i]['pointLabel'] = node[pointlabel][i]
        # Set the point size
        if pointsize is None:
            if 'pointSize' in u_nodej:
                for i in range(0, len(nodej)):
                    nodej[i]['pointSize'] = node['pointSize'][i]
        else:
            for i in range(0, len(nodej)):
                    nodej[i]['pointSize'] = node[pointsize][i]
        # Set the point Color
        if pointcolor is None:
            if 'pointColor' in u_nodej:
                for i in range(0, len(nodej)):
                    nodej[i]['pointColor'] = node['pointColor'][i]
        else:
            for i in range(0, len(nodej)):
                    nodej[i]['pointColor'] = node[pointcolor][i]

        files['labels'] = nodej

        return files
<|endoftext|>


<commit_before>"""
birthday.py
Author: Daniel
Credit: Mr. Dennison
Assignment:

Your program will ask the user the following questions, in this order:

1. Their name.
2. The name of the month they were born in (e.g. "September").
3. The year they were born in (e.g. "1962").
4. The day they were born on (e.g. "11").

If the user's birthday fell on October 31, then respond with:

  You were born on Halloween!

If the user's birthday fell on today's date, then respond with:

  Happy birthday!

Otherwise respond with a statement like this:

  Peter, you are a winter baby of the nineties.

Example Session

  Hello, what is your name? Eric
  Hi Eric, what was the name of the month you were born in? September
  And what year were you born in, Eric? 1972
  And the day? 11
  Eric, you are a fall baby of the stone age.
"""

from datetime import datetime
from calendar import month_name
todaymonth = datetime.today().month
todaydate = datetime.today().day

name = input("Hello, what is your name? ")
month = input("Hi {0}, what was the name of the month you were born in? " .format(name))
year = input("And what year were you born in, {0}? " .format(name))
day = input("And the day? ")

month = month.lower()
winter = ["december", "january", "february"]
spring = ["march", "april", "may"]
summer = ["june", "july", "august"]
fall = ["september", "october", "november"]

if month in ["december", "january", "february"]:
    season = "winter"
elif month in ["march", "april", "may"]:
    season = "spring"
elif month in ["june", "july", "august"]:
    season = "summer"
else:
    season = "fall"

if int(year) < 1980:
    timeperiod = "stone age"
elif year in ["1980", "1981", "1982", "1983", "1984", "1985", "1986", "1987", "1988", "1989"]:
    timeperiod = "eighties"
elif year in ["1990", "1991", "1992", "1993", "1994", "1995", "1996", "1997", "1998", "1999"]:
    timeperiod = "nineties"
else:
    timeperiod = "two thousands"

if month == month_name[todaymonth] and int(day) == todaydate:
    print("Happy Birthday!")
elif month in ["october",] and int(day) == 31:
    print("Happy Halloween!")
else:
    print("{0}, you are a {1} baby of the {2}. " .format(name, season, timeperiod))<commit_msg>Updated from Brython Server: 2/16/2017 2:23:29 PM<commit_after>"""
birthday.py
Author: Daniel
Credit: Mr. Dennison
Assignment:

Your program will ask the user the following questions, in this order:

1. Their name.
2. The name of the month they were born in (e.g. "September").
3. The year they were born in (e.g. "1962").
4. The day they were born on (e.g. "11").

If the user's birthday fell on October 31, then respond with:

  You were born on Halloween!

If the user's birthday fell on today's date, then respond with:

  Happy birthday!

Otherwise respond with a statement like this:

  Peter, you are a winter baby of the nineties.

Example Session

  Hello, what is your name? Eric
  Hi Eric, what was the name of the month you were born in? September
  And what year were you born in, Eric? 1972
  And the day? 11
  Eric, you are a fall baby of the stone age.
"""

from datetime import datetime
from calendar import month_name
todaymonth = datetime.today().month
todaydate = datetime.today().day

name = input("Hello, what is your name? ")
month = input("Hi {0}, what was the name of the month you were born in? " .format(name))
year = input("And what year were you born in, {0}? " .format(name))
day = input("And the day? ")

month = month.lower()
winter = ["december", "january", "february"]
spring = ["march", "april", "may"]
summer = ["june", "july", "august"]
fall = ["september", "october", "november"]

if month in ["december", "january", "february"]:
    season = "winter"
elif month in ["march", "april", "may"]:
    season = "spring"
elif month in ["june", "july", "august"]:
    season = "summer"
else:
    season = "fall"

if int(year) < 1980:
    timeperiod = "stone age"
elif year in ["1980", "1981", "1982", "1983", "1984", "1985", "1986", "1987", "1988", "1989"]:
    timeperiod = "eighties"
elif year in ["1990", "1991", "1992", "1993", "1994", "1995", "1996", "1997", "1998", "1999"]:
    timeperiod = "nineties"
else:
    timeperiod = "two thousands"

print(month,month_name[todaymonth],  int(day), todaydate)

if month == month_name[todaymonth] and int(day) == todaydate:
    print("Happy Birthday!")
elif month in ["october",] and int(day) == 31:
    print("Happy Halloween!")
else:
    print("{0}, you are a {1} baby of the {2}. " .format(name, season, timeperiod))<|endoftext|>


<commit_before>import sys
import logging
import json
import zlib
import traceback
import struct
import random
import socket
import math
from logging.handlers import DatagramHandler

WAN_CHUNK, LAN_CHUNK = 1420, 8154

PY3 = sys.version_info[0] == 3

if PY3:
    string_type = str
    integer_type = int,
else:
    string_type = basestring
    integer_type = (int, long)

class GELFHandler(DatagramHandler):
    """Graylog Extended Log Format handler

    :param host: The host of the graylog server.
    :param port: The port of the graylog server (default 12201).
    :param chunk_size: Message chunk size. Messages larger than this
        size will be sent to graylog in multiple chunks. Defaults to
        `WAN_CHUNK=1420`.
    :param debugging_fields: Send debug fields if true (the default).
    :param extra_fields: Send extra fields on the log record to graylog
        if true (the default).
    :param fqdn: Use fully qualified domain name of localhost as source
        host (socket.getfqdn()).
    :param localname: Use specified hostname as source host.
    :param facility: Replace facility with specified value. If specified,
        record.name will be passed as `logger` parameter.
    """

    def __init__(self, host, port=12201, chunk_size=WAN_CHUNK,
            debugging_fields=True, extra_fields=True, fqdn=False,
            localname=None, facility=None):
        self.debugging_fields = debugging_fields
        self.extra_fields = extra_fields
        self.chunk_size = chunk_size
        self.fqdn = fqdn
        self.localname = localname
        self.facility = facility
        DatagramHandler.__init__(self, host, port)

    def send(self, s):
        if len(s) < self.chunk_size:
            DatagramHandler.send(self, s)
        else:
            for chunk in ChunkedGELF(s, self.chunk_size):
                DatagramHandler.send(self, chunk)

    def makePickle(self, record):
        message_dict = make_message_dict(
            record, self.debugging_fields, self.extra_fields, self.fqdn,
	    self.localname, self.facility)
        return zlib.compress(json.dumps(message_dict).encode('utf-8'))

class ChunkedGELF(object):
    def __init__(self, message, size):
        self.message = message
        self.size = size
        self.pieces = struct.pack('B', int(math.ceil(len(message) * 1.0/size)))
        self.id = struct.pack('Q', random.randint(0, 0xFFFFFFFFFFFFFFFF))

    def message_chunks(self):
        return (self.message[i:i + self.size] for i
                    in range(0, len(self.message), self.size))

    def encode(self, sequence, chunk):
        return b''.join([
            b'\x1e\x0f',
            self.id,
            struct.pack('B', sequence),
            self.pieces,
            chunk
        ])

    def __iter__(self):
        for sequence, chunk in enumerate(self.message_chunks()):
            yield self.encode(sequence, chunk)

def make_message_dict(record, debugging_fields, extra_fields, fqdn, localname, facility=None):
    if fqdn:
        host = socket.getfqdn()
    elif localname:
        host = localname
    else:
        host = socket.gethostname()
    fields = {'version': "1.0",
        'host': host,
        'short_message': record.getMessage(),
        'full_message': get_full_message(record.exc_info, record.getMessage()),
        'timestamp': record.created,
        'level': SYSLOG_LEVELS.get(record.levelno, record.levelno),
        'facility': facility or record.name,
    }

    if facility is not None:
        fields.update({
            '_logger': record.name
        })

    if debugging_fields:
        fields.update({
            'file': record.pathname,
            'line': record.lineno,
            '_function': record.funcName,
            '_pid': record.process,
            '_thread_name': record.threadName,
        })
        # record.processName was added in Python 2.6.2
        pn = getattr(record, 'processName', None)
        if pn is not None:
            fields['_process_name'] = pn
    if extra_fields:
        fields = add_extra_fields(fields, record)
    return fields

SYSLOG_LEVELS = {
    logging.CRITICAL: 2,
    logging.ERROR: 3,
    logging.WARNING: 4,
    logging.INFO: 6,
    logging.DEBUG: 7,
}

def get_full_message(exc_info, message):
    return '\n'.join(traceback.format_exception(*exc_info)) if exc_info else message

def add_extra_fields(message_dict, record):
    # skip_list is used to filter additional fields in a log message.
    # It contains all attributes listed in
    # http://docs.python.org/library/logging.html#logrecord-attributes
    # plus exc_text, which is only found in the logging module source,
    # and id, which is prohibited by the GELF format.
    skip_list = (
        'args', 'asctime', 'created', 'exc_info',  'exc_text', 'filename',
        'funcName', 'id', 'levelname', 'levelno', 'lineno', 'module',
        'msecs', 'msecs', 'message', 'msg', 'name', 'pathname', 'process',
        'processName', 'relativeCreated', 'thread', 'threadName')

    for key, value in record.__dict__.items():
        if key not in skip_list and not key.startswith('_'):
            if isinstance(value, (string_type, float) + integer_type):
                message_dict['_%s' % key] = value
            else:
                message_dict['_%s' % key] = repr(value)

    return message_dict
<commit_msg>remove double entry 'msecs'<commit_after>import sys
import logging
import json
import zlib
import traceback
import struct
import random
import socket
import math
from logging.handlers import DatagramHandler

WAN_CHUNK, LAN_CHUNK = 1420, 8154

PY3 = sys.version_info[0] == 3

if PY3:
    string_type = str
    integer_type = int,
else:
    string_type = basestring
    integer_type = (int, long)

class GELFHandler(DatagramHandler):
    """Graylog Extended Log Format handler

    :param host: The host of the graylog server.
    :param port: The port of the graylog server (default 12201).
    :param chunk_size: Message chunk size. Messages larger than this
        size will be sent to graylog in multiple chunks. Defaults to
        `WAN_CHUNK=1420`.
    :param debugging_fields: Send debug fields if true (the default).
    :param extra_fields: Send extra fields on the log record to graylog
        if true (the default).
    :param fqdn: Use fully qualified domain name of localhost as source
        host (socket.getfqdn()).
    :param localname: Use specified hostname as source host.
    :param facility: Replace facility with specified value. If specified,
        record.name will be passed as `logger` parameter.
    """

    def __init__(self, host, port=12201, chunk_size=WAN_CHUNK,
            debugging_fields=True, extra_fields=True, fqdn=False,
            localname=None, facility=None):
        self.debugging_fields = debugging_fields
        self.extra_fields = extra_fields
        self.chunk_size = chunk_size
        self.fqdn = fqdn
        self.localname = localname
        self.facility = facility
        DatagramHandler.__init__(self, host, port)

    def send(self, s):
        if len(s) < self.chunk_size:
            DatagramHandler.send(self, s)
        else:
            for chunk in ChunkedGELF(s, self.chunk_size):
                DatagramHandler.send(self, chunk)

    def makePickle(self, record):
        message_dict = make_message_dict(
            record, self.debugging_fields, self.extra_fields, self.fqdn,
	    self.localname, self.facility)
        return zlib.compress(json.dumps(message_dict).encode('utf-8'))

class ChunkedGELF(object):
    def __init__(self, message, size):
        self.message = message
        self.size = size
        self.pieces = struct.pack('B', int(math.ceil(len(message) * 1.0/size)))
        self.id = struct.pack('Q', random.randint(0, 0xFFFFFFFFFFFFFFFF))

    def message_chunks(self):
        return (self.message[i:i + self.size] for i
                    in range(0, len(self.message), self.size))

    def encode(self, sequence, chunk):
        return b''.join([
            b'\x1e\x0f',
            self.id,
            struct.pack('B', sequence),
            self.pieces,
            chunk
        ])

    def __iter__(self):
        for sequence, chunk in enumerate(self.message_chunks()):
            yield self.encode(sequence, chunk)

def make_message_dict(record, debugging_fields, extra_fields, fqdn, localname, facility=None):
    if fqdn:
        host = socket.getfqdn()
    elif localname:
        host = localname
    else:
        host = socket.gethostname()
    fields = {'version': "1.0",
        'host': host,
        'short_message': record.getMessage(),
        'full_message': get_full_message(record.exc_info, record.getMessage()),
        'timestamp': record.created,
        'level': SYSLOG_LEVELS.get(record.levelno, record.levelno),
        'facility': facility or record.name,
    }

    if facility is not None:
        fields.update({
            '_logger': record.name
        })

    if debugging_fields:
        fields.update({
            'file': record.pathname,
            'line': record.lineno,
            '_function': record.funcName,
            '_pid': record.process,
            '_thread_name': record.threadName,
        })
        # record.processName was added in Python 2.6.2
        pn = getattr(record, 'processName', None)
        if pn is not None:
            fields['_process_name'] = pn
    if extra_fields:
        fields = add_extra_fields(fields, record)
    return fields

SYSLOG_LEVELS = {
    logging.CRITICAL: 2,
    logging.ERROR: 3,
    logging.WARNING: 4,
    logging.INFO: 6,
    logging.DEBUG: 7,
}

def get_full_message(exc_info, message):
    return '\n'.join(traceback.format_exception(*exc_info)) if exc_info else message

def add_extra_fields(message_dict, record):
    # skip_list is used to filter additional fields in a log message.
    # It contains all attributes listed in
    # http://docs.python.org/library/logging.html#logrecord-attributes
    # plus exc_text, which is only found in the logging module source,
    # and id, which is prohibited by the GELF format.
    skip_list = (
        'args', 'asctime', 'created', 'exc_info',  'exc_text', 'filename',
        'funcName', 'id', 'levelname', 'levelno', 'lineno', 'module',
        'msecs', 'message', 'msg', 'name', 'pathname', 'process',
        'processName', 'relativeCreated', 'thread', 'threadName')

    for key, value in record.__dict__.items():
        if key not in skip_list and not key.startswith('_'):
            if isinstance(value, (string_type, float) + integer_type):
                message_dict['_%s' % key] = value
            else:
                message_dict['_%s' % key] = repr(value)

    return message_dict
<|endoftext|>


<commit_before>from typing import Dict, cast
import json
import re

from bs4 import BeautifulSoup as Soup

from .constants import WATCH_LATER_URL
from .typing.ytcfg import YtcfgDict
from .util import first

def find_ytcfg(soup: Soup) -> YtcfgDict:
    return cast(
        YtcfgDict,
        first(json.JSONDecoder().raw_decode(
            re.sub(
                r'.+ytcfg.set\(\{', '{',
                first(x for x in soup.select('script')
                      if '"INNERTUBE_CONTEXT_CLIENT_VERSION":' in
                      x.text).text.strip().replace('\n', ''), 1))))

def ytcfg_headers(ytcfg: YtcfgDict) -> Dict[str, str]:
    return {
        'x-spf-previous': WATCH_LATER_URL,
        'x-spf-referer': WATCH_LATER_URL,
        'x-youtube-client-name': str(ytcfg['INNERTUBE_CONTEXT_CLIENT_NAME']),
        'x-youtube-client-version': ytcfg['INNERTUBE_CONTEXT_CLIENT_VERSION'],
        'x-youtube-identity-token': ytcfg['ID_TOKEN'],
        'x-youtube-page-cl': str(ytcfg['PAGE_CL']),
        'x-youtube-utc-offset': '-240',
        'x-youtube-variants-checksum': ytcfg['VARIANTS_CHECKSUM'],
    }
<commit_msg>youtube_unofficial/ytcfg: remove non-existent key<commit_after>from typing import Dict, cast
import json
import re

from bs4 import BeautifulSoup as Soup

from .constants import WATCH_LATER_URL
from .typing.ytcfg import YtcfgDict
from .util import first

def find_ytcfg(soup: Soup) -> YtcfgDict:
    return cast(
        YtcfgDict,
        first(json.JSONDecoder().raw_decode(
            re.sub(
                r'.+ytcfg.set\(\{', '{',
                first(x for x in soup.select('script')
                      if '"INNERTUBE_CONTEXT_CLIENT_VERSION":' in
                      x.text).text.strip().replace('\n', ''), 1))))

def ytcfg_headers(ytcfg: YtcfgDict) -> Dict[str, str]:
    return {
        'x-spf-previous': WATCH_LATER_URL,
        'x-spf-referer': WATCH_LATER_URL,
        'x-youtube-client-name': str(ytcfg['INNERTUBE_CONTEXT_CLIENT_NAME']),
        'x-youtube-client-version': ytcfg['INNERTUBE_CONTEXT_CLIENT_VERSION'],
        'x-youtube-identity-token': ytcfg['ID_TOKEN'],
        'x-youtube-page-cl': str(ytcfg['PAGE_CL']),
        'x-youtube-utc-offset': '-240',
    }
<|endoftext|>


<commit_before># Should be one commit behind latest
__version__ = "0.2.1-4-g97bb9be"
<commit_msg>version<commit_after># Should be one commit behind latest
__version__ = "0.2.1-6-g9073bcf"
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
图片合并加注释的工具类

Author: liyan
File: merge_img.py

Features:
1. 把多张图片合并为一张垂直依次排列的大图
2. 大图带标题，小图带编号和注释
3. 合并后的图片：vertical.png
"""

import argparse
from util import Command

def test():
	"""
	"""
	my_labels = 'first step; second step; third step; forth step'.split(';')
	try:
		print 'begin merge...'
		Command.merge_img(src_img='j_[1-4].jpg', width=300, caption='做一个测试', labels=my_labels, clean=False)
		print 'merge over.'
	except Exception, e:
		print 'except:', e
		raise

def main():
	parser = argparse.ArgumentParser(description='Xcode Builder.')
	parser.add_argument('-a', dest='action', type=str, default='merge', choices=('test', 'merge'),
											help='Action perform')
	parser.add_argument('-s', dest='src_img', type=str, default='i_[1-9].png i_[1-9][0-9].png',
											help='image patern')
	parser.add_argument('-w', dest='export', type=int, default=300,
											help='Width of the merge image')
	parser.add_argument('-c', dest='caption', type=str, default='标题： 这是一个测试',
											help='image caption')
	parser.add_argument('-l', dest='labels', type=str, default='l1;l2;l3;l4',
											help='label for eath image, split by ;')
	parser.add_argument('--clean', dest='clean', action='store_false',
											help='Remove working files')
	parser.set_defaults(clean=True)

	args = parser.parse_args()

	# test()
	index = 1
	for lable in args.labels.split(';'):
		print index, lable
		index = index + 1
	# python /opt/local/ide/git_storage/github/apk-builder/merge_img.py -s "j_[0-8].jpg" -c 金立礼包码展示逻辑 -l "未展开的悬浮球;展开的悬浮球（选择礼包）;礼包列表标签，抢“独家礼包”;获取成功：展示“独家礼包”详情;已获得的礼包列表（我的礼包）;礼包列表中直接复制激活码;礼包详情页;礼包详情页复制并返回游戏" --clean
	Command.merge_img(src_img=args.src_img, width=300, caption=args.caption, labels=args.labels.split(';'), clean=args.clean)

if __name__ == '__main__':
	main()<commit_msg>update params<commit_after># -*- coding: utf-8 -*-
"""
图片合并加注释的工具类

Author: liyan
File: merge_img.py

Features:
1. 把多张图片合并为一张垂直依次排列的大图
2. 大图带标题，小图带编号和注释
3. 合并后的图片：vertical.png
"""

import argparse
from util import Command

def test():
	"""
	"""
	my_labels = 'first step; second step; third step; forth step'.split(';')
	try:
		print 'begin merge...'
		Command.merge_img(src_img='j_[1-4].jpg', width=300, caption='做一个测试', labels=my_labels, clean=False)
		print 'merge over.'
	except Exception, e:
		print 'except:', e
		raise

def main():
	parser = argparse.ArgumentParser(description='Xcode Builder.')
	parser.add_argument('-a', dest='action', type=str, default='merge', choices=('test', 'merge'),
											help='Action perform')
	parser.add_argument('-t', dest='img_type', type=str, default='jpg',
											help='image type')
	parser.add_argument('-n', dest='img_name', type=str, default='',
											help='image name: <img_name>_[1-9].<img_type> <img_name>_[1-9][0-9].<img_type>')
	parser.add_argument('-w', dest='img_width', type=int, default=720,
											help='Width of the merge image')
	parser.add_argument('-c', dest='caption', type=str, default='标题： 这是一个测试',
											help='image caption')
	parser.add_argument('-l', dest='labels', type=str, default='l1;l2;l3;l4',
											help='label for eath image, split by ;')
	parser.add_argument('--clean', dest='clean', action='store_false',
											help='Remove working files')
	parser.set_defaults(clean=True)

	args = parser.parse_args()

	img_pattern = '%(img_name)s_[1-9].%(img_type)s %(img_name)s_[1-9][0-9].%(img_type)s' % {
					'img_name': args.img_name,
					'img_type': args.img_type
				}
	print 'img_pattern=', img_pattern
	# test()
	index = 1
	for lable in args.labels.split(';'):
		print index, lable
		index = index + 1
	# for f in *.jpg; do mv $f g_${f} ; done
	# python /opt/local/ide/git_storage/github/ci_scripts/merge_img.py -n g -c "caption of these images" -l "1;2;3..split by ;" --clean
	Command.merge_img(src_img=img_pattern, width=args.img_width, caption=args.caption, labels=args.labels.split(';'), clean=args.clean)

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


<commit_before># -*- coding: utf-8 -*-
"""zesty_metrics.middleware -- Timing middleware for StatsD metrics.
"""
from __future__ import with_statement
import time
import threading
import logging
from uuid import uuid1
from hashlib import md5

from django.core.cache import cache
from django.db import IntegrityError

from user_agents import parse as parse_ua
import statsd

from . import models
from . import conf

logger = logging.getLogger('metrics')

request_id_keys = (
    'HTTP_ACCEPT_CHARSET',
    'HTTP_ACCEPT',
    'HTTP_ACCEPT_ENCODING',
    'HTTP_ACCEPT_LANGUAGE',
    'HTTP_CONNECTION',
    'HTTP_USER_AGENT',
    'REMOTE_ADDR',
)

def id_request(request):
    """Generate a uniquish ID for a given request.
    """
    key = '|'.join([
        request.META.get(k, '')
        for k in request_id_keys
    ])
    return md5(uuid1().get_hex() + key).hexdigest()

class LocalStatsd(threading.local):
    def __init__(self):
        client = self.client = statsd.StatsClient(
            host = conf.HOST,
            port = conf.PORT,
            prefix = conf.PREFIX,
        )
        try:
            self.pipeline = client.pipeline()
        except AttributeError:
            # In case we're using an older statsd version.
            self.pipeline = client

class MetricsMiddleware(object):
    """Middleware to capture basic metrics about a request.

    Includes:

    - Performance timing
    - Last-seen data for authenticated users.
    """
    scope = LocalStatsd()

    def process_request(self, request):
        request.statsd = self.scope.pipeline
        request.zesty = self.scope
        try:
            if conf.TIME_RESPONSES:
                self.start_timing(request)
        except:
            logger.exception('Exception occurred while logging to statsd.')

    def process_exception(self, request, exception):
        try:
            if hasattr(self.scope, 'client'):
                self.scope.pipeline.incr('view.exceptions')
                view_name = (getattr(self.scope, 'view_name', 'UNKNOWN') +
                             '.exceptions')
                self.scope.pipeline.incr(view_name)
        except:
            logger.exception('Exception occurred while logging to statsd.')

    def process_view(self, request, view_func, view_args, view_kwargs):
        if conf.TIME_RESPONSES:
            self.gather_view_data(request, view_func)

    def process_response(self, request, response):
        if conf.TRACK_USER_ACTIVITY:
            self.update_last_seen_data(request)
        if conf.TIME_RESPONSES:
            try:
                self.stop_timing(request)
            except:
                logger.exception('Exception occurred while logging to statsd.')

        return response

    def start_timing(self, request):
        """Start performance timing.
        """
        self.scope.request_start = time.time()

    def gather_view_data(self, request, view_func):
        """Discover the view name.
        """
        # View name is defined as module.view
        # (e.g. django.contrib.auth.views.login)
        name = view_func.__module__

        # CBV specific
        if hasattr(view_func, '__name__'):
            name = '%s.%s' % (name, view_func.__name__)
        elif hasattr(view_func, '__class__'):
            name = '%s.%s' % (name, view_func.__class__.__name__)
        method = request.method.lower()
        if request.is_ajax():
            method += '_ajax'
        name = '%s.%s' % (name, method)

        self.scope.id = id_request(request)

        self.scope.agent = parse_ua(request.META.get('HTTP_USER_AGENT', ''))
        self.scope.view_name = "view." + name

    def stop_timing(self, request):
        """Stop performance timing.
        """
        now = time.time()
        started = getattr(self.scope, 'request_start', now)
        time_elapsed = now - started
        if hasattr(self.scope, 'client'):
            client = self.scope.pipeline
            view_name = getattr(self.scope, 'view_name', 'UNKNOWN')
            if time_elapsed:
                client.timing(
                    view_name,
                    time_elapsed,
                    conf.TIMING_SAMPLE_RATE)
                client.timing(
                    'view.aggregate-response-time',
                    time_elapsed,
                    conf.TIMING_SAMPLE_RATE)
            client.incr(view_name + '.requests')
            client.incr('view.requests')
            logger.info("Processed %s.%s in %ss", conf.PREFIX, view_name, time_elapsed)
            try:
                client.send()
            except AttributeError:
                # Client isn't a pipeline, data already sent.
                pass
            except IndexError:
                # Nothing to send.
                pass
            logger.debug("Sent stats to %s:%s", conf.HOST, conf.PORT)
            agent = getattr(self.scope, "agent", None)
            rid = getattr(self.scope, "rid", None)
            if agent and rid:
                data = {
                    'started': started,
                    'server_time': time_elapsed,
                    'agent': agent,
                    'view_name': view_name,
                }
                cache.set('request:' + rid, data, 5 * 60)

    # Other visit data
    def update_last_seen_data(self, request):
        """Update the user's LastSeenData profile.
        """
        try:
            user = request.user
        except AttributeError:
            # No user, so nothing to do here.
            return

        if user.is_authenticated():
            try:
                data = models.LastSeenData.objects.get(user=user)
            except models.LastSeenData.DoesNotExist:
                data = models.LastSeenData(user=user)
            try:
                data.update(request)
            except IntegrityError:
                # User probably got created in a concurrent request?
                pass
            except:
                logger.exception("Couldn't update user LastSeenData:")
<commit_msg>remove no-longer-necessary __future__ import<commit_after># -*- coding: utf-8 -*-
"""zesty_metrics.middleware -- Timing middleware for StatsD metrics.
"""
import time
import threading
import logging
from uuid import uuid1
from hashlib import md5

from django.core.cache import cache
from django.db import IntegrityError

from user_agents import parse as parse_ua
import statsd

from . import models
from . import conf

logger = logging.getLogger('metrics')

request_id_keys = (
    'HTTP_ACCEPT_CHARSET',
    'HTTP_ACCEPT',
    'HTTP_ACCEPT_ENCODING',
    'HTTP_ACCEPT_LANGUAGE',
    'HTTP_CONNECTION',
    'HTTP_USER_AGENT',
    'REMOTE_ADDR',
)

def id_request(request):
    """Generate a uniquish ID for a given request.
    """
    key = '|'.join([
        request.META.get(k, '')
        for k in request_id_keys
    ])
    return md5(uuid1().get_hex() + key).hexdigest()

class LocalStatsd(threading.local):
    def __init__(self):
        client = self.client = statsd.StatsClient(
            host = conf.HOST,
            port = conf.PORT,
            prefix = conf.PREFIX,
        )
        try:
            self.pipeline = client.pipeline()
        except AttributeError:
            # In case we're using an older statsd version.
            self.pipeline = client

class MetricsMiddleware(object):
    """Middleware to capture basic metrics about a request.

    Includes:

    - Performance timing
    - Last-seen data for authenticated users.
    """
    scope = LocalStatsd()

    def process_request(self, request):
        request.statsd = self.scope.pipeline
        request.zesty = self.scope
        try:
            if conf.TIME_RESPONSES:
                self.start_timing(request)
        except:
            logger.exception('Exception occurred while logging to statsd.')

    def process_exception(self, request, exception):
        try:
            if hasattr(self.scope, 'client'):
                self.scope.pipeline.incr('view.exceptions')
                view_name = (getattr(self.scope, 'view_name', 'UNKNOWN') +
                             '.exceptions')
                self.scope.pipeline.incr(view_name)
        except:
            logger.exception('Exception occurred while logging to statsd.')

    def process_view(self, request, view_func, view_args, view_kwargs):
        if conf.TIME_RESPONSES:
            self.gather_view_data(request, view_func)

    def process_response(self, request, response):
        if conf.TRACK_USER_ACTIVITY:
            self.update_last_seen_data(request)
        if conf.TIME_RESPONSES:
            try:
                self.stop_timing(request)
            except:
                logger.exception('Exception occurred while logging to statsd.')

        return response

    def start_timing(self, request):
        """Start performance timing.
        """
        self.scope.request_start = time.time()

    def gather_view_data(self, request, view_func):
        """Discover the view name.
        """
        # View name is defined as module.view
        # (e.g. django.contrib.auth.views.login)
        name = view_func.__module__

        # CBV specific
        if hasattr(view_func, '__name__'):
            name = '%s.%s' % (name, view_func.__name__)
        elif hasattr(view_func, '__class__'):
            name = '%s.%s' % (name, view_func.__class__.__name__)
        method = request.method.lower()
        if request.is_ajax():
            method += '_ajax'
        name = '%s.%s' % (name, method)

        self.scope.id = id_request(request)

        self.scope.agent = parse_ua(request.META.get('HTTP_USER_AGENT', ''))
        self.scope.view_name = "view." + name

    def stop_timing(self, request):
        """Stop performance timing.
        """
        now = time.time()
        started = getattr(self.scope, 'request_start', now)
        time_elapsed = now - started
        if hasattr(self.scope, 'client'):
            client = self.scope.pipeline
            view_name = getattr(self.scope, 'view_name', 'UNKNOWN')
            if time_elapsed:
                client.timing(
                    view_name,
                    time_elapsed,
                    conf.TIMING_SAMPLE_RATE)
                client.timing(
                    'view.aggregate-response-time',
                    time_elapsed,
                    conf.TIMING_SAMPLE_RATE)
            client.incr(view_name + '.requests')
            client.incr('view.requests')
            logger.info("Processed %s.%s in %ss", conf.PREFIX, view_name, time_elapsed)
            try:
                client.send()
            except AttributeError:
                # Client isn't a pipeline, data already sent.
                pass
            except IndexError:
                # Nothing to send.
                pass
            logger.debug("Sent stats to %s:%s", conf.HOST, conf.PORT)
            agent = getattr(self.scope, "agent", None)
            rid = getattr(self.scope, "rid", None)
            if agent and rid:
                data = {
                    'started': started,
                    'server_time': time_elapsed,
                    'agent': agent,
                    'view_name': view_name,
                }
                cache.set('request:' + rid, data, 5 * 60)

    # Other visit data
    def update_last_seen_data(self, request):
        """Update the user's LastSeenData profile.
        """
        try:
            user = request.user
        except AttributeError:
            # No user, so nothing to do here.
            return

        if user.is_authenticated():
            try:
                data = models.LastSeenData.objects.get(user=user)
            except models.LastSeenData.DoesNotExist:
                data = models.LastSeenData(user=user)
            try:
                data.update(request)
            except IntegrityError:
                # User probably got created in a concurrent request?
                pass
            except:
                logger.exception("Couldn't update user LastSeenData:")
<|endoftext|>


<commit_before>"""Constants."""

# pylint: disable=too-many-lines

MODS = {
    1: 'Wololo Kingdoms',
    2: 'Portuguese Civilization Mod III',
    3: 'Age of Chivalry',
    4: 'Sengoku',
    7: 'Realms',
    101: 'King of the Hippo'
}

SPEEDS = {
    100: 'slow',
    150: 'standard',
    169: 'standard', # de
    178: 'standard', # up15
    200: 'fast',
    237: 'fast' # up15
}

DE_MAP_NAMES = {
    9: 'Arabia',
    10: 'Archipelago',
    11: 'Baltic',
    12: 'Black Forest',
    13: 'Coastal',
    14: 'Continental',
    15: 'Crater Lake',
    16: 'Fortress',
    17: 'Gold Rush',
    18: 'Highland',
    19: 'Islands',
    20: 'Mediterranean',
    21: 'Migration',
    22: 'Rivers',
    23: 'Team Islands',
    24: 'Random',
    25: 'Scandinavia',
    26: 'Mongolia',
    27: 'Yucatan',
    28: 'Salt Marsh',
    29: 'Arena',
    30: 'King of the Hill',
    31: 'Oasis',
    32: 'Ghost Lake',
    33: 'Nomad',
    51: 'Mideast',
    # 59: Custom
    67: 'Acropolis',
    68: 'Budapest',
    69: 'Cenotes',
    70: 'City of Lakes',
    71: 'Golden Pit',
    72: 'Hideout',
    73: 'Hill Fort',
    74: 'Lombardia',
    75: 'Steppe',
    76: 'Valley',
    77: 'MegaRandom',
    78: 'Hamburger',
    79: 'CtR Random',
    80: 'CtR Monsoon',
    81: 'CtR Pyramid Descent',
    82: 'CtR Spiral',
    83: 'Kilimanjaro',
    84: 'Mountain Pass',
    86: 'Serengeti',
    108: 'Indochina',
    112: 'Bog Islands',
    122: 'Alpine Lakes',
    125: 'Ravines',
    126: 'Wolf Hill',
    139: 'Golden Swamp',
    140: 'Four Lakes'
}

MAP_NAMES = {
    9: 'Arabia',
    10: 'Archipelago',
    11: 'Baltic',
    12: 'Black Forest',
    13: 'Coastal',
    14: 'Continental',
    15: 'Crater Lake',
    16: 'Fortress',
    17: 'Gold Rush',
    18: 'Highland',
    19: 'Islands',
    20: 'Mediterranean',
    21: 'Migration',
    22: 'Rivers',
    23: 'Team Islands',
    24: 'Random',
    25: 'Scandinavia',
    26: 'Mongolia',
    27: 'Yucatan',
    28: 'Salt Marsh',
    29: 'Arena',
    30: 'King of the Hill',
    31: 'Oasis',
    32: 'Ghost Lake',
    33: 'Nomad',
    34: 'Iberia',
    35: 'Britain',
    36: 'Mideast',
    37: 'Texas',
    38: 'Italy',
    39: 'Central America',
    40: 'France',
    41: 'Norse Lands',
    42: 'Sea of Japan (East Sea)',
    43: 'Byzantinum',
    48: 'Blind Random',
    49: 'Acropolis',
    50: 'Budapest',
    51: 'Cenotes',
    52: 'City of Lakes',
    53: 'Golden Pit',
    54: 'Hideout',
    55: 'Hill Fort',
    56: 'Lombardia',
    57: 'Steppe',
    58: 'Valley',
    59: 'MegaRandom',
    60: 'Hamburger',
    61: 'CtR Random',
    62: 'CtR Monsoon',
    63: 'CtR Pyramid Descent',
    64: 'CtR Spiral',
    66: 'Acropolis',
    67: 'Budapest',
    68: 'Cenotes',
    69: 'City of Lakes',
    70: 'Golden Pit',
    71: 'Hideout',
    72: 'Hill Fort',
    73: 'Lombardia',
    74: 'Steppe',
    75: 'Valley',
    76: 'MegaRandom',
    77: 'Hamburger',
    78: 'CtR Random',
    79: 'CtR Monsoon',
    80: 'CtR Pyramid Descent',
    81: 'CtR Spiral',
    82: 'Kilimanjaro',
    83: 'Mountain Pass',
    84: 'Nile Delta',
    85: 'Serengeti',
    86: 'Socotra',
    87: 'Amazon',
    88: 'China',
    89: 'Horn of Africa',
    90: 'India',
    91: 'Madagascar',
    92: 'West Africa',
    93: 'Bohemia',
    94: 'Earth',
    95: 'Canyons',
    96: 'Enemy Archipelago',
    97: 'Enemy Islands',
    98: 'Far Out',
    99: 'Front Line',
    100: 'Inner Circle',
    101: 'Motherland',
    102: 'Open Plains',
    103: 'Ring of Water',
    104: 'Snakepit',
    105: 'The Eye',
    125: 'Ravines'
}

MAP_SIZES = {
    120: 'tiny',
    144: 'small',
    168: 'medium',
    200: 'normal',
    220: 'large',
    240: 'giant',
    255: 'maximum'
}

COMPASS = {
    'northwest': [1/3.0, 0],
    'southeast': [1/3.0, 2/3.0],
    'southwest': [0, 1/3.0],
    'northeast': [2/3.0, 1/3.0],
    'center': [1/3.0, 1/3.0],
    'west': [0, 0],
    'north': [2/3.0, 0],
    'east': [2/3.0, 2/3.0],
    'south': [0, 2/3.0]
}

VALID_BUILDINGS = [
    10, 12, 14, 18, 19, 20, 31, 32, 42, 45, 47, 49, 50, 51, 63, 64, 68, 70, 71, 72,
    78, 79, 82, 84, 85, 86, 87, 88, 90, 91, 101, 103, 104, 105, 109, 116, 117, 129,
    130, 131, 132, 133, 137, 141, 142, 153, 155, 199, 209, 210, 234, 235, 236, 276,
    331, 357, 463, 464, 465, 484, 487, 488, 490, 491, 498, 562, 563, 564, 565, 584,
    585, 586, 587, 597, 598, 617, 621, 659, 661, 665, 667, 669, 673, 674, 734, 789,
    790, 792, 793, 794, 796, 797, 798, 800, 801, 802, 804, 1189
] + [1553, 387, 110, 785, 1002] + [1021, 1187, 1251] + [946, 947, 886, 888, 881, 879, 938, 871] # 5th Age, Realms, DE, Various
<commit_msg>add socotra<commit_after>"""Constants."""

# pylint: disable=too-many-lines

MODS = {
    1: 'Wololo Kingdoms',
    2: 'Portuguese Civilization Mod III',
    3: 'Age of Chivalry',
    4: 'Sengoku',
    7: 'Realms',
    101: 'King of the Hippo'
}

SPEEDS = {
    100: 'slow',
    150: 'standard',
    169: 'standard', # de
    178: 'standard', # up15
    200: 'fast',
    237: 'fast' # up15
}

DE_MAP_NAMES = {
    9: 'Arabia',
    10: 'Archipelago',
    11: 'Baltic',
    12: 'Black Forest',
    13: 'Coastal',
    14: 'Continental',
    15: 'Crater Lake',
    16: 'Fortress',
    17: 'Gold Rush',
    18: 'Highland',
    19: 'Islands',
    20: 'Mediterranean',
    21: 'Migration',
    22: 'Rivers',
    23: 'Team Islands',
    24: 'Random',
    25: 'Scandinavia',
    26: 'Mongolia',
    27: 'Yucatan',
    28: 'Salt Marsh',
    29: 'Arena',
    30: 'King of the Hill',
    31: 'Oasis',
    32: 'Ghost Lake',
    33: 'Nomad',
    51: 'Mideast',
    # 59: Custom
    67: 'Acropolis',
    68: 'Budapest',
    69: 'Cenotes',
    70: 'City of Lakes',
    71: 'Golden Pit',
    72: 'Hideout',
    73: 'Hill Fort',
    74: 'Lombardia',
    75: 'Steppe',
    76: 'Valley',
    77: 'MegaRandom',
    78: 'Hamburger',
    79: 'CtR Random',
    80: 'CtR Monsoon',
    81: 'CtR Pyramid Descent',
    82: 'CtR Spiral',
    83: 'Kilimanjaro',
    84: 'Mountain Pass',
    86: 'Serengeti',
    87: 'Socotra',
    108: 'Indochina',
    112: 'Bog Islands',
    122: 'Alpine Lakes',
    125: 'Ravines',
    126: 'Wolf Hill',
    139: 'Golden Swamp',
    140: 'Four Lakes'
}

MAP_NAMES = {
    9: 'Arabia',
    10: 'Archipelago',
    11: 'Baltic',
    12: 'Black Forest',
    13: 'Coastal',
    14: 'Continental',
    15: 'Crater Lake',
    16: 'Fortress',
    17: 'Gold Rush',
    18: 'Highland',
    19: 'Islands',
    20: 'Mediterranean',
    21: 'Migration',
    22: 'Rivers',
    23: 'Team Islands',
    24: 'Random',
    25: 'Scandinavia',
    26: 'Mongolia',
    27: 'Yucatan',
    28: 'Salt Marsh',
    29: 'Arena',
    30: 'King of the Hill',
    31: 'Oasis',
    32: 'Ghost Lake',
    33: 'Nomad',
    34: 'Iberia',
    35: 'Britain',
    36: 'Mideast',
    37: 'Texas',
    38: 'Italy',
    39: 'Central America',
    40: 'France',
    41: 'Norse Lands',
    42: 'Sea of Japan (East Sea)',
    43: 'Byzantinum',
    48: 'Blind Random',
    49: 'Acropolis',
    50: 'Budapest',
    51: 'Cenotes',
    52: 'City of Lakes',
    53: 'Golden Pit',
    54: 'Hideout',
    55: 'Hill Fort',
    56: 'Lombardia',
    57: 'Steppe',
    58: 'Valley',
    59: 'MegaRandom',
    60: 'Hamburger',
    61: 'CtR Random',
    62: 'CtR Monsoon',
    63: 'CtR Pyramid Descent',
    64: 'CtR Spiral',
    66: 'Acropolis',
    67: 'Budapest',
    68: 'Cenotes',
    69: 'City of Lakes',
    70: 'Golden Pit',
    71: 'Hideout',
    72: 'Hill Fort',
    73: 'Lombardia',
    74: 'Steppe',
    75: 'Valley',
    76: 'MegaRandom',
    77: 'Hamburger',
    78: 'CtR Random',
    79: 'CtR Monsoon',
    80: 'CtR Pyramid Descent',
    81: 'CtR Spiral',
    82: 'Kilimanjaro',
    83: 'Mountain Pass',
    84: 'Nile Delta',
    85: 'Serengeti',
    86: 'Socotra',
    87: 'Amazon',
    88: 'China',
    89: 'Horn of Africa',
    90: 'India',
    91: 'Madagascar',
    92: 'West Africa',
    93: 'Bohemia',
    94: 'Earth',
    95: 'Canyons',
    96: 'Enemy Archipelago',
    97: 'Enemy Islands',
    98: 'Far Out',
    99: 'Front Line',
    100: 'Inner Circle',
    101: 'Motherland',
    102: 'Open Plains',
    103: 'Ring of Water',
    104: 'Snakepit',
    105: 'The Eye',
    125: 'Ravines'
}

MAP_SIZES = {
    120: 'tiny',
    144: 'small',
    168: 'medium',
    200: 'normal',
    220: 'large',
    240: 'giant',
    255: 'maximum'
}

COMPASS = {
    'northwest': [1/3.0, 0],
    'southeast': [1/3.0, 2/3.0],
    'southwest': [0, 1/3.0],
    'northeast': [2/3.0, 1/3.0],
    'center': [1/3.0, 1/3.0],
    'west': [0, 0],
    'north': [2/3.0, 0],
    'east': [2/3.0, 2/3.0],
    'south': [0, 2/3.0]
}

VALID_BUILDINGS = [
    10, 12, 14, 18, 19, 20, 31, 32, 42, 45, 47, 49, 50, 51, 63, 64, 68, 70, 71, 72,
    78, 79, 82, 84, 85, 86, 87, 88, 90, 91, 101, 103, 104, 105, 109, 116, 117, 129,
    130, 131, 132, 133, 137, 141, 142, 153, 155, 199, 209, 210, 234, 235, 236, 276,
    331, 357, 463, 464, 465, 484, 487, 488, 490, 491, 498, 562, 563, 564, 565, 584,
    585, 586, 587, 597, 598, 617, 621, 659, 661, 665, 667, 669, 673, 674, 734, 789,
    790, 792, 793, 794, 796, 797, 798, 800, 801, 802, 804, 1189
] + [1553, 387, 110, 785, 1002] + [1021, 1187, 1251] + [946, 947, 886, 888, 881, 879, 938, 871] # 5th Age, Realms, DE, Various
<|endoftext|>


<commit_before>#!/usr/bin/env python

from __future__ import print_function
import codecs

import mhdb
import mhprob

def get_utf8_writer(writer):
    return codecs.getwriter("utf8")(writer)

def _format_range(min_v, max_v):
    if min_v == max_v:
        return "%5.2f" % min_v
    else:
        return "%5.2f to %5.2f" % (min_v, max_v)

def find_item(db, item_name, err_out):
    item_row = db.get_item_by_name(item_name)
    if item_row is None:
        print("Item '%s' not found. Listing partial matches:" % item_name,
              file=err_out)
        terms = item_name.split()
        for term in terms:
            if len(term) < 2:
                # single char terms aren't very useful, too many results
                continue
            print("= Matching term '%s'" % term, file=err_out)
            rows = db.search_item_name(term, "Flesh")
            for row in rows:
                print(" ", row["name"], file=err_out)
        return None
    return item_row

def print_monsters_and_rewards(db, item_row, out):
    item_id = item_row["_id"]
    monsters = db.get_item_monsters(item_id)
    for m in monsters:
        mid = m["monster_id"]
        rank = m["rank"]
        monster = db.get_monster(mid)
        cap_ev = [0, 0]
        kill_ev = [0, 0]
        shiny_ev = 0
        has_item = False
        rewards = db.get_monster_rewards(mid, rank)
        for reward in rewards:
            cap = kill = shiny = False
            if reward["item_id"] != item_id:
                continue
            if not has_item:
                has_item = True
                out.write("%s %s\n" % (monster["name"], rank))
            if reward["condition"] == "Body Carve":
                totals = [
                    3 + mhprob.carve_delta_expected_c(skill)
                    for skill in xrange(mhprob.CARVING_SKILL_PRO,
                                        mhprob.CARVING_SKILL_GOD+1)
                ]
                cap = False
                kill = True
            elif reward["condition"] == "Tail Carve":
                totals = [
                    1 + mhprob.carve_delta_expected_c(skill)
                    for skill in xrange(mhprob.CARVING_SKILL_PRO,
                                        mhprob.CARVING_SKILL_GOD+1)
                ]
                cap = kill = True
            elif reward["condition"] == "Capture":
                totals = [
                    mhprob.capture_reward_expected_c(skill)
                    for skill in xrange(mhprob.CAP_SKILL_NONE,
                                        mhprob.CAP_SKILL_GOD+1)
                ]
                cap = True
                kill = False
            else:
                totals = [1]
                # don't include Shiny in ev calculations
                if reward["condition"].startswith("Shiny"):
                    cap = kill = False
                    shiny = True
                elif reward["condition"].startswith("Break"):
                    cap = kill = True
                else:
                    raise ValueError("Unknown condition: "
                                     + reward["condition"])

            evs = [i *  reward["stack_size"] * reward["percentage"]
                   for i in totals]
            if cap:
                cap_ev[0] += evs[0]
                cap_ev[1] += evs[-1]
            if kill:
                kill_ev[0] += evs[0]
                kill_ev[1] += evs[-1]
            if shiny:
                shiny_ev += evs[0]

            out.write("  %20s %d %5.2f / 100" % (reward["condition"],
                                                 reward["stack_size"],
                                                 evs[0]))
            out.write(" (%2d each)" % reward["percentage"])
            if len(totals) > 1:
                out.write(" " + " ".join("%0.2f" % i for i in evs[1:]))
            out.write("\n")

        if has_item:
            out.write("  %20s\n" % "= Totals")
            out.write("  %20s %s / 100\n"
                      % ("Kill", _format_range(*kill_ev)))
            out.write("  %20s %s / 100\n"
                      % ("Cap", _format_range(*cap_ev)))
            if shiny_ev:
                out.write("  %20s %5.2f / 100\n" % ("Shiny", shiny_ev))
            out.write("\n")

def print_quests_and_rewards(db, item_row, out):
    """
    Get a list of the quests for acquiring a given item and the probability
    of getting the item, depending on cap or kill and luck skills.
    """
    item_id = item_row["_id"]
    quests = db.get_item_quest_objects(item_id)
    print_monsters_and_rewards(db, item_row, out)
    if not quests:
        return
    for q in quests:
        out.write(unicode(q) + "\n")
        out.write("  %20s" % "= Quest\n")
        quest_ev = 0
        sub_used = False

        fixed_other_rewards = dict(A=0, B=0, Sub=0)
        total_reward_p = dict(A=0, B=0, Sub=0)
        for reward in q._rewards:
            slot = reward["reward_slot"]
            #reward_item_row = db.get_item(reward["item_id"])
            #print slot, reward_item_row["name"], reward["percentage"]
            if reward["percentage"] == 100:
                if reward["item_id"] != item_id:
                    fixed_other_rewards[slot] += 1
            else:
                total_reward_p[slot] += reward["percentage"]

        # sanity check values from the db
        for slot in total_reward_p.keys():
            if total_reward_p[slot] not in (0, 100):
                print("WARNING: bad total p for %s = %d"
                      % (slot, total_reward_p[slot]), file=out)

        for reward in q._rewards:
            slot = reward["reward_slot"]
            #reward_item_row = db.get_item(reward["item_id"])
            #print slot, reward_item_row["name"], reward["percentage"]
            if reward["item_id"] == item_id:
                totals = [mhprob.quest_reward_expected_c(slot, skill)
                          for skill in xrange(mhprob.LUCK_SKILL_NONE,
                                              mhprob.LUCK_SKILL_GREAT+1)]

                evs = [((i - fixed_other_rewards[slot])
                        *  reward["stack_size"] * reward["percentage"])
                       for i in totals]

                out.write("  %20s %d %5.2f / 100" % (reward["reward_slot"],
                                                 reward["stack_size"],
                                                 evs[0]))
                out.write(" (%2d each)" % reward["percentage"])
                if len(totals) > 1:
                    out.write(" %s" % " ".join("%0.2f" % i for i in evs[1:]))
                out.write("\n")

                quest_ev += evs[0]
                if reward["reward_slot"] == "Sub":
                    sub_used = True
        monsters = db.get_quest_monsters(q.id)

        cap_ev = [quest_ev, quest_ev]
        kill_ev = [quest_ev, quest_ev]
        shiny_ev = 0
        for m in monsters:
            mid = m["monster_id"]
            monster = db.get_monster(mid)
            has_item = False
            rewards = db.get_monster_rewards(mid, q.rank)
            for reward in rewards:
                cap = kill = shiny = False
                if reward["item_id"] == item_id:
                    if not has_item:
                        has_item = True
                        out.write("  %20s\n"
                                  % ("= " + monster["name"] + " " + q.rank))
                    if reward["condition"] == "Body Carve":
                        totals = [
                            3 + mhprob.carve_delta_expected_c(skill)
                            for skill in xrange(mhprob.CARVING_SKILL_PRO,
                                                mhprob.CARVING_SKILL_GOD+1)
                        ]
                        cap = False
                        kill = True
                    elif reward["condition"] == "Tail Carve":
                        totals = [
                            1 + mhprob.carve_delta_expected_c(skill)
                            for skill in xrange(mhprob.CARVING_SKILL_PRO,
                                                mhprob.CARVING_SKILL_GOD+1)
                        ]
                        cap = kill = True
                    elif reward["condition"] == "Capture":
                        totals = [
                            mhprob.capture_reward_expected_c(skill)
                            for skill in xrange(mhprob.CAP_SKILL_NONE,
                                                mhprob.CAP_SKILL_GOD+1)
                        ]
                        cap = True
                        kill = False
                    else:
                        totals = [1]
                        # don't include Shiny in ev calculations
                        if reward["condition"].startswith("Shiny"):
                            cap = kill = False
                            shiny = True
                        elif reward["condition"].startswith("Break"):
                            cap = kill = True
                        else:
                            raise ValueError("Unknown condition: "
                                             + reward["condition"])

                    evs = [i *  reward["stack_size"] * reward["percentage"]
                           for i in totals]
                    if cap:
                        cap_ev[0] += evs[0]
                        cap_ev[1] += evs[-1]
                    if kill:
                        kill_ev[0] += evs[0]
                        kill_ev[1] += evs[-1]
                    if shiny:
                        shiny_ev += evs[0]

                    out.write("  %20s %d %5.2f / 100" % (reward["condition"],
                                                         reward["stack_size"],
                                                         evs[0]))
                    out.write(" (%2d each)" % reward["percentage"])
                    if len(totals) > 1:
                        out.write(" " + " ".join("%0.2f" % i for i in evs[1:]))
                    out.write("\n")
            out.write("  %20s\n" % "= Totals")
            out.write("  %20s %s / 100\n" % ("Kill", _format_range(*kill_ev)))
            out.write("  %20s %s / 100\n" % ("Cap", _format_range(*cap_ev)))
            if shiny_ev:
                out.write("  %20s %5.2f / 100\n" % ("Shiny", shiny_ev))
        out.write("\n")

if __name__ == '__main__':
    import sys
    import os
    import os.path

    if len(sys.argv) != 2:
        print("Usage: %s 'item name'" % sys.argv[0])
        sys.exit(os.EX_USAGE)

    item_name = sys.argv[1]

    out = get_utf8_writer(sys.stdout)
    err_out = get_utf8_writer(sys.stderr)

    # TODO: doesn't work if script is symlinked
    db_path = os.path.dirname(sys.argv[0])
    db_path = os.path.join(db_path, "db", "mh4u.db")
    db = mhdb.MHDB(db_path)

    item_row = find_item(db, item_name, err_out)
    if item_row is None:
        sys.exit(os.EX_DATAERR)
    print_quests_and_rewards(db, item_row, out)
<commit_msg>fix fixed rewards<commit_after>#!/usr/bin/env python

from __future__ import print_function
import codecs

import mhdb
import mhprob

def get_utf8_writer(writer):
    return codecs.getwriter("utf8")(writer)

def _format_range(min_v, max_v):
    if min_v == max_v:
        return "%5.2f" % min_v
    else:
        return "%5.2f to %5.2f" % (min_v, max_v)

def find_item(db, item_name, err_out):
    item_row = db.get_item_by_name(item_name)
    if item_row is None:
        print("Item '%s' not found. Listing partial matches:" % item_name,
              file=err_out)
        terms = item_name.split()
        for term in terms:
            if len(term) < 2:
                # single char terms aren't very useful, too many results
                continue
            print("= Matching term '%s'" % term, file=err_out)
            rows = db.search_item_name(term, "Flesh")
            for row in rows:
                print(" ", row["name"], file=err_out)
        return None
    return item_row

def print_monsters_and_rewards(db, item_row, out):
    item_id = item_row["_id"]
    monsters = db.get_item_monsters(item_id)
    for m in monsters:
        mid = m["monster_id"]
        rank = m["rank"]
        monster = db.get_monster(mid)
        cap_ev = [0, 0]
        kill_ev = [0, 0]
        shiny_ev = 0
        has_item = False
        rewards = db.get_monster_rewards(mid, rank)
        for reward in rewards:
            cap = kill = shiny = False
            if reward["item_id"] != item_id:
                continue
            if not has_item:
                has_item = True
                out.write("%s %s\n" % (monster["name"], rank))
            if reward["condition"] == "Body Carve":
                totals = [
                    3 + mhprob.carve_delta_expected_c(skill)
                    for skill in xrange(mhprob.CARVING_SKILL_PRO,
                                        mhprob.CARVING_SKILL_GOD+1)
                ]
                cap = False
                kill = True
            elif reward["condition"] == "Tail Carve":
                totals = [
                    1 + mhprob.carve_delta_expected_c(skill)
                    for skill in xrange(mhprob.CARVING_SKILL_PRO,
                                        mhprob.CARVING_SKILL_GOD+1)
                ]
                cap = kill = True
            elif reward["condition"] == "Capture":
                totals = [
                    mhprob.capture_reward_expected_c(skill)
                    for skill in xrange(mhprob.CAP_SKILL_NONE,
                                        mhprob.CAP_SKILL_GOD+1)
                ]
                cap = True
                kill = False
            else:
                totals = [1]
                # don't include Shiny in ev calculations
                if reward["condition"].startswith("Shiny"):
                    cap = kill = False
                    shiny = True
                elif reward["condition"].startswith("Break"):
                    cap = kill = True
                else:
                    raise ValueError("Unknown condition: "
                                     + reward["condition"])

            evs = [i *  reward["stack_size"] * reward["percentage"]
                   for i in totals]
            if cap:
                cap_ev[0] += evs[0]
                cap_ev[1] += evs[-1]
            if kill:
                kill_ev[0] += evs[0]
                kill_ev[1] += evs[-1]
            if shiny:
                shiny_ev += evs[0]

            out.write("  %20s %d %5.2f / 100" % (reward["condition"],
                                                 reward["stack_size"],
                                                 evs[0]))
            out.write(" (%2d each)" % reward["percentage"])
            if len(totals) > 1:
                out.write(" " + " ".join("%0.2f" % i for i in evs[1:]))
            out.write("\n")

        if has_item:
            out.write("  %20s\n" % "= Totals")
            out.write("  %20s %s / 100\n"
                      % ("Kill", _format_range(*kill_ev)))
            out.write("  %20s %s / 100\n"
                      % ("Cap", _format_range(*cap_ev)))
            if shiny_ev:
                out.write("  %20s %5.2f / 100\n" % ("Shiny", shiny_ev))
            out.write("\n")

def print_quests_and_rewards(db, item_row, out):
    """
    Get a list of the quests for acquiring a given item and the probability
    of getting the item, depending on cap or kill and luck skills.
    """
    item_id = item_row["_id"]
    quests = db.get_item_quest_objects(item_id)
    print_monsters_and_rewards(db, item_row, out)
    if not quests:
        return
    for q in quests:
        out.write(unicode(q) + "\n")
        out.write("  %20s" % "= Quest\n")
        quest_ev = 0
        sub_used = False

        fixed_rewards = dict(A=0, B=0, Sub=0)
        total_reward_p = dict(A=0, B=0, Sub=0)
        for reward in q._rewards:
            slot = reward["reward_slot"]
            #reward_item_row = db.get_item(reward["item_id"])
            #print slot, reward_item_row["name"], reward["percentage"]
            if reward["percentage"] == 100:
                fixed_rewards[slot] += 1
            else:
                total_reward_p[slot] += reward["percentage"]

        # sanity check values from the db
        for slot in total_reward_p.keys():
            if total_reward_p[slot] not in (0, 100):
                print("WARNING: bad total p for %s = %d"
                      % (slot, total_reward_p[slot]), file=out)

        for reward in q._rewards:
            slot = reward["reward_slot"]
            #reward_item_row = db.get_item(reward["item_id"])
            #print slot, reward_item_row["name"], reward["percentage"]
            if reward["item_id"] == item_id:
                if reward["percentage"] == 100:
                    totals = [100]
                    evs = [100 * reward["stack_size"]]
                else:
                    totals = [mhprob.quest_reward_expected_c(slot, skill)
                              for skill in xrange(mhprob.LUCK_SKILL_NONE,
                                                  mhprob.LUCK_SKILL_GREAT+1)]

                    evs = [((i - fixed_rewards[slot])
                            *  reward["stack_size"] * reward["percentage"])
                           for i in totals]

                out.write("  %20s %d %5.2f / 100" % (reward["reward_slot"],
                                                 reward["stack_size"],
                                                 evs[0]))
                out.write(" (%2d each)" % reward["percentage"])
                if len(totals) > 1:
                    out.write(" %s" % " ".join("%0.2f" % i for i in evs[1:]))
                out.write("\n")

                quest_ev += evs[0]
                if reward["reward_slot"] == "Sub":
                    sub_used = True
        monsters = db.get_quest_monsters(q.id)

        cap_ev = [quest_ev, quest_ev]
        kill_ev = [quest_ev, quest_ev]
        shiny_ev = 0
        for m in monsters:
            mid = m["monster_id"]
            monster = db.get_monster(mid)
            has_item = False
            rewards = db.get_monster_rewards(mid, q.rank)
            for reward in rewards:
                cap = kill = shiny = False
                if reward["item_id"] == item_id:
                    if not has_item:
                        has_item = True
                        out.write("  %20s\n"
                                  % ("= " + monster["name"] + " " + q.rank))
                    if reward["condition"] == "Body Carve":
                        totals = [
                            3 + mhprob.carve_delta_expected_c(skill)
                            for skill in xrange(mhprob.CARVING_SKILL_PRO,
                                                mhprob.CARVING_SKILL_GOD+1)
                        ]
                        cap = False
                        kill = True
                    elif reward["condition"] == "Tail Carve":
                        totals = [
                            1 + mhprob.carve_delta_expected_c(skill)
                            for skill in xrange(mhprob.CARVING_SKILL_PRO,
                                                mhprob.CARVING_SKILL_GOD+1)
                        ]
                        cap = kill = True
                    elif reward["condition"] == "Capture":
                        totals = [
                            mhprob.capture_reward_expected_c(skill)
                            for skill in xrange(mhprob.CAP_SKILL_NONE,
                                                mhprob.CAP_SKILL_GOD+1)
                        ]
                        cap = True
                        kill = False
                    else:
                        totals = [1]
                        # don't include Shiny in ev calculations
                        if reward["condition"].startswith("Shiny"):
                            cap = kill = False
                            shiny = True
                        elif reward["condition"].startswith("Break"):
                            cap = kill = True
                        else:
                            raise ValueError("Unknown condition: "
                                             + reward["condition"])

                    evs = [i *  reward["stack_size"] * reward["percentage"]
                           for i in totals]
                    if cap:
                        cap_ev[0] += evs[0]
                        cap_ev[1] += evs[-1]
                    if kill:
                        kill_ev[0] += evs[0]
                        kill_ev[1] += evs[-1]
                    if shiny:
                        shiny_ev += evs[0]

                    out.write("  %20s %d %5.2f / 100" % (reward["condition"],
                                                         reward["stack_size"],
                                                         evs[0]))
                    out.write(" (%2d each)" % reward["percentage"])
                    if len(totals) > 1:
                        out.write(" " + " ".join("%0.2f" % i for i in evs[1:]))
                    out.write("\n")
            out.write("  %20s\n" % "= Totals")
            out.write("  %20s %s / 100\n" % ("Kill", _format_range(*kill_ev)))
            out.write("  %20s %s / 100\n" % ("Cap", _format_range(*cap_ev)))
            if shiny_ev:
                out.write("  %20s %5.2f / 100\n" % ("Shiny", shiny_ev))
        out.write("\n")

if __name__ == '__main__':
    import sys
    import os
    import os.path

    if len(sys.argv) != 2:
        print("Usage: %s 'item name'" % sys.argv[0])
        sys.exit(os.EX_USAGE)

    item_name = sys.argv[1]

    out = get_utf8_writer(sys.stdout)
    err_out = get_utf8_writer(sys.stderr)

    # TODO: doesn't work if script is symlinked
    db_path = os.path.dirname(sys.argv[0])
    db_path = os.path.join(db_path, "db", "mh4u.db")
    db = mhdb.MHDB(db_path)

    item_row = find_item(db, item_name, err_out)
    if item_row is None:
        sys.exit(os.EX_DATAERR)
    print_quests_and_rewards(db, item_row, out)
<|endoftext|>