import os, sys, io, math

class SequenceReader:
    def __init__(self, file_path):
        self.file_path = file_path

    def set_file_path(self, file_path):
        self.file_path = file_path

    def get_file_path(self):
        return self.file_path

    def read_sequence(self):
        with open(self.file_path) as f:
            lines = f.read().strip().splitlines()
        sequence = None

        for line in lines:
            if not (line.startswith(">") or line.startswith("#")):
                sequence = line
                break
            elif line.startswith(">"):
                sequence_descriptor = line
        return sequence_descriptor, sequence

class Utils:
    @staticmethod
    def find_max_index(l):
        max_index = 0
        i = 1
        while i < len(l):
            if l[i] > l[max_index]:
                max_index = i
            i = i + 1
        return max_index

    @staticmethod
    def content_to_dict(content):
        l = [i.strip() for i in content.splitlines() if i.strip()]
        return {key: value for key, value in [((int(i.split()[1])-1, int(i.split()[2]) - 1), i[0][0].replace("S", "E")) for i in l]}

    @staticmethod
    def count_for_confusion_matrix(truth_dict, prediction_dict, truth_key, prediction_key):
        start = min(truth_dict.keys())
        end = max(truth_dict.keys())
        counter = 0

        for i in range(start, end + 1):
            if prediction_dict[i] == prediction_key and truth_dict[i] == truth_key:
                counter += 1
        return counter

    @staticmethod
    def count_individual_confusion_statistics(truth_dict, prediction_dict, key):
        start = min(truth_dict.keys())
        end = max(truth_dict.keys())

        true_positive, true_negative, false_positive, false_negative = 0, 0, 0, 0

        for i in range(start, end + 1):
            if truth_dict[i] == key and prediction_dict[i] == key: true_positive += 1
            if truth_dict[i] != key and prediction_dict[i] != key: true_negative += 1
            if truth_dict[i] != key and prediction_dict[i] == key: false_positive += 1
            if truth_dict[i] == key and prediction_dict[i] != key: false_negative += 1

        return true_positive, true_negative, false_positive, false_negative

    @staticmethod
    def path_to_position_dict(path):
        return {key: value for key, value in [(index, path[index]) for index in range(len(path))]}

    @staticmethod
    def generate_position_dict(d, length):
        result = {}
        sorted_keys = sorted(d)
        i = 0
        for interval in sorted_keys:
            ll, ul = interval
            if i < ll:
                for y in range(i, ll):
                    result[y] = 'N'
            for y in range(ll, ul + 1):
                result[y] = d[interval]
            i = ul + 1
        if i < length:
            for y in range(i, length):
                result[y] = 'N'
        return result

class ViterbiAlgorithm:
    def __init__(self, hmm, sequence):
        self.hmm = hmm
        self.sequence = sequence
        self.column_count = len(self.sequence)
        self.states_list = self.hmm.get_states()
        self.matrix = [[0 for j in range(len(sequence))] for i in range(len(self.states_list))]

        self.arrow_map = {}
        self.fill_in_the_matrix()

    def fill_in_the_matrix(self):
        j = 0
        for i in range(len(self.states_list)):
            state = self.states_list[i]
            self.matrix[i][j] = self.hmm.tlp('START', state) + self.hmm.elp(state, self.sequence[j])

        for j in range(1, self.column_count):
            aa = self.sequence[j] # aa stands for amino_acid
            for i in range(len(self.states_list)):
                state = self.states_list[i]
                self.matrix[i][j] = self.hmm.elp(state, aa)
                list_to_look_for_max = []
                for k in range(len(self.states_list)):
                    inner_state = self.states_list[k]
                    list_to_look_for_max.append(self.matrix[k][j - 1] + self.hmm.tlp(inner_state, state))
                max_index = Utils.find_max_index(list_to_look_for_max)
                self.arrow_map[(i, j)] = max_index
                self.matrix[i][j] += list_to_look_for_max[max_index]

                if j == self.column_count - 1: # if we are in the last column, take into account the end state probability
                    self.matrix[i][j] += self.hmm.tlp(state, 'END')

    def construct_path(self):
        self.path = ""
        list_to_look_for_max = []
        for i in range(len(self.states_list)):
            list_to_look_for_max.append(self.matrix[i][self.column_count - 1])
        max_index = Utils.find_max_index(list_to_look_for_max)

        j = self.column_count - 1
        i = max_index
        log_probability = list_to_look_for_max[max_index]
        while j > 0:
            to_go = self.arrow_map[(i, j)]
            self.path = self.states_list[i] + self.path
            i = to_go
            j -= 1
        self.path = self.states_list[i] + self.path
        return self.path, log_probability

class HMM:
    def __init__(self, training_set_path):
        self.load_training_set(training_set_path)
        self.preprocess_training_set()

        # X and the lowercase letters are for the letters found in the training set
        self.amino_acid_alphabet = "ACDEFGHIKLMNPQRSTVWYXabcdegfhijklmnopqrutvw"

        self.states = {'H': {key: 0 for key in self.amino_acid_alphabet},
                       'E': {key: 0 for key in self.amino_acid_alphabet},
                       'T': {key: 0 for key in self.amino_acid_alphabet}}

        self.transitions = {}

        for state_i in "HET":
            for state_j in "HET":
                self.transitions[(state_i, state_j)] = 0

        for state in "HET":
            self.transitions[("START", state)] = 0

        for state in "HET":
            self.transitions[(state, "END")] = 0

        self.train()

    def get_states(self):
        return tuple("HET")

    def tlp(self, from_state, to_state):
        # tlp stands for transition_log_probability
        return self.transitions[(from_state, to_state)]

    def elp(self, state, amino_acid):
        # elp stands for emission_log_probability
        return self.states[state][amino_acid]

    def load_training_set(self, training_set_path):
        with open(training_set_path) as file:
            training_set = file.read().strip().splitlines()
        self.training_sequences = {}

        index_list = [i for i in range(len(training_set)) if training_set[i].startswith(">")]
        for index in index_list:
            self.training_sequences[training_set[index].strip()] = (training_set[index + 1].strip(), training_set[index + 2].strip())

        print(f"Loaded {len(self.training_sequences)} training samples.")

    def preprocess_training_set(self):
        print("Preprocessing training data...", end = ' ')
        sys.stdout.flush()
        for key, sequence_structure_tuple in self.training_sequences.items():
            sequence, structure = sequence_structure_tuple
            preprocessed_sequence_io = io.StringIO()
            preprocessed_structure_io = io.StringIO()
            for i in range(len(sequence)):
                structure_char = structure[i]
                sequence_char = sequence[i]
                if structure_char != "_":
                    preprocessed_sequence_io.write(sequence_char)
                    if structure_char in ('G', 'H', 'I'):
                        preprocessed_structure_io.write('H')
                    elif structure_char in ('B', 'E'):
                        preprocessed_structure_io.write('E')
                    elif structure_char in ('T', 'S', 'L'):
                        preprocessed_structure_io.write('T')

            self.training_sequences[key] = (preprocessed_sequence_io.getvalue(), preprocessed_structure_io.getvalue())
        print("Done!")

    def train(self):
        print ("Training...", end = ' ')
        sys.stdout.flush()
        inner_transition_counts = {'H': 0, 'E': 0, 'T': 0}
        start_transition_count = 0

        for key, sequence_structure_tuple in self.training_sequences.items():
            sequence, structure = sequence_structure_tuple

            for index in range(len(sequence)):
                sequence_char = sequence[index]
                structure_char = structure[index]
                if index == 0:
                    start_transition_count += 1
                    self.transitions[('START', structure_char)] += 1
                else:
                    inner_transition_counts[structure[index - 1]] += 1
                    self.transitions[(structure[index - 1], structure_char)] += 1
                    if index == len(sequence) - 1:
                        inner_transition_counts[structure_char] += 1
                        self.transitions[(structure_char, 'END')] += 1

                self.states[structure_char][sequence_char] += 1

        for state, emissions in self.states.items():
            summation = sum(emissions.values())
            for amino_acid, count in emissions.items():
                self.states[state][amino_acid] = math.log2((count + 1) / (summation + len(self.amino_acid_alphabet)))

        for state_i in "HET":
            for state_j in "HET":
                self.transitions[(state_i, state_j)] = math.log2(self.transitions[(state_i, state_j)] / inner_transition_counts[state_i])

        for state in "HET":
            self.transitions[("START", state)] = math.log2(self.transitions[("START", state)] / start_transition_count)

        for state in "HET":
            self.transitions[(state, "END")] = math.log2(self.transitions[(state, "END")] / inner_transition_counts[state])

        print("Done!")

class Main:
    def __init__(self):
        try:
            training_set_path = sys.argv[1]
            sequence_path = sys.argv[2]
        except IndexError:
            self.print_usage()
            sys.exit()

        truth_interval_dict = None
        if len(sys.argv) > 3:
            secondary_structure_path = sys.argv[3]
            with open(secondary_structure_path) as f:
                truth_interval_dict = Utils.content_to_dict(f.read().strip())

        sequence_reader = SequenceReader(sequence_path)
        header, sequence = sequence_reader.read_sequence()
        self.hmm = HMM(training_set_path)
        self.viterbi_algorithm = ViterbiAlgorithm(self.hmm, sequence)
        path, log_probability = self.viterbi_algorithm.construct_path()
        print("\nInput protein sequence:\n" + "-"*30 + "\n" + header + "\n" + sequence)
        print("\nThe path predicted by HMM:\n" + "-"*30 + "\n" + path)
        print("\nLog2 probability of this path:\n" + "-"*30 + "\n" + str(log_probability))

        if truth_interval_dict:
            truth_dict = Utils.generate_position_dict(truth_interval_dict, len(sequence))
            prediction_dict = Utils.path_to_position_dict(path)

            print("\n3x3 confusion matrix computations:")
            print("True".ljust(10), "Predicted".ljust(10), "Count".ljust(10))
            for key_i in "HET":
                for key_j in "HET":
                    print (key_i.ljust(10), key_j.ljust(10), str(Utils.count_for_confusion_matrix(truth_dict, prediction_dict, key_i, key_j)).ljust(10))

            print("Individual confusion matrix computations:")
            for key in "HET":
                print(f"Individual confusion matrix computations for {key}:")
                print("TP".ljust(10), "TN".ljust(10), "FP".ljust(10), "FN".ljust(10))
                tp, tn, fp, fn = Utils.count_individual_confusion_statistics(truth_dict, prediction_dict, key)
                print(str(tp).ljust(10), str(tn).ljust(10), str(fp).ljust(10), str(fn).ljust(10))

    def print_usage(self):
        print(f"Usage: python3 {os.path.split(sys.argv[0])[-1]} <training_set_path> <sequence_path> <secondary_structure_path>")

if __name__ == "__main__":
    main = Main()


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QColor

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 350, 100)
        self.setWindowTitle('Drawing rectangles')
        self.show()

    # 绘图是在paintEvent()方法中完成。
    # QPainter 对象放在begin()方法和end()方法之间，它执行部件上的低层次的绘画和其他绘图设备。
    # 实际的绘画我们委托给drawText()方法。
    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)
        self.drawRectangles(event, painter)
        painter.end()

    def drawRectangles(self, event, painter):
        color = QColor(0, 0, 0)
        color.setNamedColor('#d4d4d4')
        painter.setPen(color)

        painter.setBrush(QColor(200, 0, 0))
        painter.drawRect(10, 15, 90, 60)

        painter.setBrush(QColor(255, 80, 0, 160))
        painter.drawRect(130, 15, 90, 60)

        painter.setBrush(QColor(25, 0, 90, 200))
        painter.drawRect(250, 15, 90, 60)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = MainWindow()
    sys.exit(app.exec_())


# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import api, fields, models, tools, _
from odoo import SUPERUSER_ID
import io
import csv
import base64
import ftplib
from odoo.tools import pycompat
import logging
_logger = logging.getLogger(__name__)
from odoo.exceptions import UserError, AccessError

from odoo.addons.website_mail.models.mail_message import MailMessage
from datetime import datetime, timedelta
from odoo.http import request
from odoo.exceptions import ValidationError
from odoo.addons.website_sale.models.sale_order import SaleOrder

def _cart_update(self, product_id=None, line_id=None, add_qty=0, set_qty=0, **kwargs):
	""" Method monkey patched to handle multiple UoM from website """
	self.ensure_one()
	print (kwargs, 'In Override method \n\n\n\n\n\n\n')
	product_context = dict(self.env.context)
	product_context.setdefault('lang', self.sudo().partner_id.lang)
	SaleOrderLineSudo = self.env['sale.order.line'].sudo().with_context(product_context)
	# change lang to get correct name of attributes/values
	product_with_context = self.env['product.product'].with_context(product_context)
	product = product_with_context.browse(int(product_id))

	try:
		if add_qty:
			add_qty = float(add_qty)
	except ValueError:
		add_qty = 1
	try:
		if set_qty:
			set_qty = float(set_qty)
	except ValueError:
		set_qty = 0
	quantity = 0
	order_line = False
	if self.state != 'draft':
		request.session['sale_order_id'] = None
		raise UserError(_('It is forbidden to modify a sales order which is not in draft status.'))
	if line_id is not False:
		order_line = self._cart_find_product_line(product_id, line_id, **kwargs)[:1]

	# Create line if no line with product_id can be located
	if not order_line:
		if not product:
			raise UserError(_("The given product does not exist therefore it cannot be added to cart."))

		no_variant_attribute_values = kwargs.get('no_variant_attribute_values') or []
		received_no_variant_values = product.env['product.template.attribute.value'].browse([int(ptav['value']) for ptav in no_variant_attribute_values])
		received_combination = product.product_template_attribute_value_ids | received_no_variant_values
		product_template = product.product_tmpl_id

		# handle all cases where incorrect or incomplete data are received
		combination = product_template._get_closest_possible_combination(received_combination)

		# get or create (if dynamic) the correct variant
		product = product_template._create_product_variant(combination)

		if not product:
			raise UserError(_("The given combination does not exist therefore it cannot be added to cart."))

		product_id = product.id

		values = self._website_product_id_change(self.id, product_id, qty=1)

		# add no_variant attributes that were not received
		for ptav in combination.filtered(lambda ptav: ptav.attribute_id.create_variant == 'no_variant' and ptav not in received_no_variant_values):
			no_variant_attribute_values.append({
				'value': ptav.id,
			})

		# save no_variant attributes values
		if no_variant_attribute_values:
			values['product_no_variant_attribute_value_ids'] = [
				(6, 0, [int(attribute['value']) for attribute in no_variant_attribute_values])
			]

		# add is_custom attribute values that were not received
		custom_values = kwargs.get('product_custom_attribute_values') or []
		received_custom_values = product.env['product.template.attribute.value'].browse([int(ptav['custom_product_template_attribute_value_id']) for ptav in custom_values])

		for ptav in combination.filtered(lambda ptav: ptav.is_custom and ptav not in received_custom_values):
			custom_values.append({
				'custom_product_template_attribute_value_id': ptav.id,
				'custom_value': '',
			})

		# save is_custom attributes values
		if custom_values:
			values['product_custom_attribute_value_ids'] = [(0, 0, {
				'custom_product_template_attribute_value_id': custom_value['custom_product_template_attribute_value_id'],
				'custom_value': custom_value['custom_value']
			}) for custom_value in custom_values]

		# create the line
		order_line = SaleOrderLineSudo.create(values)
		if 'product_uom_id' in kwargs:
			order_line.product_uom = int(kwargs['product_uom_id'])
			order_line.product_uom_change()

		try:
			order_line._compute_tax_id()
		except ValidationError as e:
			# The validation may occur in backend (eg: taxcloud) but should fail silently in frontend
			_logger.debug("ValidationError occurs during tax compute. %s" % (e))
		if add_qty:
			add_qty -= 1

	# compute new quantity
	if set_qty:
		quantity = set_qty
	elif add_qty is not None:
		quantity = order_line.product_uom_qty + (add_qty or 0)

	# Remove zero of negative lines
	if quantity <= 0:
		linked_line = order_line.linked_line_id
		order_line.unlink()
		if linked_line:
			# update description of the parent
			linked_product = product_with_context.browse(linked_line.product_id.id)
			linked_line.name = linked_line.get_sale_order_line_multiline_description_sale(linked_product)
	else:
		# update line
		no_variant_attributes_price_extra = [ptav.price_extra for ptav in order_line.product_no_variant_attribute_value_ids]
		values = self.with_context(no_variant_attributes_price_extra=tuple(no_variant_attributes_price_extra))._website_product_id_change(self.id, product_id, qty=quantity)
		if self.pricelist_id.discount_policy == 'with_discount' and not self.env.context.get('fixed_price'):
			order = self.sudo().browse(self.id)
			product_context.update({
				'partner': order.partner_id,
				'quantity': quantity,
				'date': order.date_order,
				'pricelist': order.pricelist_id.id,
				'force_company': order.company_id.id,
			})
			product_with_context = self.env['product.product'].with_context(product_context)
			product = product_with_context.browse(product_id)
			values['price_unit'] = self.env['account.tax']._fix_tax_included_price_company(
				order_line._get_display_price(product),
				order_line.product_id.taxes_id,
				order_line.tax_id,
				self.company_id
			)

		if 'product_uom_id' in kwargs:
			values.update({'product_uom': int(kwargs['product_uom_id'])})
		else:
			del values['product_uom']

		order_line.write(values)
		order_line.product_uom_change()

		# link a product to the sales order
		if kwargs.get('linked_line_id'):
			linked_line = SaleOrderLineSudo.browse(kwargs['linked_line_id'])
			order_line.write({
				'linked_line_id': linked_line.id,
			})
			linked_product = product_with_context.browse(linked_line.product_id.id)
			linked_line.name = linked_line.get_sale_order_line_multiline_description_sale(linked_product)
		# Generate the description with everything. This is done after
		# creating because the following related fields have to be set:
		# - product_no_variant_attribute_value_ids
		# - product_custom_attribute_value_ids
		# - linked_line_id
		order_line.name = order_line.get_sale_order_line_multiline_description_sale(product)

	option_lines = self.order_line.filtered(lambda l: l.linked_line_id.id == order_line.id)

	return {'line_id': order_line.id, 'quantity': quantity, 'option_ids': list(set(option_lines.ids))}

SaleOrder._cart_update = _cart_update

class ProductBrand(models.Model):
	_name = "product.brand"

	name = fields.Char("Brand")

class product(models.Model):

	_inherit = 'product.template'

	brand_id = fields.Many2many("product.brand", string="Brand")
	extra_units = fields.Many2many('uom.uom', 'product_id', 'uom_id', 'prod_uom_rel', string="Extra Units")

	def units_web(self):

		product = self.env['product.template'].sudo().browse(self.id)
		units = [product.uom_id]
		for item in product.extra_units:
			units.append(item)

		return units


from pyspark.sql import Window
import pyspark.sql.functions as f
from app import columns

class QueryManager:
    def __init__(self, spark, trip_fare_df, trip_data_df):
        self.spark = spark
        self.trip_fare_df = trip_fare_df
        self.trip_data_df = trip_data_df

    def trips_count(self, date_column):
        """
        Args:
            date_column: desired date column in dataframe
        Returns:
            dataframe which has three columns
            1. Vendor_ID
            2. Day of Week
            3. Count (count of trips)
        """
        trip_df = self.trip_data_df.withColumn('dayofweek',
                                               f.date_format(self.trip_data_df[date_column], 'EEEE'))
        trips_by_week = (trip_df.filter(f.col(columns.vendor_id).isNotNull()).groupBy(columns.vendor_id, 'dayofweek').
                         count().orderBy(f.desc(columns.vendor_id), f.desc('count')).withColumn('max_trip_count',
                                                                                f.max('count').over(
                                                                                Window.partitionBy(
                                                                                'vendor_id')))
                         .filter(f.col('count') == f.col('max_trip_count')).drop('max_trip_count'))
        return trips_by_week

    def total_revenue(self):
        """ Calculates the total revenue of each vendor
             Returns:
            DataFrame: A DataFrame containing the total revenue for each vendor.
        """
        dataframe = (self.trip_fare_df.filter(f.col(columns.vendor_id).isNotNull()).groupBy(columns.vendor_id)
                     .agg(f.format_number(f.sum(columns.total_amount), 2).alias('total revenue')))
        return dataframe

    def avg_trip_distance(self):
        """
            Calculates the average trip distance for different numbers of passengers.

            Returns:
                DataFrame: A DataFrame containing the average trip distance for each combination of vendor
                and passenger count.
        """
        dataframe = (self.trip_data_df.filter(f.col(columns.passenger_count).
                                              isNotNull()).groupBy(columns.vendor_id, columns.passenger_count).
                     agg(f.avg(columns.trip_distance)).orderBy(f.desc(columns.passenger_count)))
        return dataframe

    def simultaneous_trips(self):
        """
        Calculates the maximum number of simultaneous trips that happened on the same day.

        Returns:
            DataFrame: A DataFrame containing the maximum number of simultaneous trips for the top 5 days.
        """
        pickup_dataframe = (self.trip_data_df.filter(f.col(columns.pickup_datetime).isNotNull()).
                            select(f.col(columns.pickup_datetime).alias('event_time'),
                                   f.lit(1).alias('event_count')))
        dropoff_dateframe = (self.trip_data_df.filter(f.col(columns.dropoff_datetime).isNotNull()).
                             select(f.col(columns.dropoff_datetime).alias('event_time'),
                                    f.lit(-1).alias('event_count')))
        event_dateframe = pickup_dataframe.union(dropoff_dateframe)
        dataframe = event_dateframe.withColumn('sum', f.sum('event_count').over(Window.partitionBy('event_time')
                                                                                .orderBy(f.asc('event_time'))))
        dataframe = dataframe.groupBy(f.date_format('event_time', 'yyyy-MM-dd').alias('day')
                                      ).agg(f.max('sum').alias('simultaneous_trips')).orderBy(
            f.desc(f.col('simultaneous_trips'))).limit(5)
        return dataframe

    def most_expensive_trips(self):
        """
        Calculates the most expensive trips for each vendor.

        Returns:
            DataFrame: A DataFrame containing the most expensive trips for each vendor.
        """
        dataframe = (self.trip_fare_df.filter(f.col(columns.vendor_id).isNotNull())
                     .groupBy(columns.vendor_id).agg(f.max(columns.total_amount).
                                                     alias(columns.total_amount)))
        return dataframe

    def avg_amount_rate_code(self):
        """
        Calculates the count of trips with a tip above the average tip amount for trips with different rate codes.

        Returns:
            DataFrame: A DataFrame containing the count of such trips for each rate code.
        """
        dataframe = self.trip_fare_df.join(self.trip_data_df, ['medallion', 'hack_license', 'vendor_id',
                                                               'pickup_datetime'], 'inner')

        average_tip_amounts = dataframe.groupBy(columns.rate_code).agg(f.avg(columns.tip_amount)
                                                                       .alias('avg_tip_amount'))

        joined_data = dataframe.join(average_tip_amounts, [columns.rate_code], 'inner')
        dataframe = joined_data.withColumn('tip_above_avg', f.col('tip_amount') > f.col('avg_tip_amount'))
        dataframe = (dataframe.groupBy(columns.rate_code).count().withColumnRenamed('count', 'trip_count').
                     orderBy(f.desc('trip_count')))
        return dataframe

    def tips_count(self):
        """ Identifies the specific day of the week when each vendor tends to receive the highest amount of tips.

        Returns:
            DataFrame: A DataFrame containing the day of the week and the corresponding highest amount of tips received
            for each vendor.
        """
        window_spec = Window.partitionBy(columns.vendor_id).orderBy(f.col("total_tips").desc())

        dataframe = (self.trip_fare_df.withColumn("day_of_week", f.date_format(columns.pickup_datetime, 'EEEE'))
                     .groupBy(columns.vendor_id, "day_of_week")
                     .agg(f.format_number(f.sum(columns.tip_amount), 2).alias("total_tips"))
                     .withColumn("rank", f.row_number().over(window_spec))
                     .filter(f.col("rank") == 1)
                     .select(columns.vendor_id, "day_of_week", "total_tips"))

        return dataframe

    def avg_fare_amount_payment(self):
        """ Calculates the average fare amount for each payment type.

        Returns:
            DataFrame: A DataFrame containing the average fare amount for each payment type.
        """
        dataframe = (self.trip_fare_df.groupBy(columns.payment_type)
                     .agg(f.format_number(f.avg(columns.fare_amount), 2).alias("average_fare_amount"))
                     .orderBy(f.desc("average_fare_amount")))

        return dataframe

    def top_vendor_drivers(self):
        """ Identifies the top 10 drivers for each vendor based on average trip distance and total tip amount.

        Returns:
            DataFrame: A DataFrame containing the vendor ID, unique driver license, average mileage covered, total tip
            amount received and the corresponding rank.
        """
        joined_df = (self.trip_data_df.withColumnRenamed(columns.vendor_id, "vendor")
                     .join(self.trip_fare_df, [columns.hack_license, columns.pickup_datetime],
                           'inner'))

        window_spec = Window.partitionBy("vendor").orderBy(f.desc("average mileage"), f.desc("total tip amount"))
        dataframe = (joined_df.groupBy(["vendor", columns.hack_license])
                     .agg(f.format_number(f.avg(columns.trip_distance), 2).alias('average mileage'),
                          f.format_number(f.sum(columns.tip_amount), 2).alias('total tip amount'))
                     .withColumn("rank", f.rank().over(window_spec))
                     .filter(f.col("rank") <= 10))

        return dataframe

    def percentage_long_trips(self):
        """ Calculates the percentage of trips with a duration greater than 30 minutes for each vendor.

        Returns:
            DataFrame: A DataFrame containing the vendor ID, total trips executed for each vendor, amount of trips whose
            duration greater than 30 minutes and percentage of these trips.
        """
        dataframe = (self.trip_data_df.filter(f.col(columns.vendor_id) != 'None')
                     .groupBy(columns.vendor_id)
                     .agg(f.count("*").alias("total_trips"),
                          f.count(f.when(f.col(columns.trip_time_in_secs) > 1800, True))
                          .alias("long_trips"))
                     .withColumn("percentage_long_trips",
                                 f.format_number((f.col("long_trips") /
                                                  f.col("total_trips")) * 100, 2)))

        return dataframe

    def top_tips_in_cash(self):
        """ Calculates top 5 biggest tips for each vendor if the user paid in cash.

        Returns:
            DataFrame: A DataFrame containing the vendor ID and top 5 largest tips paid in cash for each vendor.
        """
        window_spec = Window.partitionBy(columns.vendor_id).orderBy(f.desc(columns.tip_amount))
        dataframe = (self.trip_fare_df.filter(f.col(columns.payment_type) == "CSH")
                     .withColumn("rank", f.dense_rank().over(window_spec))
                     .filter(f.col("rank") <= 5).select(columns.vendor_id, columns.tip_amount, "rank"))

        return dataframe

    def trips_weekdays_weekend(self):
        """ Calculates the number of trips occurred on weekend and weekdays for each vendor.

        Returns:
            DataFrame: A DataFrame containing the number of trips executed on weekdays and weekends for each vendor.
        """
        weekdays = [2, 3, 4, 5, 6]

        dataframe = self.trip_fare_df.withColumn("day_of_week", f.dayofweek(f.col(columns.pickup_datetime)))
        dataframe = (dataframe.withColumn("day_type", f.when(f.col("day_of_week")
                                                             .isin(weekdays), "weekday").otherwise("weekend"))
                     .groupBy(columns.vendor_id, "day_type")
                     .count()
                     .orderBy(columns.vendor_id, "day_type"))

        return dataframe

    def trips_with_tip_mount_greater_than_fare_amount(self):
        """ Data of trips with tips amount greater than the fare amount.

        Returns:
            dataframe with columns:
            medallion, hack_license, vendor_id, pickup_datetime, payment_type, fare_amount, tip_amount.
        """

        result_columns_names = [columns.medallion, columns.hack_license, columns.vendor_id, columns.pickup_datetime,
                                columns.payment_type, columns.fare_amount, columns.tip_amount]
        trips_with_tip_mount_greater_than_fare_amount = (
            self.trip_fare_df.filter(f.col(columns.fare_amount) < f.col(columns.tip_amount))
            .select(*result_columns_names)
        )
        return trips_with_tip_mount_greater_than_fare_amount

    def total_earnings_of_each_vendor_for_first_seven_days_of_january(self):
        """ Sum of earning of each vendor for trips that started on each of the first seven days of January 2013.

        Returns:
            dataframe with columns:
            vendor_id, date(in format yyyy-MM-dd), total_earnings.
        """
        column_date = 'date'
        column_total_earnings = 'total_earnings'
        start_date_string = '2012-12-31 23:59:59.59'
        end_date_string = '2013-01-07 23:59:59.59'

        total_earnings_of_each_vendor_for_first_seven_days_of_january = (
            self.trip_fare_df
            .withColumn(column_date, f.date_format(self.trip_fare_df[columns.pickup_datetime], 'yyyy-MM-dd'))
            .filter(f.col(column_date).between(start_date_string, end_date_string))
            .orderBy(columns.vendor_id, column_date)
            .groupBy(columns.vendor_id, column_date)
            .agg(f.sum(columns.total_amount).alias(column_total_earnings))
        )
        return total_earnings_of_each_vendor_for_first_seven_days_of_january

    def driver_of_each_day(self):
        """ Driver who received the biggest amount of tips for each day
        (tips are considered received when the trip is over).

        Returns:
            dataframe with columns:
            date, hack_licence, vendor_id, tips_sum.
        """
        column_date = 'date'
        column_tips_sum = 'tips_sum'
        column_max_tips_sum = 'max_tips_sum'
        join_column_names = [columns.vendor_id, columns.medallion, columns.hack_license, columns.pickup_datetime]
        joined_df = self.trip_fare_df.join(self.trip_data_df, join_column_names, 'inner')
        drivers = (
            joined_df.withColumn('date', f.date_format(joined_df[columns.dropoff_datetime], 'yyyy-MM-dd'))
            .groupBy(columns.vendor_id, columns.hack_license, column_date)
            .agg(f.sum(columns.tip_amount).alias(column_tips_sum))
            .orderBy(column_date, f.desc(column_tips_sum))
            .withColumn(column_max_tips_sum, f.max(f.col(column_tips_sum))
                        .over(Window.partitionBy(column_date)).alias(column_max_tips_sum))
            .filter(f.col(column_max_tips_sum) == f.col(column_tips_sum))
            .select(column_date, columns.hack_license, columns.vendor_id, column_tips_sum)
        )
        return drivers

    def price_per_second_of_drive_for_each_vendor(self):
        """ Average price per second of drive for each vendor.

        Returns:
            dataframe with columns:
            vendor_id, average_fare_per_second
        """
        column_sum_fare_amount = 'sum_fare_amount'
        column_sum_trip_time_in_secs = 'sum_trip_time_in_secs'
        column_average_fare_per_second = 'average_fare_per_second'
        join_column_names = [columns.vendor_id, columns.medallion, columns.hack_license, columns.pickup_datetime]
        joined_df = self.trip_fare_df.join(self.trip_data_df, join_column_names, 'inner')
        price_per_second_of_drive_for_each_vendor = (
            joined_df.groupBy('vendor_id')
            .agg(f.sum(columns.fare_amount).alias(column_sum_fare_amount),
                 f.sum(columns.trip_time_in_secs).alias(column_sum_trip_time_in_secs))
            .withColumn(column_average_fare_per_second,
                        f.col(column_sum_fare_amount) / f.col(column_sum_trip_time_in_secs))
            .select(columns.vendor_id, column_average_fare_per_second)
        )
        return price_per_second_of_drive_for_each_vendor

    def top_vendor_for_each_payment_type(self):
        """ Vendor who received the biggest amount of money for each payment type.

        Returns:
            dataframe with columns:
            payment_type, vendor_id, sum_total_amount.
        """
        column_sum_total_amount = 'sum_total_amount'
        column_max_for_payment_type = 'max_for_payment_type'
        top_vendor_for_each_payment_type = (
            self.trip_fare_df.groupBy(columns.vendor_id, columns.payment_type)
            .agg(f.sum(columns.total_amount).alias(column_sum_total_amount))
            .orderBy(columns.payment_type, f.desc(column_sum_total_amount))
            .withColumn(column_max_for_payment_type,
                        f.max(f.col(column_sum_total_amount))
                        .over(Window.partitionBy(columns.payment_type)))
            .filter(f.col(column_sum_total_amount) == f.col(column_max_for_payment_type))
            .select(columns.payment_type, columns.vendor_id, column_sum_total_amount)
        )
        return top_vendor_for_each_payment_type

    def top_five_drivers_with_greatest_sum_of_time_in_trip(self):
        """ Top 5 drivers with greatest sum of time spent in trips.

        Returns:
            dataframe with columns:
            vendor_id, hack_license, sum_trip_time_in_secs
        """
        column_sum_trip_time_in_secs = 'sum_trip_time_in_secs'
        top_five_drivers_with_greatest_sum_of_time_in_trip = (
            self.trip_data_df.groupBy(columns.vendor_id, columns.hack_license)
            .agg(f.sum(f.col(columns.trip_time_in_secs)).alias(column_sum_trip_time_in_secs))
            .orderBy(f.desc(column_sum_trip_time_in_secs))
        ).limit(5)

        return top_five_drivers_with_greatest_sum_of_time_in_trip

    def most_popular_payment_type(self):
        """
        Calculates the most popular payment type.

        Returns:
            DataFrame: A DataFrame containing only one row with the most popular payment type.
        """

        dataframe = (
            self.trip_fare_df.groupBy(columns.payment_type)
            .count()
            .orderBy('count', ascending=False)
            .limit(1)
        )

        return dataframe

    def highest_fare_amount(self):
        """
        Calculates the highest fare when vendor is VTS.

        Returns:
            DataFrame: A DataFrame containing only one row with the highest fare amount for VTS.
        """

        dataframe = (
            self.trip_fare_df.filter(f.col(columns.vendor_id) == 'VTS')
            .orderBy(columns.fare_amount, ascending=False)
            .limit(1)
        )

        return dataframe

    def top_total_amount(self):
        """
        Calculates the top 10 total_amount values for drivers when passengers count > 5.

        Returns:
            DataFrame: A DataFrame containing 10 rows with biggest total_amount values for drivers
            when passengers count > 5.
        """
        dataframe = (
            self.trip_fare_df.join(self.trip_data_df, [columns.medallion, columns.hack_license,
                                                       columns.pickup_datetime], 'inner')
            .filter(f.col(columns.passenger_count) > 5)
            .groupBy(columns.medallion, columns.hack_license, columns.passenger_count)
            .agg(f.max(columns.total_amount))
            .orderBy(f.col(f'max({columns.total_amount})'), ascending=False)
            .limit(10)
        )

        return dataframe

    def total_revenue_per_day(self):
        """
        Calculates the total revenue for each day of the week, categorized by payment type.

        Returns:
            DataFrame: A DataFrame with columns: 'pickup_datetime', 'payment_type', 'total_amount',
            and 'total_revenue_per_day'.
        """

        dataframe = self.trip_fare_df.withColumn('day_num', f.dayofweek(columns.pickup_datetime))

        window_spec = (
            Window.partitionBy(
                f.col('day_num'),
                f.col(columns.payment_type)
            ).orderBy(f.col('day_num'))
        )

        dataframe = dataframe.withColumn('total_revenue_per_day', f.sum(f.col(columns.total_amount)).over(window_spec))

        return dataframe

    def tip_percentage(self):
        """
        Calculates percentage of tip to total_amount if payment type not cash.
        Returns:
            DataFrame: A DataFrame with new column tips_percentages and only rides which were paid not in cash.
        """
        window_spec = Window.partitionBy(columns.medallion, columns.hack_license, columns.pickup_datetime)

        dataframe = self.trip_fare_df.filter(f.col(columns.payment_type) != 'CSH')
        dataframe = dataframe.withColumn('tips_percetages',
                                         (f.sum(columns.tip_amount).over(window_spec) /
                                          f.sum(columns.total_amount).over(window_spec)) * 100)

        return dataframe

    def avg_trip_duration(self):
        """
        Calculates the average trip duration for different rate codes.
        Returns:
            DataFrame: A DataFrame grouped by rate codes and found avg trip duration time for them
        """
        dataframe = (
            self.trip_data_df
            .filter(f.col(columns.rate_code).isNotNull())
            .groupBy(columns.rate_code)
            .agg(
                f.avg(columns.trip_time_in_secs)
                .alias('avg_trip_duration')
            ).orderBy(f.asc(columns.rate_code))
        )

        return dataframe


from typing import Dict, Callable

from src.dialog.common.manage_entity.ManageEntityDialogMode import ManageEntityDialogMode
from src.property.Property import Property
from src.session.common.Session import Session
from src.storage.common.entity.Entity import Entity
from src.storage.common.entity.EntityStorage import EntityStorage

class ManageEntityContainerSaver:

    def __init__(
            self,
            session: Session,
            storage: EntityStorage,
            close_dialog: Callable[[], None],
            show_error: Callable[[str], None]
    ):
        self.__session = session
        self.__storage = storage
        self.__close_dialog = close_dialog
        self.__show_error = show_error

    def save_entity(self, key: str, props: Dict[str, Property]):
        if self.__session.get_manage_entity_mode() == ManageEntityDialogMode.CREATE:
            self.handle_new_entity(key, props)
        elif self.__session.get_manage_entity_mode() == ManageEntityDialogMode.EDIT and \
                self.__session.get_edit_entity_key() != key:
            self.handle_edit_entity_key_changed(key, props)
        elif self.__session.get_manage_entity_mode() == ManageEntityDialogMode.EDIT and \
                self.__session.get_edit_entity_key() == key:
            self.handle_edit_entity_key_unchanged(key, props)

    def handle_new_entity(self, key: str, props: Dict[str, Property]):
        if not self.__storage.check_entity_exists(key):
            self.put_entity_close_dialog(key, props)
        else:
            self.report_entity_exists(key)

    def handle_edit_entity_key_changed(self, key: str, props: Dict[str, Property]):
        if not self.__storage.check_entity_exists(key):
            self.remove_session_entity()
            self.put_entity_close_dialog(key, props)
        else:
            self.report_entity_exists(key)

    def handle_edit_entity_key_unchanged(self, key: str, props: Dict[str, Property]):
        self.put_entity_close_dialog(key, props)

    def put_entity_close_dialog(self, key: str, props: Dict[str, Property]):
        self.__storage.put_entity(
            Entity(key, props)
        )
        self.__close_dialog()

    def remove_session_entity(self):
        self.__storage.remove_entity(self.__session.get_edit_entity_key())

    def report_entity_exists(self, key: str):
        self.__show_error("Дело об АП с номером" + key + " уже существует")


import torch
import torch.nn.functional as F
import constants
import numpy as np

def gauss1D(window_size, sigma):
    center = window_size // 2
    gauss = torch.Tensor([np.exp(-(x - center)**2 / (2*(sigma**2))) for x in range(window_size)])
    gauss = gauss/gauss.sum()
    return gauss

def create_window(window_size, sigma, channels: int = 3):
    window1d = gauss1D(window_size, sigma).unsqueeze(1)
    window2d = torch.mm(window1d, window1d.t())
    window2d = window2d.repeat(channels, 1, 1, 1)
    return window2d

def rgb_to_ycbcr(image: torch.Tensor, only_use_y_channel: bool = True) -> torch.Tensor:
    """Convert RGB Image to YCbCr Image

    Args:
    - image (Tensor): Tensor image shape (B, 3, H, W)
    - only_use_y_channel (bool): whether or not extract image with only Y channel.

    Returns:
    - Tensor image: shape (B, 1, H, W) if only_use_y_channel is True and (B, 3, H, W) the other way.
    """

    if not isinstance(image, torch.Tensor) or image.size(-3) != 3:
        raise ValueError("Invalid format of image, should be Tensor(B, 3, H, W)")
    image = image.to(constants.DEVICE)
    if only_use_y_channel:
        weight = torch.tensor([[65.481], [128.533], [24.966]]).to(constants.DEVICE)
        image = torch.matmul(image.permute(0, 2, 3, 1), weight).permute(0, 3, 1, 2) + 16.0
    else:
        weight = torch.tensor([[65.481, -37.797, 112.0],
                               [128.553, -74.203, -93.786],
                               [24.966, 112.0, -18.214]]).to(constants.DEVICE)
        bias = torch.tensor([16, 128, 128]).view(1, 3, 1, 1).to(constants.DEVICE)
        image = torch.matmul(image.permute(0, 2, 3, 1), weight).permute(0, 3, 1, 2) + bias

    image /= 255.
    return image

def _ssim(img1: torch.Tensor, img2: torch.Tensor, window_size: int, sigma: float, channels: int, batch_average: bool = True) -> torch.Tensor:
    """Caculate SSIM of 2 images.

    Returns:
    - Tensor: value of SSIM, which is (B,) if batch_average is not True and scalar if True.
    """

    # to device
    window = create_window(window_size, sigma, channels).to(constants.DEVICE)
    img1 = img1.to(constants.DEVICE)
    img2 = img2.to(constants.DEVICE)

    c1 = (0.01 * constants.PIXEL_VALUE_RANGE)**2
    c2 = (0.03 * constants.PIXEL_VALUE_RANGE)**2
    mu1 = F.conv2d(img1, window, padding=window_size//2, groups=channels)
    mu2 = F.conv2d(img2, window, padding=window_size//2, groups=channels)

    mu1_sq = mu1.pow(2)
    mu2_sq = mu2.pow(2)
    mu1_mu2 = mu1*mu2

    sigma1_sq = F.conv2d(img1*img1, window, padding = window_size//2, groups = channels) - mu1_sq
    sigma2_sq = F.conv2d(img2*img2, window, padding = window_size//2, groups = channels) - mu2_sq
    sigma12 = F.conv2d(img1*img2, window, padding = window_size//2, groups = channels) - mu1_mu2

    ssim_map = ((2*mu1_mu2 + c1)*(2*sigma12 + c2))/((mu1_sq + mu2_sq + c1)*(sigma1_sq + sigma2_sq + c2))
    if batch_average:
        return ssim_map.mean()
    else:
        return ssim_map.mean(dim=(1,2,3))

class Metrics():
    def __init__(
            self,
            extract_y_channel: bool = True) -> None:
        """ Caculate PSNR and SSIM metrics.
        - extract_y_channel: whether or not extract y channel in YCrCb format
            then PSNR and SSIM will be computed on only y channel images.
        """
        self.extract_y_channel = extract_y_channel

    def extractYchannel(self):
        self.lowres = rgb_to_ycbcr(self.lowres)
        self.highres = rgb_to_ycbcr(self.highres)

    def psnr(self, img1: torch.Tensor, img2: torch.Tensor):
        """"""
        img1 = img1.to(constants.DEVICE)
        img2 = img2.to(constants.DEVICE)

        rmse = torch.sqrt(F.mse_loss(img1, img2))
        psnr = 20 * torch.log10(constants.PIXEL_VALUE_RANGE/ (rmse + 1e-10))
        return psnr

    def ssim(self, img1: torch.Tensor, img2: torch.Tensor):
        """"""
        return _ssim(img1, img2, window_size=11, sigma=0.15, channels=img1.size(-3))


#!/usr/bin/python3

import os
import requests

my_ip_file = os.path.join("/tmp", "myIp.txt")

def myIp():
    return requests.get("https://gianlu.dev/ip").text.strip()

def writToFile(filename, content):
    fp = open(filename, "wt", encoding="utf8")
    fp.write(content)
    fp.close()

def readFile(filename):
    fp = open(filename, "rt", encoding="utf8")
    content = fp.read().strip()
    fp.close()
    return content

if not os.path.exists(my_ip_file):
    writToFile(my_ip_file, "")

current_ip = myIp()
if current_ip != readFile(my_ip_file):
    print(current_ip, readFile(my_ip_file))
    writToFile(my_ip_file, current_ip)

    import Client
    Client.mainFunc()


# Standard Library
import json
import logging
import urllib.parse

# Third Party
from fastapi import APIRouter, Depends, HTTPException, Query, status
from fastapi_cache.decorator import cache

# First Party
from resc_backend.constants import (
    CACHE_NAMESPACE_FINDING,
    DEFAULT_RECORDS_PER_PAGE_LIMIT,
    ERROR_MESSAGE_500,
    ERROR_MESSAGE_503,
    FINDINGS_TAG,
    REDIS_CACHE_EXPIRE,
    RWS_ROUTE_DETAILED_FINDINGS
)
from resc_backend.db.connection import Session
from resc_backend.resc_web_service.crud import detailed_finding as detailed_finding_crud
from resc_backend.resc_web_service.dependencies import get_db_connection
from resc_backend.resc_web_service.filters import FindingsFilter
from resc_backend.resc_web_service.helpers.resc_swagger_models import Model404
from resc_backend.resc_web_service.schema import detailed_finding as detailed_finding_schema
from resc_backend.resc_web_service.schema.pagination_model import PaginationModel

router = APIRouter(prefix=f"{RWS_ROUTE_DETAILED_FINDINGS}", tags=[FINDINGS_TAG])
logger = logging.getLogger(__name__)

@router.get("",
            response_model=PaginationModel[detailed_finding_schema.DetailedFindingRead],
            summary="Get all detailed findings",
            status_code=status.HTTP_200_OK,
            responses={
                200: {"description": "Retrieve all the findings"},
                500: {"description": ERROR_MESSAGE_500},
                503: {"description": ERROR_MESSAGE_503}
            })
@cache(namespace=CACHE_NAMESPACE_FINDING, expire=REDIS_CACHE_EXPIRE)
def get_all_detailed_findings(skip: int = Query(default=0, ge=0),
                              limit: int = Query(default=DEFAULT_RECORDS_PER_PAGE_LIMIT, ge=1),
                              db_connection: Session = Depends(get_db_connection),
                              query_string: str = None
                              ) \
        -> PaginationModel[detailed_finding_schema.DetailedFindingRead]:
    """
        Retrieve all findings objects paginated
    - **query_string**

        A query string with the following format:
            param1=value1&param2=value2&param3=value3

        Where the possible parameters are:

            - vcs_providers [enum] of type VCSProviders, possible values are: BITBUCKET, AZURE_DEVOPS.
                Will default to all if non-specified.

            - finding_statuses [enum of type FindingStatus], possible values are:NOT_ANALYZED,FALSE_POSITIVE,
              TRUE_POSITIVE. Will default to all if non-specified.

            - rule_pack_versions of type [String]

            - rule_names of type [String]

            - rule_tags of type [String] findings in the result will have at least one of the specified tags
              for the rules

            - project_name of type String

            - repository_names of type [String]

            - scan_ids of type list Integer

            - start_date_time of type datetime with the following format: 1970-01-31T00:00:00

            - end_date_time of type datetime with the following format: 1970-01-31T00:00:00

    - **db_connection**

        Session of the database connection

    - **skip**

        Integer amount of records to skip to support pagination

    - **limit**

        Integer amount of records to return, to support pagination

    - **return** [FindingRead]

        The output will contain a PaginationModel containing the list of DetailedFinding type objects,
        or an empty list if no finding was found
    """

    parsed_query_string_params = dict(urllib.parse.parse_qsl(query_string))

    if parsed_query_string_params.get('scan_ids'):
        parsed_query_string_params['scan_ids'] = json.loads(parsed_query_string_params['scan_ids'])
    if parsed_query_string_params.get('vcs_providers'):
        parsed_query_string_params['vcs_providers'] = json.loads(parsed_query_string_params['vcs_providers']
                                                                 .replace('\'', '"'))
    if parsed_query_string_params.get('finding_statuses'):
        parsed_query_string_params['finding_statuses'] = json.loads(parsed_query_string_params['finding_statuses']
                                                                    .replace('\'', '"'))
    if parsed_query_string_params.get('rule_names'):
        parsed_query_string_params['rule_names'] = json.loads(parsed_query_string_params['rule_names']
                                                              .replace('\'', '"'))
    if parsed_query_string_params.get('rule_tags'):
        parsed_query_string_params['rule_tags'] = json.loads(parsed_query_string_params['rule_tags']
                                                             .replace('\'', '"'))
    if parsed_query_string_params.get('rule_pack_versions'):
        parsed_query_string_params['rule_pack_versions'] = json.loads(parsed_query_string_params['rule_pack_versions']
                                                                      .replace('\'', '"'))

    findings_filter = FindingsFilter(**parsed_query_string_params)

    findings = detailed_finding_crud.get_detailed_findings(
        db_connection, findings_filter=findings_filter, skip=skip, limit=limit)
    total_findings = detailed_finding_crud.get_detailed_findings_count(
        db_connection, findings_filter=findings_filter)

    return PaginationModel[detailed_finding_schema.DetailedFindingRead](
        data=findings, total=total_findings, limit=limit, skip=skip)

@router.get("/{finding_id}",
            response_model=detailed_finding_schema.DetailedFindingRead,
            summary="Fetch detailed finding by ID",
            status_code=status.HTTP_200_OK,
            responses={
                200: {"description": "Retrieve detailed finding <finding_id>"},
                404: {"model": Model404, "description": "Finding <finding_id> not found"},
                500: {"description": ERROR_MESSAGE_500},
                503: {"description": ERROR_MESSAGE_503}
            })
@cache(namespace=CACHE_NAMESPACE_FINDING, expire=REDIS_CACHE_EXPIRE)
def read_finding(finding_id: int, db_connection: Session = Depends(get_db_connection)) \
        -> detailed_finding_schema.DetailedFindingRead:
    """
        Retrieve detailed finding by its ID

    - **db_connection**: Session of the database connection
    - **finding_id**: ID of the finding for which details need to be fetched
    - **return**: [DetailedFindingRead]
        The output will contain the details of a finding
    """
    db_finding = detailed_finding_crud.get_detailed_finding(db_connection, finding_id=finding_id)
    if db_finding is None:
        raise HTTPException(status_code=404, detail="Finding not found")
    return db_finding


from __future__ import print_function

import numpy as np
import cv2
import subprocess
import itertools
from multiprocessing import Pool

import sys
import os
import time

import numpy as np
import theano
import theano.tensor as T

import lasagne

f = subprocess.check_output(["ls"]).split()
files = []
#make list of files that contain ellipse data
for i in f:
    if "ellipseList.txt" in i:
        files.append(i)
print(files)

class Image:
	def __init__(self, filename, window_size):
		self.im = cv2.imread(filename,0)
		#self.im = cv2.resize(self.im,(0,0),fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
		self.mask = []
		self.mask_small = []
		self.windows = []
		self.windows_small = []
		self.scores = []
		self.scores_small = []
		self.cx = []
		self.cy = []
		self.decimation_factor = []
		self.imno = 0
		#self.slide = [-6,-4,-2,0,2,4,6]
		self.slide = [-3,-2,-1,0,1,2,3]
		self.window_size = window_size

	def ellipse(self, ellipse_info):
		ellipse_info = ellipse_info.split(" ")
		axes = [float(ellipse_info[0]),float(ellipse_info[1])]
		decim_fac = int(max(max(axes[0]*2/self.window_size,axes[1]*2/self.window_size),1))
		self.decimation_factor.append(decim_fac)

		#print "best decimation is %.2f and %.2f"%(axes[0]*2/32,axes[1]*2/32)
		theta = float(ellipse_info[2])
		self.cx.append(float(ellipse_info[3]))
		self.cy.append(float(ellipse_info[4]))
		#print "diameter is %0.2f"%(2*max(axes[0],axes[1]))
		y,x = np.ogrid[0:self.im.shape[0],0:self.im.shape[1]]
		mask = np.power(((x-self.cx[-1])*np.cos(theta) + (y-self.cy[-1])*np.sin(theta))/axes[0],2) + np.power(((x-self.cx[-1])*np.sin(theta) - (y-self.cy[-1])*np.cos(theta))/axes[1],2) <= 1
		self.mask.append(mask)
		#self.mask.append(mask[::2,::2])
		#self.cx[-1] /= 2
		#self.cy[-1] /= 2

	def ellipse_decim(self, ellipse_info):
		ellipse_info = ellipse_info.split(" ")
		axes = [float(ellipse_info[0])/2,float(ellipse_info[1])/2]
		print("best decimation is %.2f and %.2f"%(axes[0]*2/32,axes[1]*2/32))
		theta = float(ellipse_info[2])
		self.cx.append(float(ellipse_info[3])/2)
		self.cy.append(float(ellipse_info[4])/2)
		#print "diameter is %0.2f"%(2*max(axes[0],axes[1]))
		y,x = np.ogrid[0:self.im.shape[0],0:self.im.shape[1]]
		mask = np.power(((x-self.cx[-1])*np.cos(theta) + (y-self.cy[-1])*np.sin(theta))/axes[0],2) + np.power(((x-self.cx[-1])*np.sin(theta) - (y-self.cy[-1])*np.cos(theta))/axes[1],2) <= 1
		self.mask.append(mask)

	def get_score(self,mask,cx,cy,x,i,ellipse_size):
		s = self.window_size/2
		flag = False
		flag = flag or cy+x[0]-s < 0
		flag = flag or cx+x[0]-s < 0
		flag = flag or cy+x[1]+s+1 > mask.shape[0]
		flag = flag or cx+x[1]+s+1 > mask.shape[1]
		if flag == True:
			return -1.
		#intersect = np.sum(self.mask[i][cy+x[0]-16:cy+x[0]+17,cx+x[1]-16:cx+x[1]+17]).astype(float)
		#union = ellipse_size - intersect + (32*32)

		intersect = np.sum(mask[cy+x[0]-s:cy+x[0]+s+1,cx+x[1]-s:cx+x[1]+s+1]).astype(float)
		union = ellipse_size - intersect + (4*s*s)
		self.imno += 1

		#CHOOSE THE SCORE YOU WANT
		return np.float32(intersect/union)
		#return intersect/ellipse_size

	def get_random_window(self,image,mask,center):
		s = self.window_size/2
		rand_mask = mask[center[0]-s:center[0]+s+1,center[1]-s:center[1]+s+1]
		if rand_mask.size < (self.window_size**2) or np.sum(rand_mask) > 5:
			return None
		return image[center[0]-s:center[0]+s+1,center[1]-s:center[1]+s+1].astype(np.float32)

	def get_windows(self):
		s = self.window_size/2
		self.image_slides = []
		self.score_slides = []
		for i in xrange(len(self.mask)):
			image = cv2.resize(self.im,(0,0),fx=1./self.decimation_factor[i],fy=1./self.decimation_factor[i],interpolation=cv2.INTER_AREA)
			mask = cv2.resize(self.mask[i].astype(np.uint8),(0,0),fx=1./self.decimation_factor[i],fy=1./self.decimation_factor[i],interpolation=cv2.INTER_AREA).astype(bool)
			mask_size = np.sum(mask)
			cx = int(round(self.cx[i]/self.decimation_factor[i]))
			cy = int(round(self.cy[i]/self.decimation_factor[i]))
			self.score_slides.append(map(lambda x: self.get_score(mask,cx,cy,x,i,mask_size), itertools.product(self.slide,self.slide)))
			self.image_slides.append(map(lambda x: image[cy+x[0]-s:cy+x[0]+s+1,cx+x[1]-s:cx+x[1]+s+1].astype(np.float32), itertools.product(self.slide,self.slide)))

		#generate random images
		self.random_slides = []
		self.random_scores = []
		mask = np.zeros(self.im.shape)
		for i in xrange(len(self.mask)):
			mask = np.maximum(mask, self.mask[i].astype(int))
		mask = mask.astype(bool)
		rand = np.random.rand(self.imno,2)
		rand[:,0] *= self.im.shape[0]
		rand[:,1] *= self.im.shape[1]
		rand = rand.astype(int)
		iterate = 0
		goal = 2*self.imno
		while(self.imno < goal):
			try:
				randy = rand[iterate,0]
				randx = rand[iterate,1]
			except IndexError:
				rand = np.random.rand(self.imno,2)
				rand[:,0] *= self.im.shape[0]
				rand[:,1] *= self.im.shape[1]
				rand = rand.astype(int)
				iterate=0
				continue
			try:
				small = mask[randy-s:randy+s+1,randx-s:randx+s+1]
				#print "shape is %d %d"%(small.shape[0],small.shape[1])
				#print "val is %d"%np.sum(small)
			except IndexError:
				iterate+=1
				continue
			iterate+=1
			if small.size - (self.window_size**2) < 10:
				continue
			elif np.sum(small) > 10:
				continue
			self.random_slides.append(self.im[randy-s:randy+s+1,randx-s:randx+s+1].astype(np.float32))
			self.random_scores.append(np.float32(0))
			self.imno += 1
			#print "Adding random image"
			#print "%d left to go"%(goal-self.imno)

	def get_data(self):
		flatten = lambda l: [item for sublist in l for item in sublist]
		return flatten(self.image_slides)+self.random_slides, flatten(self.score_slides)+self.random_scores

def info(filename):
	with open(filename,"r") as f:
		slides = []
		scores = []
		while(True):
			try:
				imgpath = f.readline().split("\n")[0]+".jpg"
				if imgpath == ".jpg":
					return np.array(slides), np.array(scores)
				#print imgpath
				e = Image(imgpath,32)
				numfaces = f.readline().strip()
				#print numfaces
				print(numfaces)
				for i in xrange(int(numfaces)):
					ellipse_info = f.readline().split("\n")[0]
					#print ellipse_info
					e.ellipse(ellipse_info)
					#plt.imshow(e.im,cmap="gray",alpha=0.5)
					#plt.imshow(e.ellipse(ellipse_info),alpha=0.1,cmap="gray")
					#plt.show()
				e.get_windows()
				ims, im_scores = e.get_data()
				for i in xrange(len(ims)):
					slides.append(ims[i])
					scores.append(im_scores[i])
				#print
				#e.get_windows()
			except ValueError as a:
				#pass
				#    print e
				return
	#return

#info(files[0])
#exit()

pool = Pool(4)
a = np.array(pool.map(info,files[:2]))

images = np.concatenate(a[:,0]).tolist()
scores = np.concatenate(a[:,1]).tolist()

i=0
while(True):
	if i==len(images):
		break
	elif images[i].shape != (33,33):
		del images[i]
		del scores[i]
	else:
		i+=1

images = np.array(images)
scores = np.array(scores)

# images_flat = []
# scores_flat = []

# for i in xrange(len(images)):
# 	assert len(images[i]) == len(scores[i])
# 	for j in xrange(len(images[i])):
# 		print type(scores[i][j])
# 		images_flat.append(images[i][j])
# 		scores_flat.append(scores[i][j])

# images = np.array(images_flat)
# scores = np.array(scores_flat)

images = images[np.where(scores >= 0)]
scores = scores[np.where(scores >= 0)]
#scores_second = np.add(-1,scores)
#scores = np.concatenate((scores[:,np.newaxis],scores_second[:,np.newaxis]),axis=1)

#data = np.stack((images,scores[:,np.newaxis]),axis=1)
#np.random.shuffle(data)
#print(data.shape)

# plt.hist(scores,bins=50)
# plt.show()

# rand_range = (np.random.rand(10)*1000).astype(int)
# for i in xrange(10):
# 	print images[rand_range[i]].shape
# 	plt.imshow(images[rand_range[i]],cmap="gray",interpolation="nearest")
# 	print scores[rand_range[i]]
# 	plt.show()

print(scores.shape)
print(np.amin(scores))

def build_cnn(input_var=None):
	# As a third model, we'll create a CNN of two convolution + pooling stages
	# and a fully-connected hidden layer in front of the output layer.

	# Input layer, as usual:
	network = lasagne.layers.InputLayer(shape=(None, 1, 33, 33),
	                                    input_var=input_var)
	# This time we do not apply input dropout, as it tends to work less well
	# for convolutional layers.

	# Convolutional layer with 32 kernels of size 5x5. Strided and padded
	# convolutions are supported as well; see the docstring.
	network = lasagne.layers.Conv2DLayer(
		network, num_filters=32, filter_size=(5, 5),
		nonlinearity=lasagne.nonlinearities.rectify,
		W=lasagne.init.GlorotUniform())
	# Expert note: Lasagne provides alternative convolutional layers that
	# override Theano's choice of which implementation to use; for details
	# please see http://lasagne.readthedocs.org/en/latest/user/tutorial.html.

	# Max-pooling layer of factor 2 in both dimensions:
	network = lasagne.layers.MaxPool2DLayer(network, pool_size=(2, 2))

	# Another convolution with 32 5x5 kernels, and another 2x2 pooling:
	network = lasagne.layers.Conv2DLayer(
			network, num_filters=32, filter_size=(5, 5),
			nonlinearity=lasagne.nonlinearities.rectify)
	network = lasagne.layers.MaxPool2DLayer(network, pool_size=(2, 2))

	# A fully-connected layer of 256 units with 50% dropout on its inputs:
	network = lasagne.layers.DenseLayer(
			lasagne.layers.dropout(network, p=.5),
			num_units=256,
			nonlinearity=lasagne.nonlinearities.rectify)

	# And, finally, the 10-unit output layer with 50% dropout on its inputs:
	network = lasagne.layers.DenseLayer(
			network,
			num_units=1,
			nonlinearity=lasagne.nonlinearities.sigmoid)

	return network

def iterate_minibatches(inputs, targets, batchsize, shuffle=False):
    assert len(inputs) == len(targets)
    if shuffle:
        indices = np.arange(len(inputs))
        np.random.shuffle(indices)
    for start_idx in range(0, len(inputs) - batchsize + 1, batchsize):
        if shuffle:
            excerpt = indices[start_idx:start_idx + batchsize]
        else:
            excerpt = slice(start_idx, start_idx + batchsize)
        yield inputs[excerpt], targets[excerpt]

def main(data,model='cnn', num_epochs=500):
    # Load the dataset
    print("Loading data...")

    X = data[0].reshape(-1, 1, 33, 33)
    X /= np.float32(255)
    Y = np.round_(data[1]).astype(np.float32)
    #X = X.astype(np.float32)
    #Y = Y.astype(np.float32)
    # X_train = X[0:300000]
    # y_train = Y[0:300000]
    # X_val = X[-20000:]
    # y_val = Y[-20000:]
    # X_test = X[300000:400000]
    # y_test = Y[300000:400000]

    X_train = X[0:50000]
    y_train = Y[0:50000]
    X_val = X[-4000:]
    y_val = Y[-4000:]
    X_test = X[50000:80000]
    y_test = Y[50000:80000]

    # Prepare Theano variables for inputs and targets
    input_var = T.tensor4('inputs')
    target_var = T.fvector('targets')

    # Create neural network model (depending on first command line parameter)
    network = build_cnn(input_var)

    # Create a loss expression for training, i.e., a scalar objective we want
    # to minimize (for our multi-class problem, it is the cross-entropy loss):
    prediction = lasagne.layers.get_output(network)
    loss = lasagne.objectives.binary_hinge_loss(prediction, target_var, log_odds=False)
    loss = loss.mean()
    # We could add some weight decay as well here, see lasagne.regularization.

    # Create update expressions for training, i.e., how to modify the
    # parameters at each training step. Here, we'll use Stochastic Gradient
    # Descent (SGD) with Nesterov momentum, but Lasagne offers plenty more.
    params = lasagne.layers.get_all_params(network, trainable=True)
    updates = lasagne.updates.nesterov_momentum(
            loss, params, learning_rate=0.01, momentum=0.9)

    # Create a loss expression for validation/testing. The crucial difference
    # here is that we do a deterministic forward pass through the network,
    # disabling dropout layers.
    test_prediction = lasagne.layers.get_output(network, deterministic=True)
    test_loss = lasagne.objectives.binary_hinge_loss(test_prediction,
                                                            target_var, log_odds=False)
    test_loss = test_loss.mean()
    # As a bonus, also create an expression for the classification accuracy:
    test_acc = T.mean(T.eq(test_prediction, target_var),
                      dtype=theano.config.floatX)
    #test_acc = T.mean(lasagne.objectives.binary_hinge_loss(prediction, target_var, log_odds=False),
    #					dtype=theano.config.floatX)

    # Compile a function performing a training step on a mini-batch (by giving
    # the updates dictionary) and returning the corresponding training loss:
    train_fn = theano.function([input_var, target_var], loss, updates=updates)

    # Compile a second function computing the validation loss and accuracy:
    val_fn = theano.function([input_var, target_var], [test_loss, test_acc])

    # Finally, launch the training loop.
    print("Starting training...")
    # We iterate over epochs:
    for epoch in range(num_epochs):
        # In each epoch, we do a full pass over the training data:
        train_err = 0
        train_batches = 0
        start_time = time.time()
        for batch in iterate_minibatches(X_train, y_train, 500, shuffle=True):
            inputs, targets = batch
            train_err += train_fn(inputs, targets)
            train_batches += 1

        # And a full pass over the validation data:
        val_err = 0
        val_acc = 0
        val_batches = 0
        for batch in iterate_minibatches(X_val, y_val, 500, shuffle=False):
            inputs, targets = batch
            err, acc = val_fn(inputs, targets)
            val_err += err
            val_acc += acc
            val_batches += 1

        # Then we print the results for this epoch:
        print("Epoch {} of {} took {:.3f}s".format(
            epoch + 1, num_epochs, time.time() - start_time))
        print("  training loss:\t\t{:.6f}".format(train_err / train_batches))
        print("  validation loss:\t\t{:.6f}".format(val_err / val_batches))
        print("  validation accuracy:\t\t{:.2f} %".format(
            val_acc / val_batches * 100))

    # After training, we compute and print the test error:
    test_err = 0
    test_acc = 0
    test_batches = 0
    for batch in iterate_minibatches(X_test, y_test, 500, shuffle=False):
        inputs, targets = batch
        err, acc = val_fn(inputs, targets)
        test_err += err
        test_acc += acc
        test_batches += 1
    print("Final results:")
    print("  test loss:\t\t\t{:.6f}".format(test_err / test_batches))
    print("  test accuracy:\t\t{:.2f} %".format(
        test_acc / test_batches * 100))

    # Optionally, you could now dump the network weights to a file like this:
    # np.savez('model.npz', *lasagne.layers.get_all_param_values(network))
    #
    # And load them again later on like this:
    # with np.load('model.npz') as f:
    #     param_values = [f['arr_%d' % i] for i in range(len(f.files))]
    # lasagne.layers.set_all_param_values(network, param_values)

main([images,scores])


import json

class Destinations:
    def __init__(self):
        self.destination = ""
        self.file_name = "destinations.json"

    def write_to_json_file(self):
        dictionary = {
            "destination": self.destination
        }
        json_object = json.dumps(dictionary, indent=1, ensure_ascii=False)
        with open(self.file_name, 'a', encoding='utf-8') as f:
            f.write(json_object)


from datetime import datetime
from typing import List, Union

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.models import CharityProject, Donation

async def get_not_closed_investing_objects(
        model: Union[CharityProject, Donation],
        session: AsyncSession
) -> List[Union[CharityProject, Donation]]:
    db_obj = await session.execute(
        select(model).where(
            model.fully_invested == 0
        ).order_by(model.create_date)
    )
    return db_obj.scalars().all()

def close_investing_object(
        obj_to_close: Union[CharityProject, Donation]
):
    obj_to_close.invested_amount = obj_to_close.full_amount
    obj_to_close.fully_invested = True
    obj_to_close.close_date = datetime.now()

def make_investing(
        new_obj: Union[CharityProject, Donation],
        model_obj: Union[CharityProject, Donation]
) -> (Union[CharityProject, Donation], Union[CharityProject, Donation]):
    new_obj_free_amount = new_obj.full_amount - new_obj.invested_amount
    model_obj_free_amount = model_obj.full_amount - model_obj.invested_amount
    if new_obj_free_amount == model_obj_free_amount:
        close_investing_object(new_obj)
        close_investing_object(model_obj)
    elif new_obj_free_amount > model_obj_free_amount:
        new_obj.invested_amount += model_obj_free_amount
        close_investing_object(model_obj)
    else:
        model_obj.invested_amount += new_obj_free_amount
        close_investing_object(new_obj)
    return new_obj, model_obj

async def investing_process(
        new_object: Union[CharityProject, Donation],
        model: Union[CharityProject, Donation],
        session: AsyncSession
):
    model_objects = await get_not_closed_investing_objects(model, session)
    for model_object in model_objects:
        new_obj, model_obj = make_investing(new_object, model_object)
        session.add(new_obj)
        session.add(model_obj)
    await session.commit()
    await session.refresh(new_object)


import torch
import seaborn as sn
from matplotlib import pyplot as plt
from model import ConvNet
from MnistDataset import Mydataset
from torch.utils.data import DataLoader
import numpy as np
import pandas as pd

torch.manual_seed(13)

def get_score(confusion_mat):
    smooth = 0.0001  #防止出现除数为0而加上一个很小的数
    tp = np.diagonal(confusion_mat)
    fp = np.sum(confusion_mat, axis=0)
    fn = np.sum(confusion_mat, axis=1)
    precision = tp / (fp + smooth)
    recall = tp / (fn + smooth)
    f1 = 2 * precision * recall / (precision + recall + smooth)
    return precision, recall, f1

def get_confusion(confusion_matrix, out, label):
    idx = np.argmax(out.detach().numpy())
    confusion_matrix[idx, label] += 1
    return confusion_matrix

def main():
    confusion_matrix = np.zeros((10, 10))

    net = ConvNet()
    net.load_state_dict(torch.load('model_parameter\\parameter_epo90.pth'))
    test_path = ['test.txt', r'dataset/test_label.txt']
    test_dataset = Mydataset(test_path[0], test_path[1], 'cpu')
    test_dataloader = DataLoader(test_dataset, 1, True)
    for i, (pic, label) in enumerate(test_dataloader):
        out = net(pic)
        confusion_matrix = get_confusion(confusion_matrix, out, label)

    precision, recall, f1 = get_score(confusion_matrix)
    print(f'precision: {np.average(precision)}\trecall: {np.average(recall)}\tf1: {np.average(f1)}')
    confusion_mat = pd.DataFrame(confusion_matrix)
    confusion_df = pd.DataFrame(confusion_mat, index=[i for i in range(10)], columns=[i for i in range(10)])
    sn.heatmap(data=confusion_df, cmap='RdBu_r')
    plt.show()
    confusion_df.to_csv(r'confusion.csv', encoding='ANSI')

if __name__ == '__main__':
    main()


from flask import Flask, render_template, flash, redirect, request, url_for, jsonify
from multiprocessing import Process, Queue
from xBee_recieve import reciever

app = Flask(__name__)

processes = []
collectedData = []

def getNewXbeeData(q):
    PORT = "COM2"
    BAUD = 9600
    MAC  = "13A20041C7BFFC"

    r = reciever(PORT, BAUD, MAC)

    while True:
        msg = r.check_for_message()
        if msg:
            q.put(msg) # data needs to first be parsed, so if the msg is a json, we need to format to [msg['x'], msg['y']]

#tester method to get generated data should function the same as getNewXbeeData
def getNewRandomData(q):
    """
    temp()\n
    accel()\n
    mag()\n
    gyro()\n
    euler()\n
    quaternion()\n
    linear_accel()\n
    gravity()\n
    """
    import time
    from random import randint

    t = 0
    lastAccel = [0,0,0]
    while True:
        r = randint(5,10)/10.0
        print(r)
        time.sleep(r)
        t += r

        data = {
            "time"  : t,
            "accel" : [lastAccel[0] + randint(-20,20),lastAccel[1] + randint(-20,20),lastAccel[2] + randint(-20,20)],
            "gyro"  : [randint(-20,20),randint(-20,20),randint(-20,20)],
            "temp"  : randint(30,100),
            }
        q.put(data)

        lastAccel = data["accel"]

@app.route("/", methods=["GET", ])
def main():
    return render_template("main.html")

#main page
@app.route('/api/<data>/<num>', methods=['GET'])
def api(data, num):
    q = processes[0][0]

    while not q.empty():
        d = q.get()
        collectedData.append(d)

    #num is current size of users data, so we only give them the data they dont have
    out = []
    if "accel" in data:
        n = 0
        if "Y" in data:
            n = 1
        elif "Z" in data:
            n = 2

        for d in collectedData[int(num)::]:
            out.append([d["time"], d["accel"][n]])

    elif "gyro" in data:
        n = 0
        if "Y" in data:
            n = 1
        elif "Z" in data:
            n = 2

        for d in collectedData[int(num)::]:
            out.append([d["time"], d["gyro"][n]])

    elif data == "temp":
        for d in collectedData[int(num)::]:
            out.append([d["time"], d["temp"]])

    return jsonify(out)

if __name__ == '__main__':
    q = Queue()
    p = Process(target=getNewRandomData, args=[q,])
    processes.append((q,p))
    p.start()

    app.run(host="0.0.0.0", port=80)
    for p in processes:
        p[1].terminate()


from django.shortcuts import render, redirect, get_object_or_404
from .forms import LibroForm
from django.shortcuts import render
from .models import Libro
from django.urls import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from django.views.generic.edit import UpdateView

class IngresarLibroView(LoginRequiredMixin, CreateView):
    model = Libro
    form_class = LibroForm
    template_name = 'libros/ingresar_libro.html'
    success_url = reverse_lazy('lista_libros')

    def form_valid(self, form):

        form.instance.usuario = self.request.user

        titulo = form.cleaned_data['titulo']
        autor = form.cleaned_data['autor']
        if not Libro.objects.filter(titulo=titulo, autor=autor).exists():
            return super().form_valid(form)
        else:

            form.add_error('titulo', 'Este libro ya existe en la biblioteca.')
            return self.form_invalid(form)

class EditarLibroView(LoginRequiredMixin, UpdateView):
    model = Libro
    form_class = LibroForm
    template_name = 'libros/editar_libro.html'

    success_url = reverse_lazy('lista_libros')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['libro'] = self.get_object()
        return context

    def form_valid(self, form):
        return super().form_valid(form)

def lista_libros(request):
    libros = Libro.objects.all().order_by('titulo')
    return render(request, 'libros/lista_libros.html', {'libros': libros})

def eliminar_libro(request, libro_id):
    libro = get_object_or_404(Libro, id=libro_id)

    if request.method == 'POST':
        libro.delete()
        return redirect('lista_libros')

    return render(request, 'libros/eliminar_libro.html', {'libro': libro})

def lista_detalle_libros(request):
    libros = Libro.objects.all().order_by('titulo')
    return render(request, 'libros/lista_detalle_libros.html', {'libros': libros})


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('foi_requests', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='foirequest',
            name='title',
            field=models.CharField(max_length=255, blank=True),
        ),
        migrations.AlterField(
            model_name='foirequest',
            name='foi_text',
            field=models.TextField(verbose_name='Your FOI Request'),
        ),
    ]


from __future__ import (nested_scopes, generators, division, absolute_import, with_statement,
                        print_function, unicode_literals)

from collections import defaultdict
from contextlib import contextmanager
import inspect
import logging
import os
import re
import sys
import traceback

from twitter.common import log
from twitter.common.collections import OrderedSet
from twitter.common.lang import Compatibility
from twitter.common.log.options import LogOptions

from pants.backend.core.tasks.task import QuietTaskMixin, Task
from pants.backend.jvm.tasks.nailgun_task import NailgunTask  # XXX(pl)
from pants.base.build_environment import get_buildroot
from pants.base.build_file import BuildFile
from pants.base.cmd_line_spec_parser import CmdLineSpecParser
from pants.base.config import Config
from pants.base.rcfile import RcFile
from pants.base.workunit import WorkUnit
from pants.commands.command import Command
from pants.engine.engine import Engine
from pants.engine.round_engine import RoundEngine
from pants.goal.context import Context
from pants.goal.error import GoalError
from pants.goal.initialize_reporting import update_reporting
from pants.goal.goal import Goal
from pants.option.bootstrap_options import create_bootstrapped_options
from pants.option.global_options import register_global_options
from pants.util.dirutil import safe_mkdir

StringIO = Compatibility.StringIO

class GoalRunner(Command):
  """Lists installed goals or else executes a named goal."""

  class IntermixedArgumentsError(GoalError):
    pass

  __command__ = 'goal'
  output = None

  def __init__(self, *args, **kwargs):
    self.targets = []
    known_scopes = ['']
    for goal in Goal.all():
      # Note that enclosing scopes will appear before scopes they enclose.
      known_scopes.extend(filter(None, goal.known_scopes()))

    self.new_options = create_bootstrapped_options(known_scopes=known_scopes)
    self.config = Config.from_cache()  # Get the bootstrapped version.
    super(GoalRunner, self).__init__(*args, needs_old_options=False, **kwargs)

  def get_spec_excludes(self):
    # Note: Only call after register_options() has been called.
    return [os.path.join(self.root_dir, spec_exclude)
            for spec_exclude in self.new_options.for_global_scope().spec_excludes]

  @property
  def global_options(self):
    return self.new_options.for_global_scope()

  @contextmanager
  def check_errors(self, banner):
    errors = {}
    def error(key, include_traceback=False):
      exc_type, exc_value, _ = sys.exc_info()
      msg = StringIO()
      if include_traceback:
        frame = inspect.trace()[-2]
        filename = frame[1]
        lineno = frame[2]
        funcname = frame[3]
        code = ''.join(frame[4]) if frame[4] else None
        traceback.print_list([(filename, lineno, funcname, code)], file=msg)
      if exc_type:
        msg.write(''.join(traceback.format_exception_only(exc_type, exc_value)))
      errors[key] = msg.getvalue()
      sys.exc_clear()

    yield error

    if errors:
      msg = StringIO()
      msg.write(banner)
      invalid_keys = [key for key, exc in errors.items() if not exc]
      if invalid_keys:
        msg.write('\n  %s' % '\n  '.join(invalid_keys))
      for key, exc in errors.items():
        if exc:
          msg.write('\n  %s =>\n    %s' % (key, '\n      '.join(exc.splitlines())))
      # The help message for goal is extremely verbose, and will obscure the
      # actual error message, so we don't show it in this case.
      self.error(msg.getvalue(), show_help=False)

  def register_options(self):
    # Add a 'bootstrap' attribute to the register function, so that register_global can
    # access the bootstrap option values.
    def register_global(*args, **kwargs):
      return self.new_options.register_global(*args, **kwargs)
    register_global.bootstrap = self.new_options.bootstrap_option_values()
    register_global_options(register_global)
    for goal in Goal.all():
      goal.register_options(self.new_options)

  def setup_parser(self, parser, args):
    if not args:
      args.append('help')

    logger = logging.getLogger(__name__)

    goals = self.new_options.goals
    specs = self.new_options.target_specs
    fail_fast = self.new_options.for_global_scope().fail_fast

    for goal in goals:
      if BuildFile.from_cache(get_buildroot(), goal, must_exist=False).exists():
        logger.warning(" Command-line argument '{0}' is ambiguous and was assumed to be "
                       "a goal. If this is incorrect, disambiguate it with ./{0}.".format(goal))

    if self.new_options.is_help:
      self.new_options.print_help(goals=goals)
      sys.exit(0)

    self.requested_goals = goals

    with self.run_tracker.new_workunit(name='setup', labels=[WorkUnit.SETUP]):
      spec_parser = CmdLineSpecParser(self.root_dir, self.address_mapper,
                                      spec_excludes=self.get_spec_excludes())
      with self.run_tracker.new_workunit(name='parse', labels=[WorkUnit.SETUP]):
        for spec in specs:
          for address in spec_parser.parse_addresses(spec, fail_fast):
            self.build_graph.inject_address_closure(address)
            self.targets.append(self.build_graph.get_target(address))
    self.goals = [Goal.by_name(goal) for goal in goals]

    rcfiles = self.config.getdefault('rcfiles', type=list,
                                     default=['/etc/pantsrc', '~/.pants.rc'])
    if rcfiles:
      rcfile = RcFile(rcfiles, default_prepend=False, process_default=True)

      # Break down the goals specified on the command line to the full set that will be run so we
      # can apply default flags to inner goal nodes.  Also break down goals by Task subclass and
      # register the task class hierarchy fully qualified names so we can apply defaults to
      # baseclasses.

      sections = OrderedSet()
      for goal in Engine.execution_order(self.goals):
        for task_name in goal.ordered_task_names():
          sections.add(task_name)
          task_type = goal.task_type_by_name(task_name)
          for clazz in task_type.mro():
            if clazz == Task:
              break
            sections.add('%s.%s' % (clazz.__module__, clazz.__name__))

      augmented_args = rcfile.apply_defaults(sections, args)
      if augmented_args != args:
        # TODO(John Sirois): Cleanup this currently important mutation of the passed in args
        # once the 2-layer of command -> goal is squashed into one.
        args[:] = augmented_args
        sys.stderr.write("(using pantsrc expansion: pants goal %s)\n" % ' '.join(augmented_args))

  def run(self):
    # TODO(John Sirois): Consider moving to straight python logging.  The divide between the
    # context/work-unit logging and standard python logging doesn't buy us anything.

    # Enable standard python logging for code with no handle to a context/work-unit.
    if self.global_options.level:
      LogOptions.set_stderr_log_level((self.global_options.level or 'info').upper())
      logdir = self.global_options.logdir or self.config.get('goals', 'logdir', default=None)
      if logdir:
        safe_mkdir(logdir)
        LogOptions.set_log_dir(logdir)

        prev_log_level = None
        # If quiet, temporarily change stderr log level to kill init's output.
        if self.global_options.quiet:
          prev_log_level = LogOptions.loglevel_name(LogOptions.stderr_log_level())
          # loglevel_name can fail, so only change level if we were able to get the current one.
          if prev_log_level is not None:
            LogOptions.set_stderr_log_level(LogOptions._LOG_LEVEL_NONE_KEY)

        log.init('goals')

        if prev_log_level is not None:
          LogOptions.set_stderr_log_level(prev_log_level)
      else:
        log.init()

    # Update the reporting settings, now that we have flags etc.
    def is_quiet_task():
      for goal in self.goals:
        if goal.has_task_of_type(QuietTaskMixin):
          return True
      return False

    # Target specs are mapped to the patterns which match them, if any. This variable is a key for
    # specs which don't match any exclusion regexes. We know it won't already be in the list of
    # patterns, because the asterisks in its name make it an invalid regex.
    _UNMATCHED_KEY = '** unmatched **'

    def targets_by_pattern(targets, patterns):
      mapping = defaultdict(list)
      for target in targets:
        matched_pattern = None
        for pattern in patterns:
          if re.search(pattern, target.address.spec) is not None:
            matched_pattern = pattern
            break
        if matched_pattern is None:
          mapping[_UNMATCHED_KEY].append(target)
        else:
          mapping[matched_pattern].append(target)
      return mapping

    is_explain = self.global_options.explain
    update_reporting(self.global_options, is_quiet_task() or is_explain, self.run_tracker)

    if self.global_options.exclude_target_regexp:
      excludes = self.global_options.exclude_target_regexp
      log.debug('excludes:\n  {excludes}'.format(excludes='\n  '.join(excludes)))
      by_pattern = targets_by_pattern(self.targets, excludes)
      self.targets = by_pattern[_UNMATCHED_KEY]
      # The rest of this if-statement is just for debug logging.
      log.debug('Targets after excludes: {targets}'.format(
          targets=', '.join(t.address.spec for t in self.targets)))
      excluded_count = sum(len(by_pattern[p]) for p in excludes)
      log.debug('Excluded {count} target{plural}.'.format(count=excluded_count,
          plural=('s' if excluded_count != 1 else '')))
      for pattern in excludes:
        log.debug('Targets excluded by pattern {pattern}\n  {targets}'.format(pattern=pattern,
            targets='\n  '.join(t.address.spec for t in by_pattern[pattern])))

    context = Context(
      config=self.config,
      new_options=self.new_options,
      run_tracker=self.run_tracker,
      target_roots=self.targets,
      requested_goals=self.requested_goals,
      build_graph=self.build_graph,
      build_file_parser=self.build_file_parser,
      address_mapper=self.address_mapper,
      spec_excludes=self.get_spec_excludes()
    )

    unknown = []
    for goal in self.goals:
      if not goal.ordered_task_names():
        unknown.append(goal)

    if unknown:
      context.log.error('Unknown goal(s): %s\n' % ' '.join(goal.name for goal in unknown))
      return 1

    engine = RoundEngine()
    return engine.execute(context, self.goals)

  def cleanup(self):
    # TODO: This is JVM-specific and really doesn't belong here.
    # TODO: Make this more selective? Only kill nailguns that affect state? E.g., checkstyle
    # may not need to be killed.
    NailgunTask.killall(log.info)
    sys.exit(1)


import yaml,os
class Common_funcs():
    def get_datas(self,path:str)-> list:
        # 打开文件
        current_path = os.getcwd().split("lagou05")[0]
        #print(current_path)
        with open(current_path+"\\lagou05"+path) as f:
            datas = yaml.safe_load(f)
            #print(datas)
            # 获取文件中key为datas的数据
            # data_all = datas["datas"]
            add_datas = datas["datas"]["add"]
            # 获取文件中key为myids的数据
            add_ids = datas["myids"]["add"]
            # 获取文件中key为datas的数据
            div_datas = datas["datas"]["div"]
            # 获取文件中key为myids的数据
            div_ids = datas["myids"]["div"]
            # 获取文件中key为datas的数据
            mul_datas = datas["datas"]["mul"]
            # 获取文件中key为myids的数据
            mul_ids = datas["myids"]["mul"]
            # 获取文件中key为datas的数据
            sub_datas = datas["datas"]["sub"]
            # 获取文件中key为myids的数据
            sub_ids = datas["myids"]["sub"]
            #print(add_ids,add_datas)
            #print(data_all)
            f.close()
            return [add_datas,add_ids,div_datas,div_ids,mul_datas,mul_ids,sub_datas,sub_ids]


from PySide6.QtCore import QObject, Property, Slot, Signal, QTimer
from typing import Optional

from .qml_file_wrapper import QmlFileWrapper

class MainController(QObject):
    main_content_qml_changed = Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self._app = parent
        self._qml_wrappers = {
            "HOME": QmlFileWrapper('Home.qml'),
            "OTHER": QmlFileWrapper('Other.qml')
        }
        self._active_id = "HOME"
        self._active_wrapper: QmlFileWrapper = self._qml_wrappers[self._active_id]
        self._counter = 0
        self._timer = QTimer()
        self._timer.setInterval(10)
        self._timer.setSingleShot(False)
        self._timer.timeout.connect(self._toggle_screen)

    @Property(str, notify=main_content_qml_changed)
    def main_content_qml(self) -> str:
        return self._active_wrapper.qml_path

    def startup(self):
        self._timer.start()

    def shutdown(self):
        print(f"Stopping after {self._counter} iterations.")

    @Slot(str, result=QmlFileWrapper)
    def get_wrapper_object_by_name(self, screen_name: str) -> Optional[QmlFileWrapper]:
        return self._qml_wrappers[screen_name.upper()]

    @Slot(str)  # QML will only send a string
    def go_to_qml_by_name(self, next_id: str) -> None:
        self._active_wrapper = self.get_wrapper_object_by_name(next_id)
        self.main_content_qml_changed.emit()

    def _toggle_screen(self):
        self._counter = self._counter + 1
        if self._active_id == "HOME":
            self._active_id = "OTHER"
        else:
            self._active_id = "HOME"

        self.go_to_qml_by_name(self._active_id)


import pytz
import base64
from typing import List
from flask import Blueprint, request, redirect, abort
from flask_login.utils import login_required
from datetime import datetime, timedelta, timezone
from flask.templating import render_template
from flask_login import current_user
from mib.rao.user_manager import UserManager, User
from mib.rao.message_manager import MessageManager, MessagePost, Message
from mib.rao.draft_manager import DraftManager, DraftPost, Draft

messages = Blueprint('messages', __name__)

@ messages.route('/messages/send', methods=['GET', 'POST'])
@login_required
def send_message():
    ''' GET: get the page for write and send a message to the chosen recipient/s
        POST: send the message to the recipient/s at the chosen date '''
    if request.method == 'POST':

        emails = request.form.get('receiver').split(',')
        recipient_list = []
        recipient_error_list = []
        message_ok = False

        for email in emails:
            email = email.strip(' ')
            user = UserManager.get_user_by_email(email)
            check = True
            if  user is not None and user.is_active:
                    recipient_list.append(user.id)
                    check = False
            if check:
                recipient_error_list.append(email)

        new_message :MessagePost = MessagePost()
        new_message.attachment_list = []
        new_message.id_sender = current_user.id
        new_message.recipients_list = recipient_list

        message_date = request.form.get('date')
        tz=timezone(timedelta(hours=1))
        message_date = datetime.fromisoformat(message_date)
        message_date = message_date.replace(tzinfo=tz)
        message_date = message_date.astimezone(pytz.UTC)
        message_date = message_date.isoformat()

        new_message.date_delivery = message_date
        new_message.text = request.form.get('text')
        uploaded_files = request.files.getlist("files")

        if uploaded_files and any(f for f in uploaded_files):
            for file in uploaded_files:
                if file:
                    attachment = file.read()
                    new_message.attachment_list.append(base64.b64encode(attachment).decode('ascii'))

        new_message = MessageManager.send_message(new_message)

        if new_message is not None:
            message_ok = True
        else:
            for email in emails:
                recipient_error_list.append(email)

        return render_template("send_message.html", form=dict(), message_ok=message_ok,
                               recipient_error_list=recipient_error_list)
    else:
        # landing from the recipients page, we want to populate the field with the chosen one
        recipient_message = request.args.items(multi=True)
        form = {'recipient': ''}
        for recipient in recipient_message:
            if recipient[1] != '':
                form['recipient'] += recipient[1] if form['recipient'] == '' else ', ' + recipient[1]

        return render_template("send_message.html", form=form)

@messages.route('/messages/<message_id>', methods=["GET"])
@login_required
def view_message(message_id):
    ''' GET: visualize the chosen message '''
    message: Message = MessageManager.get_message(message_id)

    if message is None:
        abort(404)
    else:
        recipient: User = UserManager.get_user_by_id(message.id_recipient)
        sender: User = UserManager.get_user_by_id(message.id_sender)
        return render_template("message.html",
                               sender=sender,
                               recipient=recipient,
                               message=message,
                               images=message.attachment_list)

@messages.route('/messages/<message_id>/delete', methods=["POST"])
@login_required
def deleteMessage(message_id):
    ''' POST: delete the chosen message '''

    ret: int = MessageManager.delete_message(message_id)

    if ret == 404:
        abort(404)
    elif ret == 403:
        abort(403)
    else:
        return redirect('/inbox')

@messages.route("/messages/<id>/withdraw", methods=['POST'])
@login_required
def withdraw_message(id):
    ''' POST: withdraw a message not sent yet, paying points '''

    ret: int = MessageManager.withdraw_message(id)

    if ret == 404:
        abort(404)
    elif ret == 403:
        abort(403)
    else:
        return redirect('/outbox')

@messages.route('/messages/<id_message>/forward', methods=['GET'])
@login_required
def send_forward_msg(id_message):
    ''' GET: get the send message page filled with the text to forward '''
    recipient_message = request.args.items(multi=True)
    text = MessageManager.get_message(id_message).text
    form = dict(recipient="", text=text, message_id=id_message)
    for recipient in recipient_message:
        if recipient[1] != '':
            form['recipient'] += recipient[1] if form['recipient'] == '' else ', ' + recipient[1]
    return render_template("send_message.html", form=form, forward=True)