def func():
    stream = None
    try:
        stream = open(r'D:\p1.txt')
        container = stream.read()
        print(container)
        return 1
    except Exception as err:
        print(err)
        return 2
    finally:
        print('----finally----')
        if stream:
            stream.close()
        return 3

x =func()
print(x) #返回3 finally 覆盖了上一个return

#抛出异常

def register():
    username =input('输入用户名')
    if len(username) < 6:
        raise Exception('用户长度必须六位以上')
    else:
        print('输入的用户名为是：',username)

try:
    register()
except Exception as err:
    print(err)
    print('注册失败！')
else:
    print('注册成功')


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

import sys, os, public
_title = 'bootloader配置权限'
_version = 1.0  # 版本
_ps = "bootloader配置权限检查"  # 描述
_level = 2  # 风险级别： 1.提示(低)  2.警告(中)  3.危险(高)
_date = '2023-03-15'  # 最后更新时间
_ignore = os.path.exists("data/warning/ignore/sw_bootloader_mod.pl")
_tips = [
    "根据风险描述提示的文件，对grub配置安全的权限",
    "若是grub2，则：chmod 600 /boot/grub2/grub.cfg、chown root /boot/grub2/grub.cfg",
    "若是grub，则：chmod 600 /boot/grub/grub.cfg、chown root /boot/grub/grub.cfg"
]
_help = ''
_remind = '此方案可以加强服务器grub界面的防护，进一步阻止外部入侵服务器。'

def check_run():
    dir_list = [
        ['/boot/grub2/grub.cfg', 600, 'root'],
        ['/boot/grub/grub.cfg', 600, 'root']
        ]
    # 存放没有配置权限的文件
    not_mode_list = []
    for d in dir_list:
        if not os.path.exists(d[0]):
            continue
        u_mode = public.get_mode_and_user(d[0])
        if u_mode['user'] != d[2]:
            not_mode_list.append("{} 当前权限: {} : {} 安全权限: {} : {}".format(d[0],u_mode['mode'],u_mode['user'],d[1],d[2]))
        if int(u_mode['mode']) != d[1]:
            not_mode_list.append("{} 当前权限: {} : {} 安全权限: {} : {}".format(d[0],u_mode['mode'],u_mode['user'],d[1],d[2]))
    if not_mode_list:
        return False, '以下关键文件或目录权限错误:{}'.format('、'.join(not_mode_list))
    else:
        return True, "无风险"


from datetime import date, datetime

from dateutil.relativedelta import relativedelta

from odoo import fields, models, api
from odoo.addons import decimal_precision as dp
from ..utils import serial_utils

class StockProductionLot(models.Model):
    _inherit = 'stock.production.lot'
    _sql_constraints = [
        ('name_uniq', 'UNIQUE(name)', 'el lote que intenta crear, ya existe en el sistema')
    ]

    unpelled_state = fields.Selection([
        ('draft', 'En Espera para ingresar'),
        ('waiting', 'En Espera para Iniciar'),
        ('drying', 'Secando'),
        ('stopped', 'Detenido'),
        ('done', 'Terminado')
    ],
        'Estado',

    )

    can_add_serial = fields.Boolean(
        'Puede Agregar Series',
        compute='_compute_can_add_serial'
    )

    producer_ids = fields.Many2many(
        'res.partner',
        compute='_compute_producer_ids'
    )

    product_variety = fields.Char(
        'Variedad',
        compute='_compute_product_variety'
    )

    producer_id = fields.Many2one(
        'res.partner',
        string='Productor'
    )

    reception_guide_number = fields.Integer(
        'Guía',
        related='stock_picking_id.guide_number',
        store=True
    )

    reception_state = fields.Selection(
        string='Estado de la reecepción',
        related='stock_picking_id.state'
    )

    product_canning = fields.Char(
        'Envase',
        compute='_compute_reception_data'
    )

    is_prd_lot = fields.Boolean('Es Lote de salida de Proceso')

    is_standard_weight = fields.Boolean(
        'Series Peso Estandar',
        related='product_id.is_standard_weight'
    )

    standard_weight = fields.Float(
        'Peso Estandar',
        related='product_id.weight',
        digits=dp.get_precision('Product Unit of Measure')
    )

    qty_standard_serial = fields.Integer('Cantidad de Series por Pallet')

    stock_production_lot_serial_ids = fields.One2many(
        'stock.production.lot.serial',
        'stock_production_lot_id',
        string="Detalle"
    )

    serial_without_pallet_ids = fields.One2many(
        'stock.production.lot.serial',
        'stock_production_lot_id',
        domain=[('pallet_id', '=', None)],
        string='Series sin Pallet'
    )

    stock_production_lot_available_serial_ids = fields.One2many(
        'stock.production.lot.serial',
        'stock_production_lot_id',
        domain=[('reserved_to_stock_picking_id', '=', None), ('consumed', '=', False)],
        string='Series Disponibles'
    )

    total_serial = fields.Float(
        'Total',
        compute='_compute_total_serial',
        digits=dp.get_precision('Product Unit of Measure')
    )

    count_serial = fields.Integer(
        'Total Series',
        compute='_compute_count_serial'
    )

    available_total_serial = fields.Float(
        'Total Disponible',
        compute='_compute_available_total_serial',
        search='_search_available_total_serial',
        digits=dp.get_precision('Product Unit of Measure')
    )

    qty_to_reserve = fields.Float(
        'Cantidad a Reservar',
        digits=dp.get_precision('Product Unit of Measure')
    )

    context_picking_id = fields.Integer(
        'picking del contexto',
        compute='_compute_context_picking_id'
    )

    pallet_ids = fields.One2many(
        'manufacturing.pallet',
        'lot_id'
    )

    picking_type_id = fields.Many2one(
        'stock.picking.type',
        string='Bodega',
        related='stock_picking_id.picking_type_id',
        store=True

    )

    reception_net_weight = fields.Float(
        'kg. Neto',
        related='stock_picking_id.net_weight',
        digits=dp.get_precision('Product Unit of Measure'),
        store=True
    )

    reception_date = fields.Datetime(
        'Fecha Recepción',
        related='stock_picking_id.truck_in_date',
        store=True
    )

    reception_elapsed_time = fields.Char(
        'Hr Camión en Planta',
        related='stock_picking_id.elapsed_time'
    )

    oven_init_active_time = fields.Integer(
        'Inicio Tiempo Activo',
        related='oven_use_ids.init_active_time'
    )

    finish_active_time = fields.Integer(
        'Fin Tiempo Activo',
        related='oven_use_ids.finish_active_time'
    )

    oven_use_ids = fields.One2many(
        'oven.use',
        'used_lot_id',
        'Uso de Hornos',
        sort='active_seconds desc'
    )

    drier_counter = fields.Integer(
        'Hr en Secador',
        related='oven_use_ids.active_seconds'
    )

    stock_picking_id = fields.Many2one(
        'stock.picking',
        'Recepción'
    )

    all_pallet_ids = fields.One2many(
        'manufacturing.pallet',
        'lot_id',
        string='pallets'
    )

    label_durability_id = fields.Many2one(
        'label.durability',
        'Durabilidad Etiqueta'
    )

    is_dried_lot = fields.Boolean(
        'Es lote de Secado'
    )

    product_variety = fields.Char(
        'Variedad del Producto',
        related='product_id.variety',
        store=True
    )

    product_caliber = fields.Char(
        'Calibre del Producto',
        related='product_id.caliber',
        store=True
    )

    harvest = fields.Integer(string='Cosecha', compute='_compute_lot_harvest', store=True)

    dried_report_product_name = fields.Char(compute='_compute_lot_oven_use')

    location_id = fields.Many2one('stock.location', compute='_compute_lot_location')

    serial_not_consumed = fields.Integer('Envases disponible', compute='_compute_serial_not_consumed')

    available_kg = fields.Float('Kilos Disponibles')

    available_weight = fields.Float('Datos Disponibles')

    show_guide_number = fields.Char('Guia', compute='_compute_guide_number')

    reception_weight = fields.Float('Kilos Recepcionados', compute='_compute_reception_weight')

    sale_order_id = fields.Many2one('sale.order', 'Pedido')

    workcenter_id = fields.Many2one('mrp.workcenter', 'Enviado a proceso de')

    delivered_date = fields.Date('Fecha de Envio')

    physical_location = fields.Text('Ubicacion Fisica')

    observations = fields.Text('Observaciones')

    start_date = fields.Datetime('Fecha Inicio')

    measure = fields.Char('Medida', compute='compute_measure')

    produced_qty = fields.Integer('Cantidad Producida', compute='compute_produced_qty')

    produced_weight = fields.Float('Kilos Producidos', compute='compute_produced_weight')

    production_state = fields.Char('Estado de Producccion', compute='compute_production_state')

    dispatch_state = fields.Char('Estado de Despacho', compute='compute_dispatch_state')

    client_id = fields.Many2one('res.partner', related='sale_order_id.partner_id')

    destiny_country_id = fields.Many2one('res.country', compute='compute_destiny_country')

    dispatch_date = fields.Date('Fecha de Despacho')

    show_date = fields.Datetime('Fecha de Creacion', compute='compute_show_date')

    packaging_date = fields.Date(string='Fecha de Envasado')

    change_packaging = fields.Boolean(string='¿Desea cambiar fecha de envasado?')

    best_before_date = fields.Date(string='Consumir preferentemente antes de')

    change_best = fields.Boolean(string='¿Desea cambiar fecha de consumir preferentemente antes de?')

    is_unpelled_locked = fields.Boolean(string='Bloqueado')

    unpelled_dried_id = fields.Many2one('unpelled.dried', 'Proceso de Secado')

    qty_serial_without_lot = fields.Integer(string='Cantidad de Series Temporales')

    temporary_serial_ids = fields.One2many('custom.temporary.serial', 'lot_id',
                                           string='Series temporales sin Paletizar')

    do_print_selection_serial = fields.Boolean('Imprimir Series Seleccionadas')

    last_serial_number = fields.Char('Ultima serie temporal creado')

    is_finished = fields.Boolean('Finalizado')

    ventilation_date = fields.Date(string='Fecha de Ventilacion')

    store_place = fields.Char(string='Lugar de Almacenamiento')

    is_drying = fields.Boolean('Esta secando?', compute='compute_is_drying')

    correlative_serial = fields.Char('Correlativo de Serie')

    serial_to_select_ids = fields.Many2many('stock.production.lot.serial', string='Series',
                                            compute='compute_serial_to_select_ids')

    counter_pallet = fields.Integer('Contador de pallet', default=0)

    origin_process = fields.Char('Proceso de origen')

    def set_counter_in_pallet(self, harvest):
        lot_ids = self.env['stock.production.lot'].search([('product_id.is_standard_weight', '=', True)]).filtered(
            lambda x: x.harvest == harvest)
        for lot in lot_ids:
            if len(lot.all_pallet_ids) > 0:
                for pallet in lot.all_pallet_ids:
                    pallet.write({
                        'counter_pallet_lot': lot.counter_pallet + 1
                    })
                    lot.write({
                        'counter_pallet': lot.counter_pallet + 1
                    })

    def compute_serial_to_select_ids(self):
        for item in self:
            item.serial_to_select_ids = item.stock_production_lot_serial_ids.filtered(
                lambda x: not x.reserved_to_stock_picking_id)

    @api.multi
    def compute_is_drying(self):
        for item in self:
            dried_unpelled_id = self.env['unpelled.dried'].sudo().search([('out_lot_id', '=', item.id)])
            if dried_unpelled_id:
                if dried_unpelled_id.state == 'progress':
                    item.is_drying = True
                else:
                    item.is_drying = False
            else:
                item.is_drying = False

    @api.multi
    def compute_production(self):
        for item in self:
            if item.is_prd_lot:
                final_lot_id = self.env['mrp.workorder'].search([('final_lot_id.id', '=', item.id)])
                if final_lot_id:
                    item.production_id = final_lot_id.production_id
                    item.production_state = final_lot_id.production_id.state
                else:
                    if len('temporary_serial_ids') > 0:
                        item.production_id = item.temporary_serial_ids.mapped('production_id')
                        item.production_state = item.temporary_serial_ids.mapped('production_id').state
                    elif len('stock_production_lot_serial_ids') > 0:
                        item.production_id = item.stock_production_lot_serial_ids.mapped('production_id')
                        item.production_id = item.stock_production_lot_serial_ids.mapped('production_id').state
            else:
                item.production_id = None
                item.production_state = ''

    @api.multi
    def print_all_temporary_serial(self):
        for item in self:
            serials = self.temporary_serial_ids.filtered(lambda x: not x.printed)
            serials.write({
                'printed': True
            })
            if not serials:
                raise models.ValidationError('Ya se imprimieron todas las series')
            if len(serials) > 400:
                raise models.UserError(
                    'La cantidad de series que esta intentado imprimir superando el maximo permitido \n Maximo Permitido : 400')
            return self.env.ref(
                'dimabe_manufacturing.action_print_temporary_serial'
            ).report_action(serials)

    @api.multi
    def print_selection_serial(self):
        for item in self:
            serials = item.temporary_serial_ids.filtered(lambda x: x.to_print)
            serials.write({
                'to_print': False,
                'printed': True
            })
            item.write({
                'do_print_selection_serial': False
            })
            return self.env.ref(
                'dimabe_manufacturing.action_print_temporary_serial'
            ).report_action(serials)

    @api.model
    def selected_serials_to_print(self, selected_ids):
        serials = self.env['custom.temporary.serial'].search([('id', '=', selected_ids)])
        serials.write({
            'to_print': True
        })
        serials.mapped('lot_id').write({
            'do_print_selection_serial': True
        })
        return {
            'type': 'ir.actions.client',
            'tag': 'reload',
        }

    @api.onchange('qty_serial_without_lot')
    def onchange_qty_serial_without_lot(self):
        for item in self:
            if item.qty_serial_without_lot > 400:
                raise models.UserError('No se pueden generar mas de 400 series al vez')

    @api.multi
    def generate_temporary_serial(self):
        if self.qty_serial_without_lot > 400:
            raise models.UserError('No se pueden generar mas de 400 series al vez')
        counter = self.get_last_serial()
        serials = []
        for serial in range(self.qty_serial_without_lot):
            zeros = serial_utils.get_zeros(counter)
            production_id = self.env['mrp.workorder'].search([('final_lot_id.id', '=', self.id)]).production_id
            if not production_id:
                production_id = self.env['stock.move.line'].sudo().search(
                    [('lot_id.id', '=', self.id), ('move_id.production_id', '!=', False)]).move_id.production_id
            canning_id = self.get_possible_canning_id(production_id.id)[0]
            gross_weight = self.standard_weight + canning_id.weight
            serials.append({
                'product_id': self.product_id.id,
                'producer_id': self.producer_id.id,
                'lot_id': self.id,
                'name': f'{self.name}{zeros}{counter}',
                'best_before_date': fields.Date.today() + relativedelta(
                    months=self.label_durability_id.month_qty) if not self.best_before_date else self.best_before_date,
                'harvest': self.harvest,
                'label_durability_id': self.label_durability_id.id,
                'net_weight': self.standard_weight,
                'production_id': production_id.id,
                'packaging_date': fields.Date.today() if not self.packaging_date else self.packaging_date,
                'gross_weight': gross_weight
            })
            counter += 1
        self.env['custom.temporary.serial'].create(serials)
        self.write({
            'last_serial_number': self.temporary_serial_ids[-1].name,
            'qty_serial_without_lot': 0
        })

    @api.multi
    def get_last_serial(self):
        last_serial = 0
        if len(self.temporary_serial_ids) > 0:
            qty_number = -4 if len(self.temporary_serial_ids) > 999 else -3
            last_serial = self.last_serial_number[qty_number:]
        if len(self.temporary_serial_ids) == 0:
            if len(self.stock_production_lot_serial_ids) > 0:
                qty_number = -4 if len(self.stock_production_lot_serial_ids) > 999 else -3
                last_serial = self.last_serial_number[qty_number:]

        return int(last_serial) + 1

    @api.multi
    def generate_new_pallet(self):
        for item in self:
            if len(item.temporary_serial_ids) < item.qty_standard_serial:
                raise models.ValidationError(
                    f"Series insuficientes para completar el pallet \n "
                    f"Cantidad de Series Disponible {len(item.temporary_serial_ids)}")
            item.write({
                'counter_pallet': item.counter_pallet + 1
            })
            pallet_id = self.env['manufacturing.pallet'].create({
                'producer_id': item.producer_id.id,
                'lot_id': item.id,
                'sale_order_id': item.sale_order_id.id if item.sale_order_id else None,
                'counter_pallet_lot': item.counter_pallet
            })
            temporary_ids = self.env['custom.temporary.serial'].search([('lot_id', '=', item.id)],
                                                                       limit=item.qty_standard_serial)
            temporary_ids.create_serial(pallet_id.id)
            pallet_id.write({
                'state': 'close'
            })
            workorder = self.env['mrp.workorder'].sudo().search([('final_lot_id', '=', item.id)], limit=1)
            workorder.write({
                'pt_out_weight': sum(serial.display_weight for serial in item.stock_production_lot_serial_ids)
            })
            self.update_kg(self.id)

    def do_change_date_best(self):
        for item in self:
            wiz = self.env['change.date.lot'].create({
                'lot_id': item.id,
                'best_before_date_new': item.best_before_date,
                'best_before_date_old': item.stock_production_lot_serial_ids.mapped('best_before_date')[0]
            })
            view = self.env.ref('dimabe_manufacturing.change_date_best_lot_form_view')
            return {
                'name': '¿Esta seguro de cambiar las fecha de envasado?',
                'type': 'ir.actions.act_window',
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': 'change.date.lot',
                'views': [(view.id, 'form')],
                'view_id': view.id,
                'target': 'new',
                'res_id': wiz.id,
                'context': self.env.context
            }

    def get_possible_canning_id(self, production_id):
        production_id = self.env['mrp.production'].search([('id', '=', production_id)])
        return production_id.bom_id.bom_line_ids.filtered(
            lambda a: 'envases' in str.lower(a.product_id.categ_id.name) or
                      'embalaje' in str.lower(a.product_id.categ_id.name)
                      or (
                              a.product_id.categ_id.parent_id and (
                              'envases' in str.lower(a.product_id.categ_id.parent_id.name) or
                              'embalaje' in str.lower(a.product_id.categ_id.parent_id.name))
                      )
        ).mapped('product_id')

    def do_change_date_packing(self):
        for item in self:
            wiz = self.env['change.date.lot'].create({
                'lot_id': item.id,
                'packaging_date_new': item.packaging_date,
                'packaging_date_old': item.stock_production_lot_serial_ids.mapped('packaging_date')[0]
            })
            view = self.env.ref('dimabe_manufacturing.change_date_lot_form_view')
            return {
                'name': '¿Esta seguro de cambiar las fecha de envasado?',
                'type': 'ir.actions.act_window',
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': 'change.date.lot',
                'views': [(view.id, 'form')],
                'view_id': view.id,
                'target': 'new',
                'res_id': wiz.id,
                'context': self.env.context
            }

    @api.multi
    def unlink_serial_without_pallet(self):
        for item in self:
            if item.serial_without_pallet_ids.filtered(lambda a: a.consumed):
                raise models.ValidationError('Existe una o mas series consumidas')
            else:
                item.serial_without_pallet_ids.sudo().unlink()

    @api.multi
    def unlink_selection(self):
        for item in self:
            if not item.serial_without_pallet_ids.filtered(lambda a: a.to_unlink):
                raise models.UserError("No ha seleccionado nada")
            else:
                if item.serial_without_pallet_ids.filtered(lambda a: a.consumed):
                    raise models.ValidationError('Existe una o mas series consumidas')
                else:
                    item.serial_without_pallet_ids.filtered(lambda a: a.to_unlink).sudo().unlink()

    @api.multi
    def _compute_reception_elapsed_time(self):
        for item in self:
            item.reception_elapsed_time = item.stock_picking_id.elapsed_time

    @api.multi
    def compute_show_date(self):
        for item in self:
            if item.is_dried_lot:
                dried = self.env['dried.unpelled.history'].search([('out_lot_id', '=', item.id)])
                item.show_date = dried.finish_date
            else:
                item.show_date = item.create_date

    @api.multi
    def show_pallets(self):
        return {
            'name': "Series de Salida",
            'view_type': 'form',
            'view_mode': 'tree,graph,form,pivot',
            'res_model': 'manufacturing.pallet',
            'view_id': False,
            'type': 'ir.actions.act_window',
            'views': [
                [self.env.ref('dimabe_manufacturing.manufacturing_pallet_tree_view').id, 'tree']],
            'context': self.env.context,
            'domain': [('id', 'in', self.pallet_ids.mapped("id"))]
        }

    @api.multi
    def show_lot(self):
        return {
            'type': 'ir.actions.act_window',
            'res_model': 'stock.production.lot',
            'res_id': self.id,
            'view_type': 'form',
            'view_mode': 'form',
            'views': [(self.env.ref('stock.view_production_lot_form_simple').id, 'form')],
            'target': 'current',
            'context': self.env.context
        }

    @api.multi
    def compute_destiny_country(self):
        for item in self:
            if item.stock_production_lot_serial_ids.mapped('production_id'):
                item.destiny_country_id = item.stock_production_lot_serial_ids.mapped('production_id')[
                    0].stock_picking_id.arrival_port.country_id

    @api.multi
    def compute_measure(self):
        for item in self:
            item.measure = f'{item.product_id.weight} Kilos'

    @api.multi
    def compute_produced_qty(self):
        for item in self:
            item.produced_qty = len(item.stock_production_lot_serial_ids)

    @api.multi
    def compute_produced_weight(self):
        for item in self:
            item.produced_weight = sum(item.stock_production_lot_serial_ids.mapped('display_weight'))

    @api.multi
    def compute_production_state(self):
        for item in self:
            if item.stock_production_lot_serial_ids.mapped('production_id'):
                state = item.stock_production_lot_serial_ids.mapped('production_id')[0].state
                if state == 'done':
                    item.production_state = "Finalizado"
                else:
                    item.production_state = "En proceso"
            else:
                item.production_state = "Borrador"

    @api.multi
    def compute_dispatch_state(self):
        for item in self:
            if item.stock_production_lot_serial_ids.mapped('reserved_to_stock_picking_id'):
                state = item.stock_production_lot_serial_ids.mapped('reserved_to_stock_picking_id').mapped('state')[0]
                if state == 'done':
                    item.dispatch_state = "Finalizado"
                else:
                    item.dispatch_state = "En proceso"
            else:
                item.dispatch_state = "Borrador"

    @api.multi
    def _compute_reception_weight(self):
        for item in self:
            if not item.stock_picking_id:
                weight = self.env['stock.picking'].search([('name', '=', item.name)])
                item.reception_weight = weight.production_net_weight
            if item.stock_picking_id:
                item.reception_weight = item.stock_picking_id.production_net_weight
            if item.is_dried_lot:
                dried_ids = self.env['dried.unpelled.history'].search([('out_lot_id', '=', item.id)])
                item.reception_weight = sum(dried_ids.mapped('total_out_weight'))

    @api.multi
    def check_duplicate(self):
        for item in self:
            if len(item.stock_production_lot_serial_ids) > 999:
                not_duplicates = []
                duplicates = []
                for serial in item.stock_production_lot_serial_ids.mapped('serial_number'):
                    if serial not in not_duplicates:
                        not_duplicates.append(serial)
                    else:
                        duplicates.append(serial)
                serie = len(not_duplicates)

                if len(duplicates) > 1:
                    item.stock_production_lot_serial_ids[999].update({
                        'serial_number': item.name + '1000'
                    })
                    for duplicate in duplicates:
                        serial = self.env['stock.production.lot.serial'].search([('serial_number', '=', duplicate)])
                        serie += 1
                        if len(serial) > 1:
                            serial[1].write({
                                'serial_number': item.name + '{}'.format(serie)
                            })
                        else:
                            serial.write({
                                'serial_number': item.name + '{}'.format(serie)
                            })

    @api.multi
    def _compute_guide_number(self):
        for item in self:
            if item.stock_picking_id:
                item.show_guide_number = str(item.stock_picking_id.guide_number)
            else:
                reception = self.env['stock.picking'].search([('name', '=', item.name)])
                item.show_guide_number = str(reception.guide_number)
            if item.is_dried_lot:
                dried_ids = self.env['dried.unpelled.history'].search([('out_lot_id', '=', item.id)])
                guide_numbers = []
                for dried_id in dried_ids:
                    if dried_id.lot_guide_numbers:
                        guide_numbers.append(str(dried_id.lot_guide_numbers))
                item.show_guide_number = '|'.join(guide_numbers)

    @api.depends('stock_production_lot_serial_ids', 'available_kg')
    @api.multi
    def _compute_lot_harvest(self):
        for item in self:
            if item.stock_production_lot_serial_ids:
                item.harvest = max(item.stock_production_lot_serial_ids.mapped('serial_harvest'))

    @api.multi
    def _compute_lot_location(self):
        for item in self:
            stock_quant = item.get_stock_quant()
            if len(stock_quant) > 0:
                item.location_id = stock_quant.location_id
            if item.stock_picking_id:
                item.location_id = item.stock_picking_id.location_dest_id
                return
            if item.is_dried_lot:
                location_id_dried = self.env['dried.unpelled.history'].search(
                    [('out_lot_id', '=', item.id)]).dest_location_id
                if not location_id_dried:
                    location_id_dried = self.env['unpelled.dried'].sudo().search(
                        [('out_lot_id', '=', item.id)]
                    ).dest_location_id
                item.location_id = location_id_dried
                return
            if item.is_prd_lot:
                if item.stock_production_lot_serial_ids.mapped('production_id').state == 'done':
                    item.location_id = item.stock_production_lot_serial_ids.mapped('production_id').location_dest_id
                    return
            else:
                location_id = self.env['stock.picking'].search([('name', '=', item.name)])
                item.location_id = location_id.location_dest_id
                return

    @api.multi
    def _compute_serial_not_consumed(self):
        for item in self:
            item.serial_not_consumed = len(item.stock_production_lot_serial_ids.filtered(lambda a: not a.consumed))

    @api.multi
    def _compute_can_add_serial(self):
        for item in self:
            if item.is_prd_lot:
                item.can_add_serial = True

    @api.multi
    def _compute_serial_without_pallet_ids(self):
        for item in self:
            if item.product_id.is_standard_weight:
                item.serial_without_pallet_ids = item.stock_production_lot_serial_ids.filtered(
                    lambda a: not a.pallet_id
                )

    @api.onchange('label_durability_id')
    def onchange_label_durability_id(self):
        if self.stock_production_lot_serial_ids:
            for serial_id in self.stock_production_lot_serial_ids:
                serial_id.write({
                    'label_durability_id': self.label_durability_id.id
                })

    @api.multi
    def _compute_count_serial(self):
        for item in self:
            item.count_serial = len(item.stock_production_lot_serial_ids)

    @api.multi
    def print_all_serial(self):
        return self.env.ref('dimabe_manufacturing.action_print_all_serial') \
            .report_action(self.stock_production_lot_serial_ids)

    @api.multi
    def _compute_product_variety(self):
        for item in self:
            item.product_variety = item.product_id.get_variety()

    @api.multi
    def _compute_pallet_ids(self):
        for item in self:
            if item.product_id.is_standard_weight:
                item.pallet_ids = item.stock_production_lot_available_serial_ids.mapped('pallet_id')

    @api.multi
    def _compute_context_picking_id(self):
        for item in self:
            if 'stock_picking_id' in self.env.context:
                item.context_picking_id = self.env.context['stock_picking_id']

    @api.multi
    def _compute_stock_production_lot_available_serial_ids(self):
        for item in self:
            item.stock_production_lot_available_serial_ids = item.stock_production_lot_serial_ids.filtered(
                lambda a: not a.reserved_to_stock_picking_id
            )

    @api.multi
    def _compute_available_total_serial(self):
        for item in self:
            item.available_total_serial = sum(item.stock_production_lot_serial_ids.filtered(
                lambda a: not a.reserved_to_stock_picking_id and not a.consumed
            ).mapped('display_weight'))

    @api.multi
    def _compute_producer_ids(self):
        for item in self:
            if item.is_prd_lot:
                if 'default_producer_ids' in self.env.context.keys():
                    item.producer_ids = self.env.context['default_producer_ids']
                else:
                    item.producer_ids = self.env['res.partner'].search([])
            elif item.is_dried_lot:
                dried_data = self.env['unpelled.dried'].search([
                    ('out_lot_id', '=', item.id)
                ])
                if not dried_data:
                    dried_data = self.env['dried.unpelled.history'].search([
                        ('out_lot_id', '=', item.id)
                    ])
                if dried_data:
                    item.producer_ids = self.env['res.partner'].search([
                        '|',
                        ('id', '=', dried_data.in_lot_ids.mapped('stock_picking_id.partner_id.id')),
                        ('always_to_print', '=', True)
                    ])

            else:
                item.producer_ids = self.env['res.partner'].search([
                    '|',
                    ('supplier', '=', True),
                    ('always_to_print', '=', True)

                ])
            if item.producer_ids:
                item.producer_ids = item.producer_ids.filtered(
                    lambda a: a.company_type == 'company' or a.always_to_print
                )

    @api.multi
    def _search_available_total_serial(self, operator, value):
        stock_production_lot_ids = self.env['stock.production.lot.serial'].search([
            ('consumed', '=', False),
            ('reserved_to_stock_picking_id', '=', False)
        ]).mapped('stock_production_lot_id')

        if operator == '>':
            stock_production_lot_ids = stock_production_lot_ids.filtered(
                lambda a: sum(a.stock_production_lot_serial_ids.mapped('display_weight')) > value
            )
        elif operator == '=':
            stock_production_lot_ids = stock_production_lot_ids.filtered(
                lambda a: sum(a.stock_production_lot_serial_ids.mapped('display_weight')) == value
            )
        elif operator == '<':
            stock_production_lot_ids = stock_production_lot_ids.filtered(
                lambda a: sum(a.stock_production_lot_serial_ids.mapped('display_weight')) < value
            )
        elif operator == '>=':
            stock_production_lot_ids = stock_production_lot_ids.filtered(
                lambda a: sum(a.stock_production_lot_serial_ids.mapped('display_weight')) >= value
            )
        elif operator == '<=':
            stock_production_lot_ids = stock_production_lot_ids.filtered(
                lambda a: sum(a.stock_production_lot_serial_ids.mapped('display_weight')) <= value
            )

        return [('id', 'in', stock_production_lot_ids.mapped('id'))]

    @api.multi
    def _compute_reception_data(self):
        for item in self:
            if item.stock_picking_id:
                item.product_canning = item.stock_picking_id.get_canning_move().name

    @api.multi
    def _compute_total_serial(self):
        for item in self:
            item.total_serial = sum(item.stock_production_lot_serial_ids.mapped('display_weight'))

    @api.multi
    def add_to_packing_list(self):
        picking_id = int(self.env.context['stock_picking_id'])
        self.pallet_ids.filtered(lambda a: not a.reserved_to_stock_picking_id).write({
            'add_picking': True
        })
        self.stock_production_lot_serial_ids.filtered(
            lambda a: not a.reserved_to_stock_picking_id and not a.consumed).write({
            'to_add': True
        })
        picking = self.env['stock.picking'].search([('id', '=', picking_id)])
        dispatch_line = picking.dispatch_line_ids.filtered(lambda x: x.product_id.id == self.product_id.id)
        if len(dispatch_line) > 1:
            view = self.env.ref('dimabe_manufacturing.view_confirm_order_reserved')
            wiz = self.env['confirm.order.reserved'].create({
                'sale_ids': [(4, s.id) for s in dispatch_line.mapped('sale_id')],
                'picking_principal_id': picking.id,
                'custom_dispatch_line_ids': [(4, c.id) for c in dispatch_line],
                'lot_id': self.id
            })
            return {
                'name': 'Seleccione el pedido al cual quiere reservar',
                'type': 'ir.actions.act_window',
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': 'confirm.order.reserved',
                'views': [(view.id, 'form')],
                'view_id': view.id,
                'target': 'new',
                'res_id': wiz.id,
                'context': self.env.context
            }
        else:
            self.add_selection(stock_picking_id=picking_id)
        self.clean_add_pallet()
        self.clean_add_serial()

    @api.multi
    def unreserved(self):
        for item in self:
            stock_picking = None
            if 'stock_picking_id' in self.env.context:
                stock_picking_id = self.env.context['stock_picking_id']
                stock_picking = self.env['stock.picking'].search([('id', '=', stock_picking_id)])
            if stock_picking:
                self.update_stock_quant(stock_picking.location_id.id)
                self.pallet_ids.filtered(lambda a: a.reserved_to_stock_picking_id.id == stock_picking_id).write({
                    'reserved_to_stock_picking_id': None
                })
                self.stock_production_lot_serial_ids.filtered(
                    lambda a: a.reserved_to_stock_picking_id.id == stock_picking_id).write({
                    'reserved_to_stock_picking_id': None
                })
                stock_picking.move_line_ids_without_package.filtered(lambda a: a.lot_id.id == self.id).unlink()

    @api.multi
    def write(self, values):
        for item in self:
            final_lot_id = self.env['mrp.workorder'].search([('final_lot_id', '=', item.id)])
            if final_lot_id:
                values['sale_order_id'] = final_lot_id.sale_order_id.id
            res = super(StockProductionLot, self).write(values)
            if 'available_kg' in values.keys():
                if self.stock_production_lot_serial_ids.filtered(lambda x: not x.consumed):
                    self.get_and_update(self.product_id.id)
                else:
                    self.env['stock.quant'].sudo().search(
                        [('lot_id', '=', self.id), ('location_id.usage', '=', 'internal')]).unlink()
            # if not item.producer_id and item.stock_production_lot_serial_ids:
            #     if item.stock_production_lot_serial_ids.mapped('producer_id'):
            #         item.write({
            #             'producer_id': item.stock_production_lot_serial_ids.mapped('producer_id')[0].id,
            #         })
            if not item.product_id.is_standard_weight:
                for serial in item.stock_production_lot_serial_ids:
                    if not serial.serial_number:
                        if len(item.stock_production_lot_serial_ids) > 1:
                            item.stock_production_lot_serial_ids[0].write({
                                'serial_number': item.name + '001'
                            })
                            counter = int(item.stock_production_lot_serial_ids.filtered(lambda a: a.serial_number)[
                                              -1].serial_number) + 1
                        else:
                            counter = 1
                        tmp = '00{}'.format(counter)
                        serial.serial_number = item.name + tmp[-3:]
                        item.write({
                            'available_kg': sum(
                                item.stock_production_lot_serial_ids.filtered(lambda a: not a.consumed).mapped(
                                    'real_weight'))
                        })
            # else:
            #     if len(item.stock_production_lot_serial_ids) > 999:
            #         item.check_duplicate()
            return res

    def get_stock_quant(self, location_id=None):
        if location_id:
            quant_ids = self.quant_ids.filtered(lambda x: x.location_id.id == location_id)
        else:
            quant_ids = self.quant_ids.filtered(lambda x: x.location_id.usage == 'internal')
        return quant_ids
        # if self.location_id:
        #     stock_quant = self.quant_ids.filtered(
        #         lambda a: a.location_id.id == location_id)
        #     return None if not stock_quant else stock_quant
        # else:
        #     return self.quant_ids.filtered(
        #         lambda a: a.location_id.usage == 'internal'
        #     )

    @api.multi
    def delete_all_serial(self):
        for item in self:
            for serial in item.serial_without_pallet_ids:
                serial.unlink()

    def show_available_serial(self):
        return {
            'type': 'ir.actions.act_window',
            'res_model': 'stock.production.lot',
            'res_id': self.id,
            'view_type': 'form',
            'view_mode': 'form',
            'views': [(self.env.ref('dimabe_manufacturing.available_lot_form_view').id, 'form')],
            'target': 'new',
            'nodestroy': True,
            'context': self.env.context
        }

    @api.multi
    def add_selection(self, stock_picking_id=None):
        if 'dispatch_id' in self.env.context.keys():
            picking_id = int(self.env.context['dispatch_id'])
        else:
            picking_id = stock_picking_id
        if not self.stock_production_lot_serial_ids.filtered(lambda a: a.to_add) and not self.pallet_ids.filtered(
                lambda a: a.add_picking):
            raise models.ValidationError('No se seleccionado nada')
        if isinstance(picking_id, dict):
            picking = self.env['stock.picking'].search([('id', '=', picking_id['dispatch_id'])])
        else:
            picking = self.env['stock.picking'].search([('id', '=', picking_id)])
        if self.pallet_ids.filtered(lambda a: a.add_picking):
            self.add_selection_pallet(picking.id, picking.location_id.id)
        if self.stock_production_lot_serial_ids.filtered(lambda a: a.to_add):
            self.add_selection_serial(picking.id, picking.location_id.id)
        dispatch_line = picking.dispatch_line_ids.filtered(lambda x: x.product_id.id == self.product_id.id)
        if len(dispatch_line) > 1:
            view = self.env.ref('dimabe_manufacturing.view_confirm_order_reserved')
            wiz = self.env['confirm.order.reserved'].create({
                'sale_ids': [(4, s.id) for s in dispatch_line.mapped('sale_id')],
                'picking_principal_id': picking.id,
                'custom_dispatch_line_ids': [(4, c.id) for c in dispatch_line],
                'lot_id': self.id
            })
            return {
                'name': 'Seleccione el pedido al cual quiere reservar',
                'type': 'ir.actions.act_window',
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': 'confirm.order.reserved',
                'views': [(view.id, 'form')],
                'view_id': view.id,
                'target': 'new',
                'res_id': wiz.id,
                'context': self.env.context
            }
        line = picking.move_line_ids_without_package.filtered(
            lambda a: a.lot_id.id == self.id and a.product_id.id == self.product_id.id)

        if line:
            test = self.get_reserved_quantity_by_picking(picking.id)
            line.sudo().write({
                'product_uom_qty': self.get_reserved_quantity_by_picking(picking.id)
            })
        else:
            line_create = self.env['stock.move.line'].create({
                'move_id': picking.move_ids_without_package.filtered(
                    lambda m: m.product_id.id == self.product_id.id).id,
                'picking_id': picking.id,
                'product_id': self.product_id.id,
                'product_uom_id': self.product_id.uom_id.id,
                'product_uom_qty': self.get_reserved_quantity_by_picking(picking.id),
                'location_id': picking.location_id.id,
                'location_dest_id': picking.partner_id.property_stock_customer.id,
                'date': date.today(),
                'lot_id': self.id
            })
        self.clean_add_pallet()
        self.clean_add_serial()
        picking.clean_reserved()
        if len(dispatch_line) == 1:
            dispatch_line.write({
                'real_dispatch_qty': self.get_reserved_quantity_by_picking(picking.id),
                'move_line_ids': [(4, line_create.id)] if not line else [(4, line.id)]
            })
        picking.write({
            'lot_search_id': None
        })
        self.write({
            'correlative_serial': None
        })

    def add_selection_serial(self, picking_id, location_id):
        pallets = self.stock_production_lot_serial_ids.filtered(
            lambda
                a: a.to_add and not a.reserved_to_stock_picking_id and not a.reserved_to_production_id and not a.consumed).mapped(
            'pallet_id')
        for pallet in pallets:
            pallet.write({
                'reserved_to_stock_picking_id': picking_id
            })
        self.stock_production_lot_serial_ids.filtered(
            lambda a: a.to_add and not a.reserved_to_stock_picking_id and not a.consumed).write({
            'reserved_to_stock_picking_id': picking_id
        })
        self.update_stock_quant(location_id)
        self.clean_add_serial()

    def add_selection_pallet(self, picking_id, location_id):
        self.pallet_ids.filtered(lambda p: p.add_picking).write({
            'reserved_to_stock_picking_id': picking_id
        })
        self.pallet_ids.filtered(lambda p: p.add_picking).mapped('lot_serial_ids').filtered(
            lambda s: not s.reserved_to_stock_picking_id and not s.consumed).write({
            'reserved_to_stock_picking_id': picking_id
        })
        self.update_stock_quant(location_id)

    def get_available_quantity(self):
        return sum(self.stock_production_lot_serial_ids.filtered(
            lambda r: r.reserved_to_stock_picking_id and not r.consumed).mapped('display_weight'))

    def get_reserved_quantity(self):
        return sum(self.stock_production_lot_serial_ids.filtered(lambda
                                                                     x: x.reserved_to_stock_picking_id and x.reserved_to_stock_picking_id.state != 'done' and not x.consumed).mapped(
            'display_weight'))

    def get_reserved_quantity_by_picking(self, picking_id):
        return round(sum(self.stock_production_lot_serial_ids.filtered(
            lambda a: a.reserved_to_stock_picking_id.id == picking_id).mapped(
            'display_weight')))

    def clean_add_pallet(self):
        self.pallet_ids.filtered(lambda a: a.add_picking).write({
            'add_picking': False
        })

    def clean_add_serial(self):
        self.stock_production_lot_serial_ids.filtered(lambda a: a.to_add).write({
            'to_add': False
        })

    def update_stock_quant(self, location_id):
        lot = self.env['stock.production.lot'].search([('name', '=', self.name)])
        if lot.stock_production_lot_serial_ids.filtered(lambda a: not a.consumed):

            quant = self.env['stock.quant'].sudo().search(
                [('lot_id', '=', lot.id), ('location_id.usage', '=', 'internal'), ('location_id', '=', location_id)])

            if quant:
                quant.write({
                    'reserved_quantity': sum(lot.stock_production_lot_serial_ids.filtered(lambda
                                                                                x: x.reserved_to_stock_picking_id and x.reserved_to_stock_picking_id.state != 'done' and not x.consumed).mapped(
                        'display_weight')),
                    'quantity': sum(lot.stock_production_lot_serial_ids.filtered(
                        lambda x: not x.reserved_to_stock_picking_id and not x.consumed).mapped('display_weight')),
                    'location_id': location_id
                })
            else:
                self.env['stock.quant'].sudo().create({
                    'lot_id': lot.id,
                    'product_id': lot.product_id.id,
                    'reserved_quantity': sum(lot.stock_production_lot_serial_ids.filtered(lambda
                                                                                x: x.reserved_to_stock_picking_id and x.reserved_to_stock_picking_id.state != 'done' and not x.consumed).mapped(
                        'display_weight')),
                    'quantity': sum(lot.stock_production_lot_serial_ids.filtered(
                        lambda x: not x.reserved_to_stock_picking_id and not x.consumed).mapped('display_weight')),
                    'location_id': location_id
                })
        else:
            quant = self.env['stock.quant'].sudo().search(
                [('lot_id', '=', lot.id), ('location_id.usage', '=', 'internal'),
                 ('location_id', '=', location_id)])
            quant.write({
                'reserved_quantity': 0,
                'quantity': 0,
                'location_id': location_id
            })

    def update_stock_quant_production(self, location_id):
        lot = self.env['stock.production.lot'].search([('name', '=', self.name)])
        if lot:
            if lot.stock_production_lot_serial_ids.filtered(lambda a: not a.consumed):

                quant = self.env['stock.quant'].sudo().search(
                    [('lot_id', '=', lot.id), ('location_id.usage', '=', 'internal'),
                     ('location_id', '=', location_id)])

                if quant:
                    quant.sudo().write({
                        'reserved_quantity': sum(
                            lot.stock_production_lot_serial_ids.filtered(lambda x: not x.consumed).mapped(
                                'display_weight')),
                        'quantity': sum(lot.stock_production_lot_serial_ids.filtered(
                            lambda x: not x.consumed).mapped('display_weight')),
                        'location_id': location_id
                    })
                else:
                    self.env['stock.quant'].sudo().create({
                        'lot_id': lot.id,
                        'product_id': lot.product_id.id,
                        'reserved_quantity': sum(
                            lot.stock_production_lot_serial_ids.filtered(lambda x: not x.consumed).mapped(
                                'display_weight')),
                        'quantity': sum(lot.stock_production_lot_serial_ids.filtered(lambda x: not x.consumed).mapped(
                            'display_weight')),
                        'location_id': location_id,
                        'in_date': datetime.now()
                    })
            else:
                quant = self.env['stock.quant'].sudo().search(
                    [('lot_id', '=', lot.id), ('location_id.usage', '=', 'internal'),
                     ('location_id', '=', location_id)])
                quant.write({
                    'reserved_quantity': 0,
                    'quantity': sum(lot.stock_production_lot_serial_ids.filtered(lambda x: not x.consumed).mapped(
                        'display_weight'))
                })

    def update_kg(self, lot_id):
        lot = self.env['stock.production.lot'].search([('id', '=', lot_id)])
        total = sum(lot.stock_production_lot_serial_ids.filtered(lambda a: not a.consumed).mapped('display_weight'))
        lot.sudo().write({
            'available_kg': total,
            'available_weight': total
        })

    def verify_without_lot(self):
        for item in self:
            quant = self.env['stock.quant'].sudo().search(
                [('product_id.id', '=', item.product_id.id), ('lot_id', '=', None)])
            quant.sudo().unlink()

    def change_date_packing(self):
        for item in self:
            item.change_packaging = True

    def change_date_best(self):
        for item in self:
            item.change_best = True

    def get_and_update(self, product_id, to_fix=False):
        lots = self.env['stock.production.lot'].search([('product_id', '=', product_id), ('available_kg', '>', 0)])
        for lot in lots:
            quant = self.env['stock.quant'].search([('lot_id', '=', lot.id), ('location_id.usage', '=', 'internal')])
            if quant:
                try:
                    if quant.quantity != lot.available_kg or quant.quantity != sum(
                            lot.stock_production_lot_serial_ids.mapped('display_weight')):
                        quant.write({
                            'reserved_quantity': lot.available_kg,
                            'quantity': lot.available_kg
                        })
                except:
                    query = 'DELETE FROM stock_quant where id = {}'.format(quant[0].id)
                    cr = self._cr
                    cr.execute(query)
            else:
                self.env['stock.quant'].sudo().create({
                    'lot_id': lot.id,
                    'product_id': lot.product_id.id,
                    'reserved_quantity': sum(
                        lot.stock_production_lot_serial_ids.filtered(lambda x: not x.consumed).mapped(
                            'display_weight')),
                    'quantity': sum(lot.stock_production_lot_serial_ids.filtered(lambda x: not x.consumed).mapped(
                        'display_weight')),
                    'location_id': lot.stock_production_lot_serial_ids.mapped('production_id')[
                        0].location_dest_id.id if lot.stock_production_lot_serial_ids.mapped('production_id') else 12,
                    'in_date': datetime.now()
                })
        quant = self.env['stock.quant'].search(
            [('quantity', '<', 0), ('product_id', '=', product_id), ('location_id.usage', '=', 'internal')])
        quant.sudo().unlink()

    def check_all_existence(self):
        lots = self.env['stock.production.lot'].search([('available_kg', '!=', 0), ('harvest', '=', 2021)])
        for lot in lots:
            quant = self.env['stock.quant'].search([('lot_id.id', '=', lot.id), ('location_id.usage', '=', 'internal')])
            if quant:
                if len(quant) == 1:
                    if quant.quantity != sum(
                            lot.stock_production_lot_serial_ids.filtered(lambda a: not a.consumed).mapped(
                                'display_weight')) or quant.quantity < 0:
                        if quant.location_id.usage == 'internal':
                            lot.update_stock_quant_production(quant.location_id.id)
                else:
                    for qu in quant:
                        if qu.quantity != sum(
                                lot.stock_production_lot_serial_ids.filtered(lambda a: not a.consumed).mapped(
                                    'display_weight')) or qu.quantity < 0:
                            if qu.location_id.usage == 'internal':
                                lot.update_stock_quant_production(qu.location_id.id)
            else:
                location_id = lot.location_id.id
                if location_id:
                    lot.update_stock_quant_production(location_id)

    def check_duplicate_quant(self, product_id=None, lot_id=None):
        if lot_id:
            lots = self.env['stock.production.lot'].search(['id', '=', lot_id])
        elif product_id:
            lots = self.env['stock.production.lot'].search(
                [('available_kg', '=', 0), ('harvest', '=', 2021), ('product_id', '=', product_id)])
        else:
            lots = self.env['stock.production.lot'].search([('available_kg', '=', 0), ('harvest', '=', 2021)])
        for lot in lots:
            quant = self.env['stock.quant'].search([('location_id.usage', '=', 'internal'), ('lot_id', '=', lot.id)])
            if len(quant) > 1:
                quant[1:].sudo().unlink()
            if lot.stock_production_lot_serial_ids.filtered(lambda x: not x.consumed):
                total_not_consumed = sum(
                    lot.stock_production_lot_serial_ids.filtered(lambda x: not x.consumed).mapped('display_weight'))
            else:
                total_not_consumed = 0
            if total_not_consumed == 0:
                quant.sudo().unlink()
            quant.sudo().write({
                'quantity': sum(
                    lot.stock_production_lot_serial_ids.filtered(lambda x: not x.consumed).mapped('display_weight'))
            })

    def check_no_stock_quant(self, product_id=None, lot_id=None):
        if lot_id:
            lots = self.env['stock.production.lot'].search(['id', '=', lot_id])
        elif product_id:
            lots = self.env['stock.production.lot'].search(
                [('available_kg', '=', 0), ('harvest', '=', 2021), ('product_id', '=', product_id)])
        else:
            lots = self.env['stock.production.lot'].search([('available_kg', '=', 0), ('harvest', '=', 2021)])
        for lot in lots:
            quant = self.env['stock.quant'].search([('lot_id.id', '=', lot.id), ('location_id.usage', '=', 'internal')])
            if quant:
                quant.sudo().unlink()

    @api.multi
    def select_serial(self):
        for item in self:
            view = self.env.ref('dimabe_manufacturing.available_lot_form_view_serial_selected')
            if item.correlative_serial or item.correlative_serial != '':
                serials = []
                if ',' in item.correlative_serial:
                    serials = item.correlative_serial.split(',')
                if '-' in item.correlative_serial:
                    list_serial = [int(serial) for serial in item.correlative_serial.split('-')]
                    for serial in list(range(min(list_serial), max(list_serial) + 1)):
                        zeros = '00' if serial <= 9 else '' if serial > 999 else '0'
                        serials.append(f'{zeros}{serial}')
                else:
                    serials.append(item.correlative_serial)
                for serial in serials:
                    serial_number = f'{item.name}{serial}'
                    serial_id = self.env['stock.production.lot.serial'].sudo().search(
                        [('serial_number', '=', serial_number)])
                    if not serial_id:
                        raise models.ValidationError(f'El correlativo {serial} no esta presente en el lote')
                    if serial_id.consumed:
                        raise models.ValidationError(
                            f'El correlativo {serial} ya fue utilizada en el despacho {serial_id.reserved_to_stock_picking_id.name}')
                    if serial_id.reserved_to_stock_picking_id:
                        raise models.ValidationError(
                            f'El correlativo {serial} ya se encuentra reservado en el despacho {serial_id.reserved_to_stock_picking_id.name}'
                        )
                    if serial_id.to_add:
                        raise models.ValidationError(f'El correlativo {serial} ya fue seleccionado')
                    serial_id.write({
                        'to_add': True
                    })
                item.write({
                    'correlative_serial': None,
                })
                return {
                    'type': 'ir.actions.act_window',
                    'view_mode': 'form',
                    'res_model': self._inherit,
                    'target': 'new',
                    'views': [(view.id, 'form')],
                    'res_id': self.id
                }


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

import os
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QListWidget

class ListSavedStates(QListWidget):

    def __init__(self):
        super().__init__()
        self.setFixedWidth(300)
        self.setFont(QFont("Times", 14))

    def loadSavedStates(self, dir, system, equation):
        self.addItem("0")
        for f in os.listdir("%s/%s/%s/saved_states" % (dir, system, equation)):
            if("__pycache__" not in f and "_params.dat" not in f):
                if(f[-4:] == ".dat"):
                    self.addItem(f[:-4])
                else:
                    self.addItem(f)
        self.sortItems()

    def unloadSavedStates(self):
        for i in range(self.count()):
            self.takeItem(0)


#
# @lc app=leetcode.cn id=590 lang=python3
#
# [590] N叉树的后序遍历
#

# @lc code=start
"""
# Definition for a Node.
class Node:
    def __init__(self, val, children):
        self.val = val
        self.children = children
"""
class Solution:
    def postorder(self, root: 'Node') -> List[int]:
        if not root:
            return []
        st = [root]
        ret = []
        while st:
            if st[-1].children and (not ret or (ret and ret[-1] != st[-1].children[-1])):
                st.extend(st[-1].children[::-1])
            else:
                p = st.pop()
                ret.append(p)
        return [i.val for i in ret]

# @lc code=end


"""
projekt_1.py: první projekt do Engeto Online Python Akademie
author: Veronika Fellnerova
email: veronika.fellnerova@seznam.cz
discord: Verca F.#5057
"""

import requests
from bs4 import BeautifulSoup
import re
import sys
import csv

def take_numbers(input_string):
    if re.search(r"[^0-9]", input_string):
        clean_string = re.sub(r"[^0-9]", "", input_string)
        return clean_string
    else:
        return input_string

def validate_user_inputs(user_arguments: list[str]):
    # user has to send 2 args
    if len(user_arguments) != 2:
        raise ValueError("incorrect arguments")
    # url validation
    try:
        response = requests.get(user_arguments[0])
        soup = BeautifulSoup(response.text, features="html.parser")
        title = soup.h1.get_text().strip()
    except:
        raise ValueError("url argument cannot be used")
    if (
        title
        != "Volby do Poslanecké sněmovny Parlamentu České republiky konané ve dnech 20.10. – 21.10.2017 (promítnuto usnesení NSS)"
    ):
        raise ValueError("wrong url sent")
    # file name validation
    ext = (user_arguments[1].split("."))[1]
    if ext != "csv":
        raise ValueError("file must be csv")

validate_user_inputs(sys.argv[1:])

user_input_url = sys.argv[1]
user_input_filename = sys.argv[2]

response = requests.get(user_input_url)

soup = BeautifulSoup(response.text, features="html.parser")

nazev_obce_class_selector = "overflow_name"
url_obce_class_selector = "center"
kod_obce_class_selector = "cislo"

obce_url_list = []
url_http = "https://volby.cz/pls/ps2017nss/"

for tr in soup.select("table tr"):
    obce_url_item = {}

    kod_obce_element = tr.find(class_=kod_obce_class_selector)
    if kod_obce_element is not None:
        obce_url_item["kod"] = kod_obce_element.get_text()

    obec_element = tr.find(class_=nazev_obce_class_selector)
    if obec_element is not None:
        obce_url_item["nazev"] = obec_element.get_text()

    url_element = tr.find(class_=url_obce_class_selector)
    if url_element is not None:
        url_tag = url_element.find("a")
        if url_tag is not None:
            obce_url_item["url"] = url_http + url_tag.get("href")

    obce_url_list.append(obce_url_item)

obce_url_list = list(filter(None, obce_url_list))

list_vysledky_obce = []

for obec_element in obce_url_list:
    response = requests.get(obec_element["url"])

    volici_v_seznamu_obec_1_okresk_selector = "#ps311_t1 td:nth-child(4)"

    soup = BeautifulSoup(response.text, features="html.parser")

    okrsek_odkazy = []

    if soup.find(attrs={"id": "s1"}):
        # vice okrsku
        for okrsek in soup.find_all(class_="cislo"):
            okrsek_element = okrsek.find("a")
            okrsek_odkazy.append(url_http + okrsek_element.get("href"))
        output_dict = {
            "code": obec_element["kod"],
            "location": obec_element["nazev"],
            "registered": 0,
            "envelopes": 0,
            "valid": 0,
        }
        for okrsek_odkaz in okrsek_odkazy:
            okrsek_response = requests.get(okrsek_odkaz)
            okrsek_soup = BeautifulSoup(okrsek_response.text, features="html.parser")
            registered = int(
                take_numbers(
                    okrsek_soup.select_one("table tr:nth-child(2) td:nth-child(1)").text
                )
            )
            envelopes = int(
                take_numbers(
                    okrsek_soup.select_one("table tr:nth-child(2) td:nth-child(2)").text
                )
            )
            valid = int(
                take_numbers(
                    okrsek_soup.select_one("table tr:nth-child(2) td:nth-child(5)").text
                )
            )
            output_dict["registered"] = output_dict["registered"] + registered
            output_dict["envelopes"] = output_dict["envelopes"] + envelopes
            output_dict["valid"] = output_dict["valid"] + valid

            for row in okrsek_soup.select(".t2_470 table tr"):
                y = row.select_one(".t2_470 table tr td:nth-child(2)")
                nazev_strany = ""
                if y is not None:
                    if y.text != "-":
                        nazev_strany = y.text
                celkem = row.select_one(".t2_470 table tr td:nth-child(3)")
                celkem_hlasu = 0
                if celkem is not None:
                    if celkem.text != "-":
                        celkem_hlasu = take_numbers(celkem.text)
                        celkem_hlasu = take_numbers(celkem.text)
                        celkem_hlasu = take_numbers(celkem.text)

                if nazev_strany not in output_dict:
                    output_dict[nazev_strany] = celkem_hlasu
                else:
                    output_dict[nazev_strany] = int(output_dict[nazev_strany]) + int(
                        celkem_hlasu
                    )

        output_dict = {
            key: value for key, value in output_dict.items() if key != ""
        }  # delete empty items in dict

        list_vysledky_obce.append(output_dict)

    else:
        # 1 okrsek
        output_dict = {
            "code": obec_element["kod"],
            "location": obec_element["nazev"],
            "registered": take_numbers(
                soup.select_one("#ps311_t1 td:nth-child(4)").text
            ),
            "envelopes": take_numbers(
                soup.select_one("#ps311_t1 td:nth-child(5)").text
            ),
            "valid": take_numbers(soup.select_one("#ps311_t1 td:nth-child(8)").text),
        }

        for row in soup.select(".t2_470 table tr"):
            y = row.select_one(".t2_470 table tr td:nth-child(2)")
            nazev_strany = ""
            if y is not None:
                if y.text != "-":
                    nazev_strany = y.text
            celkem = row.select_one(".t2_470 table tr td:nth-child(3)")
            celkem_hlasu = 0
            if celkem is not None:
                if celkem.text != "-":
                    celkem_hlasu = take_numbers(celkem.text)
            output_dict[nazev_strany] = celkem_hlasu

        output_dict = {
            key: value for key, value in output_dict.items() if key != ""
        }  # delete empty items in dict
        list_vysledky_obce.append(output_dict)

# Write to csv
csv_headers = list_vysledky_obce[0].keys()

with open(user_input_filename, mode="w", encoding="utf-8", newline="") as file:
    writer = csv.DictWriter(file, fieldnames=csv_headers)
    writer.writeheader()

    for vysledek_obce in list_vysledky_obce:
        row_data = {csv_header: vysledek_obce[csv_header] for csv_header in csv_headers}
        writer.writerow(row_data)


#!/usr/bin/python3

def add_tuple(tuple_a=(), tuple_b=()):
    la = len(tuple_a)
    lb = len(tuple_b)
    idx = 0
    res = [0, 0]
    while idx < 2:
        if idx < la:
            res[idx] += tuple_a[idx]
        if idx < lb:
            res[idx] += tuple_b[idx]
        idx += 1

    return tuple(res)


import numpy as np
from ipywidgets import widgets
import ase
import ase.io
import ase.neighborlist
from itertools import permutations
from tqdm.notebook import tqdm, trange
import nglview
from IPython.display import display, FileLink
from zipfile import ZipFile
import os
import glob

import warnings
warnings.simplefilter('ignore')

# Class to define and operate on environments
class Environments:
    def __init__(self):
        self.myindex = -1
        self.indeces = np.array([],dtype=int)
        self.delta = np.array([])
        self.distance =  np.array([])
        # degeneracy defaults to 1 and is different from 1 for unique environments
        self.degeneracy = 1

# Class to find environments
class EnvironmentFinder:

    def __init__(self):
        # self.fractionalFlag is True if the coordinates are fractional
        self.fractionalFlag=False
        # uniqueFlags is True if unique environments are to be calculated
        self.uniqueFlag=True
        # self.verboseFlag is True if verbose mode is on
        self.verboseFlag=True
        # self.allEnvs stores all calculated environments
        self.allEnvs=np.ndarray((0,),dtype=object)
        # self.uniqueEnvs stores the unique environments
        self.uniqueEnvs = np.ndarray((0,),dtype=object)
        # self.tolerance is the tolerance to determine if two elements of the
        # distance vectors are the same
        self.tolerance=0
        # self.atom_types contains the unique atom types
        self.atom_types = np.empty(1)
        # Max number of neighbors in environment
        self.max_neighbors=1
        self.max_neighbors_flag=False
        #env=Environments()
        #env.delta.shape = (0,3)
        #uniqueEnvs = np.append(uniqueEnvs,env)
        # self.box_layout contains options to display a box
        self.box_layout = widgets.Layout(display='flex',
                    flex_flow='column',
                    align_items='stretch',
                    border='solid',
                    width='90%')

    def plotConf(self):
        """ Plot configuration using nglview """

        v = nglview.show_ase(self.conf)
        v.add_representation("unitcell")
        boxy=widgets.Box([v],layout=self.box_layout)
        display(boxy)

    def chooseConfiguration(self,filename):
        """ Choose configuration by filename

        Args:
            filename (string): the file name

        Returns:
            no value
        """

        self.conf = ase.io.read(filename)
        self.atom_types = np.unique(self.conf.get_chemical_symbols())
        self.atom_types = np.append(self.atom_types,"Any")

    def chooseAndPlotConfiguration(self,filename):
        """ Choose and plot configuration by filename

        Args:
            filename (string): the file name

        Returns:
            no value
        """

        self.chooseConfiguration(filename)
        self.plotConf()

    def setMaximumNumberOfNeighbors(self,max_neighbors):
        self.max_neighbors_flag = True
        self.max_neighbors = max_neighbors

    def calculateEnvironments(self,lista,listb,cutoff):
        """ Find environments

        This function calculates all environments centered at the atom in
        lista using atoms in listb as neighbors if they are within the cutoff.

        Args:
            lista (numpy vector): list of central atoms
            listb (numpy vector): list of neighboring atoms
            cutoff (float): cut off for the calculation of neighbors

        Returns:
            no value
        """

        self.allEnvs = np.ndarray((0,),dtype=object)
        # Find all environments
        # Loop over input particles of type atom_type_1:
        myindeces=lista
        nl = ase.neighborlist.NeighborList((cutoff/2.0)*np.ones(self.conf.get_number_of_atoms()),skin=0.1,bothways=True)
        nl.update(self.conf)
        mat = self.conf.get_cell()
        for index in myindeces:
            neighbors, offsets = nl.get_neighbors(index)
            # Iterate over the neighbors of the current particle:
            Environment = Environments()
            Environment.myindex = index
            Environment.delta.shape = (0,3)
            for neigh, offset in zip(neighbors, offsets):
                if (neigh in listb): # Only if neighbor is in listb
                    delta = self.conf.positions[neigh] + np.dot(offset, mat) - self.conf.positions[index]
                    distance=np.linalg.norm(delta)
                    if (distance>1.e-10):
                        if (not self.fractionalFlag):
                            Environment.delta = np.append(Environment.delta,np.array([[delta[0], delta[1], delta[2]]])*0.1,axis=0)
                        else:
                            Environment.delta = np.append(Environment.delta,np.array([[delta[0]/mat[0][0], delta[1]/mat[1][1], delta[2]/mat[2][2]]]),axis=0)
                        Environment.distance = np.append(Environment.distance,distance)
                        Environment.indeces = np.append(Environment.indeces,neigh)
            # Use maximum number of neighbors
            if (self.max_neighbors_flag==True):
                 # Sort
                 sortindeces=np.argsort(Environment.distance,kind='stable')
                 Environment.delta =    Environment.delta[sortindeces,:]
                 Environment.distance = Environment.distance[sortindeces]
                 Environment.indeces =  Environment.indeces[sortindeces]
                 # Choose first max_neighbors
                 Environment.delta =    Environment.delta[:self.max_neighbors,:]
                 Environment.distance = Environment.distance[:self.max_neighbors]
                 Environment.indeces =  Environment.indeces[:self.max_neighbors]
            self.allEnvs = np.append(self.allEnvs,Environment)

    def CalculateUniqueEnvironments(self):
        """ Calculate unique Environments

        This algorithm calculates unique environments by comparing all possible
        permutations of the environments. However, it discards entire sets of
        permutations if it is found that there is no possibility of match.

        The number of operations scales roughly as as N^2*(\sum_{i=1}^M M+1-i)
        where N is the total number of environments and M is the number of i
        atoms in the environments.

        Args:
            none

        Returns:
            no value
        """

        num_of_templates=self.allEnvs.shape[0]
        flag_unique=np.ones(num_of_templates)
        same_as=np.linspace(0,num_of_templates-1,num_of_templates)
        # Disregard empty environments
        for i in range(num_of_templates):
            if (self.allEnvs[i].indeces.shape[0]==0):
                flag_unique[i]=0
        for i in trange(num_of_templates,desc="Progress", leave=False):
            if ( self.allEnvs[i].indeces.shape[0]>0 and flag_unique[i]==1):
                for j in range(i+1,num_of_templates):
                    # Not empty,  unique, and same number of neighbors
                    if ( self.allEnvs[j].indeces.shape[0]>0 and flag_unique[j]==1 and self.allEnvs[i].indeces.shape[0]==self.allEnvs[j].indeces.shape[0]):
                        atom_match = np.zeros(self.allEnvs[j].indeces.shape[0])
                        for k1 in range(self.allEnvs[i].indeces.shape[0]):
                            for k2 in range(self.allEnvs[j].indeces.shape[0]):
                                if (np.count_nonzero(np.isclose(self.allEnvs[i].delta[k1,:],self.allEnvs[j].delta[k2,:],atol=self.tolerance))==3 ):
                                    #print(i,j,self.allEnvs[i].delta[k1,:],self.allEnvs[j].delta[k2,:],np.isclose(self.allEnvs[i].delta[k1,:],self.allEnvs[j].delta[k2,:],atol=self.tolerance))
                                    atom_match[k1] = 1
                                    break
                            # If no match was found for a given atom the whole self.allEnvs[j] must be discarded
                            if (atom_match[k1]==0):
                                break
                        # If a match was found for every atom in self.allEnvs[i]
                        #print(i,j,atom_match)
                        if np.all(atom_match==np.ones(atom_match.shape[0])):
                            flag_unique[j]=0
                            same_as[j] = i
                            #break
        self.uniqueEnvs = np.ndarray((0,),dtype=object)
        for i in range(num_of_templates):
            if (flag_unique[i]==1):
                self.uniqueEnvs = np.append(self.uniqueEnvs,self.allEnvs[i])
                self.uniqueEnvs[-1].degeneracy = np.sum(np.ones(num_of_templates)[same_as==i])

    def printEnvironmentSummaryInfo(self,Environments):
        if (self.verboseFlag):
            num_of_templates=Environments.shape[0]
            if (num_of_templates>0):
                avg_num_neighbors = 0.0
                for i in range(num_of_templates):
                    avg_num_neighbors += Environments[i].indeces.shape[0]
                avg_num_neighbors /= num_of_templates
            else:
                avg_num_neighbors = 0
            print("Found " + str(num_of_templates) + " environments each with " + str(int(avg_num_neighbors))  + " neighbors on average")
            if (num_of_templates>0):
                for i in range(num_of_templates):
                    print("Environment " + str(int(i+1)) + ": degeneracy = " + str(int(Environments[i].degeneracy)) + " - number of neighbors = ", str(int(Environments[i].indeces.shape[0])) )

    def printEnvironments(self,Environments):
        num_of_templates=Environments.shape[0]
        for i in range(num_of_templates):
            env_atom_types = np.asarray(self.conf.get_chemical_symbols())[Environments[i].indeces.astype(int)]
            env_positions = Environments[i].delta*10
            env = ase.Atoms(env_atom_types,env_positions)
            ase.io.write('-', env, format='proteindatabank')

    def printEnvironmentsToFile(self,Environments):
        num_of_templates=Environments.shape[0]
        for i in range(num_of_templates):
            env_atom_types = np.asarray(self.conf.get_chemical_symbols())[Environments[i].indeces.astype(int)]
            env_positions = Environments[i].delta*10
            env = ase.Atoms(env_atom_types,env_positions)
            fileName="env" + str(i+1) + ".pdb"
            ase.io.write(fileName, env, format='proteindatabank')

    def printEnvironmentsToZipFile(self,Environments):
        num_of_templates=Environments.shape[0]
        download_directory="Download"
        if not os.path.exists(download_directory):
            os.mkdir(download_directory)
        zipObj = ZipFile(download_directory + '/download.zip', 'w')
        for i in range(num_of_templates):
            env_atom_types = np.asarray(self.conf.get_chemical_symbols())[Environments[i].indeces.astype(int)]
            env_positions = Environments[i].delta*10
            env = ase.Atoms(env_atom_types,env_positions)
            fileName=download_directory + "/env" + str(i+1) + ".pdb"
            ase.io.write(fileName, env, format='proteindatabank')
            zipObj.write(fileName)
        zipObj.close()
        local_file = FileLink(download_directory + '/download.zip', result_html_prefix="Click here to download the environments in PDB format: ")
        display(local_file)
        fileList = glob.glob(download_directory + '/env*')
        for filePath in fileList:
            os.remove(filePath)

    def plotEnv(self,myEnvironment):
        env_atom_types = np.asarray(self.conf.get_chemical_symbols())[myEnvironment.indeces.astype(int)] #,np.array('C')] #Template[env_number].myindex)]
        env_atom_types = np.append(env_atom_types,np.asarray(self.conf.get_chemical_symbols())[myEnvironment.myindex])
        env_positions = np.vstack((myEnvironment.delta*10,np.array([0,0,0]) ) )
        env = ase.Atoms(env_atom_types,env_positions)
        v = nglview.show_ase(env)
        boxy=widgets.Box([v],layout=self.box_layout)
        display(boxy)

    def chooseEnvPlotAll(self,number):
        if (self.allEnvs.shape[0]>0 and ((number-1)<self.allEnvs.shape[0])):
            self.plotEnv(self.allEnvs[number-1])
        else:
            print("Error")

    def chooseEnvPlotUnique(self,number):
        if (self.uniqueEnvs.shape[0]>0):
            self.plotEnv(self.uniqueEnvs[number-1])
            if (self.verboseFlag):
                print("Degeneracy of the environment is " + str(int(self.uniqueEnvs[number-1].degeneracy)) )
                print("Number of neighbors in the environment is " + str(int(self.uniqueEnvs[number-1].indeces.shape[0])) )

    def chooseEnvPlot(self,number):
        if (self.uniqueFlag and self.uniqueEnvs.shape[0]>0):
            self.chooseEnvPlotUnique(number)
        elif (not(self.uniqueFlag) and self.allEnvs.shape[0]>0):
            self.chooseEnvPlotAll(number)
        else:
            print("Error")

    def calculateEnvironmentsType(self,atom_type_1,atom_type_2,cutoff,tolerance):
        self.tolerance=tolerance
        chemical_symbols = np.asarray(self.conf.get_chemical_symbols())
        lista=np.argwhere(chemical_symbols == atom_type_1).flatten()
        listb=np.argwhere(chemical_symbols == atom_type_2).flatten()
        if (atom_type_1=="Any"):
            lista=np.linspace(0,chemical_symbols.shape[0]-1,chemical_symbols.shape[0]).astype(int)
        if (atom_type_2=="Any"):
            listb=np.linspace(0,chemical_symbols.shape[0]-1,chemical_symbols.shape[0]).astype(int)
        self.calculateEnvironments(lista,listb,cutoff)
        if (self.uniqueFlag):
            self.CalculateUniqueEnvironments()
            self.printEnvironmentSummaryInfo(self.uniqueEnvs)
        else:
            self.printEnvironmentSummaryInfo(self.globalTemplate)

    def calculateEnvironmentsString(self,listastring,listbstring,cutoff,tolerance):
        self.tolerance=tolerance
        lista=np.fromstring(listastring, dtype=int, sep=',')-1
        listb=np.fromstring(listbstring, dtype=int, sep=',')-1
        self.calculateEnvironments(lista,listb,cutoff)
        if (self.uniqueFlag):
            self.CalculateUniqueEnvironments()
            self.printEnvironmentSummaryInfo(self.uniqueEnvs)
        else:
            self.printEnvironmentSummaryInfo(self.allEnvs)

    def calculateEnvironmentsMinMaxStride(self,mina,maxa,stridea,minb,maxb,strideb,cutoff,tolerance):
        self.tolerance=tolerance
        lista=np.arange(int(mina),int(maxa)+1,int(stridea))-1
        listb=np.arange(int(minb),int(maxb)+1,int(strideb))-1
        self.calculateEnvironments(lista,listb,cutoff)
        if (self.uniqueFlag):
            self.CalculateUniqueEnvironments()
            self.printEnvironmentSummaryInfo(self.uniqueEnvs)
        else:
            self.printEnvironmentSummaryInfo(self.allEnvs)


#!/usr/bin/env python3
#/*
#* Programmer: MM KU5E@KU5E.COM
#* date: 04/22/2022
#* Purpose: Help a PHP
#*/

#imports

#methods
def disassemble(prob):
	signPos = prob.find('+')
	a = int(prob[:signPos])
	b = int(prob[signPos + 1:])
	ans = a + b
	return ans

#main
def main():
	count = int(input())
	for i in range(count):
		math = input()
		if math == 'P=NP':
			print('skipped')
		else:
			print(disassemble(math))
	return 0

#if name main main
if __name__ == "__main__":
	main();


# -*- coding: utf-8 -*-
"""
Created on Fri Feb 10 09:08:05 2017

@author: Frederik Vardinghus
"""

from __future__ import division
import numpy as np
import matplotlib.pyplot as plt

j = np.complex(0,1)
N = 500

x = np.zeros(N)
#x[3] = 1
lin = np.linspace(0,2*np.pi,N)
#lin = np.linspace(-np.pi,np.pi,N)
for i in range(len(lin)):
    x[i] = np.sin(lin[i])

def X(x,f):
    a = 0
    for n in range(len(x)):
        a += x[n]*np.exp(-j*2*np.pi*f*n)
    return a

#lin2 = np.linspace(-0.5,0.5,N)
lin2 = np.linspace(0,1,N)

amp = np.zeros(len(lin),dtype="complex64")
for i in range(len(amp)):
    amp[i] = X(x,lin2[i])

plt.plot(lin,np.real(amp),".")


#-*- coding:utf-8 -*-
import sys
import os
import time
import random
import numpy as np
import tensorflow as tf
import cv2 as cv

SIZE = 256
WIDTH = 16
HEIGHT = 16
NUM_CLASSES = 36
iterations = 800

SAVER_DIR = "model_file/"
LOG_DIR = SAVER_DIR + "logfile/"
DATASET_DIR = "/"

def get_train():
    time_begin = time.time()
    #Get the total number of pictures in the first iteration
    input_count = 0
    for i in range(0, NUM_CLASSES):
        # dir = 'train/%s/' % i
        dir = DATASET_DIR + 'train/%s/' % i
        for root,dirs,files in os.walk(dir):
            for filename in files:
                if filename == "Thumbs.db":
                    continue
                # if filename ==
                input_count = input_count + 1

    input_images = np.array([[0]*SIZE for i in range(input_count)])
    input_labels = np.array([[0]*NUM_CLASSES for i in range(input_count)])
    #Get data content in the second iteration
    index = 0
    for i in range(0, NUM_CLASSES):
        dir = DATASET_DIR + 'train/%s/' % i
        a = 0
        for root,dirs,files in os.walk(dir):
            for filename in files:
                if filename == "Thumbs.db":
                    continue
                filename = dir + filename
                img = cv.imread(filename,0)

                height = img.shape[0]
                width = img.shape[1]
                a = a + 1
                for h in range(0,height):
                    for w in range(0,width):
                        m = img[h][w]
                        if m > 150:
                            input_images[index][w+h*width] = 1
                        else:
                            input_images[index][w+h*width] = 0
                input_labels[index][i] = 1
                index = index + 1
    print('[---------------]')
    print('train data successfully loaded!')
    return time_begin, input_count, input_images, input_labels

def get_test():
    tes_count = 0
    for i in range(0, NUM_CLASSES):
        dir = DATASET_DIR + 'test/%s/' % i
        for root,dirs,files in os.walk(dir):
            for filename in files:
                if filename == "Thumbs.db":
                    continue
                tes_count = tes_count + 1
    tes_images = np.array([[0]*SIZE for i in range(tes_count)])
    tes_labels = np.array([[0]*NUM_CLASSES for i in range(tes_count)])
    index = 0
    for i in range(0, NUM_CLASSES):
        dir = DATASET_DIR + 'test/%s/' % i
        for root,dirs,files in os.walk(dir):
            for filename in files:
                if filename == "Thumbs.db":
                    continue
                filename = dir + filename
                img = cv.imread(filename,0)
                height = img.shape[0]
                width = img.shape[1]
                for h in range(0,height):
                    for w in range(0,width):
                        m = img[h][w]
                        if m > 150:
                            tes_images[index][w+h*width] = 1
                        else:
                            tes_images[index][w+h*width] = 0
                tes_labels[index][i] = 1
                index = index + 1
    print('[---------------]')
    print('test data successfully loaded!')
    return tes_count, tes_images, tes_labels

class CNN:
    def __init__(self,iterations, time_begin, input_count, input_images,
                input_labels, tes_count, tes_images, tes_labels):
        self.W_conv1 = None
        self.b_conv1 = None
        self.W_conv2 = None
        self.b_conv2 = None
        self.W_fc1 = None
        self.b_fc1 = None
        self.W_fc2 = None
        self.b_fc2 = None
        self.keep_prob = None
        self.iterations = iterations
        self.time_begin = time_begin
        self.input_count = input_count
        self.input_images = input_images
        self.input_labels = input_labels
        self.tes_count = tes_count
        self.tes_images = tes_images
        self.tes_labels = tes_labels

    def conv_layer(self,inputs, W, b):
        L1_conv = tf.nn.conv2d(inputs,W,strides=[1,1,1,1],padding='SAME')
        L1_relu = tf.nn.relu(L1_conv + b)
        return tf.nn.max_pool(L1_relu,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')

    def full_connect(self,inputs,W,b):
        return tf.nn.relu(tf.matmul(inputs,W)+b)

    def average(self, seq):
        return float(sum(seq)) / len(seq)

    def fit(self):
        # with tf.name_scope('Input'):
        x = tf.placeholder(tf.float32,shape=[None,SIZE], name = "x_input")
        y_ = tf.placeholder(tf.float32,shape=[None,NUM_CLASSES])
        self.keep_prob = tf.placeholder(tf.float32, name = 'keep_prob')
        x_image = tf.reshape(x,[-1,WIDTH,HEIGHT,1])

        #The first convolution layer, 16*16*1-> 8*8*12
        self.W_conv1 = tf.Variable(tf.truncated_normal([5,5,1,12],stddev=0.1),name="W_conv1")
        self.b_conv1 = tf.Variable(tf.constant(0.1,shape=[12]),name="b_conv1")
        L1_pool = CNN.conv_layer(self, x_image, self.W_conv1, self.b_conv1)

        #The second convolution layer, 8*8*12-> 4*4*24
        self.W_conv2 = tf.Variable(tf.truncated_normal([5,5,12,24],stddev=0.1),name="W_conv2")
        self.b_conv2 = tf.Variable(tf.constant(0.1,shape=[24]),name="b_conv2")
        L2_pool = CNN.conv_layer(self, L1_pool, self.W_conv2, self.b_conv2)

        # #The third convolution layer, 4*4*24-> 2*2*36
        # self.W_conv3 = tf.Variable(tf.truncated_normal([5,5,24,36],stddev=0.1),name="W_conv3")
        # self.b_conv3 = tf.Variable(tf.constant(0.1,shape=[36]),name="b_conv3")
        # L3_pool = CNN.conv_layer(self, L2_pool, self.W_conv3, self.b_conv3)

        #The first fullconnect layer, 2*2*36-> 64
        self.W_fc1 = tf.Variable(tf.truncated_normal([4*4*24,128],stddev=0.1),name="W_fc1")
        self.b_fc1 = tf.Variable(tf.constant(0.1,shape=[128]),name="b_fc1")
        h_pool2_flat = tf.reshape(L2_pool,[-1,4*4*24])
        h_fc1 = CNN.full_connect(self, h_pool2_flat, self.W_fc1, self.b_fc1)
        h_fc1_drop = tf.nn.dropout(h_fc1,self.keep_prob)

        #readout layer, 64->NUM_CLASSES
        self.W_fc2 = tf.Variable(tf.truncated_normal([128,NUM_CLASSES],stddev=0.1),name="W_fc2")
        self.b_fc2 = tf.Variable(tf.constant(0.1,shape=[NUM_CLASSES]),name="b_fc2")
        y_conv = tf.matmul(h_fc1_drop, self.W_fc2) + self.b_fc2
        pyx = tf.nn.softmax(y_conv, name = "y_pred")

        with tf.name_scope('loss'):
            cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_,logits=y_conv))
            loss_summary = tf.summary.scalar('loss', cross_entropy)

        with tf.name_scope('train'):
            train_step = tf.train.AdamOptimizer((1e-5)).minimize(cross_entropy)

        with tf.name_scope('accuracy'):
            with tf.name_scope('correct_prediction'):
                correct_prediction = tf.equal(tf.argmax(y_conv,1),tf.argmax(y_,1))
            with tf.name_scope('accuracy'):
                accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
                acc_summary = tf.summary.scalar('accuracy', accuracy)

        #Use tensorboard to record loss and accuracy charts
        merged = tf.summary.merge([loss_summary, acc_summary])
        with tf.Session() as sess:
            sess.run(tf.global_variables_initializer())

            time_elapsed = time.time() - self.time_begin
            print('[=============]')
            print("Reading data takes time %d second." % time_elapsed)
            print ("Read a total of %s training data, %s tags." % (self.input_count, self.input_count))
            print ("Read a total of %s test data %s tags." % (self.tes_count, self.tes_count))

            # saver = tf.compat.v1.train.Saver()
            saver = tf.train.Saver()
            writer = tf.summary.FileWriter(LOG_DIR, sess.graph)

            tr_start = time.time()
            batch_size = 64
            batches_count = int(self.input_count/batch_size)
            remainder = self.input_count % batch_size
            print ("Training set divided into %s batchs, Each batch before have %s datas, Last Batch have %s datas." % (batches_count+1, batch_size, remainder))

            print('[=============]')
            print('Train start!')
            for it in range(self.iterations + 1):
                sum_loss = []
                for n in range(batches_count):
                    summary, loss, out = sess.run([merged, cross_entropy, train_step], feed_dict = {x:self.input_images[n*batch_size:(n+1)*batch_size],
                                                                                y_:self.input_labels[n*batch_size:(n+1)*batch_size],self.keep_prob:0.5})
                    sum_loss.append(loss)
                if remainder > 0:
                    start_index = batches_count * batch_size
                    loss, out = sess.run([cross_entropy, train_step], feed_dict = {x:self.input_images[start_index:input_count-1],
                                                                                y_:self.input_labels[start_index:input_count-1],
                                                                                self.keep_prob:0.5})
                    sum_loss.append(loss)
                writer.add_summary(summary, it)
                avg_loss = CNN.average(self, sum_loss)
                iterate_accuracy = 0
                if it % 5 == 0:
                    loss1, iterate_accuracy = sess.run([cross_entropy,accuracy], feed_dict = {x :self.tes_images,
                                                                                y_ :self.tes_labels,self.keep_prob : 1.0})
                    print('The %0.4d iteration training accuracy is: %0.5f%% ' % (it,iterate_accuracy*100) +
                          '    Loss value is: %0.5f' % avg_loss + '    Test loss value is: %0.5f.' % loss1)
                    if iterate_accuracy >= 0.9999999:
                        break
                    acc = iterate_accuracy

            print('[=============]')
            print ('Train end!')
            tr_end = time.time() - tr_start
            print('The final accuracy of training is: %0.3f%%!' % (acc*100))
            print('The final loss of training is: %0.5f!' % (avg_loss))
            print ("This training takes a total of time: %d second." % tr_end)

            if not os.path.exists(SAVER_DIR) :
                print ('The training model save path does not exist, Automatically create a path now.')
                os.makedirs(SAVER_DIR)
            saver_path = saver.save(sess, SAVER_DIR)
            print("The model save path is: %s" % saver_path)
            print('The graph save path is: %s' % LOG_DIR)
            writer.close()

if __name__ == "__main__":

    # tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
    time_begin, input_count, input_images, input_labels = get_train()
    tes_count, tes_images, tes_labels = get_test()

    cnn = CNN(iterations, time_begin, input_count, input_images,
              input_labels, tes_count, tes_images, tes_labels)
    cnn.fit()

#????é”Ÿæ–¤æ‹?????????????????????
    # val_count = 0
    # for i in range(NUM_CLASSES):
    #     dir = 'valid/%s/' % i
    #     for root,dirs,files in os.walk(dir):
    #         for filename in files:
    #             if filename == "Thumbs.db":
    #                 continue
    #             val_count = val_count + 1
    # val_images = np.array([[0]*SIZE for i in range(val_count)])
    # val_labels = np.array([[0]*NUM_CLASSES for i in range(val_count)])
    # index = 0
    # for i in range(NUM_CLASSES):
    #     dir = 'valid/%s/' % i
    #     for root,dirs,files in os.walk(dir):
    #         for filename in files:
    #             if filename == "Thumbs.db":
    #                 continue
    #             filename = dir + filename
    #             img = cv.imread(filename,0)
    #             height = img.shape[0]
    #             width = img.shape[1]
    #             for h in range(0,height):
    #                 for w in range(0,width):
    #                     m = img[h][w]
    #                     if m > 150:
    #                         val_images[index][w+h*width] = 1
    #                     else:
    #                         val_images[index][w+h*width] = 0
    #             val_labels[index][i] = 1
    #             index = index + 1
    #     print('[---------------]')
    #     print('%s é”Ÿæ–¤æ‹·å›¾ç‰‡é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿï¿½??' % i)