# -*- coding: utf-8 -*-
from ..models import utils
from odoo.exceptions import UserError
from odoo.exceptions import ValidationError
from copy import deepcopy
from collections import defaultdict
from odoo.tools import float_repr
from odoo import api, fields, models, release, _
from pprint import pprint
from datetime import datetime

file_types = [
    ('F', 'Facturação'),
    ('A', 'Aquisição de bens e serviços'),
]

class SafTWizard(models.TransientModel):
    _inherit = "account.general.ledger.report.handler"
    _name = "saft.ao.wizard"
    _description = "Generate XML File"

    type = fields.Selection(
        string="File Type", selection=file_types, help="Tipo do ficheiro de exportação")
    comment = fields.Text("Comment")
    company_id = fields.Many2one(string="Company", comodel_name="res.company", required=True,
                                 default=lambda l: l.env.user.company_id)
    date_from = fields.Date("Start Date")
    date_to = fields.Date("End Date")
    content_xml = fields.Text("")
    name = fields.Char("Name", compute='_compute_name')
    status = fields.Datetime.now(),

    @api.depends('date_to', 'date_from')
    def _compute_name(self):
        self.name = "XML SAF-T AO PERIOD %s - %s" % (
            self.date_to or '/',
            self.date_from or '/'
        )

    @api.constrains('date_from', 'date_to')
    def check_dates(self):
        if self.date_from > self.date_to:
            raise ValidationError('Start Date must be lower than End Date')

    def get_customer(self):
        customer = self.env['res.partner'].search([('customer', '=', True)])
        return customer

    def print_report_xml(self):
        options = self._get_options()
        return self.get_xml(options)

    def get_movement_article(self):
        articles = self.env['stock.move.line'].search(
            [('state', '=', 'done')])
        return articles

    def get_account_tax(self):
        taxes = self.env['account.tax'].search(
            [('active', '=', True)])
        return taxes

    @staticmethod
    def check_product_type(product_type):
        if product_type in ['service', 'monthly']:
            return 'S'
        return 'P'

    def check_saft_tax(self, tax_lines, tax_mapped):
        _tax = None
        last_tax_amount = 0
        for tax in tax_lines:
            if tax_mapped.count(tax.tax_on) > 1:
                last_tax_amount = 0
                for tax_use in tax_lines.filtered(lambda l: l.tax_on == tax.tax_on):
                    if last_tax_amount == 0:
                        if tax_use.amount >= last_tax_amount:
                            _tax = tax_use
                            last_tax_amount = tax_use.amount
                    else:
                        if tax_use.amount >= last_tax_amount:
                            _tax |= tax_use
                            last_tax_amount = tax_use.amount
            else:
                if _tax:
                    _tax |= tax
                else:
                    _tax = tax
        return _tax

    def get_customer_id(self, customer):
        if not customer.vat:
            final_consumer = self.env['res.partner'].search(
                [('vat', '=', '999999999')])
            if final_consumer:
                customer = final_consumer[0]
        final_consumer = self.env['res.partner'].search([('ref', '=', 'CF')])
        if final_consumer:
            customer = final_consumer[0]
        return customer.ref

    @api.model
    def _fill_saft_report_payments_values(self, options, values):

        result = {
            'payments': {
                "number_of_entries": 0,
                "total_debit": 0,
                "total_credit": 0,
                "payment": [],
            }
        }

        payment_data = {}

        invoices = self.env['account.move'].search([("invoice_date", ">=", options['date']['date_from']),
                                                    ("invoice_date", "<=",
                                                     options['date']['date_to']),
                                                    ('company_id', '=',
                                                     self.env.company.id),
                                                    ('move_type', 'in', [
                                                        'out_invoice']),
                                                    ('state', 'in', ['posted'])],
                                                   order="invoice_date asc")
        payments_ = []
        payments = []
        for inv in invoices:
            for payment_rec in self.env['account.payment'].search([("ref", '=', inv.name)]):
                payments_.append(payment_rec)

        for item in payments_:
            if item.id:
                payments.append(item)

        for payment in payments:
            if payment.id:
                payment_status = 'N'
                if payment.state == 'cancelled':
                    payment_status = 'A'

                lined = payment.mapped("line_ids")

                move = self.env['account.move'].search(
                    [("name", '=', payment.ref)])

                payment_data = {
                    "payment_ref_no": str(payment.receipt_no).replace((str(move.invoice_date).split('-'))[0], '20'),
                    "period": utils.extract_period(move.invoice_date),
                    "transaction_id": "%s %s %s" % (
                        str(move.invoice_date), str(payment.journal_id.code).replace(' ', ''),
                        str(payment.name).replace('/', '').replace(' ', '')),
                    "transaction_date": move.invoice_date,
                    "payment_type": 'RG',
                    "description": 'P ' + str(payment.invoice_line_ids.mapped('move_name')),
                    "system_id": payment.name,
                    "document_status": {
                        "payment_status": payment_status,
                        "payment_status_date": str((payment.system_entry_date).strftime("%Y-%m-%d %H:%M:%S")).replace(
                            ' ',
                            'T') if payment.system_entry_date else str(
                            datetime.now().strftime("%Y-%m-%d %H:%M:%S")).replace(
                            ' ',
                            'T'),
                        # "Reason": "",
                        "source_id": payment.create_uid.id,
                        "source_payment": 'P',
                    },
                    "payment_method": {
                        "payment_mechanism": payment.payment_mechanism or 'TB',
                        "payment_amount": utils.gross_total(payment.amount),
                        "payment_date": payment.date,
                    },
                    "source_id": payment.create_uid.id,
                    "system_entry_date": str(payment.system_entry_date).replace(' ',
                                                                                'T') if payment.system_entry_date else str(
                        (payment.write_date).strftime("%Y-%m-%d %H:%M:%S")).replace(' ', 'T'),
                    "customer_id": 'CF',
                    "line": []
                }

                lined_in = self.env['account.move'].search(
                    [("name", '=', payment.ref), ('move_type', 'in', ['out_invoice'])], order="invoice_date asc")

                for line in lined_in.line_ids:
                    if line.tax_ids:
                        lines = {
                            "line_number": line.id,
                            "source_document_id": {
                                "originating_on": payment.name,
                                "invoice_date": move.invoice_date,
                                "description": payment.ref or payment.name,
                            },
                            "settlement_amount": sum(line.mapped("discount")),
                            "taxs": [],

                        }

                        if move.move_type == "out_refund" and move.payment_state in ["not_open", "paid"]:
                            lines["debit_amount"] = move.amount_untaxed
                        elif move.move_type == "out_invoice" and move.payment_state in ["not_open", "paid"]:
                            lines["credit_amount"] = move.amount_untaxed

                        for tax in line.tax_ids:
                            if tax.tax_on == "invoice":
                                lines["taxs"].append({
                                    "tax_type": tax.saft_tax_type if tax.saft_tax_code in ['IVA', 'NS',
                                                                                'IS'] else "IVA",
                                    # FIXME: 4.1.4.19.15.2.
                                    "tax_country_region": tax.country_region,
                                    "tax_code": tax.saft_tax_code if tax.saft_tax_type in ['IVA', 'NS',
                                                                                'IS'] else tax.saft_tax_code,
                                    'tax_percentage': tax.amount if tax.amount_type in ["percent", "division"] else "0"
                                })

                        for tax in line.tax_ids:
                            if tax.tax_on == "invoice":
                                lines[
                                    "tax_exemption_reason"] = tax.exemption_reason if tax.amount == 0 and tax.exemption_reason else False
                                lines['tax_exemption_code'] = "M21" if tax.amount == 0 else ""
                        payment_data["line"].append(lines)

                payment_data["document_totals"] = {
                    "tax_payable": utils.gross_total(move.amount_tax),
                    "net_total": utils.gross_total(move.amount_untaxed),
                    "gross_total": utils.gross_total(move.amount_total),
                    "settlement": {
                        "settlement_amount": 0.0,
                    },
                }

                if lined.currency_id != lined.company_id.currency_id:
                    payment_data["document_totals"]["currency"] = {
                        "currency_code": lined.currency_id.name,
                        "currency_amount": lined.amount_total,
                        "exchange_rate": lined.currency_id.rate
                    }

                if move.move_type == "out_refund" and move.payment_state in ["not_paid", "paid"]:
                    result["payments"]["total_debit"] += utils.gross_total(
                        move.amount_untaxed)
                elif move.move_type == "out_invoice" and move.payment_state in ["not_paid", "paid"]:
                    result["payments"]["total_credit"] += utils.gross_total(
                        move.amount_untaxed)

            result['payments']['payment'].append(payment_data)
        result['payments']['number_of_entries'] = len(payments)
        # for rec in result['payments']['payment']:
        #     for re in rec['line']:
        #         print(re)
        values.update(result)

    @api.model
    def _fill_saft_report_sales_order_values(self, options, values):

        result = {
            'working_documents': {
                "number_of_entries": 0,
                "total_debit": 0,
                "total_credit": 0,
                "work_documents": [],
            }
        }

        sales = self.env['sale.order'].search([("date_order", ">=", fields.Datetime.from_string(self.date_from)),
                                               ("date_order", "<=", fields.Datetime.from_string(self.date_to)),
                                               ('company_id', '=',
                                                self.env.company.id),
                                               ('state', 'in', [
                                                   'sale'])
                                               ],
                                              order="name asc")
        # for rec in sales:
        #     print()
        #     print(rec.date_order, rec.name, rec.partner_id, rec.user_id, rec.state)

        for sale in sales:
            status_code = 'N'
            if sale.state == 'cancel':
                status_code = 'A'
            if sale.state in ['sale', 'done']:
                status_code = 'F'
            source_billing = "P"
            sale_order = {
                "document_number": sale.work_type + " " + sale.name.split(' ')[-1],
                "document_status": {
                    "work_status": status_code,
                    "work_status_date": str((sale.date_order).strftime("%Y-%m-%d %H:%M:%S")).replace(' ', 'T'),
                    "source_id": sale.user_id.id,
                    "source_billing": source_billing,
                },
                "hash": sale.hash,
                "hash_control": "0" or sale.hash_control,
                "period": utils.extract_period(sale.create_date),
                "work_date": str(sale.date_order)[0:10],
                "work_type": sale.work_type,
                "source_id": sale.user_id.id,
                "system_entry_date": str((sale.system_entry_date.strftime("%Y-%m-%d %H:%M:%S")).replace(' ',
                                                                                'T') if sale.system_entry_date else str(
                    sale.date_order.strftime("%Y-%m-%d %H:%M:%S")).replace(' ', 'T')),
                "customer_id": 'CF',
                "lines": [],
                "document_totals": {
                    "tax_payable": utils.gross_total(sale.amount_tax),
                    "net_total": utils.gross_total(sale.amount_untaxed),
                    "gross_total": utils.gross_total(sale.amount_total),
                }

            }

            for line in sale.order_line:

                lines = {
                    "line_number": line.id,
                    "product_code": line.product_id.id or line.product_id.default_code,
                    "product_description": line.product_id.name[:200],
                    "quantity": line.product_uom_qty,
                    "unit_of_measure": "UN",
                    "unit_price": line.price_unit,
                    "tax_base": line.price_subtotal if line.price_unit == 0.0 else 0.0,
                    "tax_point_date": str(sale.date_order)[0:10],
                    "description": line.product_id.name[:200],
                    "credit_amount": utils.gross_total(line.price_subtotal),
                    "tax_exemption_reason": 0,
                    "taxs": [],
                }

                taxes_to_use = self.check_saft_tax(line.tax_id,
                                                   line.tax_id.mapped('tax_on'))
                if taxes_to_use:
                    for tax in taxes_to_use:
                        if tax.tax_on != 'withholding':
                            tax_values = {
                                "tax_type": tax.saft_tax_type if tax.saft_tax_code in ['IVA', 'NS', 'IS'] else "IVA",
                                # FIXME: 4.1.4.19.15.2.
                                "tax_country_region": tax.country_region,
                                # "tax_code": tax.tax_type if tax.tax_code == 'NS' else tax.tax_code,
                                "tax_code": tax.saft_tax_code if tax.saft_tax_type in ['IVA', 'NS',
                                                                                'IS'] else tax.saft_tax_code,
                            }
                            if tax.amount_type in ["percent", "division"]:
                                tax_values["tax_percentage"] = utils.gross_total(
                                    tax.amount)
                            elif tax.amount_type in ["fixed"]:
                                tax_values["tax_amount"] = utils.gross_total(
                                    tax.amount)
                            if tax.tax_on == "invoice":
                                lines["tax_exemption_reason"] = tax.exemption_reason if tax.amount == 0 else False,
                                lines["tax_exemption_code"] = "M21" if tax.amount == 0 else "",
                            lines["taxs"].append(tax_values)
                if not lines["taxs"]:
                    lines["taxs"].append({
                        "tax_type": "NS",
                        "tax_country_region": "AO",
                        "tax_code": "NS",
                        "tax_percentage": "0"})
                    lines["tax_exemption_reason"] = "Isento nos termos da alínea l) do nº1 do artigo 12.º do CIVA"
                    lines["tax_exemption_code"] = "M21"

                sale_order["lines"].append(lines)

            result['working_documents']["work_documents"].append(sale_order)
            result['working_documents']["total_credit"] += utils.gross_total(
                sale.amount_untaxed)

            result['working_documents']["number_of_entries"] += 1
        values.update(result)

    @api.model
    def _fill_saft_report_products_values(self, options, values):
        res = {
            'product_vals_list': []
        }
        default_product = {
            'product_type': 'S',
            'product_code': 'HS12D',
            'product_group': 'Todos',
            'product_description': 'Serviços',
            'product_number_code': 'HS12D',
            # 'CustomsDetails': product.customs_details or "",
        }

        for product in self.env['product.product'].search([]):
            product_val = {
                'product_type': self.check_product_type(product['type']),
                'product_code': product['id'],
                'product_group': product['categ_id']['name'],
                'product_description': product['description_sale'].strip()[:200] if product['description_sale'] else
                product['name'].strip()[:200],
                'product_number_code': product['default_code'] or product['id'],
                # 'CustomsDetails': product.customs_details or "",
            }
            res['product_vals_list'].append(product_val)
        res['product_vals_list'].append(default_product)

        values.update(res)

    @api.model
    def _fill_saft_report_general_ledger_values(self, options, values):

        result = {
            "sales_invoices": {
                "number_of_entries": 0,
                "total_debit": 0,
                "total_credit": 0,
                "invoices": [],
            },
            "invoices": {
                "number_of_entries": 0,
                "invoices": [],
            },

            # Codigo Acrescentado
            "purchase_invoices": {
                "number_of_entries": 0,
                "invoices": [],
            }
        }
        # Sales Invoicing
        invoices = self.env['account.move'].search([("invoice_date", ">=", self.date_from),
                                                    ("invoice_date", "<=", self.date_to),
                                                    ('move_type', '=', 'out_invoice'),
                                                    ('company_id', '=', self.env.company.id),
                                                    ('state', '=', 'posted'),
                                                    ('payment_state', 'in', ['paid', 'not_paid'])],
                                                   order="invoice_date,name asc")
        print("olha encontraste vendas?", invoices)
        # invoices.clean_number_invoices(self.date_from, self.date_to)
        for inv in invoices:
            status_code = 'N'
            if inv.state == 'cancel':
                status_code = 'A'
            elif inv.journal_id.self_billing is True:
                status_code = 'S'
            source_billing = "P"

            # FACTURAS CLIENTES

            if inv.move_type in ["out_invoice"]:
                invoice_customer = {
                    "invoice_no": inv.name,
                    "document_status": {
                        "invoice_status": status_code,
                        "invoice_status_date": str(inv.system_entry_date).replace(' ',
                                                                                'T') if inv.system_entry_date else str(
                            inv.create_date).replace(' ', 'T'),
                        # "Reason": "",  # TODO GENERATE CONTENT FOR REASON
                        "source_id": inv.user_id.id,
                        "source_billing": source_billing,
                    },
                    "hash": inv.hash,
                    "hash_control": inv.hash_control,
                    "period": int(str(inv.invoice_date)[5:7]),
                    "invoice_date": inv.invoice_date,
                    "invoice_type": "FT" if inv.move_type == "out_invoice" else "NC",
                    # 'order_references': inv.name,

                    "special_regimes": {
                        "self_billing_indicator": 1 if inv.journal_id.self_billing else 0,
                        "cash_vat_scheme_indicator": 1 if inv.company_id.tax_exigibility else 0,
                        "third_parties_billing_indicator": 0,
                    },
                    "source_id": inv.user_id.id,
                    # "EACCode": "N/A",
                    "system_entry_date": str(inv.system_entry_date).replace(' ', 'T') if inv.system_entry_date else str(
                        inv.create_date).replace(' ', 'T'),
                    "transaction_id": "%s %s %s" % (
                        inv.date, inv.journal_id.code.replace(' ', ''),
                        inv.name.replace(' ', '').replace('/', '')) if inv.name else '',
                    "customer_id": 'CF',
                    # "ShipTo": "",  # TODO: 4.1.4.15
                    # "ShipFrom": "",  # TODO: 4.1.4.16
                    # "MovementEndTime": "",  # TODO: 4.1.4.17,
                    # TODO: 4.1.4.18,
                    "movement_start_time": str(inv.system_entry_date).replace(' ',
                                                                              'T') if inv.system_entry_date else str(
                        inv.create_date).replace(' ', 'T'),
                    "lines": [],
                    "document_totals": {
                        "tax_payable": utils.gross_total(inv.amount_tax),
                        "net_total": utils.gross_total(inv.amount_untaxed),
                        # TODO: we must review this with invoice in different currency
                        "gross_total": utils.gross_total(inv.amount_total),
                        # TODO: we must review this with invoice in different currency
                        "currency": {
                            "currency_code": inv.currency_id.name,
                            "Currency_amount": utils.gross_total(inv.amount_total),
                            "exchange_rate": inv.currency_id.rate,
                        } if inv.currency_id != inv.company_id.currency_id else {},
                        "settlement": {
                            "settlement_discount": inv.settlement_discount or 0,
                            "settlement_amount": inv.settlement_amount or 0,
                            # "SettlementDate": inv.settlement_date or "",
                            "payment_terms": inv.payment_id.name if inv.payment_id.name else "",
                        },
                        "payments": [{
                            "payment_mechanism": payment.payment_mechanism or "TB",
                            "payment_amount": utils.gross_total(payment.amount),
                            "payment_date": payment.payment_date,
                        } for payment in inv.payment_id]

                    },
                    "withholding_tax": [{
                        "withholding_tax_type": tax.tax_id.saft_wth_type,
                        "withholding_tax_description": tax.tax_id.name,
                        "withholding_tax_amount": utils.gross_total(tax.amount),
                    } for tax in inv.tax_line_ids.filtered(lambda r: r.tax_id.tax_on == "withholding")],
                }
                if not invoice_customer['document_totals']['payments']:
                    invoice_customer['document_totals'].pop('payments')

                # payments = []
                # for payment in inv.payment_ids:
                #     payment_values = {
                #         "PaymentMechanism": payment.payment_mechanism,
                #         "PaymentAmount": utils.gross_total(payment.amount),
                #         "PaymentDate": payment.payment_date,
                #     }
                #     payments.append(payment_values)
                # invoice_customer['DocumentTotals']['Payment'] = payments

                for line in inv.invoice_line_ids:
                    lines = {
                        "line_Number": line.id,
                        # "OrderReferences": {"OriginatingON": inv.origin or "", "OrderDate": ""},  # TODO:4.1.4.19.2.
                        "product_code": line.product_id.id if line.product_id else 'HS12D',
                        "product_description": line.product_id.description_sale.strip()[
                                               :200] if line.product_id.description_sale else line.product_id.name.strip()[
                                                                                :200],
                        "quantity": line.quantity,
                        "unit_of_measure": line.product_uom_id.name,
                        "unit_price": line.price_unit,
                        "tax_base": line.price_subtotal if line.price_unit == 0.0 else 0.0,
                        "tax_point_date": inv.date,
                        "credit_amount": False,
                        "debit_amount": False

                    }

                    if inv.move_type == "out_refund":
                        lines['references'] = {
                            "reference": inv.name,
                        }

                    lines['description'] = line.product_id.name.strip()[:200],
                    # lines['ProductSerialNumber'] = {
                    #     "SerialNumber": line.product_id.default_code or "S/N",  # TODO: 4.1.4.19.12.
                    # }

                    if inv.move_type == "out_refund" and inv.payment_state in ["not_paid", "paid"]:
                        lines["debit_amount"] = utils.gross_total(
                            line.price_subtotal)

                    if inv.move_type == "out_invoice" and inv.payment_state in ["not_paid", "paid"]:
                        lines["credit_amount"] = utils.gross_total(
                            line.price_subtotal)

                    lines["tax"] = []

                    taxes_to_use = self.check_saft_tax(
                        line.tax_ids, line.tax_ids.mapped('tax_on'))
                    if taxes_to_use:
                        for tax in taxes_to_use:
                            if tax.tax_on != 'withholding':
                                tax_values = {
                                    "tax_type": tax.saft_tax_type if tax.saft_tax_code in ['IVA', 'NS',
                                                                                'IS'] else "IVA",
                                    # FIXME: 4.1.4.19.15.2.
                                    "tax_country_region": tax.country_region,
                                    # "tax_code": tax.tax_type if tax.tax_code == 'NS' else tax.tax_code,
                                    "tax_code": tax.saft_tax_code if tax.saft_tax_type in ['IVA', 'NS',
                                                                                'IS'] else tax.saft_tax_code,
                                }
                                if tax.amount_type in ["percent", "division"]:
                                    tax_values["tax_percentage"] = utils.gross_total(
                                        tax.amount)
                                elif tax.amount_type in ["fixed"]:
                                    tax_values["tax_amount"] = utils.gross_total(
                                        tax.amount)
                                if tax.tax_on == "invoice":
                                    if tax.amount == 0:
                                        lines["tax_exemption_reason"] = tax.exemption_reason,
                                        lines["tax_exemption_code"] = "M21" if tax.amount == 0 else " ",
                                lines["tax"].append(tax_values)
                    if not lines["tax"]:
                        lines["tax"].append({"tax_type": "NS",
                                             "tax_country_region": "AO",
                                             "tax_code": "NS",
                                             "tax_percentage": "0"})
                        lines["tax_exemption_reason"] = "Isento nos termos da alínea l) do nº1 do artigo 12.º do CIVA"
                        lines["tax_exemption_code"] = "M21"
                    lines["settlement_amount"] = line.discount
                    # lines["CustomsInformation"] = {  # TODO: 4.1.4.19.19.
                    #     "ARCNo": "",
                    #     "IECAmount": "",
                    # }
                    invoice_customer["lines"].append(lines)

                if inv.currency_id == inv.company_id.currency_id:
                    invoice_customer["document_totals"].pop("currency")

                if not [tax.id for tax in inv.tax_line_ids.filtered(lambda r: r.tax_id.tax_on == "withholding")]:
                    invoice_customer.pop("withholding_tax")

                result["sales_invoices"]["invoices"].append(invoice_customer)

                if inv.move_type == "out_refund":
                    result["sales_invoices"]["total_debit"] += utils.gross_total(
                        inv.amount_untaxed)

                # if is normal or invoiced
                elif inv.move_type == "out_invoice" and inv.payment_state in ["not_paid", "paid"]:
                    result["sales_invoices"]["total_credit"] += utils.gross_total(
                        inv.amount_untaxed)

                result["sales_invoices"]["number_of_entries"] += 1

            else:
                invoice_supplier = {
                    "invoice_no": inv.sequence_number,
                    "source_id": inv.user_id.id,
                    "period": int(str(inv.invoice_date)[5:7]),
                    "invoice_date": inv.invoice_date,
                    "invoice_type": "ND" if inv.move_type == "in_refund" else "FT",
                    "supplier_id": inv.partner_id.ref or inv.partner_id.id,
                    "document_totals": {
                        "tax_payable": utils.gross_total(inv.amount_tax),
                        "net_total": utils.gross_total(inv.amount_untaxed),
                        # TODO: we must review this with invoice in different currency
                        "gross_total": utils.gross_total(inv.amount_total),
                        "deductible": {
                            "tax_base": utils.gross_total(inv.amount_untaxed),
                            # TODO: we must review this with invoice in different currency
                            "deductible_tax": "",
                            "deductible_percentage": "",
                            # "Currency": {
                            # "CurrencyCode": inv.currency_id.name,
                            #  "CurrencyAmount": utils.gross_total(inv.amount_total),
                            #  } if inv.currency_id != inv.company_id.currency_id else {},

                        },
                        "payments": [{
                            "payment_mechanism": payment.payment_mechanism or "TB",
                            "payment_amount": utils.gross_total(payment.amount),
                            "payment_date": payment.payment_date,
                        } for payment in inv.payment_id]

                    },
                    "withholding_tax": [{
                        "withholding_tax_type": tax.tax_id.saft_wth_type,
                        "withholding_tax_description": tax.tax_id.name,
                        "withholding_tax_amount": utils.gross_total(tax.amount),
                    } for tax in inv.tax_line_ids.filtered(lambda r: r.tax_id.tax_on == "withholding")]

                }
                if not invoice_supplier['document_totals']['payments']:
                    invoice_supplier['document_totals'].pop('payments')

                # if inv.currency_id == inv.company_id.currency_id:
                # invoice_supplier["DocumentTotals"].pop("Currency")

                result["invoices"]["invoices"].append(invoice_supplier)
                result["invoices"]["number_of_entries"] += 1
        values.update(result)

    @api.model
    def _fill_saft_report_tax_table_values(self, options, values):
        result = {"tax_table": []}
        control = []

        for tax in self.env['account.tax'].search([('active', '=', True)]):
            if tax.saft_tax_type not in control:
                tax_table = {
                    'tax_type': tax.saft_tax_type if tax.saft_tax_code in ['IVA', 'NS', 'IS'] else "IVA",
                    'tax_country_region': 'AO',
                    # 'tax_code':tax.tax_type if tax.tax_code == 'NS' else tax.tax_code,
                    'tax_code': tax.saft_tax_code if tax.saft_tax_type in ['IVA', 'NS', 'IS'] else tax.saft_tax_code,
                    'description': tax.description,
                    'tax_percentage': tax.amount if tax.amount_type in ["percent",
                                                                        "division"] else "0.0"
                }

                control.append(tax.saft_tax_type)
                result['tax_table'].append(tax_table)
                print(tax_table)
        values.update(result)

    @api.model

    def _fill_saft_report_partner_ledger_values(self, options, values):
        res = {
            'customer_vals_list': [],
            'supplier_vals_list': [],
            'partner_detail_map': defaultdict(lambda: {
                'type': False,
                'addresses': [],
                'contacts': [],
            }),
        }

        all_partners = self.env['res.partner']

        # Fill 'customer_vals_list' and 'supplier_vals_list'
        report = self.env.ref('account_reports.partner_ledger_report')
        new_options = report._get_options(options)
        new_options['account_type'] = [
           {'id': 'trade_receivable', 'selected': True},
            {'id': 'non_trade_receivable', 'selected': True},
            {'id': 'trade_payable', 'selected': True},
            {'id': 'non_trade_payable', 'selected': True},
        ]
        handler = self.env['account.partner.ledger.report.handler']
        partners_results = handler._query_partners(new_options)
        partner_vals_list = []
        rslts_array = tuple((partner, res_col_gr[options['single_column_group']]) for partner, res_col_gr in partners_results)
        init_bal_res = handler._get_initial_balance_values(tuple(partner.id for partner, results in rslts_array), options)
        initial_balances_map = {}
        initial_balance_gen = ((partner_id, init_bal_dict.get(options['single_column_group'])) for partner_id, init_bal_dict in init_bal_res.items())

        for partner_id, initial_balance in initial_balance_gen:
            initial_balances_map[partner_id] = initial_balance
        for partner, results in partners_results:
            # Ignore Falsy partner.
            if not partner:
                continue

            all_partners |= partner

            partner_sum = results.get('sum', {})
            partner_init_bal = results.get('initial_balance', {})

            opening_balance = partner_init_bal.get('debit', 0.0) \
                              - partner_init_bal.get('credit', 0.0)
            closing_balance = partner_init_bal.get('debit', 0.0) \
                              + partner_sum.get('debit', 0.0) \
                              - partner_init_bal.get('credit', 0.0) \
                              - partner_sum.get('credit', 0.0)
            partner_vals_list.append({
                'partner': partner,
                'account_id': partner['property_account_receivable_id'],
                'opening_balance': opening_balance,
                'closing_balance': closing_balance,
            })

        if all_partners:
            domain = [('partner_id', 'in', tuple(all_partners.ids))]
            tables, where_clause, where_params = self.env.ref('account_reports.general_ledger_report')._query_get(new_options,'strict_range', domain=domain)
            self._cr.execute(f'''
                SELECT
                    account_move_line.partner_id,
                    SUM(account_move_line.balance)
                FROM {tables}
                JOIN account_account account ON account.id = account_move_line.account_id
                WHERE {where_clause}
                AND account.account_type IN ('asset_receivable', 'liability_payable')
                GROUP BY account_move_line.partner_id
            ''', where_params)

            for partner_id, balance in self._cr.fetchall():
                res['partner_detail_map'][partner_id]['type'] = 'customer' if balance >= 0.0 else 'supplier'

        for partner_vals in partner_vals_list:
            partner_id = partner_vals['partner'].id
            if res['partner_detail_map'][partner_id]['type'] == 'customer':
                res['customer_vals_list'].append(partner_vals)
            elif res['partner_detail_map'][partner_id]['type'] == 'supplier':
                res['supplier_vals_list'].append(partner_vals)

        # Fill 'partner_detail_map'.
        all_partners |= values['company'].partner_id
        partner_addresses_map = defaultdict(dict)
        partner_contacts_map = defaultdict(lambda: self.env['res.partner'])

        def _track_address(current_partner, partner):
            if partner.zip and partner.city:
                address_key = (partner.zip, partner.city)
                partner_addresses_map[current_partner][address_key] = partner

        def _track_contact(current_partner, partner):
            phone = partner.phone or partner.mobile
            if phone:
                partner_contacts_map[current_partner] |= partner

        for partner in all_partners:
            _track_address(partner, partner)
            _track_contact(partner, partner)
            for child in partner.child_ids:
                _track_address(partner, child)
                _track_contact(partner, child)

        no_partner_address = self.env['res.partner']
        no_partner_contact = self.env['res.partner']
        for partner in all_partners:
            res['partner_detail_map'][partner.id].update({
                'partner': partner,
                'addresses': list(partner_addresses_map[partner].values()),
                'contacts': partner_contacts_map[partner],
            })
            if not res['partner_detail_map'][partner.id]['addresses']:
                no_partner_address |= partner
            if not res['partner_detail_map'][partner.id]['contacts']:
                no_partner_contact |= partner

        # if no_partner_address:
        #     raise UserError(_(
        #         "Please define at least one address (Zip/City) for the following partners: %s.",
        #         ', '.join(no_partner_address.mapped('display_name')),
        #     ))
        # if no_partner_contact:
        #     raise UserError(_(
        #         "Please define at least one contact (Phone or Mobile) for the following partners: %s.",
        #         ', '.join(no_partner_contact.mapped('display_name')),
        #     ))

        # Add newly computed values to the final template values.
        values.update(res)

    @api.model
    def _prepare_saft_report_values(self, options):
        def format_float(amount, digits=2):
            return float_repr(amount or 0.0, precision_digits=digits)

        def format_date(date_str, formatter):
            date_obj = fields.Date.to_date(date_str)
            return date_obj.strftime(formatter)

        company = self.env.company

        # print("\n\nCompany:.....", company.display_name)

        if not company.company_registry:
            raise UserError(
                _("Please define `Company Registry` for your company."))

        options["single_column_group"] = tuple(options["column_groups"].keys())[0]

        template_values = {
            'company': company,
            'fiscal_year': company.accounting_year.name,
            'tax_entity': company.tax_entity,
            'xmlns': '',
            'file_version': 'undefined',
            'accounting_basis': 'undefined',
            'today_str': fields.Date.to_string(fields.Date.context_today(self)),
            'software_version': release.version,
            'date_from': options['date']['date_from'],
            'date_to': options['date']['date_to'],
            'format_float': format_float,
            'format_date': format_date,
        }

        self._fill_saft_report_general_ledger_values(options, template_values)
        self._fill_saft_report_products_values(options, template_values)
        self._fill_saft_report_tax_table_values(options, template_values)
        self._fill_saft_report_partner_ledger_values(options, template_values)
        self._fill_saft_report_sales_order_values(options, template_values)
        self._fill_saft_report_payments_values(options, template_values)

        return template_values

    def get_xml(self):
        options = self.env.ref('account_reports.general_ledger_report')._get_options()
        options = deepcopy(options)
        # options = self._force_strict_range(options)
        options.pop('multi_company', None)
        options['unfolded_lines'] = []
        options['unfold_all'] = False
        options['date']['date_from'] = self.date_from
        options['date']['date_to'] = self.date_to

        # print("\nGet_xml: .....  . . .. ", options)

        template_vals = self._prepare_saft_report_values(options)

        # print("Template Vals\n")
        # pprint(template_vals)
        # print("\nTemplate Vals: .....  . . .. ",template_vals)

        self.content_xml = self.env['ir.qweb']._render('l10n_ao_saft.saft_report',template_vals)
        self.content_xml = self.content_xml.replace('<AuditFile>',
                                                    """<?xml version="1.0" encoding="utf-8"?>
                      <AuditFile xmlns="urn:OECD:StandardAuditFile-Tax:AO_1.01_01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:OECD:StandardAuditFile-Tax:AO_1.01_01 https://raw.githubusercontent.com/assoft-portugal/SAF-T-AO/master/XSD/SAFTAO1.01_01.xsd">""")

        self.content_xml = self.content_xml.strip()

        req = self.download()
        return req

    def download(self):

        print("\nID::", self.id)

        return {
            'type': 'ir.actions.act_url',
            'url': '/web/download/saft_ao_file/%s' % self.id,
            'target': 'new',
        }


import os
import cv2
import re
import PIL
import sys
import json
import time
import timm
import math
import copy
import torch
import pickle
import logging
import fnmatch
import argparse
import itertools
import torchvision
from util import *
import numpy as np
import pandas as pd
from apex import amp
import seaborn as sns
import albumentations
import torch.nn as nn
from PIL import Image
from pathlib import Path
from copy import deepcopy
import scikitplot as skplt
from sklearn import metrics
import torch.optim as optim
from timm import create_model
from datetime import datetime
from timm.data.loader import *
from torchvision import models
import matplotlib.pyplot as plt
import torch.nn.functional as F
import torch.utils.data as data
from cutmix.cutmix import CutMix
from torch.autograd import Variable
from tqdm import tqdm, tqdm_notebook
from torch.optim import lr_scheduler
#from pytorch_metric_learning import loss
import torch.utils.model_zoo as model_zoo
from timm.models.layers.activations import *
from timm.utils import accuracy, AverageMeter
from apex.parallel import convert_syncbn_model
from timm.utils import ApexScaler, NativeScaler
from cutmix.utils import CutMixCrossEntropyLoss
from timm.models.registry import register_model
from collections import OrderedDict, defaultdict
from torch.utils.tensorboard import SummaryWriter
from warmup_scheduler import GradualWarmupScheduler
from timm.models.resnet import resnet26d, resnet50d
from torchvision import transforms, models, datasets
from timm.models.helpers import build_model_with_cfg
from torch.utils.data.sampler import SubsetRandomSampler
from randaugment import RandAugment, ImageNetPolicy, Cutout
from apex.parallel import DistributedDataParallel as ApexDDP
from timm.models.layers import DropPath, to_2tuple, trunc_normal_
from timm.data import IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD
from timm.loss import LabelSmoothingCrossEntropy, SoftTargetCrossEntropy
from timm.models.efficientnet import efficientnet_b0, efficientnet_b1, efficientnet_b2, efficientnet_b3
from sklearn.metrics import classification_report, confusion_matrix,accuracy_score, roc_curve, auc, roc_auc_score
#from timm.data import Dataset, DatasetTar, RealLabelsImagenet, create_loader, Mixup, FastCollateMixup, AugMixDataset

TRAIN = False
TYPE = sys.argv[1]

# if TYPE=='orig':
data_dir = '/scratch/es5223/medsynth/data/TBX11K_classification_splits/'
if TYPE=='cyclegan':
    data_dir = '/scratch/es5223/medsynth/data_syntheticCT/TBX11K_cycleGAN_classification_splits/'
elif TYPE=='cyclegan+ns':
    DD = '/scratch/es5223/medsynth/data_preprocessedXray/imgs_cyclegan_n2s_xu/'
elif TYPE=='cyclegan+nv':
    DD = '/scratch/es5223/medsynth/data_preprocessedXray/imgs_cyclegan_n2v_xu/'
elif TYPE=='ns':
    DD = '/scratch/es5223/medsynth/data_preprocessedXray/noise2self_Xu/imgs_n2s/'

for TRIAL in range(3):
    CHECK_POINT_PATH = 'models_trials/X_'+str(TYPE)+'_VT_TRIAL_'+str(TRIAL)+'.pth'

    torch.backends.cudnn.benchmark = True

    def load_image_joint(im_path):
        if TYPE!='orig' and 'cyclegan' in TYPE:
            im_path = DD + '/'.join(im_path.split('/')[-2:])
            if '.png' in im_path:
                im_path = im_path.replace('.png','_fake.png')
            elif '.jpg' in im_path:
                im_path = im_path.replace('.jpg','_fake.png')
            if not os.path.isfile(im_path):
                print("im_path af ", im_path)
        elif TYPE=='ns':
            im_path = DD + '/'.join(im_path.split('/')[-2:])
            if not os.path.isfile(im_path):
                print("im_path af ", im_path)
        x_img = cv2.imread(im_path, cv2.IMREAD_GRAYSCALE) * 1/256.
        x_img = cv2.resize(x_img,dsize=(224,224))

        return x_img

    def is_valid_file(path):
        return True
    device = torch.device("cuda:0")
    batch_size = 80
    # Batch_size (48 or 50 for EfficientNet-B0, img_size=320, cuda=0 or cuda=1)
    # Batch_size (64 or 68 for EfficientNet-B1, img_size=240, cuda=0 or cuda=1)
    num_epochs = 500
    lr = 0.01
    beta = 1
    step_size = 130
    img_size = 224
    test_size = int((256 / 224) * img_size)

    mean = [0.485]
    std = [0.229]
    num_workers = 4
    # Define your transforms for the training and testing sets
    data_transforms = {
        'train': transforms.Compose([
            #transforms.Resize(224),
            transforms.ToTensor(),
            transforms.Normalize(0., 1.),
            transforms.RandomErasing()
        ]),
        'val': transforms.Compose([
            #transforms.Resize(224),
            transforms.ToTensor(),
            transforms.Normalize(0., 1.)
        ]),
        'test': transforms.Compose([
            #transforms.Resize(224),
            transforms.ToTensor(),
            transforms.Normalize(0., 1.)
        ])
    }

    # Load the datasets with ImageFolder
    print("data_dir ", data_dir)
    image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x),
                                              data_transforms[x],
                                              loader=load_image_joint,
                                              is_valid_file=is_valid_file) for x in ['train', 'val', 'test']}

    class_names = image_datasets['train'].classes
    num_classes = len(class_names)
    data_loader = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=batch_size,
                                                 shuffle=True, num_workers=num_workers, pin_memory = True)
                  for x in ['train', 'val', 'test']}

    dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val', 'test']}

    print(class_names)
    print(dataset_sizes)
    print(device)

    ### we get the class_to_index in the data_Set but what we really need is the cat_to_names  so we will create
    _ = image_datasets['val'].class_to_idx
    cat_to_name = {_[i]: i for i in list(_.keys())}
    print(cat_to_name)

    # Run this to test the data loader
    images, labels = next(iter(data_loader['val']))

    model = create_model('vit_small_patch16_224', pretrained=True, in_chans=1, num_classes=num_classes)

    # Create classifier
    for param in model.parameters():
        param.requires_grad = True

    print(model)
    criterion = LabelSmoothingCrossEntropy()
    optimizer = optim.SGD(model.parameters(), lr=lr, momentum=0.9, nesterov=True, weight_decay=0.0001)
    scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=step_size, gamma=0.1)
    scheduler_warmup = GradualWarmupScheduler(optimizer, multiplier=1, total_epoch=5, after_scheduler=scheduler)
    #show our model architechture and send to GPU
    model.to(device)

    def count_parameters(model):
        return sum(p.numel() for p in model.parameters() if p.requires_grad)
    count = count_parameters(model)
    print("The number of parameters of the model is:", count)

    #https://github.com/clovaai/CutMix-PyTorch
    def rand_bbox(size, lam):
        W = size[2]
        H = size[3]
        cut_rat = np.sqrt(1. - lam)
        cut_w = np.int(W * cut_rat)
        cut_h = np.int(H * cut_rat)

        # uniform
        cx = np.random.randint(W)
        cy = np.random.randint(H)

        bbx1 = np.clip(cx - cut_w // 2, 0, W)
        bby1 = np.clip(cy - cut_h // 2, 0, H)
        bbx2 = np.clip(cx + cut_w // 2, 0, W)
        bby2 = np.clip(cy + cut_h // 2, 0, H)

        return bbx1, bby1, bbx2, bby2

    def train_model(model, criterion, optimizer, scheduler, num_epochs=200, checkpoint = None):
        since = time.time()

        if checkpoint is None:
            best_model_wts = copy.deepcopy(model.state_dict())
            best_loss = math.inf
            best_acc = 0.
        else:
            print(f'Val loss: {checkpoint["best_val_loss"]}, Val accuracy: {checkpoint["best_val_accuracy"]}')
            model.load_state_dict(checkpoint['model_state_dict'])
            best_model_wts = copy.deepcopy(model.state_dict())
            optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
            scheduler.load_state_dict(checkpoint['scheduler_state_dict'])
            best_loss = checkpoint['best_val_loss']
            best_acc = checkpoint['best_val_accuracy']

        # Tensorboard summary
        writer = SummaryWriter()
        start_time_per_epoch = time.time()

        for epoch in range(num_epochs):
            print('Epoch {}/{}'.format(epoch + 1, num_epochs)) #(epoch, num_epochs -1)
            print('-' * 20)

            # Each epoch has a training and validation phase
            for phase in ['train', 'val']:
                if phase == 'train':
                    model.train()  # Set model to training mode
                else:
                    model.eval()   # Set model to evaluate mode

                running_loss = 0.0
                running_corrects = 0

                # Iterate over data.
                for i, (inputs, labels) in enumerate(data_loader[phase]):
                    inputs = inputs.to(device).float()
                    labels = labels.to(device)

                    r = np.random.rand(1)
                    if r < 0.5: #cutmix_prob=0.5
                    # generate mixed sample
                        lam = np.random.beta(beta, beta)
                        rand_index = torch.randperm(inputs.size()[0]).to(device)
                        target_a = labels
                        target_b = labels[rand_index]
                        bbx1, bby1, bbx2, bby2 = rand_bbox(inputs.size(), lam)
                        inputs[:, :, bbx1:bbx2, bby1:bby2] = inputs[rand_index, :, bbx1:bbx2, bby1:bby2]
                    # adjust lambda to exactly match pixel ratio
                        lam = 1 - ((bbx2 - bbx1) * (bby2 - bby1) / (inputs.size()[-1] * inputs.size()[-2]))

                    # zero the parameter gradients
                    optimizer.zero_grad()

                    #if i % 1000 == 999:
                    #if i % 10 == 9:
                    if i>0:
                        print('[%d, %d/%d] loss: %.8f' %
                              (epoch + 1, i,len(data_loader[phase]), running_loss / (i * inputs.size(0))))

                    # forward
                    # track history if only in train
                    with torch.set_grad_enabled(phase == 'train'):
                        outputs = model(inputs)

                        if r < 0.5:
                            loss = criterion(outputs, target_a) * lam + criterion(outputs, target_b) * (1. - lam)
                        else:
                            loss = criterion(outputs, labels)

                        #loss = criterion(outputs, labels)
                        _, preds = torch.max(outputs, 1)

                        # backward + optimize only if in training phase
                        if phase == 'train':
                            loss.backward()
                            optimizer.step()

                    # statistics
                    running_loss += loss.item() * inputs.size(0)
                    running_corrects += torch.sum(preds == labels.data)

                if phase == 'train':
                    scheduler_warmup.step()

                epoch_loss = running_loss / dataset_sizes[phase]
                epoch_acc = running_corrects.double() / dataset_sizes[phase]

                print('{} Loss: {:.8f} Acc: {:.8f}'.format(
                    phase, epoch_loss, epoch_acc))

                # Record training loss and accuracy for each phase
                if phase == 'train':
                    writer.add_scalar('Train/Loss', epoch_loss, epoch)
                    writer.add_scalar('Train/Accuracy', epoch_acc, epoch)
                    writer.flush()
                else:
                    writer.add_scalar('Valid/Loss', epoch_loss, epoch)
                    writer.add_scalar('Valid/Accuracy', epoch_acc, epoch)
                    writer.flush()
                # deep copy the model

                if phase == 'val' and epoch_acc > best_acc:
                    print(f'New best model found!')
                    print(f'New record ACC: {epoch_acc}, previous record acc: {best_acc}')
                    best_loss = epoch_loss
                    best_acc = epoch_acc
                    best_epoch = epoch
                    best_model_wts = copy.deepcopy(model.state_dict())
                    torch.save({'model_state_dict': model.state_dict(),
                                'optimizer_state_dict': optimizer.state_dict(),
                                'best_val_loss': best_loss,
                                'best_val_accuracy': best_acc,
                                'scheduler_state_dict' : scheduler.state_dict(),
                                },
                                CHECK_POINT_PATH
                                )
                    print(f'New record acc is SAVED: {epoch_acc}')

            end_time_per_epoch = (time.time() - start_time_per_epoch)
            print('Time for training the last epoch: {:.0f}m {:.0f}s'.format(
            end_time_per_epoch // 60, end_time_per_epoch % 60))

        time_elapsed = time.time() - since
        print('Total training time complete in {:.0f}m {:.0f}s'.format(
            time_elapsed // 60, time_elapsed % 60))
        print('Best val Acc: {:.8f} Best val loss: {:.8f}'.format(best_acc, best_loss))
        print('Best epoch ', best_epoch)

        # load best model weights
        model.load_state_dict(best_model_wts)
        return model, best_loss, best_acc

    try:
        checkpoint = torch.load(CHECK_POINT_PATH)
        print("checkpoint loaded")
    except:
        checkpoint = None
        print("checkpoint not found")
    if checkpoint == None:
        CHECK_POINT_PATH = CHECK_POINT_PATH

    if TRAIN:
        num_epochs = 50
        model, best_val_loss, best_val_acc = train_model(model,
                                                         criterion,
                                                         optimizer,
                                                         scheduler,
                                                         num_epochs = num_epochs,
                                                         checkpoint = checkpoint
                                                         )

        torch.save({'model_state_dict': model.state_dict(),
                    'optimizer_state_dict': optimizer.state_dict(),
                    'best_val_loss': best_val_loss,
                    'best_val_accuracy': best_val_acc,
                    'scheduler_state_dict': scheduler.state_dict(),
                    }, CHECK_POINT_PATH)

    count = count_parameters(model)
    print("num parameters ", count)
    print("CHECK_POINT_PATH ", CHECK_POINT_PATH)
    compute_validate_meter(model, data_loader['test'], CHECK_POINT_PATH)


import pygame

class Compass:
    def __init__(self, surface, func_list):
        self.screen=surface
        self.dg=func_list[0]
        self.npc=func_list[1]
        self.ms=func_list[2]
        self.pl=func_list[3]
        self.level=[[0 for i in range(42)] for j in range(64)]
        self.color={'mist':(0,0,0), 'bk':(255, 255, 255), 'wall1':(100, 100, 100),
                    'floor1':(190, 190, 190), 'box':(225, 185, 0), 'grass':(124, 252, 0),
                    'tree':(0,128, 0), 'swamp':(50, 205, 50), 'water':(30, 144, 255),
                    'lava':(255, 0, 0), 'stairs':(128, 0, 0), 'fence':(150, 150, 150), 'door':(128, 128, 0),
                    'clay1':(105, 50, 0), 'clay2':(130, 90, 50), 'deco1':(255, 99, 71),
                    'deco2':(110, 255, 195), 'trap':(0, 0, 255), 'npc':(186, 85, 211)}
        self.colorMap={0:'wall1',  # 灰色砖墙
            1:'floor1',  # 黑色地板
            2:'stairs', # 楼梯
            3:'grass',  # 草地
            4:'water',  # 水体
            5:'lava',  # 岩浆
            6: 'swamp',  # 沼泽
            7: 'tree',  # 树木
            8:'fence',  # 铁栅栏和gate
            9:'clay1',      #洞穴墙
            10:'clay2',     #洞穴地面
            64 :'door',       #不透明门
            65 :'box',       #箱子
            66 :'trap',       #陷阱
            67:'deco1',  #不可交互的装饰品
            68:'deco2'      #可交互物品
        }
        self.judge=0
        self.pic=pygame.image.load(r'asset\compass.png').convert_alpha()

    def getColor(self, x):
        if x<=99:
            return self.colorMap[x]
        elif x>99: return 'npc'
        else: return 'floor1'

    def getChar(self, x, y):
        return self.level[x][y]

    def setChar(self, x, y, val):
        self.level[x][y]=val

    def getMap(self):
        for x in range(0, 64):
            for y in range(0, 42):
                dgp = self.convertDg(self.dg.getChar(x, y))
                surp = self.convertSur(self.dg.sur.getChar(x, y))
                self.setChar(x, y, max(dgp, surp))
        for k in self.npc.npc_pos:
            self.setChar(*k, 100)

    @staticmethod
    def convertDg(x):
        if x in {0, 10, 15, 22}:
            return 0        #灰色砖墙
        elif x in {1, 2, 11, 12, 14, 23, 24, 25, 26}:
            return 1        #黑色地板
        elif x in {3, 4, 16, 17, 29, 30}:
            return 2        #楼梯
        elif x in {5, 6}:
            return 3        #草地
        elif x in {8, 9}:
            return 4        #水体
        elif x in {18, 19}:
            return 5        #岩浆
        elif x in {20, 21}:
            return 6        #沼泽
        elif x==7:
            return 7        #树木
        elif x==13:
            return 8        #铁栅栏和gate
        elif x in {27, 28}:     #褐色墙壁
            return 9
        elif x in {31, 32}:     #褐色地面
            return 10

    @staticmethod
    def convertSur(x):
        if x in {0, 1, 2, 12, 39}:
            return 64       #不透明门
        elif x in {3, 4}:
            return 8        #铁栅栏和gate
        elif x in range(5, 10):
            return 65       #箱子
        elif x in {10, 11, 13, 14, 15}:
            return 66       #陷阱
        elif x in {16, 17, 18, 24, 26, 29, 32, 34, 36, 42}:
            return 67       #不可交互的装饰品
        elif x in {22, 23, 25, 27, 28, 30, 31, 33, 34, 37, 38, 40, 41}:     #其他装饰
            return 68
        else: return -1

    def drawMist(self, x, y):
        for i in range(0, 64):
            for j in range(0, 42):
                judge=self.ms.getChar(i, j)
                if not judge:
                    pygame.draw.rect(self.screen, self.color['mist'], (x+4*i, 4*j+y, 4, 4), 0)

    def drawMap(self, x, y):
        for i in range(0, 64):
            for j in range(0, 42):
                judge=self.getChar(i, j)
                tag=self.getColor(judge)
                pygame.draw.rect(self.screen, self.color[tag], (x+4*i, y+4*j, 4, 4), 0)

    def drawCompass(self, x, y):
        if self.judge:
            self.getMap()
            self.screen.blit(self.pic, (x-9, y-9))
            self.drawMap(x, y)
            pygame.draw.rect(self.screen, self.color['bk'], (self.pl.xat*4+x, self.pl.yat*4+y, 4, 4), 0)
            self.drawMist(x, y)

    def openMap(self):
        self.judge=1-self.judge


from mpl_toolkits.mplot3d import Axes3D
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

def visualize_svd(A, fig, pos=111, show_axes=True):
    ax = fig.add_subplot(pos, projection='3d')
    ax.view_init(elev=30, azim=30)
    ax.set_aspect('equal')

    s = np.linspace(0, 2*np.pi, 50)
    t = np.linspace(0, np.pi, 50)

    X = np.outer(np.cos(s), np.sin(t))
    Y = np.outer(np.sin(s), np.sin(t))
    Z = np.outer(np.ones(np.size(s)), np.cos(t))

    for i in range(len(s)):
        for j in range(len(t)):
            X[i,j], Y[i,j], Z[i,j] = A @ np.array([X[i,j], Y[i,j], Z[i,j]])

    ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='plasma', edgecolor=None, alpha=0.7)
    #ax.plot_wireframe(X, Y, Z, edgecolor='black', linewidth=0.2)

    if show_axes:
        u, s, vh = np.linalg.svd(A)
        for s1 in np.diag(s):
            b = np.dot(u, s1) # było v
            ax.plot([0, b[0]], [0, b[1]], [0, b[2]], linewidth=2)

    # aspect ratio 1:1
    max_range = np.array([X.max()-X.min(), Y.max()-Y.min(), Z.max()-Z.min()]).max() / 2.0
    mid_x = (X.max()+X.min()) * 0.5
    mid_y = (Y.max()+Y.min()) * 0.5
    mid_z = (Z.max()+Z.min()) * 0.5
    ax.set_xlim(mid_x - max_range, mid_x + max_range)
    ax.set_ylim(mid_y - max_range, mid_y + max_range)
    ax.set_zlim(mid_z - max_range, mid_z + max_range)

if __name__ == "__main__":

    #A = np.random.rand(3, 3)
    A = np.array([[7,0,0],[2,3,0],[0,0,4]])
    # print(A)
    u, sd, vh = np.linalg.svd(A)
    s = np.diag(sd)
    v = vh.T
    I = np.identity(3)

    for i, T in enumerate((I, v, s @ v, A), 1):
        fig = plt.figure()
        visualize_svd(T, fig, 111, i == 4)
        plt.show()
    #plt.savefig('main.png', dpi=1200)


import glob
import matplotlib.pyplot as plt
import os, sys
import pandas as pd
import numpy as np
import seaborn as sns
from scipy import stats

colors = [ "amber", "faded green"]
palette = sns.xkcd_palette(colors)
sns.palplot(palette)
plt.rcParams.update({'font.size': 15})
sns.set_style("white")

#%%

RE = "/dors/capra_lab/projects/enhancer_ages/reilly15/results/pleiotropy/"
path = "/dors/capra_lab/projects/enhancer_ages/reilly15/data/multiintersect/"
f = "%strim-0.5_multiintersect_hu_count.bed" % path

#%%

def custom_round(x, base=10):
    return int(base * round(float(x)/base))

def match_len(simple_df, complex_df, base_len):

    columns = ["enh_id", "enh_len"]
    columns_names = ["matching_ids", "matching_len"]

    simple = simple_df[columns].drop_duplicates()

    simple.columns = columns_names
    simple.matching_len = simple.matching_len.astype(float).apply(lambda x: custom_round(x, base=base_len)) # round to the nearest 100bp

    complex = complex_df[columns].drop_duplicates()
    complex.columns = columns_names

    complex.matching_len = complex.matching_len.astype(float).apply(lambda x: custom_round(x, base=base_len))

    lens = set(list(simple.matching_len.unique()) + list(complex.matching_len.unique()))

    match_dict = {}

    for length in lens:
        complexn = len(complex.loc[complex.matching_len == length])
        simplen = len(simple.loc[simple.matching_len == length])

        sn = min(complexn, simplen)

        if length > 0 and sn > 0:

            # find 100 matched enhancer samples

            complex_ids = complex.loc[complex.matching_len == length].sample(n = complexn, replace = False) # sample w/ replacement
            simple_ids = simple.loc[simple.matching_len == length].sample(n = simplen, replace = False) # sample w/ replacement
            balanced = pd.concat([simple_ids, complex_ids])
            match_dict[sn] = balanced

    final_matched_id = pd.concat(match_dict.values())

    return final_matched_id.matching_ids.unique()

def format_df(f):

    df = pd.read_csv(f, sep= '\t', header = None)

    df.columns = ["chr_enh","start_enh", "end_enh",	"enh_id", "fourth_col", "id",\
    "core_remodeling","arch","seg_index","mrca","enh_len", "taxon", "mrca_2",\
    "taxon2",	"mya",	"mya2",	"seg_den",	"datatype", "count_overlap"]

    df["enh_len"] = df.end_enh - df.start_enh

    df["mrca"] = df["mrca"].astype(float).round(3)

    df = df.loc[df.chr_enh != "chrX"]
    df = df.loc[df.enh_len < 10000]

    #df = pd.merge(df, syn_gen_bkgd, how = "left", on = "mrca")

    median = df.seg_index.median()
    #median = 3
    df.loc[df.seg_index >=median, "core_remodeling"] = 1
    df.loc[df.seg_index >=median, "arch"] = "complexenh"

    df.loc[df.seg_index <median, "core_remodeling"] = 0
    df.loc[df.seg_index <median, "arch"] = "simple"

    return df

def get_counts(res, strat):

    if strat == 1:
        counts = res.groupby(["mrca_2", "core_remodeling"])["enh_id"].count().reset_index()

        # add empty dataframe for complex human enhancers (do not exist by our def)
        empty = pd.DataFrame({"mrca_2": [0.000],
        "core_remodeling": [1],
        "enh_id": [0]
        })

        counts = pd.concat([counts, empty]) # concat the dataframe

        counts =counts.sort_values(by = ["core_remodeling", 'mrca_2']).reset_index()

    else:
        counts = res.groupby("arch")["enh_id"].count().reset_index()
        counts =counts.sort_values(by = "arch", ascending = False).reset_index()

    counts["enh_id"] = counts["enh_id"].astype(int)
    counts = counts.drop(["index"], axis = 1)

    return counts
#%%

df = format_df(f)
#%% remove human, primate specific sequences. Sequence must be as olds as euarchontaglires (common ancestor with mouse) in order to be evaluated here.
# removes 470 sequences

print(len(df))
print(median)
#%%
df.groupby(["core_remodeling", "arch"])["enh_id"].count()

#%%

simple_df = df.loc[df.core_remodeling ==0]

complex_df = df.loc[(df.core_remodeling ==1) & (df.enh_len<=simple_df.enh_len.max())]

#%%

matched_id = match_len(simple_df, complex_df, 100)

matched = df.loc[df.enh_id.isin(matched_id)]

matched["arch"] = "simple"
matched.loc[matched.core_remodeling ==1, "arch"] = "complexenh"
matched.mrca = matched.mrca.round(3)
#matched = pd.merge(matched, syn_gen_bkgd[["mrca", "mrca_2", "taxon2"]], how = "left", on ="mrca")
matched = matched.loc[matched.chr_enh != "chrX"]
matched.head()
#%%

sns.distplot(matched.loc[matched.core_remodeling == 0, "enh_len"], kde = False, norm_hist = True, label = "simple")
sns.distplot(matched.loc[matched.core_remodeling != 1, "enh_len"], kde = False, norm_hist = True, label = "complex")
plt.legend()

#%% plot simple v. complex
order = ["simple", "complexenh"]
sns.boxplot(x= "arch", y = "count_overlap", data = matched, order = order)

#%%
from matplotlib import gridspec
from matplotlib.ticker import MultipleLocator

fig = plt.figure(figsize = (12, 8))
gs = gridspec.GridSpec(1, 2, width_ratios=[1, 3])
ax0 = plt.subplot(gs[0])

splot = sns.barplot(x = "arch", y = "count_overlap", data = matched,
            palette = palette, order = order,
            ax = ax0)
STRAT = 0
agecounts = get_counts(matched, STRAT)

for n, p in enumerate(splot.patches):

    value = agecounts.iloc[n]["enh_id"].astype(int)

    splot.annotate(value,
                   (p.get_x() + p.get_width() / 2.,0.05),
                   ha = 'center', va = 'baseline',
                   size=15,
                   rotation = 90,
                   color = "white",
                   xytext = (0, 1),
                   textcoords = 'offset points'
                   )
ax0.set_xticklabels(["Simple", "Complex"], rotation = 90)
ax0.set(xlabel="", ylabel ="Number of Active Species", ylim=(0,2))
ax0.yaxis.set_major_locator(MultipleLocator(0.5))

sns.set("poster")

ax2 = plt.subplot(gs[1])
mplot = sns.barplot(x = "taxon2", y = "count_overlap", hue = "core_remodeling",
              data = matched.sort_values(by = "mrca_2"),
                palette = palette,
            ax = ax2)

STRAT = 1
agecounts = get_counts(matched, STRAT)

for n, p in enumerate(mplot.patches):

    value = agecounts.iloc[n]["enh_id"].astype(int)

    mplot.annotate(value,
                   (p.get_x() + p.get_width() / 2.,0.05),
                   ha = 'center', va = 'baseline',
                   size=15,
                   rotation = 90,
                   color = "white",
                   xytext = (0, 1),
                   textcoords = 'offset points'
                   )

ax2.set_xticklabels(ax2.get_xticklabels(), rotation = 90)
sns.set("poster")
ax2.yaxis.set_major_locator(MultipleLocator(0.5))
ax2.set(ylabel="",  ylim=(0,2))
ax2.legend().remove()
plt.savefig("%sFigS14-JOINT_barplot_reilly15_cross_species_overlap_x_mrca_2.pdf" % RE, bbox_inches = "tight" )

#%%
mwu, p = stats.mannwhitneyu(matched.loc[matched.arch == "simple", "count_overlap"],\
matched.loc[matched.arch != "simple", "count_overlap"])
print(mwu, p)

#%%
matched.groupby("arch")["count_overlap"].mean()

#%%
RE


from __future__ import unicode_literals
import youtube_dl

def my_status(d):
    if d['status'] == 'finished':
        print('Finished!')

ydl_opts = {
    'progress_hooks': [my_status]
}

with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download(['https://www.youtube.com/playlist?list=PL86SiVwkw_ofvEbosKlapvTrLs7geMKvp'])


bl_info = {
    "name": "Select Vertex Group by Name",
    "description": "Select Vertex Group by name.",
    "author": "LQR471814",
    "blender": (2, 90, 0),
    "category": "Mesh",
}

import bpy

class OPERATOR_OT_SelectVertexGroup(bpy.types.Operator):
    bl_idname = "object.select_vertex_group"
    bl_label = "Select Vertex Group by Name"
    bl_description = "Select Vertex Group by name."
    bl_options = {'REGISTER', 'UNDO'}

    name : bpy.props.StringProperty(name = "Vertex Group Name", default = "")

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        selected = context.selected_objects

        for obj in selected:
            grp = obj.vertex_groups.get(self.name)
            if grp == None:
                self.report({'ERROR'}, "Vertex group does not exist in object!")
                return {"CANCELLED"}

            obj.vertex_groups.active_index = grp.index

        return {"FINISHED"}

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

def menu_func(self, context):
    self.layout.operator(OPERATOR_OT_SelectVertexGroup.bl_idname)

def register():
    bpy.utils.register_class(OPERATOR_OT_SelectVertexGroup)
    bpy.types.TOPBAR_MT_app_system.append(menu_func)

def unregister():
    bpy.utils.unregister_class(OPERATOR_OT_SelectVertexGroup)
    bpy.types.TOPBAR_MT_app_system.remove(menu_func)

if __name__ == "__main__":
    register()


from concurrent import futures
from json import dumps

import grpc
import message_pb2
import message_pb2_grpc
from kafka import KafkaProducer

def produce_kafka_message(message_string):
    producer = KafkaProducer(bootstrap_servers=['localhost:9092'],
                             value_serializer=lambda x:
                             dumps(x).encode('utf-8'))
    data = {'message': message_string}
    producer.send('messages', value=data)

class MessageService(message_pb2_grpc.MessagingServiceServicer):

    def streamingMessage(self, request_iterator, context):
        for iterable in request_iterator:
            message = iterable.message
            print(f'message received on server: {message}')
            produce_kafka_message(message)
            response_message = 'message on server received'
            yield message_pb2.StreamingMessageResponse(message=response_message)

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    message_pb2_grpc.add_MessagingServiceServicer_to_server(MessageService(), server)
    server.add_insecure_port('[::]:50052')
    server.start()
    print("Started")
    server.wait_for_termination()

if __name__ == '__main__':
    serve()


import sys
import argparse

# genequest imports

sys.path.append("../GeneQuest")
import genequest
from genequest.io_handler.parser import FastaReader
# from genequest.io.parser import FastaReader

if __name__ == '__main__':

    # CLI arguments
    parser = argparse.ArgumentParser()
    required = parser.add_argument_group("Required arguments")
    optional = parser.add_argument_group("Optional arguments")

    # required arguments
    required.add_argument("-r" "--reads", type=str, required=True,
                        help="FASTA file containg reads")
    required.add_argument("-q", "--gene_query", type=str, required=True,
                        help="FASTA file gene of interest")

    # optional arguments
    # NOTE: these are not used yet. Used for alignment only
    optional.add_argument("-k", "--kmer_size", type=int, required=False, default=3,
                          help="size of the sequence fragments")
    optional.add_argument("-ms", "--match_score", type=int, required=False, default=10,
                          help="Score applied for matching nucleotide")
    optional.add_argument("-gs", "--gap_score", type=int, required=False, default=0,
                          help="Penalty score applied for gaps")
    optional.add_argument("-mis", "--mistmatch_score", type=int, required=False, default=-5,
                          help="Penalty score applied for nucleotide mismatch")

    args = parser.parse_args()

    # parsing fasta file containg reads and gene query
    # -- printing sequence information
    reads = FastaReader(args.reads)
    gene_query = FastaReader(args.gene_query)

    print("Loaded Sequence information:")
    print("query sequence length: {}".format(len(gene_query)))
    print("total number of reads: {}".format(len(reads)))

    # assemble the genome
    # -- group the geomes based on scaffold_id
    # -- apply the run_de_brujin() function

    # next step is the alignment
    # -- iterate all generated contigs into the run_local_alignment(query, contig)
        # returns alignment score a positional alignment data

    # write out the results


from copy import deepcopy
import re

import pytest
from marshmallow import ValidationError

from clean_code.compile_reading_list import (
    ReadingListSchema,
    format_review,
    load_review_yml,
    main,
)

valid_dict = {
    "title": "title",
    "author": "author",
    "availability": ["list", "of", "strings"],
    "recommendation": {"level": "moderate", "parts": "parts"},
    "price": "price as string",
    "length": {"time": "> 10 hrs", "pages": 300},
    "ease_of_use": "moderate",
    "comment": "any old string",
}

def test_load_review_yml():
    validated_schema = load_review_yml(valid_dict)

    assert validated_schema.data["ease of use"] == "moderate"

    optional_keys = ["comment"]
    for key in valid_dict:
        altered_dict = deepcopy(valid_dict)
        altered_dict.pop(key)
        if key in optional_keys:
            valid_schema = load_review_yml(altered_dict)
            assert key not in valid_schema
        else:
            with pytest.raises(ValidationError):
                load_review_yml(altered_dict)

    invalid_dict = deepcopy(valid_dict)
    invalid_dict["recommendation"]["level"] = "junk"
    with pytest.raises(ValidationError):
        load_review_yml(invalid_dict)

    invalid_dict = deepcopy(valid_dict)
    invalid_dict["length"]["time"] = "junk"
    error_msg = re.escape(
        "Invalid value for 'time'. Available options are:\n"
        "- <1 min\n"
        "- 1 min\n"
        "- 10 mins\n"
        "- 30 mins\n"
        "- 1 hr\n"
        "- 2 hrs\n"
        "- 5 hrs\n"
        "- > 10 hrs\n"
    )
    with pytest.raises(ValidationError, match=error_msg):
        load_review_yml(invalid_dict)

    invalid_dict = deepcopy(valid_dict)
    invalid_dict["ease_of_use"] = "junk"
    with pytest.raises(ValidationError):
        load_review_yml(invalid_dict)

def test_formatting():
    validated_schema = ReadingListSchema(strict=True).load(valid_dict)

    result = format_review(validated_schema)
    expected = (
        "title by author\n"
        "+++++++++++++++\n"
        "\n"
        "- availability\n"
        "    - list\n"
        "    - of\n"
        "    - strings\n"
        "- recommendation\n"
        "    - moderate (parts)\n"
        "- price\n"
        "    - price as string\n"
        "- length\n"
        "    - time: > 10 hrs\n"
        "    - pages: 300\n"
        "- ease of use\n"
        "    - moderate\n"
        "\n"
        "**Other comments**\n"
        "\n"
        "any old string\n"
    )

    assert result == expected

def test_main():
    main()


from typing import List
from fastapi import HTTPException, Depends
from starlette.status import HTTP_400_BAD_REQUEST
from app.db.repositories.base import BaseRepository
from app.models.accident_statement_sketch import Accident_Sketch_Create, Accident_Sketch_InDB, Only_Sketch, Accident_Sketch_Update
from app.api.dependencies.auth import get_other_user_by_user_id
from databases import Database
import json

CREATE_ACCIDENT_SKETCH_FOR_ACCIDENT_QUERY = """
    INSERT INTO accident_statement_sketch(statement_id, sketch)
    VALUES (:statement_id, :sketch)
    RETURNING id, statement_id, sketch, created_at, updated_at;
"""

GET_SKETCH_BY_STATEMENT_ID_QUERY = """
    SELECT sketch
    FROM accident_statement_sketch
    WHERE statement_id = :statement_id ;
"""

GET_ACCIDENT_SKETCH_BY_STATEMENT_ID_QUERY = """
    SELECT id, statement_id, sketch, created_at, updated_at
    FROM accident_statement_sketch
    WHERE statement_id = :statement_id ;
"""

UPDATE_SKETCH_QUERY="""
    UPDATE accident_statement_sketch
    SET sketch = :sketch
    WHERE statement_id = :statement_id
    RETURNING id, statement_id, sketch, created_at, updated_at;
    """

DELETE_SKETCH_QUERY ="""
    DELETE FROM accident_statement_sketch
    WHERE statement_id = :statement_id
"""

class AccidentSketchRepository(BaseRepository):

    async def create_new_accident_sketch(self, *, new_accident_sketch: Accident_Sketch_Create, statement_id:int)->Accident_Sketch_InDB:
        sketch = await self.get_accident_sketch_by_statement_id(statement_id=statement_id)
        if sketch:
            await self.delete_sketch(statement_id=statement_id)
        query_values = new_accident_sketch.get_dict()
        new_sketch = await self.db.fetch_one(query=CREATE_ACCIDENT_SKETCH_FOR_ACCIDENT_QUERY, values=query_values)
        return Accident_Sketch_InDB(**new_sketch)

    async def delete_sketch(self, *, statement_id:int):
        await self.db.fetch_one(query=DELETE_SKETCH_QUERY, values={"statement_id": statement_id})
        return (print(f"Sketch for {statement_id} is deleted."))

    # async def create_new_accident_sketch(self, *, new_accident_sketch: Accident_Sketch_Create , accident_id: int, user_id:int) -> InsuranceInDB:
    #     insurance = await self.get_last_created_insurance_by_vehicle_id(vehicle_id=vehicle_id)
    #     if insurance.expire_date and insurance.expire_date > datetime.date.today() :
    #         raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail="Wait current insurance expire")
    #     if insurance.number == "ADD INSURANCE":
    #         raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail="Please update empty insurance registry")

    #     query_values = new_insurance.dict(exclude_unset=True)
    #     query_values["vehicle_id"] = vehicle_id
    #     if query_values["expire_date"] and query_values["expire_date"] < datetime.date.today():
    #                     raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail="This insurance is expired")
    #     if query_values["start_date"] and query_values["expire_date"] and query_values["start_date"]> query_values["expire_date"] :
    #                     raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail="Insurance start date is after expire date")
    #     # raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail="You can only update selected vehicle.")
    #     created_insurance = await self.db.fetch_one(query=CREATE_INSURANCE_FOR_VEHICLE_QUERY, values=query_values)
    #     return created_insurance

    async def get_accident_sketch_by_statement_id(self, *, statement_id: int) ->Only_Sketch:
        sketch = await self.db.fetch_one(query=GET_SKETCH_BY_STATEMENT_ID_QUERY, values={"statement_id": statement_id})
        if not sketch:
            return None
        return Only_Sketch.get_list(sketch['sketch'])

    async def update_accident_sketch_by_statement_id(self, *, statement_id: int, updated_sketch: Accident_Sketch_Update) -> Accident_Sketch_InDB:
        sketch = await self.db.fetch_one(query=GET_ACCIDENT_SKETCH_BY_STATEMENT_ID_QUERY, values={"statement_id": statement_id})
        sketch = Accident_Sketch_InDB(**sketch)
        if not sketch:
            return None
        sketch_update_params = sketch.copy(update=updated_sketch.get_dict())
        try:
            updated_sketch = await self.db.fetch_one(
                query=UPDATE_SKETCH_QUERY,
                values= sketch_update_params.dict(exclude={"id","created_at", "updated_at"}),
                )
            return Accident_Sketch_InDB(**updated_sketch)
        except Exception as e:
            print(e)
            raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail="Invalid update params.")


import pygame

from boss import BossEvent

class Projectile(pygame.sprite.Sprite):

    def __init__(self, player):
        super().__init__()
        self. velocity = 7
        self.player = player
        self.image = pygame.image.load('cometfall/assets/projectile.png')
        self.image = pygame.transform.scale(self.image, (50, 50))
        self.rect = self.image.get_rect()
        self.rect.x = player.rect.x + 130
        self.rect.y = player.rect.y + 60
        self.origin_image = self.image
        self.game = player.game
        self.angle = 0

    def remove(self):
        self.player.all_projectiles.remove(self)

    def move(self, rotate=False):
        self.rect.x += self.velocity
        if rotate:
            self.rotate()
        # test si le projectile entre en collision avec un monstre
        for monster in self.player.game.check_colision(self, self.game.all_monster):
            self.remove()  # supprimer le projectile
            monster.damage(self.player.attack)  # infliger des dégats

        # infliger des dégats au boss
        if isinstance(self.player.game.event, BossEvent):
            for boss in self.player.game.check_colision(self, self.game.event.all_objects):
                self.remove()  # supprimer le projectile
                boss.damage(self.player.attack)  # infliger des dégats

        # verifier si notre n'est plus recent sur l'ecran
        if self.rect.x > 1080:
            # supprimer le projectile (en dehors de l'ecran)
            self.remove()

    def rotate(self):
        # tourner le projectile
        self.angle += 12
        self.image = pygame.transform.rotozoom(self.origin_image, self.angle, 1)
        self.rect = self.image.get_rect(center=self.rect.center)


from unittest import mock

from django.conf import settings
from django.utils import timezone

from sentry import features
from sentry.api.serializers import (
    DetailedOrganizationSerializer,
    DetailedOrganizationSerializerWithProjectsAndTeams,
    OnboardingTasksSerializer,
    serialize,
)
from sentry.auth import access
from sentry.features.base import OrganizationFeature
from sentry.models import OrganizationOnboardingTask
from sentry.models.organizationonboardingtask import OnboardingTask, OnboardingTaskStatus
from sentry.testutils import TestCase

class OrganizationSerializerTest(TestCase):
    def test_simple(self):
        user = self.create_user()
        organization = self.create_organization(owner=user)

        result = serialize(organization, user)

        assert result["id"] == str(organization.id)
        assert result["features"] == {
            "advanced-search",
            "change-alerts",
            "crash-rate-alerts",
            "custom-event-title",
            "custom-symbol-sources",
            "data-forwarding",
            "dashboards-basic",
            "dashboards-edit",
            "discover-basic",
            "discover-query",
            "event-attachments",
            "images-loaded-v2",
            "integrations-alert-rule",
            "integrations-chat-unfurl",
            "integrations-event-hooks",
            "integrations-incident-management",
            "integrations-issue-basic",
            "integrations-issue-sync",
            "integrations-ticket-rules",
            "invite-members",
            "invite-members-rate-limits",
            "minute-resolution-sessions",
            "open-membership",
            "relay",
            "shared-issues",
            "sso-basic",
            "sso-saml2",
            "symbol-sources",
            "team-insights",
        }

    @mock.patch("sentry.features.batch_has")
    def test_organization_batch_has(self, mock_batch):
        user = self.create_user()
        organization = self.create_organization(owner=user)

        features.add("organizations:test-feature", OrganizationFeature)
        features.add("organizations:disabled-feature", OrganizationFeature)
        mock_batch.return_value = {
            f"organization:{organization.id}": {
                "organizations:test-feature": True,
                "organizations:disabled-feature": False,
            }
        }

        result = serialize(organization, user)
        assert "test-feature" in result["features"]
        assert "disabled-feature" not in result["features"]

class DetailedOrganizationSerializerTest(TestCase):
    def test_detailed(self):
        user = self.create_user()
        organization = self.create_organization(owner=user)
        acc = access.from_user(user, organization)

        serializer = DetailedOrganizationSerializer()
        result = serialize(organization, user, serializer, access=acc)

        assert result["id"] == str(organization.id)
        assert result["role"] == "owner"
        assert result["access"] == settings.SENTRY_SCOPES
        assert result["relayPiiConfig"] is None

class DetailedOrganizationSerializerWithProjectsAndTeamsTest(TestCase):
    def test_detailed_org_projs_teams(self):
        # access the test fixtures so they're initialized
        self.team
        self.project
        acc = access.from_user(self.user, self.organization)
        serializer = DetailedOrganizationSerializerWithProjectsAndTeams()
        result = serialize(self.organization, self.user, serializer, access=acc)

        assert result["id"] == str(self.organization.id)
        assert result["role"] == "owner"
        assert result["access"] == settings.SENTRY_SCOPES
        assert result["relayPiiConfig"] is None
        assert len(result["teams"]) == 1
        assert len(result["projects"]) == 1

class OnboardingTasksSerializerTest(TestCase):
    def test_onboarding_tasks_serializer(self):
        completion_seen = timezone.now()
        serializer = OnboardingTasksSerializer()
        task = OrganizationOnboardingTask.objects.create(
            organization=self.organization,
            task=OnboardingTask.FIRST_PROJECT,
            status=OnboardingTaskStatus.PENDING,
            user=self.user,
            completion_seen=completion_seen,
        )

        result = serialize(task, self.user, serializer)
        assert result["task"] == "create_project"
        assert result["status"] == "pending"
        assert result["completionSeen"] == completion_seen
        assert result["data"] == {}

class TrustedRelaySerializer(TestCase):
    def test_trusted_relay_serializer(self):
        completion_seen = timezone.now()
        serializer = OnboardingTasksSerializer()
        task = OrganizationOnboardingTask.objects.create(
            organization=self.organization,
            task=OnboardingTask.FIRST_PROJECT,
            status=OnboardingTaskStatus.PENDING,
            user=self.user,
            completion_seen=completion_seen,
        )

        result = serialize(task, self.user, serializer)
        assert result["task"] == "create_project"
        assert result["status"] == "pending"
        assert result["completionSeen"] == completion_seen
        assert result["data"] == {}


#!/usr/bin/env python3

import asyncio
import logging
import sys

from . import Choice, Console, GUI

if __debug__ or sys.flags.dev_mode:
    logging.basicConfig(level=logging.DEBUG)

    _loop = asyncio.get_event_loop()
    _loop.slow_callback_duration = 0.02

    logging.debug("loop = %r @%#x", _loop, id(_loop))
    del _loop

async def _main():

    __loop = asyncio.get_running_loop()
    logging.debug("loop = %r @%#x", __loop, id(__loop))

    await asyncio.sleep(0.1)

    print("Das Lamm sagt Hurz!", end='', flush=True)

    await asyncio.sleep(0.1)

    console = Console()
    element = Choice(["1", "wunschvorstellung", "3", "4", "fünf", "sechs"])
    gui = GUI(element, console=console)

    await gui.handle()

    print('', flush=True)

    console.close()

    await asyncio.sleep(0.1)

loop = asyncio.get_event_loop()
logging.debug("loop = %r @%#x", loop, id(loop))
loop.run_until_complete(_main())

pending_tasks = asyncio.all_tasks(loop)
if pending_tasks:

    for task in pending_tasks:

        logging.debug("pending task: %s", task)
        task.cancel()

    loop.run_until_complete(asyncio.gather(*pending_tasks, loop=loop,
                                           return_exceptions=True))

    for task in pending_tasks:

        if task.cancelled():
            continue

        exception = task.exception()
        if exception is not None:
            logging.exception("pending exception: %s", exception,
                              exc_info=(type(exception), exception,
                                        exception.__traceback__))

loop.run_until_complete(loop.shutdown_asyncgens())
asyncio.set_event_loop(None)
loop.close()


from flask import Flask, request, render_template
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

app = Flask(__name__)

app.config.update(
    SECRET_KEY = 'admin',
    #SQLAlchemy_DATABASE_URI = '<database>://<userid>:<password>@<server>/<database_name>',
    SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://postgres:admin@localhost/catalog_db',
    #SQLAlchemy_TRACK_MODIFICATION = False
)

db = SQLAlchemy(app)

@app.route('/index')
@app.route('/')
def hello_flask():
    return 'Hello flask!'

@app.route('/new/')
def query_strings():
    query_val = request.args.get('greeting')
    return '
 the greeting is : {0}
'.format(query_val)

@app.route('/user')
@app.route('/user/<name>')
def no_query_strings(name='mina'):
    return '
 hello there ! {}
'.format(name)

## strings
@app.route('/text/<string:name>')
def working_with_strings(name):
    return '
 here is a string: ' + name + '
'

## numbers
@app.route('/numbers/<int:num>')
def working_with_numbers(num):
    return '
 the number you picked is: ' + str(num) + '
'

## numbers2
@app.route('/add/<int:num1>/<int:num2>')
def adding_int(num1, num2):
    return '
 sum is : {}'.format(num1+num2)+'
'

## floats
@app.route('/product/<float:num1>/<float:num2>')
def product_two_numbers(num1, num2):
    return  '
 the product is {}'.format(num1*num2) + '
'

## using templates
@app.route('/temp')
def using_templates():
    return render_template('hello.html')

## JINJA templates
@app.route('/watch')
def movie_2017():
    movie_list = ['autopsy of jane doe',
                  'neon moon',
                  'hhost ninja',
                  'fox and yetti']
    return render_template('movies.html',
                           movies=movie_list,
                           name='Harry')
## JINJA templates
@app.route('/tables')
def movie_plus():
    movie_dict = {'autopsy of jane doe': 02.14,
                  'neon moon': 3.20,
                  'hhost ninja': 1.50,
                  'fox and yetti': 02.52}
    return render_template('table_data.html',
                           movies = movie_dict,
                           name = 'Sally')

@app.route('/filters')
def filter_data():
    movie_dict = {'autopsy of jane doe': 02.14,
                  'neon moon': 3.20,
                  'hhost ninja': 1.50,
                  'fox and yetti': 02.52}

    return render_template('filter_data.html',
                           movies=movie_dict,
                           name=None,
                           film='a chritmas carol')

@app.route('/macros')
def jinja_macros():
    movie_dict = {'autopsy of jane doe': 02.14,
                  'neon moon': 3.20,
                  'hhost ninja': 1.50,
                  'fox and yetti': 02.52}
    return render_template('using_macros.html', movies=movie_dict)

class Publication(db.Model):
    __tablename__ = 'publication'
    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(80), nullable = False)

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

    def __repr__(self):
        return 'The Publisher is {}'.format(self.name)

class Book(db.Model):
    __tablename__ = 'book'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(500), nullable=False, index=True)
    author = db.Column(db.String(350))
    avg_rating = db.Column(db.Float)
    format = db.Column(db.String(50))
    imgage = db.Column(db.String(100), unique=True)
    num_pages = db.Column(db.Integer)
    pub_date = db.Column(db.DateTime, default=datetime.utcnow())

    ## Relationship
    pub_id = db.Column(db.Integer, db.ForeignKey('publication.id'))

    def __init__(self, title, author, avg_rating, book_format, imgage, num_pages, pub_id):
        self.title = title
        self.author = author
        self.avg_rating = avg_rating
        self.format = book_format
        self.imgage = imgage
        self.num_pages = num_pages
        self.pub_id = pub_id

    def __repr__(self):
        return '{} by {}'.format(self.title, self.author)

if __name__ == '__main__':
    db.create_all()
    app.run(debug=True)


from selenium import webdriver
from selenium.webdriver.common.by import By

# 5. Test case: Verify that the user can book a flight on expedia.com
# Steps:
# Launch the browser and navigate to https://www.expedia.com
def visit_website(url):
    driver.get(url)

# Locate the flights tab and click on it
def locate_flights_tab_and_click():
    driver.find_element(By.XPATH, "//*[@id='multi-product-search-form-1']/div/div/div[1]/ul/li[2]/a/span").click() # flights tab

# Locate the origin field and enter a valid departure city or airport "New York"
def enter_city_departure():
    driver.find_element(By.XPATH, "//button[@aria-label='Leaving from']").click() # leaving from

    input_from = driver.find_element(By.XPATH, "//input[@id='location-field-leg1-origin']")
    input_from.send_keys("New York")
    input_from.submit()

# Locate the destination field and enter a valid arrival city or airport "London"
def enter_city_destination():
    driver.find_element(By.XPATH, "//button[@aria-label='Going to']").click()  # going to

    input_to = driver.find_element(By.XPATH, "//input[@id='location-field-leg1-destination']")
    input_to.send_keys("London")
    input_to.submit()

# Locate the departure date field and select a valid date from the calendar "May 20"
# Locate the return date field and select a valid date from the calendar "May 27"
def dates_for_flight():
    driver.find_element(By.XPATH, "//button[@id='d1-btn']").click() # for dates
    driver.find_element(By.XPATH, "//button[@data-day='29'][1]").click()
    driver.find_element(By.XPATH, "//button[@data-day='30'][1]").click()

    driver.find_element(By.XPATH, "//button[@data-stid='apply-date-picker']").click() # done button

# Click on the search button or press enter
def search():
    driver.find_element(By.XPATH, "//button[@data-testid='submit-button']").click()

    captcha_frame = driver.find_element(By.XPATH, "(//div[@id='app'])[2]")
    driver.switch_to.frame(captcha_frame)
    driver.find_element(By.XPATH, "//button[@id='home_children_button']").click()

    driver.execute_script("document.getElementById('app').style.display = 'none';")

# Verify that the results page contains available flights matching the search criteria
def verify():
    verify_text = driver.find_element(By.XPATH, "(//span[@class='is-visually-hidden'])[7]")
    verify_text = verify_text.text
    assert verify_text.__contains__("New York") and verify_text.__contains__("London")

if __name__ == '__main__':
    url = "https://www.expedia.com"

    driver = webdriver.Chrome()
    driver.maximize_window()
    driver.implicitly_wait(10)

    visit_website(url)
    locate_flights_tab_and_click()
    enter_city_departure()
    enter_city_destination()
    dates_for_flight()
    search()
    verify()

# Its not working properly