#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""IS211 Assignment 6 by Diandra Vega"""

import conversions
import conversions_refactored
import unittest
import random

class conversionTests(unittest.TestCase):
    """Class for testing conversion functionality in conversions.py"""
    nums = random.sample(range(1, 100), 5)

    def testConvertCelsiusToKelvin(self):
        """convertCelsiusToKelvin returns correct Kelvin conversion"""
        for celsius in self.nums:
            to_kelvin = float(celsius) + 273.15
            result = conversions.convertCelsiusToKelvin(celsius)
            self.assertEqual(to_kelvin, result)

    def testConvertCelsiusToFahrenheit(self):
        """convertCelsiusToFahrenheit returns correct Fahrenheit conversion"""
        for celsius in self.nums:
            to_fahrenheit = float(celsius) * 9 / 5 + 32
            result = conversions.convertCelsiusToFahrenheit(celsius)
            self.assertEqual(to_fahrenheit, result)

    def testConvertFahrenheitToCelsius(self):
        """convertFahrenheitToCelsius returns correct Celsius conversion"""
        for fahrenheit in self.nums:
            to_celsius = (float(fahrenheit) - 32) * 5 / 9
            result = conversions.convertFahrenheitToCelsius(fahrenheit)
            self.assertEqual(to_celsius, result)

    def testConvertFahrenheitToKelvin(self):
        """convertFahrenheitToKelvin returns correct Kelvin conversion"""
        for fahrenheit in self.nums:
            to_kelvin = (float(fahrenheit) + 459.67) * 5 / 9
            result = conversions.convertFahrenheitToKelvin(fahrenheit)
            self.assertEqual(to_kelvin, result)

    def testConvertKelvinToFahrenheit(self):
        """convertKelvinToFahrenheit returns correct Fahrenheit conversion"""
        for kelvin in self.nums:
            to_fahrenheit = float(kelvin) * 9 / 5 - 459.67
            result = conversions.convertKelvinToFahrenheit(kelvin)
            self.assertEqual(to_fahrenheit, result)

    def testConvertKelvinToCelsius(self):
        """convertKelvinToCelsius returns correct Celsius conversion"""
        for kelvin in self.nums:
            to_celsius = float(kelvin) - 273.15
            result = conversions.convertKelvinToCelsius(kelvin)
            self.assertEqual(to_celsius, result)

    def testItemEqualsSelf(self):
        """convert() returns itself when converted from itself"""
        testcase = ['yards',
                    'miles',
                    'meters',
                    'fahrenheit',
                    'celsius',
                    'kelvin']

        for val in testcase:
            unit1=unit2 = val

            for num in self.nums:
                self.assertEqual(conversions_refactored.convert(unit1, unit2,
                                                                num), num)

class conversionsRefactoredTests(unittest.TestCase):
    """Unit testing for conversions_refactored.py"""
    nums = random.sample(range(1, 100), 5)

    def testConvertTemperatures(self):
        """convert() returns correct temperature unit conversions"""

        for val in self.nums:
            celsius_to_kelvin = float(val) + 273.15
            celsius_to_fahrenheit = float(val) * 9 / 5 + 32
            fahrenheit_to_celsius = (float(val) - 32) * 5 / 9
            fahrenheit_to_kelvin = (float(val) + 459.67) * 5 / 9
            kelvin_to_fahrenheit = float(val) * 9 / 5 - 459.67
            kelvin_to_celsius = float(val) - 273.15

            test1 = conversions_refactored.convert("celsius", "kelvin", val)
            test2 = conversions_refactored.convert("celsius", "fahrenheit",
                                                     val)
            test3 = conversions_refactored.convert("fahrenheit", "celsius",
                                                     val)
            test4 = conversions_refactored.convert("fahrenheit", "kelvin",
                                                     val)
            test5 = conversions_refactored.convert("kelvin", "fahrenheit",
                                                     val)
            test6 = conversions_refactored.convert("kelvin", "celsius", val)

            self.assertEqual(celsius_to_kelvin, test1,
                             "Celsius to Kelvin conversion failed")
            self.assertEqual(celsius_to_fahrenheit, test2,
                             "Celsius to Fahrenheit conversion failed")
            self.assertEqual(fahrenheit_to_celsius, test3,
                             "Fahrenheit to Celsius conversion failed")
            self.assertEqual(fahrenheit_to_kelvin, test4,
                             "Fahrenheit to Kelvin conversion failed")
            self.assertEqual(kelvin_to_fahrenheit, test5,
                             "Kelvin to Fahrenheit conversion failed")
            self.assertEqual(kelvin_to_celsius, test6,
                             "Kelvin to Celsius conversion failed")

    def testConvertDistance(self):
        """convert() returns correct distance conversions"""

        for val in self.nums:
            yards_to_miles = float(val) / 1760
            yards_to_meters = float(val) / 1.094
            meters_to_yards = float(val) * 1.094
            meters_to_miles = float(val) / 1609.344
            miles_to_yards = float(val) * 1760
            miles_to_meters = float(val) * 1609.344

            test1 = conversions_refactored.convert("yards", "miles", val)
            test2 = conversions_refactored.convert("yards", "meters", val)
            test3 = conversions_refactored.convert("meters", "yards", val)
            test4 = conversions_refactored.convert("meters", "miles", val)
            test5 = conversions_refactored.convert("miles", "yards", val)
            test6 = conversions_refactored.convert("miles", "meters", val)

            self.assertEqual(yards_to_miles, test1,
                             "Yards to Miles conversion failed")
            self.assertEqual(yards_to_meters, test2,
                             "Yards to Meters conversion failed")
            self.assertEqual(meters_to_yards, test3,
                             "Meters to Yards conversion failed")
            self.assertEqual(meters_to_miles, test4,
                             "Meters to Miles conversion failed")
            self.assertEqual(miles_to_yards, test5,
                             "Miles to Yards conversion failed")
            self.assertEqual(miles_to_meters, test6,
                             "Miles to Meters conversion failed")

    def testInvalidUnits(self):
        """convert() fails with invalid units"""
        testcase = {'test1': 'cat',
                    'test2': 'dog',
                    'test3': 'bird',
                    'test4': 'cow',
                    'test5': 'pig'}

        for key, val in testcase.iteritems():
            unit1 = key
            unit2 = val

            for num in self.nums:
                self.assertRaises(conversions_refactored.ConversionNotPossible,
                                  conversions_refactored.convert, unit1, unit2,
                                  num)

if __name__ == '__main__':
    unittest.main()


import os
import click
import inspect
from itertools import chain
from nornir_cli.common_commands import _doc_generator
from nornir_cli import __version__

CMD_FOLDERS = ["common_commands", "custom_commands"]

PACKAGE_NAME = "nornir_cli"

SETTINGS = {
    "nornir_scrapli": {
        "NetconfScrape": "scrapli_netconf.driver",
        "NetworkDriver": "scrapli.driver",
        "GenericDriver": "scrapli.driver",
    },
    "nornir_netmiko": {
        "BaseConnection": "netmiko",
        "file_transfer": "netmiko",
    },
}

PARAMETER_TYPES = {
    str: click.STRING,
    type(None): click.STRING,
    int: click.INT,
    float: click.FLOAT,
    bool: click.BOOL,
}

# options callback
# def callback(ctx, param, value):
#     if value != param.get_default(ctx):
#         ctx.obj["kwargs"].update(dict([[param.name, _json_loads([value])[0]]]))
#         ctx.obj["parameters"].append({ctx.obj["original"]: ctx.obj["kwargs"]})
#         ctx.obj["generator"] = (
#             dict(list(item.items())) for item in ctx.obj["parameters"]
#         )

# get original function from original modules (check SETTINGS)
def get_sources(plugin, l):
    try:
        for key, value in SETTINGS[plugin].items():
            m = lambda: None
            m.sub = __import__(value, fromlist=[key])
            o = getattr(m.sub, key, None)
            source_f = [f for f in o.__dict__.keys() if not f.startswith("_")]
            command = sorted(
                [i for i in source_f if l[l.find("_") + 1 : :] in i], key=len
            )
            if command:
                return getattr(o, command[0], None)
            elif inspect.isfunction(o):
                return o
    except KeyError:
        return

def _get_cmd_folder(cmd_folders):
    for cmd_folder in cmd_folders:
        yield os.path.abspath(os.path.join(os.path.dirname(__file__), cmd_folder))

def _get_cli(path, cmd_name, cmd_folder):
    if f"cmd_{cmd_name}.py" in os.listdir(cmd_folder):
        obj = __import__(f"{path}.cmd_{cmd_name}", None, None, ["cli"])
        return obj.cli

# mini factory for the production of classes for our plugins
# https://click.palletsprojects.com/en/7.x/commands/?highlight=multi%20command#custom-multi-commands
def class_factory(name, plugin, BaseClass=click.Group):
    def list_commands(self, ctx):
        ctx.obj[plugin] = __import__(plugin, fromlist=["tasks"])
        return [
            filename[4:-3]
            for filename in os.listdir(next(_get_cmd_folder(["common_commands"])))
            if filename.endswith(".py") and filename.startswith("cmd_")
        ] + list(ctx.obj[plugin].tasks.__all__)

    def list_custom_commands(self, ctx):
        cmd_folders = _get_cmd_folder(CMD_FOLDERS)
        return [
            filename[4:-3]
            for filename in chain(*map(os.listdir, cmd_folders))
            if filename.endswith(".py") and filename.startswith("cmd_")
        ]

    def get_command(self, ctx, cmd_name):
        ctx.obj["kwargs"] = {}
        try:
            # init, filter, show_inventory, etc
            command = _get_cli(
                f"{PACKAGE_NAME}.common_commands",
                cmd_name,
                next(_get_cmd_folder(["common_commands"])),
            )
            if command:
                return command

            # nornir-plugin commands
            plugin_command = _get_cli(
                f"{PACKAGE_NAME}.plugin_commands",
                "common",
                next(_get_cmd_folder(["plugin_commands"])),
            )

            ctx.obj[plugin] = __import__(plugin, fromlist=["tasks"])
            ctx.obj["original"] = getattr(ctx.obj[plugin].tasks, cmd_name, None)

            # decorate the command and cover it with click.Options
            return decorator(plugin, ctx)(plugin_command)
        except (ImportError, AttributeError):
            return

    def get_custom_command(self, ctx, cmd_name):
        try:
            for abs_path, rel_path in zip(_get_cmd_folder(CMD_FOLDERS), CMD_FOLDERS):
                command = _get_cli(f"{PACKAGE_NAME}.{rel_path}", cmd_name, abs_path)
                if command:
                    return command
        except (ImportError, AttributeError):
            return

    newclass = type(
        name,
        (BaseClass,),
        {
            "list_commands": list_commands if plugin else list_custom_commands,
            "get_command": get_command if plugin else get_custom_command,
        },
    )
    return newclass

# dynamically create a class for plugin/group and inherit it
def dec(param=None):
    def wrapper(f):
        return init_nornir_cli.group(cls=scls, chain=True)(f)

    scls = class_factory("LazyClass", param)
    return wrapper

#
def decorator(plugin, ctx):
    def wrapper(f):
        # methods with a large and complex __doc__ :(
        method_exceptions = ("send_interactive",)

        short_help = obj_or.__doc__.split("\n")[1].strip(", ., :")

        f.__doc__ = "\n".join(list(_doc_generator(obj_or.__doc__)))

        if obj_or.__name__ in method_exceptions:
            f.__doc__ = f"{short_help}\n" + "\n".join(
                list(
                    _doc_generator(obj_or.__doc__[obj_or.__doc__.find("    Args:") : :])
                )
            )

        cmd = click.command(name=obj_or.__name__, short_help=short_help)(f)

        click.option(
            "--pg_bar",
            is_flag=True,
            show_default=True,
        )(cmd)
        click.option(
            "--show_result/--no_show_result",
            default=True,
            show_default=True,
        )(cmd)

        # get original function from the main module
        original_function = get_sources(plugin, obj_or.__name__)
        sig0 = inspect.signature(obj_or)
        p = dict(sig0.parameters)
        if original_function:
            sig = inspect.signature(original_function)
            k = dict(sig.parameters)
            p.update(k)
        all_dict = {
            key: value
            for key, value in p.items()
            if key not in ["self", "task", "args", "kwargs"]
        }
        # dynamically generate options
        for k, v in all_dict.items():
            default_value = str(v.default) if not isinstance(v.default, type) else None
            click.option(
                "--" + k,
                default=default_value,
                show_default=True,
                required=False if default_value else True,
                # expose_value=False,
                # callback=callback,
                # is_eager=True,
                type=PARAMETER_TYPES.setdefault(type(v.default), click.STRING),
            )(cmd)
            # last original functions with arguments
            ctx.obj["queue_parameters"][obj_or].update({k: v.default})
        # list of dictionaries with original function (key) and set of arguments (value)
        ctx.obj["queue_functions"].append(ctx.obj["queue_parameters"])
        # ctx.obj["queue_functions"] in the form of a generator expression
        ctx.obj["queue_functions_generator"] = (
            func_param for func_param in ctx.obj["queue_functions"]
        )
        return cmd

    # get original function from Nornir plugin
    obj_or = ctx.obj["original"]

    ctx.obj["queue_parameters"] = {}

    ctx.obj["queue_parameters"][obj_or] = {}

    return wrapper

@click.group()
@click.version_option(version=__version__)
@click.pass_context
def init_nornir_cli(ctx):
    """
    Nornir CLI

    Orchestrate your Inventory and start Tasks and Runbooks
    """

    ctx.ensure_object(dict)
    # list of dictionaries with original function (key) and set of arguments (value)
    ctx.obj["queue_functions"] = []
    # last original functions with arguments
    ctx.obj["queue_parameters"] = {}

@dec("nornir_netmiko")
def nornir_netmiko():
    """
    nornir_netmiko plugin
    """
    pass

@dec("nornir_scrapli")
def nornir_scrapli():
    """
    nornir_scrapli plugin
    """
    pass

@dec("nornir_napalm.plugins")
def nornir_napalm():
    """
    nornir_napalm plugin
    """
    pass

@dec()
def custom():
    """
    custom nornir runbooks
    """
    pass


#encoding: utf-8
# Julio 2008 - Martin Salcedo
from OpenOrange import *
from Report import Report
from Currency import Currency

class SalesByCustomerMonthly(Report):

    def defaults(self):
        Report.defaults(self)
        record = self.getRecord()
        record.SortBy = 0
        record.IncludeInvoices=True
        record.IncludeDebitNotes=True
        record.IncludeCreditNotes=True

    def run(self):
        record = self.getRecord()
        self.record = record

        mlist = []
        fdate = date(record.FromDate.year,record.FromDate.month,1)
        tdate = date(record.ToDate.year,record.ToDate.month,1)
        while (fdate <= tdate):
            mlist.append("%s-%s" %(fdate.year,str(fdate.month).rjust(2,"0")))
            fdate = addMonths(fdate,1)
        mlist.sort()

        iquery = Query()
        if (record.UserCustomerGroup):
            iquery.sql  = "SELECT IF((C.GroupCode IS NULL OR C.GroupCode = ''),I.CustCode,C.GroupCode) CustCode, \n"
            iquery.sql += "       IF((C.GroupCode IS NULL OR C.GroupCode = ''),C.Name,CG.Name) CustName, \n"
            iquery.sql += "       IF((C.GroupCode IS NULL OR C.GroupCode = ''),'C','G') LineType, \n"
        else:
            iquery.sql  = "SELECT I.CustCode, C.Name AS CustName, 'C' LineType, \n"

        iquery.sql += "I.TransDate, YEAR(I.TransDate) YY, MONTH(I.TransDate) MM, SUM(I.SubTotal) SubTotal,[I].{Currency},[I].{CurrencyRate},[I].{BaseRate},[I].{TransDate},[I].{TransTime} \n"
        iquery.sql += "FROM [Invoice] I \n"
        iquery.sql += "INNER JOIN [Customer] C ON C.Code = I.CustCode \n"
        iquery.sql += "LEFT JOIN CustomerGroup CG ON CG.Code = C.GroupCode \n"
        iquery.sql += "WHERE?AND I.TransDate BETWEEN d|%s| AND d|%s| \n" %(record.FromDate,record.ToDate)
        iquery.sql += "WHERE?AND I.Status = i|1| AND (I.Invalid = 0 OR I.Invalid IS NULL ) \n"
        if (record.CustomerGroup):
            iquery.sql += "WHERE?AND C.GroupCode = s|%s| \n" %record.CustomerGroup
        if (record.CustCode):
            iquery.sql += "WHERE?AND I.CustCode = s|%s| \n" %record.CustCode
        if (record.Salesman):
            if (record.UseSalesman == 0):
                iquery.sql += "WHERE?AND I.Salesman = s|%s| \n" %record.Salesman
            elif (record.UseSalesman == 1):
                iquery.sql += "WHERE?AND C.Salesman = s|%s| \n" %record.Salesman
        if not (record.IncludeInvoices and record.IncludeCreditNotes and record.IncludeDebitNotes):
            invoicetypes = [-1]
            if record.IncludeInvoices: invoicetypes.append(0)
            if record.IncludeCreditNotes: invoicetypes.append(1)
            if record.IncludeDebitNotes: invoicetypes.append(2)
            iquery.sql += "WHERE?AND I.InvoiceType IN (%s)\n" % ",".join(["i|%s|" % x for x in invoicetypes])
        iquery.sql += "GROUP BY {CustCode},[I].{Currency},[I].{CurrencyRate},[I].{BaseRate},YY,MM \n"
        self.printReportTitle("Sales Statistic By Customer/Month")
        self.startTable()

        self.startHeaderRow()
        self.addValue(tr("Code"))
        self.addValue(tr("Name"))
        for mline in mlist:
            self.addValue(mline)
        self.addValue(tr("Total"))
        self.endHeaderRow()

        slist = {}
        clist = []
        tt = {}
        if (iquery.open()):
            for rline in iquery:
                ymonth = "%s-%s" %(rline.YY,str(rline.MM).rjust(2,"0"))
                listkey = (rline.CustCode, rline.CustName)
                cy = Currency.bring(rline.Currency)
                SubTotal = cy.convertToBase(rline.SubTotal,rline.CurrencyRate,rline.BaseRate,0)
                if (not listkey in clist):
                    clist.append(listkey)
                if (not slist.has_key(rline.CustCode)):
                    slist[rline.CustCode] = {}
                    tt[rline.CustCode] = 0.0
                    slist[rline.CustCode]["CustName"] = rline.CustName
                    slist[rline.CustCode]["LineType"] = rline.LineType
                if (not slist[rline.CustCode].has_key(ymonth)):
                    slist[rline.CustCode][ymonth] = 0
                slist[rline.CustCode][ymonth] += SubTotal
                tt[rline.CustCode] += SubTotal

            if (record.SortBy == 2):
                def sorter(key):
                    return tt[key[0]]
                clist.sort(key=sorter, reverse=True)
            else:
                clist.sort(key=lambda x: x[record.SortBy])
            GTotal = {}
            GTotal["Total"] = 0
            for rline in clist:
                custcode,custname = rline
                fcolor = self.DefaultForeColor
                if (slist[custcode]["LineType"] == "G"):
                    fcolor = "#0000CC"
                self.startRow()
                if (str(slist[custcode]["LineType"]) == "G"):
                    self.addValue(custcode,CallMethod="openByCustomer",Parameter="%s" %custcode,Color=fcolor)
                else:
                    self.addValue(custcode,Color=fcolor)
                self.addValue(slist[custcode]["CustName"],Color=fcolor)
                Total = 0
                for dline in mlist:
                    amount = slist[custcode].get(dline,0.0)
                    self.addValue(amount,Color=fcolor)
                    Total += amount
                    if (not GTotal.has_key(dline)):
                        GTotal[dline] = 0
                    GTotal[dline] += amount
                GTotal["Total"] += Total
                self.addValue(Total,Color=fcolor)
                self.endRow()
            self.startHeaderRow()
            self.addValue("")
            self.addValue("Totales")
            for dline in mlist:
                self.addValue(GTotal.get(dline,0.0))
            self.addValue(GTotal.get("Total",0.0))
            self.endHeaderRow()
        self.endTable()

        if (record.ShowWithoutMovement):
            self.startTable()
            self.row("")
            self.startRow(Style="B")
            self.addValue(tr("Customers without movement"))
            self.endRow()

            self.endTable()

            self.startTable()
            cquery = Query()
            cquery.sql = "SELECT C.Code,C.Name FROM [Customer] C "
            if (record.Salesman):
                cquery.sql += "WHERE?AND C.Salesman = s|%s| " %record.Salesman
            cquery.sql += "ORDER BY C.Code "
            if (cquery.open()):
                #alert(cquery.sql)
                self.startHeaderRow()
                self.addValue(tr("Code"))
                self.addValue(tr("Name"))
                self.endHeaderRow()

                for rline in cquery:
                    if (not rline.Code in clist):
                        self.startRow()
                        self.addValue(rline.Code)
                        self.addValue(rline.Name)
                        self.endRow()
            self.endTable()

    def openByCustomer(self, param, value):
        obc = SalesByCustomerMonthly()
        obc.getRecord().FromDate = self.record.FromDate
        obc.getRecord().ToDate = self.record.ToDate
        obc.getRecord().Salesman = self.record.Salesman
        obc.getRecord().CustomerGroup = param
        obc.getRecord().SortBy = self.record.SortBy
        obc.getRecord().UserCustomerGroup = False
        obc.getRecord().SortBy = self.record.SortBy
        obc.getRecord().IncludeInvoices = self.record.IncludeInvoices
        obc.getRecord().IncludeDebitNotes = self.record.IncludeDebitNotes
        obc.getRecord().IncludeCreditNotes = self.record.IncludeCreditNotes
        obc.open(False)


###~~~MiniPi - Raspberry Pi Car Control - Daniel Osborne 2017~~~###

'''A module for controlling a model car via a Raspberry Pi Zero.'''

##Import required modules:
import RPi.GPIO as GPIO
#from msvcrt import getch ##Windows
from getch import getch ##Linux
from threading import Thread
import time

##Define module variables:
developerMode = True #temp - default changed later
slowForSeconds = 5

##Pin dictionary stores GPIO pin numbers against pin names so that pin numbers need only be configured here:
pinDictionary = {
    'forward': 17,
    'backward': 18,
    'left': 23,
    'right': 22,
}

##Status object tracks current operation desired:
status = {
    'running': True,
    'drive': None,
    'slowingStarted': None,
    'steering': None,
    'indicatorLights': None,
    'mainLights': None,
    'brakeLights': False,
    'reversingLights': False,
    'parkingLights': False,
    'horn': False,
    'sound': False,
}

##Define output functions:
def print_developer(message):
	'''A function to print a message if in developer mode.'''
	global developerMode
	if developerMode:
		print(message)

##Define pin control functions:
def configure_pin(pinDictionaryKey):
	'''A function to configure a GPIO pin.'''
	GPIO.setup(pinDictionary[pinDictionaryKey], GPIO.OUT)

def unconfigure_pins():
	'''A function to unconfigure the GPIO pins.'''
	GPIO.cleanup()

def control_pin(pinDictionaryKey,value):
	'''A function to control a GPIO pin.'''
	assert (value or not value)
	GPIO.output(pinDictionary[pinDictionaryKey], value)
	print("Set pin " + str(pinDictionary[pinDictionaryKey]) + " to " + str(value))

def start_up():
	'''A function to handle the start up of the program and initialise all of the required pins.'''
	GPIO.setmode(GPIO.BCM)
	for eachKey in pinDictionary.keys():
		configure_pin(eachKey)
		control_pin(eachKey, False)

##Define control functions:
def slowing_control():
	'''A function to control drive motor slowing.'''
	global status
	if (status['slowingStarted'] == None):
		return False
	elif ((time.time() - status['slowingStarted']) >= slowForSeconds):
		status['slowingStarted'] = None
		return False
	else:
		print_developer("Action Cancelled: Still slowing...")
		status['drive'] = 'slowing'
		return True

def drive_control():
	'''A function to enact changes to the status of the drive.'''
	global status
	if status['running']:
		if not slowing_control():
			##Control drive:
			if (status['drive'] == None):
				control_pin('forward',False)
				control_pin('backward',False)
			elif (status['drive'] == 'slowing'):
				control_pin('forward',True)
				control_pin('backward',True)
				status['slowingStarted'] = time.time()
			elif (status['drive'] == 'forward'):
				control_pin('backward',False)
				control_pin('forward',True)
			elif (status['drive'] == 'backward'):
				control_pin('forward',False)
				control_pin('backward',True)
			else:
				print("Warning: Unknown driving status!")

def steering_control():
	'''A function to enact changes to the status of the steering.'''
	global status
	if status['running']:
		##Control steering:
		if (status['steering'] == None):
			control_pin('left',False)
			control_pin('right',False)
		elif (status['steering'] == 'left'):
			control_pin('right',False)
			control_pin('left',True)
		elif (status['steering'] == 'right'):
			control_pin('left',False)
			control_pin('right',True)
		else:
			print("Warning: Unknown steering status!")

def lights_control():
	'''A function to enact changes to the status of the lights.'''
	pass

def sound_control():
	'''A function to enact changes to the status of the sound.'''
	pass

##Define status setting functions:
def forward_pressed():
	'''A function to handle the event of a forward button being pressed.'''
	global status
	if (status['drive'] == 'forward'):
		status['drive'] = None
		print_developer("No longer going forward...")
	elif (status['drive'] == 'backward'):
		status['drive'] = 'slowing'
		print_developer("Now slowing...")
	elif (status['drive'] == 'slowing'):
		status['drive'] = 'forward'
		print_developer("Trying to go forward...")
	elif (status['drive'] == None):
		status['drive'] = 'forward'
		print_developer("Now going forward...")

def backward_pressed():
	'''A function to handle the event of a backward button being pressed.'''
	global status
	if (status['drive'] == 'backward'):
		status['drive'] = None
		print_developer("No longer going backward...")
	elif (status['drive'] == 'forward'):
		status['drive'] = 'slowing'
		print_developer("Now slowing...")
	elif (status['drive'] == 'slowing'):
		status['drive'] = 'backward'
		print_developer("Trying to go backward...")
	elif (status['drive'] == None):
		status['drive'] = 'backward'
		print_developer("Now going backward...")

def left_pressed():
	'''A function to handle the event of a left button being pressed.'''
	global status
	if (status['steering'] == 'left'):
		status['steering'] = None
		print_developer("Now going straight...")
	elif ((status['steering'] == 'right') or (status['steering'] == None)):
		status['steering'] = 'left'
		print_developer("Now turning left...")

def right_pressed():
	'''A function to handle the event of a right button being pressed.'''
	global status
	if (status['steering'] == 'right'):
		status['steering'] = None
		print_developer("Now going straight...")
	elif ((status['steering'] == 'left') or (status['steering'] == None)):
		status['steering'] = 'right'
		print_developer("Now turning right...")

def stop_all():
	'''A function to handle a spacebar pressed 'stop-all' event.'''
	global status
	if (status['drive'] in ['forward','backward']): #Prevents emergency stop cancelling slowing countdown.
		status['drive'] = None
	status['steering'] = None
	status['lights'] = None
	print_developer("Emergency stop performed!")

def left_indicator_pressed():
	'''A function to handle the event of a left indicator button being pressed.'''
	global status
	if (status['indicatorLights'] == 'left'):
		status['indicatorLights'] = None
		print_developer("Left indicator cancelled...")
	elif (status['indicatorLights'] in ['right',None,'hazard']):
		status['indicatorLights'] = 'left'
		print_developer("Now indicating left...")

def right_indicator_pressed():
	'''A function to handle the event of a right indicator button being pressed.'''
	global status
	if (status['indicatorLights'] == 'right'):
		status['indicatorLights'] = None
		print_developer("Right indicator cancelled...")
	elif (status['indicatorLights'] in ['left',None,'hazard']):
		status['indicatorLights'] = 'right'
		print_developer("Now indicating right...")

def hazards_pressed():
	'''A function to handle the event of a hazards button being pressed.'''
	global status
	if (status['indicatorLights'] == 'hazard'):
		status['indicatorLights'] = None
		print_developer("Hazard lights cancelled...")
	else:
		status['indicatorLights'] = 'hazard'
		print_developer("Hazard warning lights set...")

def toggle_parking_lights():
	'''A function to toggle the parking lights on / off.'''
	global status
	if (status['parkingLights']):
		status['parkingLights'] = False
		print_developer("Parking lights turned off...")
	else:
		status['parkingLights'] = True
		print_developer("Parking lights turned on...")

def dipped_beam_pressed():
	'''A function to handle the event of a dipped beam button being pressed.'''
	global status
	if (status['mainLights'] == 'dipped'):
		status['mainLights'] = None
		print_developer("Dipped beam lights turned off...")
	elif (status['mainLights'] in ['main',None]):
		status['mainLights'] = 'dipped'
		print_developer("Dipped beam lights turned on...")

def main_beam_pressed():
	'''A function to handle the event of a main beam button being pressed.'''
	global status
	if (status['mainLights'] == 'main'):
		status['mainLights'] = None
		print_developer("Main beam lights turned off...")
	elif (status['mainLights'] in ['dipped',None]):
		status['mainLights'] = 'main'
		print_developer("Main beam lights turned on...")

def toggle_horn():
	'''A function to toggle the horn on / off.'''
	global status
	if (status['horn']):
		status['horn'] = False
		print_developer("Horn turned off...")
	else:
		status['horn'] = True
		print_developer("Horn turned on...")

def toggle_sound():
	'''A function to toggle the sound on / off.'''
	global status
	if (status['sound']):
		status['sound'] = False
		print_developer("Sound turned off...")
	else:
		status['sound'] = True
		print_developer("Sound turned on...")

def toggle_developer_mode():
	'''A function to toggle developer mode on / off.'''
	global developerMode
	if developerMode:
		developerMode = False
		print("Developer mode turned off...")
	else:
		developerMode = True
		print("Developer mode turned on...")

def action_control_key(key):
	'''A function to action a controlling key press.'''
	if (key == 32):
		stop_all()
		drive_control()
		steering_control()
		lights_control()
		sound_control()
	elif (key in [72,119]): ##Up arrow and 'w'
		forward_pressed()
		drive_control()
	elif (key in [80,115]): ##Down arrow and 's'
		backward_pressed()
		drive_control()
	elif (key in [75,97]): ##Left arrow and 'a'
		left_pressed()
		steering_control()
	elif (key in [77,100]): ##Right arrow and 'd'
		right_pressed()
		steering_control()
	elif (key == 108): ##'l'
		left_indicator_pressed()
		lights_control()
	elif (key == 114): ##'r'
		right_indicator_pressed()
		lights_control()
	elif (key == 35):
		hazards_pressed()
		lights_control()
	elif (key == 104): ##'#'
		toggle_horn()
		sound_control()
	elif (key == 113): ##'q'
		toggle_sound()
		sound_control()
	elif (key == 63): ##'?'
		toggle_developer_mode()
	elif (key == 112): ##'p'
		toggle_parking_lights()
		lights_control()
	elif (key == 110): ##'n'
		dipped_beam_pressed()
		lights_control()
	elif (key == 109): ##'m'
		main_beam_pressed()
		lights_control()

##Define input functions:
def watch_keyboard():
	'''A function to monitor the keyboard for key-press events and act upon them.'''
	global status
	while status['running']:
		watching = True
		while watching:
			key = ord(getch())
			if (key == 27): ##Escape.
				print("Are you sure you want to exit? Press 'Y' to confirm or any other key to cancel: ")
				key = ord(getch())
				if (key == 89):
					watching = False
					stop_all()
					drive_control()
					steering_control()
					lights_control()
					status['running'] = False
					print("Exiting...")
					break
			elif (key == 224): ##Special keys
				key = ord(getch())
				##print_developer(key)
				action_control_key(key)
			else:
				##print_developer(key)
				action_control_key(key)
			key = None

##Define running code:
if __name__ == '__main__':
	print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
	print("MiniPi starting up!..")
	print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

	##Configure the required pins into the required format:
	unconfigure_pins() ##As some boot in the wrong configuration or already loaded.
	start_up()
	##Start listener thread - Reads key input and uses this to change the status list:
	watch_keyboard()
	##Unconfigure pins for complete exit.
	unconfigure_pins()
	print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
	print("Shutdown complete!")
	print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

#temp - need lights
#temp - need sound
#temp - need to activate and deactive brake lights for slowing. - in light control thread -> look for 'slowing' status
#temp - need to activate and deactive reversing lights for reversing - in light control thread -> look for 'backward' status
#temp - add auto cancelling of indicator after turning!
#temp - is shutdown waiting long enough?
#temp - key bindings - could have text file to save and ability to load different 'users'.
#temp - are slowing and off set the correct way around in drive_control?


# MIT License
#
# Copyright (c) 2018-2019 Red Hat, Inc.

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import datetime
import logging
from typing import List, Optional, Dict, Any, Set

import requests

from ogr.abstract import PRStatus, GitTag, CommitFlag, CommitComment
from ogr.abstract import (
    PullRequest,
    PRComment,
    Issue,
    IssueStatus,
    IssueComment,
    Release,
)
from ogr.exceptions import (
    OurPagureRawRequest,
    PagureAPIException,
    OgrException,
    OperationNotSupported,
)
from ogr.factory import use_for_service
from ogr.read_only import if_readonly, GitProjectReadOnly
from ogr.parsing import parse_git_repo
from ogr.services.base import BaseGitService, BaseGitProject, BaseGitUser
from ogr.utils import RequestResponse

logger = logging.getLogger(__name__)

@use_for_service("pagure.io")
@use_for_service("src.fedoraproject.org")
class PagureService(BaseGitService):
    def __init__(
        self,
        token: str = None,
        instance_url: str = "https://src.fedoraproject.org",
        read_only: bool = False,
        insecure: bool = False,
        **_,
    ) -> None:
        super().__init__()
        self.instance_url = instance_url
        self._token = token
        self.read_only = read_only

        self.session = requests.session()

        adapter = requests.adapters.HTTPAdapter(max_retries=5)

        self.insecure = insecure
        if self.insecure:
            self.session.mount("http://", adapter)
        else:
            self.session.mount("https://", adapter)

        self.header = {"Authorization": "token " + self._token} if self._token else {}

    def __str__(self) -> str:
        return f'PagureService(read_only={self.read_only}, instance_url="{self.instance_url}")'

    def __eq__(self, o: object) -> bool:
        if not issubclass(o.__class__, PagureService):
            return False

        return (
            self._token == o._token  # type: ignore
            and self.read_only == o.read_only  # type: ignore
            and self.instance_url == o.instance_url  # type: ignore
            and self.insecure == o.insecure  # type: ignore
            and self.header == o.header  # type: ignore
        )

    def get_project(self, **kwargs) -> "PagureProject":
        return PagureProject(service=self, **kwargs)

    def get_project_from_url(self, url: str) -> "PagureProject":
        repo_url = parse_git_repo(potential_url=url)
        project = self.get_project(
            repo=repo_url.repo,
            namespace=repo_url.namespace,
            is_fork=repo_url.is_fork,
            username=repo_url.username,
        )
        return project

    @property
    def user(self) -> "PagureUser":
        return PagureUser(service=self)

    def call_api(
        self, url: str, method: str = None, params: dict = None, data=None
    ) -> dict:
        """ Method used to call the API.
        It returns the raw JSON returned by the API or raises an exception
        if something goes wrong.
        """
        response = self.call_api_raw(url=url, method=method, params=params, data=data)

        if response.status_code == 404:
            error_msg = (
                response.json["error"]
                if response.json and "error" in response.json
                else None
            )
            raise PagureAPIException(
                f"Page `{url}` not found when calling Pagure API.",
                pagure_error=error_msg,
            )

        if not response.json:
            logger.debug(response.content)
            raise PagureAPIException("Error while decoding JSON: {0}")

        if not response.ok:
            logger.error(response.json)
            if "error" in response.json:
                error_msg = response.json["error"]
                raise PagureAPIException(
                    f"Pagure API returned an error when calling `{url}`: {error_msg}",
                    pagure_error=error_msg,
                )
            raise PagureAPIException(f"Problem with Pagure API when calling `{url}`")

        return response.json

    def call_api_raw(
        self, url: str, method: str = None, params: dict = None, data=None
    ):
        method = method or "GET"
        try:
            response = self.get_raw_request(
                method=method, url=url, params=params, data=data
            )

        except requests.exceptions.ConnectionError as er:
            logger.error(er)
            raise PagureAPIException(f"Cannot connect to url: `{url}`.", er)
        return response

    def get_raw_request(
        self, url, method="GET", params=None, data=None, header=None
    ) -> RequestResponse:

        response = self.session.request(
            method=method,
            url=url,
            params=params,
            headers=header or self.header,
            data=data,
            verify=not self.insecure,
        )

        json_output = None
        try:
            json_output = response.json()
        except ValueError:
            logger.debug(response.text)

        return RequestResponse(
            status_code=response.status_code,
            ok=response.ok,
            content=response.content,
            json=json_output,
            reason=response.reason,
        )

    @property
    def api_url(self):
        return f"{self.instance_url}/api/0/"

    def get_api_url(self, *args, add_api_endpoint_part=True) -> str:
        """
        Get a URL from its parts.

        :param args: str parts of the url (e.g. "a", "b" will call "/a/b")
        :param add_api_endpoint_part: Add part with API endpoint "/api/0/", True by default
        :return: str
        """
        args_list: List[str] = []

        args_list += filter(lambda x: x is not None, args)

        if add_api_endpoint_part:
            return self.api_url + "/".join(args_list)
        return f"{self.instance_url}/" + "/".join(args_list)

    def get_api_version(self) -> str:
        """
        Get Pagure API version.
        :return:
        """
        request_url = self.get_api_url("version")
        return_value = self.call_api(request_url)
        return return_value["version"]

    def get_error_codes(self):
        """
        Get a dictionary of all error codes.
        :return:
        """
        request_url = self.get_api_url("error_codes")
        return_value = self.call_api(request_url)
        return return_value

    def change_token(self, token: str):
        self._token = token
        self.header = {"Authorization": "token " + self._token}

class PagureProject(BaseGitProject):
    service: PagureService

    def __init__(
        self,
        repo: str,
        namespace: Optional[str],
        service: "PagureService",
        username: str = None,
        is_fork: bool = False,
    ) -> None:
        super().__init__(repo, service, namespace)
        self.read_only = service.read_only

        self._is_fork = is_fork
        self._username = username

        self.repo = repo
        self.namespace = namespace

    def __str__(self) -> str:
        return f'PagureProject(namespace="{self.namespace}", repo="{self.repo}")'

    def __eq__(self, o: object) -> bool:
        if not isinstance(o, PagureProject):
            return False

        return (
            self.repo == o.repo
            and self.namespace == o.namespace
            and self.service == o.service
            and self._username == o._username
            and self._is_fork == o._is_fork
            and self.read_only == o.read_only
        )

    @property
    def _user(self) -> str:
        if not self._username:
            self._username = self.service.user.get_username()
        return self._username

    def _call_project_api(
        self,
        *args,
        add_fork_part: bool = True,
        add_api_endpoint_part=True,
        method: str = None,
        params: dict = None,
        data: dict = None,
    ) -> dict:
        """
        Call project API endpoint.

        :param args: str parts of the url (e.g. "a", "b" will call "project/a/b")
        :param add_fork_part: If the projects is a fork, use "fork/username" prefix, True by default
        :param add_api_endpoint_part: Add part with API endpoint "/api/0/"
        :param method: "GET"/"POST"/...
        :param params: http(s) query parameters
        :param data: data to be sent
        :return: dict
        """
        request_url = self._get_project_url(
            *args,
            add_api_endpoint_part=add_api_endpoint_part,
            add_fork_part=add_fork_part,
        )

        return_value = self.service.call_api(
            url=request_url, method=method, params=params, data=data
        )
        return return_value

    def _call_project_api_raw(
        self,
        *args,
        add_fork_part: bool = True,
        add_api_endpoint_part=True,
        method: str = None,
        params: dict = None,
        data: dict = None,
    ) -> RequestResponse:
        """
        Call project API endpoint.

        :param args: str parts of the url (e.g. "a", "b" will call "project/a/b")
        :param add_fork_part: If the projects is a fork, use "fork/username" prefix, True by default
        :param add_api_endpoint_part: Add part with API endpoint "/api/0/"
        :param method: "GET"/"POST"/...
        :param params: http(s) query parameters
        :param data: data to be sent
        :return: RequestResponse
        """
        request_url = self._get_project_url(
            *args,
            add_api_endpoint_part=add_api_endpoint_part,
            add_fork_part=add_fork_part,
        )

        return_value = self.service.call_api_raw(
            url=request_url, method=method, params=params, data=data
        )
        return return_value

    def _get_project_url(self, *args, add_fork_part=True, add_api_endpoint_part=True):
        additional_parts = []
        if self._is_fork and add_fork_part:
            additional_parts += ["fork", self._user]
        request_url = self.service.get_api_url(
            *additional_parts,
            self.namespace,
            self.repo,
            *args,
            add_api_endpoint_part=add_api_endpoint_part,
        )
        return request_url

    def get_project_info(self):
        return_value = self._call_project_api(method="GET")
        return return_value

    def get_branches(self) -> List[str]:
        return_value = self._call_project_api("git", "branches", method="GET")
        return return_value["branches"]

    def get_description(self) -> str:
        return self.get_project_info()["description"]

    def get_owners(self) -> List[str]:
        project = self.get_project_info()
        return project["access_users"]["owner"]

    def who_can_close_issue(self) -> Set[str]:
        users: Set[str] = set()
        project = self.get_project_info()
        users.update(project["access_users"]["admin"])
        users.update(project["access_users"]["commit"])
        users.update(project["access_users"]["ticket"])
        users.update(project["access_users"]["owner"])
        return users

    def who_can_merge_pr(self) -> Set[str]:
        users: Set[str] = set()
        project = self.get_project_info()
        users.update(project["access_users"]["admin"])
        users.update(project["access_users"]["commit"])
        users.update(project["access_users"]["owner"])
        return users

    def can_close_issue(self, username: str, issue: Issue) -> bool:
        allowed_users = self.who_can_close_issue()
        if username in allowed_users:
            return True
        if username == issue.author:
            return True

        return False

    def can_merge_pr(self, username) -> bool:
        allowed_users = self.who_can_merge_pr()
        if username in allowed_users:
            return True

        return False

    def get_issue_list(self, status: IssueStatus = IssueStatus.open) -> List[Issue]:
        payload = {"status": status.name.capitalize()}

        raw_issues = self._call_project_api("issues", params=payload)["issues"]
        issues = [self._issue_from_pagure_dict(issue_dict) for issue_dict in raw_issues]
        return issues

    def get_issue_info(self, issue_id: int) -> Issue:
        raw_issue = self._call_project_api("issue", str(issue_id))
        return self._issue_from_pagure_dict(raw_issue)

    def _get_all_issue_comments(self, issue_id: int) -> List[IssueComment]:
        raw_comments = self._call_project_api("issue", str(issue_id))["comments"]
        return [
            self._issuecomment_from_pagure_dict(raw_comment)
            for raw_comment in raw_comments
        ]

    def issue_comment(self, issue_id: int, body: str) -> IssueComment:
        payload = {"comment": body}
        self._call_project_api(
            "issue", str(issue_id), "comment", data=payload, method="POST"
        )
        return IssueComment(comment=body, author=self._username)

    def create_issue(self, title: str, body: str) -> Issue:
        payload = {"title": title, "issue_content": body}
        new_issue = self._call_project_api("new_issue", data=payload, method="POST")[
            "issue"
        ]
        return self._issue_from_pagure_dict(new_issue)

    def issue_close(self, issue_id: int) -> Issue:
        payload = {"status": "Closed"}
        self._call_project_api(
            "issue", str(issue_id), "status", data=payload, method="POST"
        )
        issue = self.get_issue_info(issue_id)
        return issue

    def get_pr_list(
        self, status: PRStatus = PRStatus.open, assignee=None, author=None
    ) -> List[PullRequest]:

        payload = {"status": status.name.capitalize()}
        if assignee is not None:
            payload["assignee"] = assignee
        if author is not None:
            payload["author"] = author

        raw_prs = self._call_project_api("pull-requests", params=payload)["requests"]
        prs = [self._pr_from_pagure_dict(pr_dict) for pr_dict in raw_prs]
        return prs

    def get_pr_info(self, pr_id: int) -> PullRequest:
        raw_pr = self._call_project_api("pull-request", str(pr_id))
        result = self._pr_from_pagure_dict(raw_pr)
        return result

    def _get_all_pr_comments(self, pr_id: int) -> List[PRComment]:
        raw_comments = self._call_project_api("pull-request", str(pr_id))["comments"]

        parsed_comments = [
            self._prcomment_from_pagure_dict(comment_dict)
            for comment_dict in raw_comments
        ]
        return parsed_comments

    @if_readonly(return_function=GitProjectReadOnly.pr_comment)
    def pr_comment(
        self,
        pr_id: int,
        body: str,
        commit: str = None,
        filename: str = None,
        row: int = None,
    ) -> PRComment:
        payload: Dict[str, Any] = {"comment": body}
        if commit is not None:
            payload["commit"] = commit
        if filename is not None:
            payload["filename"] = filename
        if row is not None:
            payload["row"] = row

        self._call_project_api(
            "pull-request", str(pr_id), "comment", method="POST", data=payload
        )

        return PRComment(comment=body, author=self.service.user.get_username())

    @if_readonly(return_function=GitProjectReadOnly.pr_close)
    def pr_close(self, pr_id: int) -> PullRequest:
        return_value = self._call_project_api(
            "pull-request", str(pr_id), "close", method="POST"
        )

        if return_value["message"] != "Pull-request closed!":
            raise PagureAPIException(return_value["message"])

        return self.get_pr_info(pr_id)

    @if_readonly(return_function=GitProjectReadOnly.pr_merge)
    def pr_merge(self, pr_id: int) -> PullRequest:
        return_value = self._call_project_api(
            "pull-request", str(pr_id), "merge", method="POST"
        )

        if return_value["message"] != "Changes merged!":
            raise PagureAPIException(return_value["message"])

        return self.get_pr_info(pr_id)

    @if_readonly(return_function=GitProjectReadOnly.pr_create)
    def pr_create(
        self, title: str, body: str, target_branch: str, source_branch: str
    ) -> PullRequest:

        return_value = self._call_project_api(
            "pull-request",
            "new",
            method="POST",
            data={
                "title": title,
                "branch_to": target_branch,
                "branch_from": source_branch,
                "initial_comment": body,
            },
        )

        pr_object = self._pr_from_pagure_dict(return_value)
        return pr_object

    def update_pr_info(self, pr_id: int, title: str, description: str):
        """
        Update pull-request information.

        :param pr_id: int The ID of the pull request
        :param title: str The title of the pull request
        :param description str The description of the pull request
        :return: PullRequest
        """
        try:
            updated_pr = self._call_project_api(
                "pull-request",
                str(pr_id),
                method="POST",
                data={"title": title, "initial_comment": description},
            )
            logger.info(f"PR updated.")
            return self._pr_from_pagure_dict(updated_pr)
        except Exception as ex:
            raise PagureAPIException("there was an error while updating the PR", ex)

    @if_readonly(return_function=GitProjectReadOnly.fork_create)
    def fork_create(self) -> "PagureProject":
        request_url = self.service.get_api_url("fork")
        self.service.call_api(
            url=request_url,
            method="POST",
            data={"repo": self.repo, "namespace": self.namespace, "wait": True},
        )
        return self._construct_fork_project()

    def _construct_fork_project(self) -> "PagureProject":
        return PagureProject(
            service=self.service,
            repo=self.repo,
            namespace=self.namespace,
            username=self._user,
            is_fork=True,
        )

    def get_fork(self, create: bool = True) -> Optional["PagureProject"]:
        """
        Provide GitProject instance of a fork of this project.

        Returns None if this is a fork.

        :param create: create a fork if it doesn't exist
        :return: instance of GitProject or None
        """
        if self.is_fork:
            raise OgrException("Cannot create fork from fork.")

        for fork in self.get_forks():
            fork_info = fork.get_project_info()
            if self._user in fork_info["user"]["name"]:
                return fork

        if not self.is_forked():
            if create:
                return self.fork_create()
            else:
                logger.info(
                    f"Fork of {self.repo}"
                    " does not exist and we were asked not to create it."
                )
                return None
        return self._construct_fork_project()

    def exists(self):
        response = self._call_project_api_raw()
        return response.ok

    def is_forked(self) -> bool:
        """
        Is this repo forked by the authenticated user?

        :return: if yes, return True
        """
        f = self._construct_fork_project()
        return bool(f.exists() and f.parent.exists())

    @property
    def is_fork(self) -> bool:
        return bool(self.get_project_info()["parent"])

    @property
    def parent(self) -> Optional["PagureProject"]:
        """
        Return parent project if this project is a fork, otherwise return None
        """
        if self.is_fork:
            return PagureProject(
                repo=self.repo,
                namespace=self.get_project_info()["parent"]["namespace"],
                service=self.service,
            )
        return None

    def get_git_urls(self) -> Dict[str, str]:
        return_value = self._call_project_api("git", "urls")
        return return_value["urls"]

    def _issue_from_pagure_dict(self, issue_dict: dict) -> Issue:
        return Issue(
            title=issue_dict["title"],
            id=issue_dict["id"],
            status=IssueStatus[issue_dict["status"].lower()],
            url=self._get_project_url("issue", str(issue_dict["id"])),
            description=issue_dict["content"],
            author=issue_dict["user"]["name"],
            created=datetime.datetime.fromtimestamp(int(issue_dict["date_created"])),
        )

    def _issuecomment_from_pagure_dict(self, comment_dict: dict) -> IssueComment:
        return IssueComment(
            comment=comment_dict["comment"],
            author=comment_dict["user"]["name"],
            created=datetime.datetime.fromtimestamp(int(comment_dict["date_created"])),
            edited=None,
        )

    def _pr_from_pagure_dict(self, pr_dict: dict) -> PullRequest:
        return PullRequest(
            title=pr_dict["title"],
            id=pr_dict["id"],
            status=PRStatus[pr_dict["status"].lower()],
            url="/".join(
                [
                    self.service.instance_url,
                    pr_dict["project"]["url_path"],
                    "pull-request",
                    str(pr_dict["id"]),
                ]
            ),
            description=pr_dict["initial_comment"],
            author=pr_dict["user"]["name"],
            source_branch=pr_dict["branch_from"],
            target_branch=pr_dict["branch"],
            created=datetime.datetime.fromtimestamp(int(pr_dict["date_created"])),
        )

    @staticmethod
    def _prcomment_from_pagure_dict(comment_dict: dict) -> PRComment:
        return PRComment(
            comment=comment_dict["comment"],
            author=comment_dict["user"]["name"],
            created=datetime.datetime.fromtimestamp(int(comment_dict["date_created"])),
            edited=datetime.datetime.fromtimestamp(int(comment_dict["edited_on"]))
            if comment_dict["edited_on"]
            else None,
        )

    @staticmethod
    def _commit_status_from_pagure_dict(
        status_dict: dict, uid: str = None
    ) -> CommitFlag:
        return CommitFlag(
            commit=status_dict["commit_hash"],
            comment=status_dict["comment"],
            state=status_dict["status"],
            context=status_dict["username"],
            url=status_dict["url"],
            uid=uid,
        )

    def change_token(self, new_token: str) -> None:
        """
        Change an API token.

        Only for this instance.
        """
        self.service.change_token(new_token)

    def get_file_content(self, path: str, ref="master") -> str:
        try:
            result = self._call_project_api_raw(
                "raw", ref, "f", path, add_api_endpoint_part=False
            )
            if not result or result.reason == "NOT FOUND":
                raise FileNotFoundError(f"File '{path}' on {ref} not found")
            return result.content.decode()
        except OurPagureRawRequest as ex:
            raise FileNotFoundError(f"Problem with getting file '{path}' on {ref}", ex)

    def get_sha_from_tag(self, tag_name: str) -> str:
        tags_dict = self.get_tags_dict()
        if tag_name not in tags_dict:
            raise PagureAPIException(f"Tag '{tag_name}' not found.")

        return tags_dict[tag_name].commit_sha

    def commit_comment(
        self, commit: str, body: str, filename: str = None, row: int = None
    ) -> CommitComment:
        raise OperationNotSupported("Commit comments are not supported on Pagure.")

    @if_readonly(return_function=GitProjectReadOnly.set_commit_status)
    def set_commit_status(
        self,
        commit: str,
        state: str,
        target_url: str,
        description: str,
        context: str,
        percent: int = None,
        uid: str = None,
    ) -> "CommitFlag":
        data: Dict[str, Any] = {
            "username": context,
            "comment": description,
            "url": target_url,
            "status": state,
        }
        if percent:
            data["percent"] = percent
        if uid:
            data["uid"] = uid

        response = self._call_project_api("c", commit, "flag", method="POST", data=data)
        return self._commit_status_from_pagure_dict(
            response["flag"], uid=response["uid"]
        )

    def get_commit_statuses(self, commit: str) -> List[CommitFlag]:
        response = self._call_project_api("c", commit, "flag")
        return [
            self._commit_status_from_pagure_dict(flag) for flag in response["flags"]
        ]

    def get_tags(self) -> List[GitTag]:
        response = self._call_project_api("git", "tags", params={"with_commits": True})
        tags = [GitTag(name=n, commit_sha=c) for n, c in response["tags"].items()]
        return tags

    def get_tags_dict(self) -> Dict[str, GitTag]:
        response = self._call_project_api("git", "tags", params={"with_commits": True})
        tags_dict = {
            n: GitTag(name=n, commit_sha=c) for n, c in response["tags"].items()
        }
        return tags_dict

    def get_releases(self) -> List[Release]:
        # git tag for Pagure is shown as Release in Pagure UI
        git_tags = self.get_tags()
        return [self._release_from_git_tag(git_tag) for git_tag in git_tags]

    @staticmethod
    def _release_from_git_tag(git_tag: GitTag) -> Release:
        return Release(
            title=git_tag.name,
            body="",
            tag_name=git_tag.name,
            url="",
            created_at="",
            tarball_url="",
            git_tag=git_tag,
        )

    def get_forks(self) -> List["PagureProject"]:
        """
        Get forks of the project.

        :return: [PagureProject]
        """
        forks_url = self.service.get_api_url("projects")
        projects_response = self.service.call_api(
            url=forks_url, params={"fork": True, "pattern": self.repo}
        )
        fork_objects = [
            PagureProject(
                repo=fork["name"],
                namespace=fork["namespace"],
                service=self.service,
                username=fork["user"]["name"],
                is_fork=True,
            )
            for fork in projects_response["projects"]
        ]
        return fork_objects

class PagureUser(BaseGitUser):
    service: PagureService

    def __init__(self, service: PagureService) -> None:
        super().__init__(service=service)

    def __str__(self) -> str:
        return f'PagureUser(username="{self.get_username()}")'

    def get_username(self) -> str:
        request_url = self.service.get_api_url("-", "whoami")

        return_value = self.service.call_api(url=request_url, method="POST", data={})
        return return_value["username"]

    def get_projects(self) -> List["PagureProject"]:
        user_url = self.service.get_api_url("user", self.get_username())
        raw_projects = self.service.call_api(user_url)["repos"]

        project_objects = [
            PagureProject(
                repo=project["name"],
                namespace=project["namespace"],
                service=self.service,
            )
            for project in raw_projects
        ]
        return project_objects

    def get_forks(self) -> List["PagureProject"]:
        user_url = self.service.get_api_url("user", self.get_username())
        raw_forks = self.service.call_api(user_url)["forks"]

        fork_objects = [
            PagureProject(
                repo=fork["name"],
                namespace=fork["namespace"],
                service=self.service,
                is_fork=True,
            )
            for fork in raw_forks
        ]
        return fork_objects


# -*- encoding:utf-8 -*-

"""
商家用户相关
"""

import logging

from commercial.const import CouponTemplateChoices
from commercial.manager.db_manager import get_club_by_account_and_password, create_club_user_info_by_user_info_and_club, \
    get_club_by_id_db, get_club_user_info_by_user_info_and_club, get_club_user_info_by_club, \
    get_charge_off_record_by_club_user_infos
from commercial.models import CouponChargeOffRecord
from footprint.manager.coupon_manager import get_user_coupon_by_coupon_code, charge_off_coupon, get_user_coupon_by_id
from user_info.manager.user_info_mananger import get_user_info_by_user_id_db
from utilities.date_time import datetime_to_str

def club_user_login(account, password, user_info):
    """
    商家用户登录, 如果没有直接创建
    """
    club = get_club_by_account_and_password(account, password)
    if not club:
        return None
    club_user_info, created = create_club_user_info_by_user_info_and_club(user_info, club)
    if created:
        logging.info('create ClubUserInfo: %s, %s', club.id, user_info.id)

    return club_user_info

def build_user_coupon_info_for_charge_off(club_id, coupon_code):
    """
    构造用户优惠券信息 --> 核销展示使用
    """
    club = get_club_by_id_db(club_id)
    if not club:
        return None

    coupon = get_user_coupon_by_coupon_code(coupon_code)
    if not coupon:
        return None

    user_info = get_user_info_by_user_id_db(coupon.user.id)
    coupon_money = 0 if coupon.template.template_type == CouponTemplateChoices.GENERAL else coupon.template.money

    return {
        'club_info': {
            'avatar': "https://zongz.cn" + club.avatar.url,
            'name': club.name,
            'address': club.address,
            'telephone': club.telephone,
            'club_id': club.id,
        },
        'coupon_info': {
            'coupon_id': coupon.id,
            'coupon_money': coupon_money,
            'coupon_type': coupon.template.template_type,
            'coupon_name': coupon.template.name,
            'coupon_deadline': datetime_to_str(coupon.template.deadline)
        },
        'user_info': {
            'avatar': user_info.avatar,
            'nickname': user_info.nickname,
            'consume_count': CouponChargeOffRecord.objects.filter(user_id=coupon.user.id).count()
        }
    }

def charge_off_user_coupon(coupon_code, club_id, user_info):
    """
    核销用户优惠券
    """
    user_coupon = get_user_coupon_by_coupon_code(coupon_code)

    if not user_coupon:
        return u'找不到对应的优惠券'

    if user_coupon.is_used:
        return u'优惠券已经被核销了'

    club = get_club_by_id_db(club_id)
    if not club:
        return u'俱乐部不存在'

    club_user_info = get_club_user_info_by_user_info_and_club(user_info, club)
    if not club_user_info:
        return u'商户账号不存在'

    coupon_charge_off_record = CouponChargeOffRecord.objects.create(
        club_user=club_user_info, coupon_id=user_coupon.id, user_id=user_coupon.user.id
    )
    charge_off_coupon(user_coupon)  # 除了记录之外, 还需要核销优惠券自身
    logging.info('charge off user coupon: %s, %s, %s', club.id, user_coupon.id, coupon_charge_off_record.id)

    return u''

def build_club_consume_user_coupon_info(club_id):
    """
    构造商户消耗用户优惠券详情
    """
    club = get_club_by_id_db(club_id)
    if not club:
        return None

    club_user_infos = get_club_user_info_by_club(club_id)
    charge_off_records = get_charge_off_record_by_club_user_infos(club_user_infos)
    money, consume_infos = build_club_consume_infos(charge_off_records)

    return {
        'club_info': {
            'avatar': "https://zongz.cn" + club.avatar.url,
            'name': club.name,
            'address': club.address,
            'telephone': club.telephone,
            'club_id': club.id,
        },
        'consume_sum': {
            'count': len(consume_infos),
            'money': money
        },
        'consume_infos': consume_infos
    }

def build_club_consume_infos(charge_off_records):
    """
    构造商户消耗优惠券的信息
    """
    money = 0
    consume_infos = []

    for record in charge_off_records:
        coupon = get_user_coupon_by_id(record.coupon_id)
        coupon_money = 0 if coupon.template.template_type == CouponTemplateChoices.GENERAL \
            else coupon.template.money
        consume_infos.append(
            {
                'nickname': get_user_info_by_user_id_db(coupon.user_id).nickname,
                'coupon_money': coupon_money,
                'confirm_user': record.club_user.user_info.nickname,
                'confirm_time': datetime_to_str(record.created_time, '%m-%d %H:%M')
            }
        )
        money += coupon_money

    return money, consume_infos

def build_club_detail_info(club_id):
    """
    构造商户的详细信息
    """
    club = get_club_by_id_db(club_id)
    assert club is not None

    return {
        'avatar': club.update_avatar or "https://zongz.cn" + club.avatar.url,
        'name': club.name,
        'address': club.address,
        'telephone': club.telephone,
        'club_id': club.id,
        'principal': club.principal,
        'representative': club.representative,
        'license': "https://zongz.cn" + club.license.url,
        'remark': club.remark,
        'business_type': club.business_type
    }

def club_update_detail(avatar_url, club_id):
    """
    商户更新自己的头像
    """
    club = get_club_by_id_db(club_id)
    assert club is not None

    club.update_avatar = avatar_url
    club.save()


class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """

        length = len(s)
        flag = []
        ans = 0
        front = 0
        tail = 0

        while tail < length:
            if s[tail] in flag:
                ans = max(ans, tail - front)
                while (s[front] != s[tail]):
                    flag.remove(s[front])
                    front = front + 1
                front = front + 1
                tail = tail + 1
            else:
                flag.append(s[tail])
                tail = tail + 1

        ans = max(ans, length - front)
        return ans

# print Solution().lengthOfLongestSubstring('abcabcbb')


__author__ = 'Teddy'
import numpy as np
import cv2
import argparse
from PIL import Image

BASE_DIR = "trainData/"
FILE_NAME = "/1.png"

class KNearestClass:
    def kNearTrain(self):
        #The following line is modified for OpenCV 3.0
        trainData, labels = self.getTrainingData()
        knn = cv2.ml.KNearest_create()
        #knn.train(trainData,labels)
        #print(trainData.shape, labels.shape)
        knn.train(trainData, cv2.ml.ROW_SAMPLE, labels)
        return knn

    def getTrainingData(self):
        trainData = np.array([cv2.imread(BASE_DIR + str(0) + FILE_NAME).flatten()])
        labels = np.array([0])
        for x in range(1,10):
            trainData = np.vstack([trainData, (cv2.imread(BASE_DIR + str(x) + FILE_NAME).flatten())])
            labels = np.vstack([labels, [x]])
        return trainData.astype(np.float32), labels

    def solve(self, cv2im):
        input = np.array([cv2im.flatten()]).astype(np.float32)
        #print(input.shape)
        res = self.model.findNearest(input,1)
        return res

    def __init__(self):
        self.model = self.kNearTrain()

if __name__ == "__main__":
    model = KNearestClass()
    im = cv2.imread("2.png")
    res = model.solve(im)
    print(res[0])


### Island: Elementary. Problem: Create intervals

"""
My answer.
"""
def create_intervals(data):
    """
        Create a list of intervals out of set of ints.
    """
    sort_data = sorted(list(data))
    ans = []
    if(len(data) > 1):
        left = sort_data[0]
        tmp = left
        counter = 1
        right = sort_data[counter]
        while(counter < len(sort_data)):
            if(right == tmp + 1):
                tmp = right
            else:
                ans.append((left, tmp))
                left = right
                tmp = right
            counter += 1
            if(counter < len(sort_data)):
                right = sort_data[counter]
            elif(counter == len(sort_data)):
                ans.append((left, tmp))

    elif(len(data) == 1):
        elem = data.pop()
        ans.append((elem, elem))

    return ans

if __name__ == '__main__':
    #These "asserts" using only for self-checking and not necessary for auto-testing
    assert create_intervals({1, 2, 3, 4, 5, 7, 8, 12}) == [(1, 5), (7, 8), (12, 12)], "First"
    assert create_intervals({1, 2, 3, 4, 5, 6, 7, 8}) == [(1, 8)], "Second"


from bcdebug import debug
#
# ConditionAllInSameSet
#
# A condition that tests if a list of objects are in the
# same set as another object.  If any of them are in the
# same set, the condition is true.
#
import App

#NonSerializedObjects = ( "debug", )

#debug = App.CPyDebug(__name__).Print
#debug("Loading " + __name__ + " Condition module...")

class ConditionAnyInSameSet:
	def __init__(self, pCodeCondition, sObjectName, *lsOtherObjectNames):
		debug(__name__ + ", __init__")
		self.pCodeCondition = pCodeCondition
		# Set our primary object's name..
		self.sObjectName = sObjectName

		# Save a reference to our module, so the module isn't
		# unloaded unexpectedly.
		self.pModule = __import__(__name__)

		# Setup our interrupt handlers, for checking of the object
		# enters or leaves the set.
		self.pEventHandler = App.TGPythonInstanceWrapper()
		self.pEventHandler.SetPyWrapper(self)

		# Setup our object list and set our initial state.
		self.SetObjects(lsOtherObjectNames)

	def RegisterExternalFunctions(self, pAI):
		debug(__name__ + ", RegisterExternalFunctions")
		pAI.RegisterExternalFunction("SetTarget", { "CodeID" : self.pCodeCondition.GetObjID(), "FunctionName" : "SetTarget" })

	def SetTarget(self, sTarget):
		# Change the contents of self.pObjectGroup so they
		# just contain sTarget.
		#debug("SetTarget from %s to (%s)" % (self.pObjectGroup.GetNameTuple(), sTarget))
		debug(__name__ + ", SetTarget")
		self.SetObjects(sTarget)

	def __getstate__(self):
		debug(__name__ + ", __getstate__")
		dState = self.__dict__.copy()
		dState["pModule"] = self.pModule.__name__
		dState["pEventHandler"].pContainingInstance = self
		return dState

	def __setstate__(self, dict):
		debug(__name__ + ", __setstate__")
		self.__dict__ = dict
		self.pModule = __import__(self.pModule)
		del self.pEventHandler.pContainingInstance

	def SetObjects(self, pObjectGroup):
		# If we had an object group before, scrap our old info.
		debug(__name__ + ", SetObjects")
		if hasattr(self, "pObjectGroup")  and  hasattr(self, "pEverythingGroup"):
			# Remove our old event handlers.
			App.g_kEventManager.RemoveBroadcastHandler(
				App.ET_OBJECT_GROUP_OBJECT_ENTERED_SET, self.pEventHandler, "EnteredSet", self.pEverythingGroup)
			App.g_kEventManager.RemoveBroadcastHandler(
				App.ET_OBJECT_GROUP_OBJECT_EXITED_SET, self.pEventHandler, "ExitedSet", self.pEverythingGroup)

		# Set our object group...
		self.pObjectGroup = App.ObjectGroup_ForceToGroup( pObjectGroup )

		# We need another group including our primary object..
		self.pEverythingGroup = App.ObjectGroup()
		if self.pObjectGroup:
			for sName in ((self.sObjectName, ) + self.pObjectGroup.GetNameTuple()):
				self.pEverythingGroup.AddName(sName)

		# We need event handlers for when any of our objects
		# enter or exit a set.  We'll base this off of the
		# pEverythingGroup object group.
		self.pEverythingGroup.SetEventFlag( App.ObjectGroup.ENTERED_SET )
		App.g_kEventManager.AddBroadcastPythonMethodHandler(App.ET_OBJECT_GROUP_OBJECT_ENTERED_SET, self.pEventHandler, "EnteredSet", self.pEverythingGroup)
		self.pEverythingGroup.SetEventFlag( App.ObjectGroup.EXITED_SET )
		App.g_kEventManager.AddBroadcastPythonMethodHandler(App.ET_OBJECT_GROUP_OBJECT_EXITED_SET, self.pEventHandler, "ExitedSet", self.pEverythingGroup)

		# SetInitialState will setup the rest.
		self.SetInitialState()

	def SetInitialState(self):
		# Get our primary object, and the set it's in.
		debug(__name__ + ", SetInitialState")
		self.sPrimarySet = ""
		pPrimary = App.ObjectClass_GetObject( None, self.sObjectName )
		if pPrimary:
			pSet = pPrimary.GetContainingSet()
			if pSet:
				self.sPrimarySet = pSet.GetName()

		# Now get the names of the sets that our other objects
		# are in.  If any of them matches the primary set (and
		# the primary set isn't ""), we're true.
		self.dSetNames = {}
		if not self.pObjectGroup:
			return
		lsObjectNames = self.pObjectGroup.GetNameTuple()
		sFirstObject = lsObjectNames[0]
		bMatch = 0
		for sObjectName in lsObjectNames:
			# Get the object and save the name of the set it's currently in.
			pObject = App.ObjectClass_GetObject(App.SetClass_GetNull(), sObjectName)
			if (pObject != None):
				sSetName = pObject.GetContainingSet().GetName()
				self.dSetNames[sObjectName] = sSetName
				# Check if this set is the same as our primary
				# set.
				if sSetName == self.sPrimarySet:
					# Yep.
					bMatch = 1
			else:
				self.dSetNames[sObjectName] = ""

		self.pCodeCondition.SetStatus(bMatch)

	def EnteredSet(self, pObjEvent):
		# Get the object...
		debug(__name__ + ", EnteredSet")
		pObj = App.ObjectClass_Cast(pObjEvent.GetObjPtr())
		sSetName = pObj.GetContainingSet().GetName()

		# Is this our primary ship?
		if pObj.GetName() == self.sObjectName:
			# Yep.  Update our primary setname.
			self.sPrimarySet = sSetName

			# And check if any other objects are in
			# this set.
			bMatch = 0
			for sName in self.dSetNames.values():
				if sName == self.sPrimarySet:
					# Yep, found a match.
					bMatch = 1
					break

			# If we found a match, we should be true.
			# Otherwise, we should be false:
			if self.pCodeCondition.GetStatus() != bMatch:
				self.pCodeCondition.SetStatus(bMatch)

		else:
			# Not our primary ship.
			# It's one of the ships in our list.  Set its
			# new set name.
			self.dSetNames[pObj.GetName()] = sSetName

			# And check if this set name is the same as our
			# primary set name.  If so, our condition should
			# be true.
			if sSetName == self.sPrimarySet:
				if self.pCodeCondition.GetStatus() != 1:
					self.pCodeCondition.SetStatus(1)

		# Call the next handler for this event...
		self.pEventHandler.CallNextHandler(pObjEvent)

	def ExitedSet(self, pObjEvent):
		# Get the object...
		debug(__name__ + ", ExitedSet")
		pObj = App.ObjectClass_Cast(pObjEvent.GetObjPtr())

		# Is this our primary ship?
		if pObj.GetName() == self.sObjectName:
			# Yep.  Update our primary setname.
			self.sPrimarySet = ""

			# And make sure we're false now.
			if self.pCodeCondition.GetStatus() != 0:
				self.pCodeCondition.SetStatus(0)
		else:
			# Nope.  It's one of the ships from our list.
			# Clear the ship's set name.
			sOldSet = self.dSetNames[pObj.GetName()]
			self.dSetNames[pObj.GetName()] = ""

			# If this ship used to be in the primary ship's
			# set, we may need to trigger ourselves false.
			if sOldSet == self.sPrimarySet:
				# Check if there are any more matches
				# in the list of sets...
				bMatch = 0
				for sSet in self.dSetNames.values():
					if sSet != ""  and  sSet == self.sPrimarySet:
						# Found a match.
						bMatch = 1
						break

				# If we found a match, we should be true.
				# Otherwise, we should be false:
				if self.pCodeCondition.GetStatus() != bMatch:
					self.pCodeCondition.SetStatus(bMatch)

		# Call the next handler for this event...
		self.pEventHandler.CallNextHandler(pObjEvent)


import numpy as np
from tensorflow.examples.tutorials.mnist import input_data

mnist=input_data.read_data_sets('MNIST_data',one_hot=True)       #载入数据
[x_train,y_train]=[mnist.train.images,mnist.train.labels]
[x_test,y_test]=[mnist.test.images,mnist.test.labels]

class FC:                                       #定义全连接层类
    def __init__(self,w,b):
        self.w=w
        self.b=b
        self.image=None
        self.dw=None
        self.db=None

    def forward(self,din):
        self.image=din
        return np.dot(din,self.w)+self.b

    def backward(self,dout):
        self.dw=np.dot(self.image.T,dout)
        self.db=np.sum(dout,axis=0)
        return np.dot(dout,self.w.T)

class Relu:                                      #定义ReLU层类
    def __init__(self):
        self.mask=None                           #mask来记录被置零的位置

    def forward(self,image):
        self.mask=(image<=0)
        image[self.mask]=0
        return image

    def backward(self,dout):
        dout[self.mask]=0
        return dout

class SoftmaxWithLoss:                          #定义softmax层和损失函数类
    def __init__(self):
        self.loss=None
        self.prediction=None
        self.y=None

    def forward(self,din,y):
        self.y=y
        x=np.mat(din)-np.max(np.mat(din),1)#防止溢出
        self.prediction=np.array(np.exp(x)/np.sum(np.exp(x),1))
        self.loss=-np.sum(self.y*np.log(self.prediction+1e-07))

    def backward(self):
        return (self.prediction-self.y)/self.y.shape[0]

def predict(image):                                    #输入图片，返回预测值
    for layer in layers.values():
        image=layer.forward(image)
    return image

def accuracy(image,y):                               #输入图片和对应标签，返回正确率
    prediction=np.argmax(predict(image),axis=1)
    y=np.argmax(y,axis=1)
    return np.sum(prediction==y)/image.shape[0]

params={}                                               #初始化参数
params['w1']=np.random.normal(0,0.01,(784,100))
params['b1']=np.zeros(100)
params['w2']=np.random.normal(0,0.01,(100,10))
params['b2']=np.zeros(10)

layers={}                                               #构建网络结构
layers['FC1']=FC(params['w1'],params['b1'])
layers['Relu1']=Relu()
layers['FC2']=FC(params['w2'],params['b2'])
softmax=SoftmaxWithLoss()

batch_size=100                                                    #批大小
batch_n=x_train.shape[0]//batch_size                              #批量
learning_rate=0.1                                                 #学习率

for epoch in range(20):                                     #训练20代
    for batch in range(batch_n):                            #小批量
        x_batch,y_batch=mnist.train.next_batch(batch_size)  #载入数据
        softmax.forward(predict(x_batch),y_batch)           #正向传播
        dout=softmax.backward()                             #获得最后一层dZ^([2])
        for layer in list(layers.values())[::-1]:          #开始反向传播
            dout=layer.backward(dout)
        params['w1']-=learning_rate*layers['FC1'].dw        #更新各层参数
        params['b1']-=learning_rate*layers['FC1'].db
        params['w2']-=learning_rate*layers['FC2'].dw
        params['b2']-=learning_rate*layers['FC2'].db
    print('Epoch'+str(epoch)+': train_acc:'+str('%.2f'%(100*accuracy(x_train,y_train)))+'% test_acc:'+str('%.2f'%(100*accuracy(x_test,y_test)))+'%')


import os
import sys
import random

from pyramid.config import Configurator
from pyramid.events import subscriber, BeforeRender
from pyramid.httpexceptions import HTTPNotFound

PROJECT_PATH = os.path.realpath(os.path.dirname(__file__))
PROJECT_BASE_PATH = os.sep.join(PROJECT_PATH.split(os.sep)[:-1])
MEDIA_VERSION = random.randint(1, 1000000)

# include paths
sys.path.insert(0, PROJECT_PATH)
sys.path.insert(0, os.path.join(PROJECT_PATH, 'apps'))

from session.mongo import MongoSessionFactoryConfig

# from auth.security import auth_callback
def auth_callback(identity, request):
    return ['group:admins']

# logging
import logging
logger = logging.getLogger(__name__)

def notfound(request):
    return HTTPNotFound('Page not found.')

@subscriber(BeforeRender)
def add_global(event):
    """
    add template context procesors
    """
    event['DEVELOP'] = event['request'].registry.settings.get('DEVELOP', False)
    event['STATIC_URL'] = event['request'].registry.settings.get('static_url', '/static/')
    event['MEDIA_VERSION'] = MEDIA_VERSION

def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(
        settings=settings,
        # session_factory=session_factory,
        # root_factory='main.resources.RootFactory',
        # authorization_policy=authorization_policy,
        # authentication_policy=authentication_policy,
    )
    config.include('pyramid_jinja2')
    config.include('cornice')

    # templates
    config.add_renderer('.html', 'pyramid_jinja2.renderer_factory')
    config.add_renderer('.jinja2', 'pyramid_jinja2.renderer_factory')
    config.add_jinja2_search_path('templates')

    config.add_notfound_view(notfound, append_slash=True)
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_subscriber(add_global, BeforeRender)

    config.commit()  # need to commit because cornice HTTPForbidden conflict
    config.include('main')
    return config.make_wsgi_app()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
from textblob import TextBlob
import sys
#text = '''
#The titular threat of The Blob has always struck me as the ultimate movie
#monster: an insatiably hungry, amoeba-like mass able to penetrate
#virtually any safeguard, capable of--as a doomed doctor chillingly
#describes it--"assimilating flesh on contact.
#Snide comparisons to gelatin be damned, it's a concept with the most
#devastating of potential consequences, not unlike the grey goo scenario
#proposed by technological theorists fearful of
#artificial intelligence run rampant.
#'''

def main():
    text = sys.argv[1]
    blob = TextBlob(text)
    blob.tags           # [('The', 'DT'), ('titular', 'JJ'),
                        #  ('threat', 'NN'), ('of', 'IN'), ...]

    mynewtext = blob.noun_phrases
    #print(mynewtext)    # WordList(['titular threat', 'blob',
                        #            'ultimate movie monster',
                        #            'amoeba-like mass', ...])
    output = ""
    for word in mynewtext:
        output += word + " "
    print(output)
    return output
    #blob.translate(to="es")  # 'La amenaza titular de The Blob...'

if __name__ == "__main__":
   main()


# Import some useful libraries
import numpy as np
from sklearn.svm import SVC
from sklearn.svm import NuSVC
from sklearn.svm import LinearSVC
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import GridSearchCV
from sklearn import preprocessing

# Import user files
import src.readData as rd
import src.featureExtraction as fe

def main():
	# ------------------------------------------------------------------------
	# READ DATA
	# ------------------------------------------------------------------------

	# Read train data from file
	img_train_data = rd.read_image_data("data/set_train/")
	if img_train_data == -1:
		print("ERROR: Could not read data!")
		return

	# Read associated target values from file
	train_targets = rd.read_file("data/targets.csv")
	if train_targets.all() == -1:
		print("ERROR: Could not read targets!")
		return

	# ------------------------------------------------------------------------
	# PREPROCESS AND FEATURE EXTRACTION
	# ------------------------------------------------------------------------

	# Extract features
	train_features = fe.subvoxels_heuristics(
		img_train_data,
		subvoxels_size_=np.array([5,5,5]),
		print_info_="train ")

	# Scale features to zero mean and unit variance
	train_scaler = preprocessing.StandardScaler().fit(train_features)
	train_features_scaled = train_scaler.transform(train_features)

	# # Get histogram vector features of training data
	train_feature_matrix = fe.slice_histogram(img_train_data, 30, 50)
	if train_feature_matrix.all() == -1:
		print("ERROR: Could not compute features!")
		return

	# # Postprocess features
	#(train_feature_matrix, low_std_indices) = postp.low_variance_filter(train_feature_matrix, threshold_=10)
	#print(train_feature_matrix.shape)

	# ------------------------------------------------------------------------
	# CLASSIFICATION MODELS
	# ------------------------------------------------------------------------

	# Declare classifier list
	classifier = [
		SVC()]

	# Make parameter lists
	C = np.arange(-1.0,4.0)
	C = 10 ** C
	gamma = np.arange(-3.0,4.0)
	gamma = 10 ** gamma
	kernel = ["rbf", "linear"]
	coef0 = np.arange(0.0,1.0)
	degree = np.arange(3,7)

	# Generate dicts
	param_SVC = {
		"C":C,
		"kernel":kernel,
		"degree":degree,
		"gamma":gamma,
		"coef0":coef0,
		"probability":[True],
		"class_weight":["balanced"]}

	# Save dicts in list
	param_grid = [
		param_SVC]

	# ------------------------------------------------------------------------
	# CROSSVALIDATION
	# ------------------------------------------------------------------------

	print("\nCross validation")

	# Validate each classification model on subsets
	clf = []

	for cl in classifier:
		index = classifier.index(cl)

		clf.append(GridSearchCV(cl,
			param_grid[index],
			scoring="neg_log_loss",
			cv=10))

		clf[index].fit(train_features_scaled, train_targets)

	# ------------------------------------------------------------------------
	# MODEL SELECTION
	# ------------------------------------------------------------------------

	print("\nModel selection")

	# Select model according to highest score (lowest error)
	best_params = []
	best_score = []
	best_estimator = []

	for cl in clf:
		index = clf.index(cl)

		best_score.append(cl.best_score_)
		best_params.append(cl.best_params_)
		best_estimator.append(cl.best_estimator_)

	best_model_index = best_score.index(max(best_score))
	print(best_params)
	print(best_score)

	# ------------------------------------------------------------------------
	# CLASSIFICATION
	# ------------------------------------------------------------------------

	# Read train data from file
	img_test_data = rd.read_image_data("data/set_test/")
	if img_test_data == -1:
		print("ERROR: Could not read data!")
		return

	# Get features
	test_features = fe.subvoxels_heuristics(
		img_test_data,
		subvoxels_size_=np.array([5,5,5]),
		print_info_="test ")

	# Preprocess features
	train_scaler = preprocessing.StandardScaler().fit(test_features)
	test_features_scaled = train_scaler.transform(test_features)

	# Predict with best model parameters
	prediction_test_targets = best_estimator[best_model_index].predict_proba(test_features_scaled)[:,1]

	# Dump prediction to file
	id_array = np.arange(1,len(prediction_test_targets)+1)
	submission_array = np.column_stack((id_array, prediction_test_targets))

	np.savetxt("final_sub.csv", submission_array, delimiter=",", header="ID,Prediction", comments="", fmt="%d,%f")

	return


# -*- coding: utf-8 -*-
from django.db import models
from django_extensions.db.models import TimeStampedModel

from admin_app.core.models import Source

class Keyset(TimeStampedModel):
    title = models.CharField(
        max_length=255,
        verbose_name=u'название',
        )
    source = models.ForeignKey(
        Source,
        related_name='keysets',
        verbose_name=u'ресурс',
        )

    def __unicode__(self):
        return u'{0} {1}'.format(
            self.source.title,
            self.title
        )

    class Meta:
        unique_together = ('title', 'source')
        verbose_name = u'Набор ключей'
        verbose_name_plural = u'Наборы ключей'

class Mapping(TimeStampedModel):
    keyset = models.ForeignKey(
        Keyset,
        related_name='mappings',
        verbose_name=u'набор ключей',
    )
    key = models.CharField(
        max_length=255,
        verbose_name=u'ключ',
    )
    value = models.CharField(
        max_length=255,
        verbose_name=u'значение',
    )

    def __unicode__(self):
        return u'{0} {1} {2}'.format(
            self.keyset.title,
            self.key,
            self.value
        )

    class Meta:
        unique_together = ('keyset', 'key')
        verbose_name = u'Маппинг'
        verbose_name_plural = u'Маппинг'


import numpy as np

# TODO: В дальнейшем написать блок по задачам теорвера

class ProblemGenerator:

    def __init__(self, tier_param):

        self._tier = tier_param % 4  # TODO: 0-3

        self._types = {'algebra': ['det', 'eig', 'rank'],
                       'geometry': ['dot', 'vector_prod', 'norm']}

        self._curr_type = list(self._types.keys())[np.random.randint(0, len(self._types))]

    def _generator(self):

        task = getattr(self, '_' +
                       self._types[self._curr_type][np.random.randint(0, len(self._types[self._curr_type]))] +
                       '_' + self._curr_type + '_task')

        return task()

    def _det_algebra_task(self):

        length = elements = 2 + self._tier

        matrix = np.random.randint(-elements, elements, (length, length))

        task = 'Вычислить определитель матрицы:\n{}'.format(matrix)

        answer = int(round(np.linalg.det(matrix)))

        return task, [answer]

    def _eig_algebra_task(self):

        length, elements = 2 + self._tier, 1 + self._tier

        matrix = np.random.randint(-elements, elements, (length, length))

        matrix = 0.5 * (matrix + np.transpose(matrix))

        task = 'Вычислить собственные числа матрицы:\n(Округлить до сотых)\n{}'.format(matrix)

        eigenvalues = np.linalg.eigvals(matrix)

        answer = [round(ans, 2) for ans in eigenvalues]

        return task, list(answer)

    def _rank_algebra_task(self):

        length, elements = max(2, 1 + self._tier), 2 + self._tier

        matrix = np.random.randint(-elements, elements, (length, length))

        task = 'Найти ранг матрицы:\n{}'.format(matrix)

        answer = np.linalg.matrix_rank(matrix)

        return task, [answer]

    def _dot_geometry_task(self):

        value = 2 * (2 ** self._tier)

        length = 2 ** self._tier

        vector1, vector2 = np.random.randint(0, value, length), np.random.randint(0, value, length)

        task = 'Вычислить скалярное произведение векторов:\nv = {}\nu = {}'.format(vector1, vector2)

        answer = np.vdot(vector1, vector2)

        return task, [answer]

    def _vector_prod_geometry_task(self):

        value = 2 + 2 * self._tier

        vector1, vector2 = np.random.randint(-value, value, 3), np.random.randint(-value, value, 3)

        task = 'Вычислить векторное произведение векторов:\nv = {}\nu = {}'.format(vector1, vector2)

        answer = np.cross(vector1, vector2)

        return task, list(answer)

    def _norm_geometry_task(self):

        value = 2 + 2 ** self._tier

        length = 2 ** self._tier

        vector = np.random.randint(-value, value, length)

        task = 'Вычислить норму вектора:\n(Округлить до сотых)\nv = {}'.format(vector)

        answer = round(np.linalg.norm(vector), 2)

        return task, [answer]

    @property
    def get_task(self):

        return self._generator()


import cv2

minArea = 500
color = (255,0,255)
numberPlatesCasCade = cv2.CascadeClassifier("C:/Users/Nour/PycharmProjects/OpenCVPython/venv/Lib/site-packages/cv2/data/haarcascade_russian_plate_number.xml")
path = "C:/Users/Nour/Desktop/2.jpg"
img = cv2.imread(path)

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

numberplates = numberPlatesCasCade.detectMultiScale(gray,1.1,4)

for (x,y,w,h)in numberplates:
    area = w*h
    if area > minArea :
         cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
         cv2.putText(img,"Number plate",(x,y-5),cv2.FONT_HERSHEY_COMPLEX_SMALL,1,color,2)
         imgRoi = img[y:y+h,x:x+w]
         cv2.imshow("ROI",imgRoi)
cv2.imshow("Result",img)
cv2.waitKey(0)


import numpy as np
import pylab as pl

from   diff2          import diff2
from   scipy.optimize import minimize

def X0(airmass, params):
      ##  Dependence on moonfrac for a given airmass.
      return  params[0] + params[1] * airmass ** 0.75

def Y0(moonfrac, params):
      ##  Dependence on moonfrac for a given airmass.
      Y = moonfrac - 0.1

      return  params[0] * np.exp(Y / 0.29) - params[0]

_airmass  = [1.0, 1.2, 1.6, 2.0, 2.4, 2.8, 3.0]
fits      = []

index     =  2

for airmass in _airmass:
  dat = np.loadtxt('dat/moonfit_{:.1f}_{:d}.txt'.format(airmass, index))
  pl.plot(dat[:,0], dat[:,1], label='{:.2f}'.format(airmass))

  res = minimize(diff2, np.array([1.0]), args=([dat[:,0], dat[:,1], Y0]), method='Nelder-Mead', tol=1e-6)

  # print(airmass, res.x)

  pl.plot(dat[:,0], Y0(dat[:,0], res.x), 'k-')

  fits.append([airmass, res.x])

pl.legend(frameon=False)
pl.show()
pl.clf()

##
fits = np.array(fits)

pl.plot(fits[:,0], fits[:,1], 'k-')

_abs = np.arange(0.0, 3.0, 0.01)

res  = minimize(diff2, np.array([0.0, 1.0]), args=([fits[:,0], fits[:,1], X0]), method='Nelder-Mead', tol=1e-6)

print(res.x)

pl.plot(fits[:,0], X0(fits[:,0], res.x), 'c--')

pl.show()


from flask_restful import Resource, reqparse, Api
from flask import Flask, make_response
from flask_cors import CORS
from module.aladinV2 import Aladin
from module.yes24V2 import Yes24
# import module.aladin as Aladin
#import module.yes24 as Yes24
import json

class Search(Resource):
    def get(self):
        try:
            parser = reqparse.RequestParser()
            parser.add_argument('word', required=True,
                                type=str, help='Please enter word')
            parser.add_argument('mode', required=True,
                                type=int, help='Please enter mode')
            args = parser.parse_args()
            result = ''
            if args['mode'] == 0:
                aladin = Aladin(args['word'])
                result = aladin.result()
            elif args['mode'] == 1:
                yes24 = Yes24(args['word'])
                result = yes24.result()
            """
            elif args['mode'] == "common":
            """
            resp = make_response(json.dumps(result, ensure_ascii=False))
            return resp
        except Exception as e:
            return {'error': str(e)}

app = Flask('api_offbookstore')
CORS(app)
app.config['JSON_AS_ASCII'] = False
api = Api(app)
api.add_resource(Search, '/search')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=7000, debug=True)