# -*- coding: utf-8 -*-
from odoo import fields, models, api
from odoo.exceptions import ValidationError
from odoo.addons.pabs_payroll.models.pabs_payroll import WEEK, STATES
from odoo.addons.pabs_payroll.models.pabs_payroll_high_investment import VALUES
from datetime import datetime

class PabsPayrollCollection(models.Model):
  _name = 'pabs.payroll.contract'
  _description = 'Nómina Sección de Contratos'

  name = fields.Char(string='Folio')

  state = fields.Selection(selection=STATES,
    string='Estado',
    default='draft')

  warehouse_id = fields.Many2one(comodel_name='stock.warehouse',
    string='Oficina de Ventas',
    required=True)

  user_id = fields.Many2one(comodel_name='res.users',
    string='Usuario',
    default=lambda self: self.env.user)

  week_number = fields.Selection(selection=WEEK,
    string='Semana',
    required=True,
    default=lambda self: self._calc_week_number())

  first_date = fields.Date(string='Fecha Inicio')

  end_date = fields.Date(string='Fecha Fin')

  salary_ids = fields.One2many(comodel_name='pabs.payroll.salary',
    inverse_name='payroll_id',
    string='Sueldos')

  ### SE PASO PARA COBRANZA
  """complement_ids = fields.One2many(comodel_name='pabs.payroll.complements',
    inverse_name = 'payroll_id',
    string='Complementos')"""

  high_investment_det_ids = fields.One2many(comodel_name='pabs.payroll.high.investment.det',
    inverse_name='payroll_id',
    string='Inversión alta detallada')

  def _calc_week_number(self):
    today = datetime.today()
    week_number = (int(today.strftime("%U")) - 1)
    if week_number < 10:
      week_number = str(week_number).zfill(2)
    else:
      week_number = str(week_number)
    self.week_number = week_number
    return week_number

  @api.onchange('week_number')
  def calc_dates(self):
    registry_obj = self.env['pabs.payroll.registry']
    res = {}
    year = fields.Date.today().year
    week_config_obj = self.env['week.number.config']
    year_config_obj = self.env['week.year']
    year_id = year_config_obj.search([
      ('name','=',year)],limit=1)
    if not year_id:
      raise ValidationError((
        "No se ha configurado el año en curso, favor de comunicarse con sistemas"))
    for rec in self:
      if rec.week_number:
        record = week_config_obj.search([
          ('number_week','=',rec.week_number),
          ('year','=',year_id.id)])
        if not record:
          rec.first_date = False
          rec.end_date = False
          return {
            'warning': {
              'title': ("Error en busqueda de Semana"),
              'message': "No se encontró coincidencias para la {}".format(
              dict(rec._fields['week_number'].selection).get(rec.week_number))
            }
          }
        rec.first_date = record.first_date
        rec.end_date = record.end_date
    ### IDS DE LOS ALMACENES
    warehouse_ids = registry_obj._get_warehouse_ids()
    res['domain'] = {'warehouse_id': [('id', 'in', tuple(warehouse_ids) )], }
    return res

  @api.onchange('warehouse_id','first_date', 'end_date')
  def _calc_all_contracts(self):
    contract_obj = self.env['pabs.contract']
    payment_scheme_obj = self.env['pabs.payment.scheme']
    for rec in self:
      rec.high_investment_det_ids = [(5,0,0)]
      rec.salary_ids = [(5,0,0)]
      commission_records = []
      salary_records = []
      salary_scheme = payment_scheme_obj.search([
        ('name','=','SUELDO')])
      commission_scheme = payment_scheme_obj.search([
        ('name','=','COMISION')])
      if rec.warehouse_id and rec.first_date and rec.end_date:
        all_contracts = contract_obj.search([
          ('warehouse_id','=',rec.warehouse_id.id),
          ('state','=','contract'),
          ('invoice_date','>=',rec.first_date),
          ('invoice_date','<=',rec.end_date)])
        employee_ids = all_contracts.mapped('employee_id')
        for employee_id in employee_ids:
          contract_ids = all_contracts.filtered(lambda r: r.employee_id.id == employee_id.id)
          for contract_id in contract_ids:
            if rec.warehouse_id.id == contract_id.employee_id.warehouse_id.id:
              if contract_id.payment_scheme_id.id == commission_scheme.id:
                initial = contract_id.initial_investment
                bonus = 0
                if initial >= 500 and initial < 1000:
                  bonus = VALUES['500']
                elif initial >= 1000:
                  bonus = VALUES['1000']
                if bonus:
                  commission_records.append([0,0,{
                    'contract_id' : contract_id.id,
                    'employee_id' : contract_id.employee_id.id,
                    'contract_date' : contract_id.invoice_date,
                    'high_investment' : initial,
                    'high_investment_bonus' : bonus,
                  }])
          salary_contract = contract_ids.filtered(
            lambda r: r.payment_scheme_id.id == salary_scheme.id)
          if len(salary_contract) == 1:
            salary_records.append([0,0,{
              'employee_id' : employee_id.id,
              'contract1_id' : salary_contract[0].id,
            }])
          elif len(salary_contract) == 2:
            salary_records.append([0,0,{
              'employee_id' : employee_id.id,
              'contract1_id' : salary_contract[0].id,
              'contract2_id' : salary_contract[1].id,
            }])
          elif len(salary_contract) > 2:
            raise ValidationError((
              "El asistente: {} tiene {} contratos a sueldo".format(employee_id.name, len(salary_contract))))
      if commission_records:
        rec.high_investment_det_ids = commission_records
      if salary_records:
        rec.salary_ids = salary_records

  def validate(self):
    ### CREAR OBJETO DE REGISTRO
    registry_obj = self.env['pabs.payroll.registry']
    registry_ids = registry_obj.search([
      ('warehouse_id','=',self.warehouse_id.id),
      ('week_number','=',self.week_number)])
    if not registry_ids:
      warehouse_ids = registry_obj._get_warehouse_ids()
      for warehouse_id in warehouse_ids:
        rec_data = {
          'warehouse_id' : warehouse_id,
          'week_number' : self.week_number,
        }
        if warehouse_id == self.warehouse_id.id:
          rec_data.update({
            'payroll_contract_id' : self.id,
          })
        registry_obj.create(rec_data)
    else:
      registry_ids.payroll_contract_id = self.id
    self.state = 'to review'
    self.name = 'Nómina {} {}'.format(
      self.warehouse_id.name,
      dict(self._fields['week_number'].selection).get(self.week_number))

  @api.model
  def create(self, vals):
    week_config_obj = self.env['week.number.config']
    year_config_obj = self.env['week.year']
    year = fields.Date.today().year
    year_id = year_config_obj.search([
      ('name','=',year)],limit=1)
    record = week_config_obj.search([
      ('number_week','=',vals['week_number']),
      ('year','=',year_id.id)])
    vals['first_date'] = record.first_date
    vals['end_date'] = record.end_date
    return super(PabsPayrollCollection, self).create(vals)

  _sql_constraints = [
    ('unique_warehouse_on_week',
      'UNIQUE(week_number, warehouse_id)',
      'No se puede crear el registro: solo puede existir un registro por Semana'),
    ]


# unit test for solver
# tests based on Bathe
# for newmark pg 782
import unittest
import pytest

from solvers.newmark_solver import NewmarkSolver, NewmarkExplicit, NewmarkImplicitForce

from tests.utils import *

import numpy as np
from scipy import sparse

class TestNewmark(unittest.TestCase):
    def setUp(self):
        # newmark settings
        self.settings = {
            "beta": 0.25,
            "gamma": 0.5,
        }

        # example from bathe
        M = [[2, 0], [0, 1]]
        K = [[6, -2], [-2, 4]]
        C = [[0, 0], [0, 0]]
        F = np.zeros((2, 13))
        F[1, :] = 10
        self.M = sparse.csc_matrix(np.array(M))
        self.K = sparse.csc_matrix(np.array(K))
        self.C = sparse.csc_matrix(np.array(C))
        self.F = sparse.csc_matrix(np.array(F))

        self.u0 = np.zeros(2)
        self.v0 = np.zeros(2)

        self.n_steps = 12
        self.t_step = 0.28
        self.t_total = self.n_steps * self.t_step

        self.time = np.linspace(
            0, self.t_total, int(np.ceil((self.t_total - 0) / self.t_step)+1)
        )

        self.number_eq = 2
        return

    def test_a_init(self):
        force = self.F[:, 0].toarray()[:, 0]
        # check computation of the acceleration
        solver = NewmarkSolver()

        solver._is_sparse_calculation = True
        acc = solver.calculate_initial_acceleration(self.M, self.C, self.K, force, self.u0, self.v0)

        # assert if true
        np.testing.assert_array_equal(acc, np.array([0, 10]))
        return

    def run_newmark_test(self,solver):
        res = solver()

        res.beta = self.settings["beta"]
        res.gamma = self.settings["gamma"]

        res.initialise(self.number_eq, self.time)

        res.calculate(self.M, self.C, self.K, self.F, 0, self.n_steps)
        # check solution
        np.testing.assert_array_almost_equal(
            np.round(res.u, 2),
            np.round(
                np.array(
                    [
                        [0, 0],
                        [0.00673, 0.364],
                        [0.0505, 1.35],
                        [0.189, 2.68],
                        [0.485, 4.00],
                        [0.961, 4.95],
                        [1.58, 5.34],
                        [2.23, 5.13],
                        [2.76, 4.48],
                        [3.00, 3.64],
                        [2.85, 2.90],
                        [2.28, 2.44],
                        [1.40, 2.31],
                    ]
                ),
                2,
            ),
        )

    def test_sparse_solver_newmark_explicit(self):
        self.M, self.K, self.C, self.F = set_matrices_as_sparse(self.M, self.K, self.C, self.F)
        # set_matrices_as_sparse()
        self.run_newmark_test(NewmarkExplicit)

    def test_sparse_solver_newmark_implicit(self):
        self.M, self.K, self.C, self.F = set_matrices_as_sparse(self.M, self.K, self.C, self.F)
        # set_matrices_as_sparse()
        self.run_newmark_test(NewmarkImplicitForce)

    def test_sparse_solver_newmark_explicit_constant_force_vector(self):
        self.M, self.K, self.C, self.F = set_matrices_as_sparse(self.M, self.K, self.C, self.F)

        # create force vector
        self.F = self.F[:,0].toarray()[:,0]

        # run test
        self.run_newmark_test(NewmarkExplicit)

    def test_sparse_solver_newmark_implicit_constant_force_vector(self):
        self.M, self.K, self.C, self.F = set_matrices_as_sparse(self.M, self.K, self.C, self.F)

        # create force vector
        self.F = self.F[:,0].toarray()[:,0]

        # run test
        self.run_newmark_test(NewmarkImplicitForce)

    def test_np_array_solver_newmark_explicit(self):
        self.M, self.K, self.C, self.F = set_matrices_as_np_array(self.M, self.K, self.C, self.F)
        self.run_newmark_test(NewmarkExplicit)

    def test_np_array_solver_newmark_implicit(self):
        self.M, self.K, self.C, self.F = set_matrices_as_np_array(self.M, self.K, self.C, self.F)
        self.run_newmark_test(NewmarkImplicitForce)

    def run_test_solver_newmark_two_stages(self, solver):
        """
               Test newmark solver with 2 stages, where the different stages have different time steps
               :return:
               """
        res = solver()

        res.beta = self.settings["beta"]
        res.gamma = self.settings["gamma"]

        new_t_step = 0.5
        new_n_steps = 5
        new_t_start = self.time[-1] + new_t_step
        new_t_total = new_t_step * (new_n_steps - 1) + new_t_start
        self.time = np.concatenate(
            (self.time, np.linspace(new_t_start, new_t_total, new_n_steps))
        )

        diff = np.diff(self.time)
        turning_idxs = sorted(np.unique(diff.round(decimals=7), return_index=True)[1])

        F = np.zeros((2, len(self.time)))
        F[1, :] = 10
        self.F = sparse.csc_matrix(np.array(F))

        res.initialise(self.number_eq, self.time)

        # run stages
        for i in range(len(turning_idxs) - 1):
            res.update(turning_idxs[i])
            res.calculate(
                self.M, self.C, self.K, self.F, turning_idxs[i], turning_idxs[i + 1]
            )
        res.update(turning_idxs[-1])
        res.calculate(
            self.M, self.C, self.K, self.F, turning_idxs[-1], len(self.time) - 1
        )

        # check solution stage 1
        np.testing.assert_array_almost_equal(
            np.round(res.u[0:13, :], 2),
            np.round(
                np.array(
                    [
                        [0, 0],
                        [0.00673, 0.364],
                        [0.0505, 1.35],
                        [0.189, 2.68],
                        [0.485, 4.00],
                        [0.961, 4.95],
                        [1.58, 5.34],
                        [2.23, 5.13],
                        [2.76, 4.48],
                        [3.00, 3.64],
                        [2.85, 2.90],
                        [2.28, 2.44],
                        [1.40, 2.31],
                    ]
                ),
                2,
            ),
        )

        # check solution stage 2
        np.testing.assert_array_almost_equal(
            np.round(res.u[13:, :], 2),
            np.round(
                np.array([[-0.31, 2.56], [-1.28, 2.70], [-0.91, 2.31], [0.52, 1.81], [2.04, 2.08]]),
                2,
            ),
        )

    def test_np_array_solver_newmark_explicit_two_stages(self):
        self.M, self.K, self.C, self.F = set_matrices_as_np_array(self.M, self.K, self.C, self.F)
        self.run_test_solver_newmark_two_stages(NewmarkExplicit)

    def test_np_array_solver_newmark_implicit_two_stages(self):
        self.M, self.K, self.C, self.F = set_matrices_as_np_array(self.M, self.K, self.C, self.F)
        self.run_test_solver_newmark_two_stages(NewmarkImplicitForce)

    def test_sparse_solver_newmark_explicit_two_stages(self):
        self.M, self.K, self.C, self.F = set_matrices_as_sparse(self.M, self.K, self.C, self.F)
        self.run_test_solver_newmark_two_stages(NewmarkExplicit)

    def test_sparse_solver_newmark_implicit_two_stages(self):
        self.M, self.K, self.C, self.F = set_matrices_as_sparse(self.M, self.K, self.C, self.F)
        self.run_test_solver_newmark_two_stages(NewmarkImplicitForce)

    def test_solver_newmark_static_explicit(self):
        # with damping solution converges to the static one
        res = NewmarkExplicit()

        n_steps = 500
        t_total = n_steps * self.t_step
        time = np.linspace(0, t_total, int(np.ceil((t_total - 0) / self.t_step)))
        res.initialise(self.number_eq, time)

        res.beta = self.settings["beta"]
        res.gamma = self.settings["gamma"]

        F = sparse.csc_matrix(np.zeros((2, 500)))
        F[1, :] = 10
        # rayleigh damping matrix
        f1 = 1
        f2 = 10
        d1 = 1
        d2 = 1
        damp_mat = (
            1
            / 2
            * np.array(
                [
                    [1 / (2 * np.pi * f1), 2 * np.pi * f1],
                    [1 / (2 * np.pi * f2), 2 * np.pi * f2],
                ]
            )
        )
        damp_qsi = np.array([d1, d2])
        # solution
        alpha, beta = np.linalg.solve(damp_mat, damp_qsi)
        damp = self.M.dot(alpha) + self.K.dot(beta)
        res.calculate(self.M, damp, self.K, F, 0, n_steps - 1)
        # check solution
        np.testing.assert_array_almost_equal(
            np.round(res.u[0], 2), np.round(np.array([0, 0]), 2)
        )
        np.testing.assert_array_almost_equal(
            np.round(res.u[-1], 2), np.round(np.array([1, 3]), 2)
        )
        return

    def test_load_function_explicit(self):
        """
        Test if Newmark solver returns equal results while using a load function and an initial force matrix. The load
        function is chosen such that at each time step it calculates the same value as the tested force matrix at that
        time step.
        :return:
        """

        def load_function(t,u=None):
            # half load each time step
            if t>0:
                self.F[:, t] = self.F[:,t-1] * 0.5
            return self.F[:, t].toarray()[:,0]

        # manually make force matrix
        force_matrix = np.zeros(self.F.shape)
        force_matrix[:, 0] = self.F.toarray()[:,0]
        for i in range(1, force_matrix.shape[1]):
            force_matrix[:, i] = force_matrix[:, i-1]/2

        # calculate using custom load function
        res_func = NewmarkExplicit()
        res_func.update_rhs_at_time_step_func = load_function
        res_func.beta = self.settings["beta"]
        res_func.gamma = self.settings["gamma"]
        res_func.initialise(self.number_eq, self.time)
        res_func.calculate(self.M, self.C, self.K, self.F, 0, self.n_steps)

        # calculate using initial load matrix
        res_manual = NewmarkExplicit()
        res_manual.beta = self.settings["beta"]
        res_manual.gamma = self.settings["gamma"]
        res_manual.initialise(self.number_eq, self.time)
        res_manual.calculate(self.M, self.C, self.K, force_matrix, 0, self.n_steps)

        # check if solutions are equal
        np.testing.assert_array_almost_equal(res_func.u, res_manual.u)

    @pytest.mark.workinprogress
    def test_load_function_implicit(self):
        """
        Test if Newmark solver returns equal results while using a load function and implicit Newmark solver and an
        initial force matrix. The load function is chosen such that at each time step it calculates the same value as
        the tested force matrix at that time step.
        :return:
        """

        def load_function(u,t):
            # force is a function of the displacement
            F = np.sin(u) * 10

            return F

        # calculate using custom load function and implicit Newmark solver
        res_func = NewmarkImplicitForce()
        res_func.load_func = load_function
        res_func.beta = self.settings["beta"]
        res_func.gamma = self.settings["gamma"]
        res_func.initialise(2, self.time)
        res_func.u0 = [np.pi/2,np.pi/2]
        res_func.u0 = [0, 0]

        F = np.ones((2,len(self.time)))*10
        res_func.calculate(self.M, self.C, self.K, F, 0, self.n_steps)

    def test_output_interval_newmark_explicit(self):
        self.M, self.K, self.C, self.F = set_matrices_as_np_array(self.M, self.K, self.C, self.F)

        # reshape force vector
        F = np.zeros((2, self.n_steps + 1))
        F[1, :] = 10
        self.F = sparse.csc_matrix(np.array(F))

        output_interval = 10

        # write all output
        res = NewmarkExplicit()
        res.initialise(self.number_eq, self.time)
        res.calculate(self.M, self.C, self.K, self.F, 0, self.n_steps)
        expected_displacement = np.concatenate((res.u[0::output_interval, :], res.u[None, -1, :]), axis=0)

        # write every other step
        res_2 = NewmarkExplicit()
        res_2.output_interval = output_interval
        res_2.initialise(self.number_eq, self.time)
        res_2.calculate(self.M, self.C, self.K, self.F, 0, self.n_steps)

        # assert
        np.testing.assert_array_almost_equal(expected_displacement, res_2.u)

    def test_output_interval_newmark_implicit(self):
        self.M, self.K, self.C, self.F = set_matrices_as_np_array(self.M, self.K, self.C, self.F)

        # reshape force vector
        F = np.zeros((2, self.n_steps + 1))
        F[1, :] = 10
        self.F = sparse.csc_matrix(np.array(F))

        output_interval = 10

        # write all output
        res = NewmarkImplicitForce()
        res.initialise(self.number_eq, self.time)
        res.calculate(self.M, self.C, self.K, self.F, 0, self.n_steps)
        expected_displacement = np.concatenate((res.u[0::output_interval, :], res.u[None, -1, :]), axis=0)

        # write every other step
        res_2 = NewmarkImplicitForce()
        res_2.output_interval = output_interval
        res_2.initialise(self.number_eq, self.time)
        res_2.calculate(self.M, self.C, self.K, self.F, 0, self.n_steps)

        # assert
        np.testing.assert_array_almost_equal(expected_displacement, res_2.u)


import numpy as np
from skimage.draw import polygon2mask
import pycocotools.mask as coco_mask
from detectron2.structures import BoxMode
import os
import dask.dataframe as dd
import itertools

HEIGHT = 295
WIDTH = 510

def load_mask(polygon_vertices):
    """Recebe os vértices de um polígono e retorna sua máscara binária.

    Args:
        polygon_vertices (list): Lista com os vértices de um polígono anotado.

    Returns:
        ndarray: Máscara binária que representa o polígono anotado.
    """

    mask = np.zeros([HEIGHT, WIDTH], dtype=np.uint8) #Dim: Height, Width, 3 (RGB - 3 canais de cores)

    calculatedMask = polygon2mask(mask.shape, polygon_vertices)

    #Atribui o valor 1 para os pontos onde o polígono existe. O restante permanece como 0.
    mask[calculatedMask] = 1

    return mask

def getPolygonPoints(line):
    """Calcula os pontos de um polígono com base em uma linha.

    Args:
        line (list): Uma lista representando 2 linhas com 8 pontos [x1, y1, x2, y2, ...].
                     Essa lista vem com as colunas adicionais da anotação, que são removidas aqui nesta função.

    Returns:
        dict: Um dicionário contendo uma máscara (mask) baseada nos pontos do polígono.
    """

    '''O primeiro elemento é removido pois como recebemos todas as colunas de anotação, o primeiro
    elemento é uma string contendo o frame_id'''
    line.pop(0)

    line = np.array(line)
    listOfPoints_y = []
    listOfPoints_x = []

    for i in range(2):

        m = (int(line[3]) - int(line[1])) / (int(line[2]) - int(line[0]) + 0.000001)
        b = int(line[1]) - m * int(line[0])

        if m == 0:
            return False

        y = np.array([0, 640])
        x = np.array([(y[0] - b) / m, (y[1] - b) / m])

        '''Subtraímos 65 pixels de cada dimensão pois as imagens originais foram cortadas
        para remoção dos dados sensíveis.'''
        x -= 65
        y -= 65

        if not i:
            listOfPoints_x.extend((int(x[0]) / 1.0, int(x[1]) / 1.0))
            listOfPoints_y.extend((int(y[0]) / 1.0, int(y[1]) / 1.0))
        else:
            listOfPoints_x.extend((int(x[1]) / 1.0, int(x[0]) / 1.0))
            listOfPoints_y.extend((int(y[1]) / 1.0, int(y[0]) / 1.0))

        line = line[4:]

    polygon_vertices = [
        [listOfPoints_y[0], listOfPoints_x[0]],
        [listOfPoints_y[1], listOfPoints_x[1]],
        [listOfPoints_y[2], listOfPoints_x[2]],
        [listOfPoints_y[3], listOfPoints_x[3]]
    ]

    return {'mask': load_mask(polygon_vertices)}

def load_pipeline_image(df_partitioned):
    """Carrega as imagens do pipeline a partir de um dataframe particionado.

    Args:
        df_partitioned (DataFrame): O dataframe particionado contendo as informações das imagens.

    Returns:
        list: Uma lista contendo as informações das imagens no formato adequado para o pipeline.
    """

    pipeline_dataset = []

    for df_index, df_row in df_partitioned.iterrows():
        row = list(df_row)

        polygon_info = getPolygonPoints(row)

        if polygon_info == False:
            continue

        mask = polygon_info['mask']
        y, x = np.where(mask == 1)
        bbox = [np.min(x), np.min(y), np.subtract(np.max(x), np.min(x)), np.subtract(np.max(y), np.min(y))]

        obj = {
            "bbox": bbox,
            "bbox_mode": BoxMode.XYXY_ABS,
            "segmentation": coco_mask.encode(np.asarray(mask, order="F")),
            "category_id": 0
        }

        objs = [obj]

        image_name = df_row.image_name
        image_path = f"/content/all-images/{image_name}.png"

        image_info = {
            'file_name': image_path,
            'image_id': image_name,
            'height': HEIGHT,
            'width': WIDTH,
            'annotations': objs
        }

        pipeline_dataset.append(image_info)

    return pipeline_dataset

def load_pipeline_dataset(dataframe_annotation):
    """Carrega o dataset do pipeline a partir de um dataframe de anotações.

    Args:
        dataframe_annotation (DataFrame): O dataframe contendo as anotações das imagens.

    Returns:
        list: Uma lista contendo as informações do dataset no formato adequado para o pipeline.
    """

    meta = {"frame_id": np.int64, "x1": np.int64, "y1": np.int64, "x2": np.int64,
            "y2": np.int64, "x3": np.int64, "y3": np.int64, "x4": np.int64, "y4": np.int64,
            "image_name": object}

    dask_dataframe = dd.from_pandas(dataframe_annotation, npartitions=8)
    result = dask_dataframe.map_partitions(load_pipeline_image, meta=meta).compute()

    final_result = list(itertools.chain.from_iterable(result))

    return final_result


from platform import system
import os
import torch
import LOSS_mutil
import numpy as np
from torch.nn import DataParallel
from dataset import Massachusetts_road_mean, Massachusetts_road_std, DeepGlobe_road_std, DeepGlobe_road_mean, Ottawa_road_mean, Ottawa_road_std, plus_road_std, plus_road_mean, WHU_road_mean, WHU_road_std, minqin_road_std, minqin_road_mean
# from poly import poly as poly

min_lr = 7e-8
max_lr = 1e-3

from Net.CSCNet_attention_mutil import model

save_name = 'CSCNet_attention_mutil' # 训练文件保存路径

print('本次运行模型为CSCNet_attention_mutil，学习率变动范围是{} <<<--->>> {}'.format(min_lr,max_lr))

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)
gpu_num = torch.cuda.device_count()

# 是否并行
if gpu_num > 1:
      print('多Gpu，',gpu_num)
      num_workers = (20 if system() == 'Linux' else 0)
      model = DataParallel(model)
elif gpu_num ==1:
      print('单Gpu，',gpu_num)
      num_workers = (10 if system() == 'Linux' else 0)
else:
      print('无GPU')
# num_workers =0

# 计算得到的权重（道路，背景）

epoch = 50
batch_size_start = 4

save_dir = os.path.join('result', save_name)
# transforme_p = np.linspace(0, 1, epoch) # 图像增强概率值
# size = [int(x) for x in np.linspace(200, 500, epoch)] # 图像重采样的尺寸

# optimizer = optim.Adam(model.parameters(), lr=max_lr)
optimizer = torch.optim.RAdam(model.parameters(), lr=max_lr, weight_decay=1e-6)
criterion = LOSS_mutil.UUNetloss(device)
# scheduler = optim.lr_scheduler.CosineAnnealingWarmRestarts(optimizer, 47, 2, min_lr)
# scheduler = poly(optimizer, 0.9, 219492)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 10, 0.2, verbose=True)

# 根据epoch和size计算batchsize

# # 1/10epoch计算
# transforme_p = np.linspace(0, 1, int(epoch/20)) # 图像增强概率值
# size = [int(x) for x in np.linspace(200, 500, int(epoch/20))] # 图像重采样的尺寸
# batch_size_start_pixel_nums = int(size[0]**2)
# batch_size_end_pixel_nums = int(size[-1]**2)
# all_nums = batch_size_start_pixel_nums * batch_size_start
# batch_size = [int(all_nums/x) for x in np.linspace(batch_size_start_pixel_nums, batch_size_end_pixel_nums, int(epoch/20))]
# batch_size = [x for x in batch_size for i in range(20)]
# size = [x for x in size for i in range(20)]
# transforme_p = [x for x in transforme_p for i in range(20)]

# 不进行数据增强
batch_size = [16 for x in range(epoch)]
size = [512 for x in np.linspace(200, 512, epoch)]
transforme_p = [0.5 for x in range(epoch)]

print(len(size),len(transforme_p),len(batch_size))
# 均值和方差（使用哪个数据集，注释掉另外的数据集）
mean = Massachusetts_road_mean.to(device)
std = Massachusetts_road_std.to(device)
# #
# mean = DeepGlobe_road_mean.to(device)
# std = DeepGlobe_road_std.to(device)
#
# mean = WHU_road_mean.to(device)
# std = WHU_road_std.to(device)
# mean = minqin_road_mean.to(device)
# std = minqin_road_std.to(device)
#
# mean = Ottawa_road_mean.to(device)
# std = Ottawa_road_std.to(device)
#
# mean = plus_road_mean.to(device)
# std = plus_road_std.to(device)

print('数据集均值方差是：', mean, std, '\n',
      '损失函数是：', criterion, '\n',
      '学习率迭代器：', scheduler, '\n',
      '迭代次数是：', epoch, '\n',
      '保存路径是：', save_dir, '\n',
      '优化器是：', optimizer, '\n',
      'batch_size是：', batch_size[0], '\n',
      '训练时输入网络的图像大小是：', size[0], '\n',
      '数据增强概率是：', transforme_p[0], '\n')
print(model)


#!/usr/bin/env python
## -*- coding: utf-8 -*-
#
# File: import_reports.py
# Author: Matthew A. Weidner <@jopawp>
# Date: 09/04/2016
# Descr: Imports sqlite3 database h1-reports.db from downloaded HackerOne
# 		 reports located in reports/
# 		 Use this to recreate the databse after schema modification.

import os
import sys
import json
import npyscreen
import sqlite3
import pdb
from subprocess import call

class AddressDatabase(object):
	def __init__(self, filename="h1-reports.db"):
		self.dbfilename = filename
		db = sqlite3.connect(self.dbfilename)
		c = db.cursor()
		c.execute(
				"CREATE TABLE IF NOT EXISTS reports\
						( record_internal_id INTEGER PRIMARY KEY, \
						report_id     TEXT, \
						created_at    TIME, \
						disclosed_at  TIME, \
						title         TEXT, \
						program       TEXT, \
						reporter      TEXT, \
						json          TEXT \
						)" \
						)
		db.commit()
		c.close()

	def add_record(self, report_id='', created='', disclosed='', title='', program='', reporter='', json_str=''):
		#print(report_id, date[:10], json_str)
		#input("Press Enter to continue...")
		title = title.strip()
		db = sqlite3.connect(self.dbfilename)
		c = db.cursor()
		c.execute('INSERT INTO reports(report_id, created_at, disclosed_at, title, program, \
			reporter, json) VALUES(?,?,?,?,?,?,?)', \
			(report_id, created, disclosed, title, program, reporter, json_str))
		db.commit()
		c.close()

if __name__ == '__main__':
	mydb = AddressDatabase()
	archive_dir = '/home/orion/bugbounty/h1/reports/'
	report_dir = archive_dir #+ 'new/'
	print('Adding reports from: ' + report_dir)
	for file_name in os.listdir(report_dir):
		if os.path.isfile(report_dir + file_name):
			f = open(report_dir + file_name)
			raw = f.read()
			if raw != '':
				j = json.loads(raw)
				if j['reporter'] is not None:
					rep = j['reporter']['username']
				else:
					rep = 'Unknown'
				#print('Adding ' + str(j['id']))
				mydb.add_record(report_id=str(j['id']), created=j['created_at'], \
						disclosed=j['disclosed_at'], title=j['title'],\
						program=j['team']['profile']['name'], \
						reporter=rep, json_str=raw)
	# find ./ -type f -size +0 -exec mv -t ../ {} +
	#call(['find', report_dir, '-type', 'f', '-size', '+0', '-exec', 'mv', \
		#	'-t', archive_dir, '{}', '+'])


import tensorflow as tf
from tensorflow.keras import layers, Model, metrics
from tqdm import tqdm

from ._loss import quantization

mae_metric = metrics.MeanAbsoluteError(name="mae")
loss_tracker = metrics.Mean(name="loss")

class BaseXModel(Model):

    def __init__(self, n_features, k_prototypes, deep=True, *args, **kwargs):
        super().__init__(*args, **kwargs)
        input = layers.Input(shape=(n_features,))
        if deep:
            x = layers.Dense(n_features, activation='tanh')(input)
            x = layers.Dense(n_features, activation='tanh')(x)
            # output = layers.Softmax(k_prototypes, use_bias=False)(x)
            output = layers.Dense(k_prototypes, use_bias=False)(x)
        else:
            output = layers.Dense(k_prototypes, activation='relu', use_bias=False)(input)
        self.base_model = tf.keras.Model(inputs=input, outputs=output)

    def fit(self, X, y, epochs, verbose=False):
        # Unpack the data. Its structure depends on your model and
        # on what you pass to `fit()`.

        pbar = tqdm(range(epochs)) if verbose else None
        x = tf.Variable(X, dtype='float32')
        self.loss_ = []
        for epoch in range(epochs):
            with tf.GradientTape() as tape:
                y_latent = self(x, training=True)  # Forward pass
                y_pred = self.base_model(y_latent, training=True)
                softm = tf.math.softmax(y_pred)
                maxd = tf.math.reduce_max(softm, axis=1)
                cost = tf.math.log(1/maxd) * maxd
                loss = tf.reduce_sum(cost)

            # Compute gradients
            trainable_vars = self.trainable_variables
            gradients = tape.gradient(loss, trainable_vars)
            # Update weights
            self.optimizer.apply_gradients(zip(gradients, trainable_vars))
            # Compute our own metrics
            loss_tracker.update_state(loss)
            self.loss_.append(loss.numpy())

            if verbose:
                pbar.set_description(f"Epoch: {epoch+1} - Loss: {loss.numpy():.2f}")
        return self


from django.conf.urls import patterns, url
from rango import views

urlpatterns = patterns('',
        url(r'^$', views.index, name='index'),
        url(r'^about/', views.about, name='about'),
        url(r'^add_category/$', views.add_category, name='add_category'),
        url(r'^category/(?P<category_name_url>\w+)$', views.category, name='category'),
        url(r'^category/(?P<category_name_url>\w+)/add_page/$', views.add_page, name='add_page'),
        url(r'^register/$', views.register, name='register'),
        url(r'^login/$', views.user_login, name='login'),
        url(r'^restricted/', views.restricted, name='restricted'),
        url(r'^logout/$', views.user_logout, name='logout'),
        )


import re
import lib
import modif_lib

def real_len(w):
    """Подсчёт длины слова без титла"""

    if '#' in w:
        return len(w) - 1

    return len(w)

def repl(w, d, mode='search'):
    """Замена буквосочетания"""

    for coll in d:

        if mode == 'match':
            if re.match(coll, w):
                w = re.sub(coll, d[coll], w, 1)

        else:
            if re.search(coll, w):
                w = re.sub(coll, d[coll], w)

    return w

def repl_var(w, p, d, mode='search'):
    """Замена неоднозначного буквосочетания"""

    for coll in d:

        if mode == 'match':
            if re.match(coll, w):
                if p in d[coll]:
                    w = re.sub(coll, d[coll][p], w, 1)
                else:
                    w = re.sub(coll, d[coll][''], w, 1)

        else:
            if re.search(coll, w):
                if p in d[coll]:
                    w = re.sub(coll, d[coll][p], w)
                else:
                    w = re.sub(coll, d[coll][''], w)

    return w

def modif_titlo_on_start(w, p):
    """Замена буквосочетаний под титлом (только в начале слов)"""

    w = repl(w, modif_lib.titlo_on_start, 'match')

    # Случаи с неоднозначным раскрытием
    w = repl_var(w, p, modif_lib.titlo_on_start_var, 'match')

    return w

def modif_titlo(w):
    """Замена буквосочетаний под титлом (везде)"""
    return repl(w, modif_lib.titlo)

def modif_abbr(w, p):
    """Замена буквосочетаний в сокращённых корнях без титла"""

    # Случаи с неоднозначным раскрытием (надстроки случаев с однозначным)
    w = repl_var(w, p, modif_lib.abbr_var_super)

    w = repl(w, modif_lib.abbr)

    # Случаи с неоднозначным раскрытием (подстроки случаев с однозначным)
    w = repl_var(w, p, modif_lib.abbr_var_sub)

    return w

def modif_not_on_end(w):
    """Замены *не* на конце слов"""

    for coll in modif_lib.not_on_end:
        mo = re.search(coll, w)

        if mo and mo.end() != real_len(w):
            w = re.sub(coll, modif_lib.not_on_end[coll], w, 1)

    return w

def modif_varia(w):
    """Замена разных буквосочетаний вне зависимости от положения в слове"""
    return repl(w, modif_lib.varia)

def modif_stv(w):
    """Замена -ств- и -ск-"""

    mo = re.search('[ЕЬ]С(ТВ|К)', w)

    if mo and mo.start() > 2:
        w = re.sub('[ЕЬ]С(ТВ|К)', 'С\\1', w)

    mo = re.search('С(ТВ|К)', w)

    if mo and mo.start() > 2:
        if w[mo.start() - 1] in set(lib.cons_hush) - {'Ц'}:
            w = w[:mo.start()] + 'Е' + w[mo.start():]
        elif w[mo.start() - 1] == 'Л':
            w = w[:mo.start()] + 'Ь' + w[mo.start():]

    return w

def modif_mv(w):
    """Замена -мь- и -вь- только внутри слов"""

    mo = re.search('([МВ])Ь', w)

    if mo and mo.end() < real_len(w):
        if w[mo.end()] not in set(lib.vows) - {'Ъ', 'Ь'}:
            w = re.sub('([МВ])Ь', '\\1', w)

    return w

def modif_on_end(w, p):
    """Замена буквосочетаний на конце слов"""

    for coll in modif_lib.on_end:
        mo = re.search(coll + '$', w)

        if mo and mo.end() == real_len(w):
            w = w[:mo.start()] + re.sub(coll, modif_lib.on_end[coll], w[mo.start():])

    for coll in modif_lib.on_end_var:
        mo = re.search(coll + '$', w)

        if mo and mo.end() == real_len(w):
            if p in modif_lib.on_end_var[coll]:
                w = w[:mo.start()] + re.sub(coll, modif_lib.on_end_var[coll][p], w[mo.start():])
            else:
                w = w[:mo.start()] + re.sub(coll, modif_lib.on_end_var[coll][''], w[mo.start():])

    return w

def modif_errors(w):
    """Исправление ошибок"""

    w = repl(w, modif_lib.errors)
    w = repl(w, modif_lib.errors_on_start, 'match')

    return w

def modif(wort, pos):
    wort_init = wort

    if '#' in wort:
        wort = modif_titlo_on_start(wort, pos)
        wort = modif_titlo(wort)

    if wort_init != wort:
        wort = wort[:-1]

    if '#' not in wort:
        wort = modif_abbr(wort, pos)

    wort = modif_not_on_end(wort)
    wort = modif_varia(wort)

    if not re.search('Ж[ЕЬ]?СК', wort):
        wort = modif_stv(wort)

    wort = modif_mv(wort)
    wort = modif_on_end(wort, pos)

    return modif_errors(wort)


def subarraySum(nums, k):
    """
    :type nums: List[int]
    :type k: int
    :rtype: int
    """

    # sum=0
    # p=0
    # res=0
    #
    # while p < len(nums):
    #
    #     sum = sum + nums[p]
    #
    #     if sum > k:
    #         sum = nums[p]
    #
    #     if sum == k:
    #         res +=1
    #         sum=nums[p]
    #
    #     p += 1
    #
    # print(res)
    from collections import defaultdict
    m = defaultdict(int)
    sum = 0
    count = 0
    for i in nums:
        sum += i
        if sum == k:
            count += 1

        if sum - k in m:
            count += m[sum - k]
        m[sum] += 1
    return count

subarraySum([1,2,3,1,2],3)


from edrnsite.collaborations import PackageMessageFactory as _
from eke.site.interfaces import IPerson
from zope import schema
from zope.interface import Interface

class IGroupSpaceIndex(Interface):
    '''A group space index provides the view and discussion for a group.'''
    chair = schema.Object(
        title=_(u'Chair'),
        description=_(u'The person in charge of this group.'),
        required=False,
        schema=IPerson
    )
    coChair = schema.Object(
        title=_(u'Co-Chair'),
        description=_(u'The assistant to the person in charge of this group.'),
        required=False,
        schema=IPerson
    )
    members = schema.List(
        title=_(u'Members'),
        description=_(u'Members of this group.'),
        required=False,
        value_type=schema.Object(
            title=_(u'Member'),
            description=_(u'A member of this group.'),
            schema=IPerson
        )
    )


"""Insert LMS specific objects into the DB."""

from behave import step  # pylint:disable=no-name-in-module
from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker

from lms import db, models
from tests.bdd.step_context import StepContext
from tests.conftest import get_database_url

DATABASE_URL = get_database_url()

class LMSDBContext(StepContext):
    context_key = "db"

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.engine = create_engine(DATABASE_URL)
        self.session_maker = sessionmaker(bind=self.engine.connect())
        db.init(self.engine, stamp=False, drop=True)

        self.session = None
        self.modified_tables = None

    def create_row(self, model_class, data):
        model_class = getattr(models, model_class)
        model = model_class(**data)
        self.session.add(model)
        self.session.commit()

        self.modified_tables.append(model_class.__table__)

    def wipe(self, tables):
        if not tables:
            return

        table_names = ", ".join(f'"{table.name}"' for table in tables)
        self.session.execute(text(f"TRUNCATE {table_names} CASCADE;"))
        self.session.commit()

    def do_setup(self):
        self.session = self.session_maker()
        self.modified_tables = []

    def do_teardown(self):
        self.wipe(self.modified_tables)
        self.session.close()

@step("I create an LMS DB '{model_class}'")
def create_row_from_fixture(context, model_class):
    context.db.create_row(model_class, data={row[0]: row[1] for row in context.table})


import cv2
from PIL import Image, ImageDraw
import numpy as np
# 调用摄像头

# 调用第一摄像头
cap = cv2.VideoCapture(0)

while True:
	# 返回
	ret, frame = cap.read()
	# BGR 是cv2保存格式，
	img_pil = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
	draw = ImageDraw.Draw(img_pil)
	draw.text((100, 100), 'press q to exit', fill=(255, 255, 255))

	#
	frame = cv2.cvtColor(np.asarray(img_pil), cv2.COLOR_RGB2BGR)

	cv2.imshow("widow", frame)

	if cv2.waitKey() & 0xFF == ord('q'):
		cv2.imwrite("imgs/out.jpg", frame)
		break

cap.release()

# 都去摄像头图像信息

# 图片上

cv2都去图片信息.py

cv2都去图片信息.py


#----------------------------------
#
#    Towers of Hanoi
#    By: Darren Kent
#
#    Button.py
#    This Class is a Simple Button
#
#----------------------------------

# Imports
import os
import pygame

class Button:
    def __init__( self , xPos , yPos , buttonId , standardFilename , hoverFilename , buttonHandler ):
        self.X = xPos
        self.Y = yPos
        self.ButtonId = buttonId
        self.StandardImage = pygame.image.load( os.path.join( os.path.join( 'data' , 'textures' ) , standardFilename ))
        self.HoverImage = pygame.image.load( os.path.join( os.path.join( 'data' , 'textures' ) , hoverFilename ))
        self.Width = self.StandardImage.get_width()
        self.Height = self.StandardImage.get_height()
        self.Hover = False
        self.ButtonHandler = buttonHandler

        self.Text = pygame.font.SysFont( "times", 24 , True , False )
        self.Label = self.Text.render( str(self.ButtonId) , 1 , (255,255,255) )

    def IsMouseInside( self ):
        return self.Hover

    def SetMouseHover( self , mouseX , mouseY ):
        if( mouseX > self.X and mouseX < self.X + self.Width ):
            if( mouseY > self.Y and mouseY < self.Y + self.Height ):
                self.Hover = True
                return
        self.Hover = False

    def ExecuteButton( self ):
        self.ButtonHandler( self )

    def DrawButton( self , screen ):
        if( self.Hover ):
            screen.blit( self.HoverImage , ( self.X , self.Y ))
        else:
            screen.blit( self.StandardImage , ( self.X , self.Y ))

    def DrawButtonWithText( self , screen ):
        self.DrawButton( screen )
        screen.blit( self.Label , (  self.X + (self.Width - self.Label.get_width()) / 2 , self.Y + (self.Height - self.Label.get_height()) / 2 ))


import os
from numpy import array, sqrt
from random import choice
from unittest import TestCase, skip
from numpy.testing import assert_allclose
from proto.nav_data import *
from proto.nav_data import def_leap
from proto.parse_rinex import parse_rinex
from datetime import datetime

def distance(R1, R2):
    """
    Calculates euclidean distance (along the straight line)
    :param R1: vector in ECEF
    :param R2: vector in ECEF
    :return: Euclidean distance between R1 and R2 [in meters]
    """
    return sqrt(sum(map(lambda x, y: (x - y) ** 2, R1, R2)))

class TestNavGPS(TestCase):
    """
    Source: http://web.ics.purdue.edu/~ecalais/teaching/gps_geodesy/lab_4.pdf
    """

    def setUp(self):
        path = os.getcwd()
        if not os.path.basename(path) == 'data':
            os.chdir(os.path.join(path, 'proto', 'tests', 'data'))
        nav_file = 'epgga2.010'
        navigations = parse_rinex(nav_file)

        self.t = 346500     # seconds from epoch
        self.n = navigations['G31'][0]
        self.right_pos = array([11660.379642, 11313.211213, -21326.822815])

    def test_eph2pos(self):
        XYZ = self.n.eph2pos(self.n.epoch + self.t) / 1000
        dist = sqrt(sum(map(lambda x, y: (x - y) ** 2, XYZ, self.right_pos)))
        print("%.2f m <-- distance between exact and calculated positions" % (dist * 1000))
        assert_allclose(XYZ, self.right_pos, rtol=1e-6)
        assert_allclose(dist, 0., atol=1e-2)

    @skip("Not implemented")
    def test_utc2gps(self):
        self.fail("utc2gps test is not implemented")

class TestNavGLO(TestCase):
    def setUp(self):
        path = os.getcwd()
        if not os.path.basename(path) == 'data':
            os.chdir(os.path.join(path, 'proto', 'tests', 'data'))
        nav_file = 'log_000.15g'
        navigations = parse_rinex(nav_file)
        sats = [k for k, v in navigations.items() if len(v) > 1]   # list of possible satellites
        sat = choice(sats)  # choose one satellite randomly
        print("PRN: " + sat)
        self.navs = navigations[sat]
        # self.navs = navigations['R19']
        # for j, n in enumerate(self.navs):
        #     print j, n.date
        # print self.navs[1].date - self.navs[0].date

    @staticmethod
    def middle(x):
        """
        :param x: array of length N
        :return: array of length N-1 of the middles between elements of x
        """
        return list(map(lambda z: z[0].date + ((z[1].date - z[0].date) / 2),
                   zip(x[:-1], x[1:])))

    def test_eph2pos(self):
        dt = self.middle(self.navs)
        print("dt =", dt)
        num = 0
        d1 = self.navs[num].eph2pos(dt[num])
        d2 = self.navs[num+1].eph2pos(dt[num])
        print("at {} d1 = {}".format(dt[num], d1, self.navs[num].date))
        print("at {} d2 = {}".format(dt[num], d2, self.navs[num+1].date))
        assert_allclose(d1, d2, rtol=1e-2)  # FIXME: usually it fails

class TestDef_leap(TestCase):
    def test_def_leap(self):
        self.assertEqual(def_leap(datetime(1980, 11, 22, 0, 0, 0)), 0)
        self.assertEqual(def_leap(datetime(1981, 11, 22, 0, 0, 0)), 1)
        self.assertEqual(def_leap(datetime(1982, 11, 22, 0, 0, 0)), 2)
        self.assertEqual(def_leap(datetime(1983, 11, 22, 0, 0, 0)), 3)
        self.assertEqual(def_leap(datetime(1985, 11, 22, 0, 0, 0)), 4)
        self.assertEqual(def_leap(datetime(1988, 11, 22, 0, 0, 0)), 5)
        self.assertEqual(def_leap(datetime(1990, 11, 22, 0, 0, 0)), 6)
        self.assertEqual(def_leap(datetime(1991, 11, 22, 0, 0, 0)), 7)
        self.assertEqual(def_leap(datetime(1992, 11, 22, 0, 0, 0)), 8)
        self.assertEqual(def_leap(datetime(1993, 11, 22, 0, 0, 0)), 9)
        self.assertEqual(def_leap(datetime(1994, 11, 22, 0, 0, 0)), 10)
        self.assertEqual(def_leap(datetime(1996, 11, 22, 0, 0, 0)), 11)
        self.assertEqual(def_leap(datetime(1998, 11, 22, 0, 0, 0)), 12)
        self.assertEqual(def_leap(datetime(1999, 11, 22, 0, 0, 0)), 13)
        self.assertEqual(def_leap(datetime(2006, 11, 22, 0, 0, 0)), 14)
        self.assertEqual(def_leap(datetime(2009, 11, 22, 0, 0, 0)), 15)
        self.assertEqual(def_leap(datetime(2012, 11, 22, 0, 0, 0)), 16)
        self.assertEqual(def_leap(datetime(2015, 11, 22, 0, 0, 0)), 17)


# Imports the Google Cloud client library
from google.cloud import logging
from google.cloud.logging import DESCENDING
import re

class LogResolver:
    def __init__(self):
        self.logging_client = logging.Client()
        # log_name = 'projects/eoslaomao/logs/nodeos'
        # self.logger = logging_client.logger(log_name)

    def get_latency(self):
        try:
            FILTER = 'logName:nodeos'
            for entry in self.logging_client.list_entries(filter_=FILTER, order_by=DESCENDING):
                print(entry.payload)
                m = re.search(r"latency:\ (.*)\ ms", entry.payload)
                if hasattr(m, 'group'):
                    latency = m.group(0).split(" ")[1]
                    print("latency:" + latency + "ms")
                    return int(latency)
        except Exception as e:
            print(e)
            return -1


import argparse
import datetime

from bespoke import *

from utils import *

def evaluate(pred_comms, test_comms):
    scores_1, scores_2 = eval_comms_bidirectional(pred_comms, test_comms)
    mean_score_1 = scores_1.mean(0)
    print_results(mean_score_1, 'AvgOverAxis0')
    mean_score_2 = scores_2.mean(0)
    print_results(mean_score_2, 'AvgOverAxis1')
    mean_score_all = (mean_score_1 + mean_score_2) / 2.
    print_results(mean_score_all, 'AvgGlobal')
    return mean_score_1, mean_score_2, mean_score_all

def main(args):
    adj_mat, comms, *_ = load_snap_dataset(args.dataset, args.root)
    # Split comms
    train_comms, test_comms = split_comms(comms, args.train_size, args.seed, args.max_size)
    print(f'[{args.dataset}] # Nodes: {adj_mat.shape[0]}'
          f' # TrainComms: {len(train_comms)} # TestComms: {len(test_comms)}',
          flush=True)
    # Fit
    model = Bespoke(args.n_roles, args.n_patterns, args.eps, unique=True)
    model.fit(adj_mat, train_comms)
    pred_comms = model.sample_batch(args.pred_size)
    # Evaluating
    print(f'-> (All)  # Comms: {len(pred_comms)}')
    evaluate(pred_comms, test_comms)
    # Save
    if len(args.save_dst) > 0:
        write_comms_to_file(pred_comms, args.save_dst)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--dataset', type=str, help='dataset name', default='dblp')
    parser.add_argument('--root', type=str, help='data directory', default='datasets')
    parser.add_argument('--seed', type=int, help='random seed', default=0)
    parser.add_argument('--train_size', type=int, help='the number of training communities', default=500)
    parser.add_argument('--max_size', type=int,
                        help='Communities whose size is larger than this value will be discarded.',
                        default=0)
    parser.add_argument('--n_roles', type=int, help='the number of node labels', default=4)
    parser.add_argument('--n_patterns', type=int, help='the number of community patterns', default=5)
    parser.add_argument('--eps', type=int, help='maximum tolerance for seed selection', default=5)
    parser.add_argument('--pred_size', type=int, help='the number of communities to extract', default=50000)
    parser.add_argument('--save_dst', type=str, help='where to save the searched communities',
                        default='bespoke_comms.txt')

    args = parser.parse_args()
    seed_all(args.seed)

    print('= ' * 20)
    print('##  Starting Time:', datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), flush=True)
    main(args)
    print('## Finishing Time:', datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), flush=True)
    print('= ' * 20)


from django.contrib import admin
from btlgd.models import Article, Call

# Register your models here.
admin.site.site_header = "desing-BTL"
admin.site.site_title = "BTL"
admin.site.index_title = "Manager"

class AdminArticle(admin.ModelAdmin):
    list_display = ('name', 'ordered_date')

admin.site.register(Article, AdminArticle)

admin.site.register(Call)


import Chemins
from Utils import UTILS_Adaptations
from Utils.UTILS_Traduction import _
import wx
from Ctrl import CTRL_Bouton_image
import wx.lib.agw.hypertreelist as HTL
from wx.lib.agw.customtreectrl import EVT_TREE_ITEM_CHECKED
import datetime

from Ctrl import CTRL_Bandeau
from Ctrl import CTRL_Calendrier
from Ctrl import CTRL_Saisie_transport
from Ctrl import CTRL_Saisie_date
import GestionDB

def MelangeDictionnaires(d1={}, d2={}):
    for key, value in d2.items() :
        d1[key] = value
    return d1

def DateEngEnDateDD(dateEng):
    return datetime.date(int(dateEng[:4]), int(dateEng[5:7]), int(dateEng[8:10]))

class CTRL_Choix_unites(HTL.HyperTreeList):
    def __init__(self, parent, IDindividu=None):
        HTL.HyperTreeList.__init__(self, parent, -1)
        self.parent = parent
        self.IDindividu = IDindividu
        self.MAJenCours = False

        self.SetBackgroundColour(wx.WHITE)
        self.SetAGWWindowStyleFlag( HTL.TR_NO_HEADER | wx.TR_HIDE_ROOT | wx.TR_HAS_BUTTONS | wx.TR_HAS_VARIABLE_ROW_HEIGHT | wx.TR_FULL_ROW_HIGHLIGHT )
        self.EnableSelectionVista(True)

        self.SetToolTip(wx.ToolTip(_(u"Cochez les unités conditionnelles")))

        # Création des colonnes
        self.AddColumn(_(u"Unités"))
        self.SetColumnWidth(0, 220)

        # Binds
        self.Bind(EVT_TREE_ITEM_CHECKED, self.OnCheckItem)

        self.MAJ()

    def OnCheckItem(self, event):
        if self.MAJenCours == False :
            item = event.GetItem()
            # Active ou non les branches enfants
            if self.GetPyData(item)["type"] == "activite" :
                if self.IsItemChecked(item) :
                    self.EnableChildren(item, True)
                    self.CheckChilds(item)
                else:
                    self.CheckChilds(item, False)
                    self.EnableChildren(item, False)

    def GetCoches(self):
        dictCoches = {}
        parent = self.root
        for index in range(0, self.GetChildrenCount(self.root)):
            parent = self.GetNext(parent)
            # Recherche des activités cochées
            if self.IsItemChecked(parent) :
                IDactivite = self.GetPyData(parent)["ID"]
                # Recherche des unités cochées
                listeUnites = []
                item, cookie = self.GetFirstChild(parent)
                for index in range(0, self.GetChildrenCount(parent)):
                    if self.IsItemChecked(item) :
                        IDunite = self.GetPyData(item)["ID"]
                        listeUnites.append(IDunite)
                    item = self.GetNext(item)
                if len(listeUnites) > 0 :
                    dictCoches[IDactivite] = listeUnites
        return dictCoches

    def GetUnites(self) :
        dictCoches = self.GetCoches()
        listeUnites = []
        for IDactivite, listeUnitesTemp in dictCoches.items() :
            for IDunite in listeUnitesTemp :
                listeUnites.append(IDunite)
        return listeUnites

    def SetUnites(self, texteUnites=""):
        listeCoches = []
        listeTemp = texteUnites.split(";")
        for IDunite in listeTemp :
            listeCoches.append(int(IDunite))
        self.MAJ(listeCoches)

    def GetTexteUnites(self):
        """ Retourne une chaine texte des ID cochés """
        listeUnites = self.GetUnites()
        listeTemp = []
        for IDunite in listeUnites :
            listeTemp.append(str(IDunite))
        texte = ";".join(listeTemp)
        return texte

    def MAJ(self, listeCoches=[]):
        """ Met à jour (redessine) tout le contrôle """
        self.dictUnites = self.Importation()
        self.MAJenCours = True
        self.DeleteAllItems()
        self.root = self.AddRoot(_(u"Racine"))
        self.Remplissage(listeCoches)
        self.MAJenCours = False

    def Remplissage(self, listeCoches=[]):
        # Tri des activités par date de fin de validité
        listeActivites = []
        for IDactivite, dictActivite in self.dictUnites.items() :
            listeActivites.append((dictActivite["date_fin"], IDactivite))
        listeActivites.sort(reverse=True)

        # Remplissage
        for date_fin, IDactivite in listeActivites :

            # Niveau Activité
            label = self.dictUnites[IDactivite]["nom"]
            niveauActivite = self.AppendItem(self.root, label, ct_type=1)
            self.SetPyData(niveauActivite, {"type" : "activite", "ID" : IDactivite, "label" : label})
            self.SetItemBold(niveauActivite, True)

            # Niveau Unité
            for ordre, IDunite, nomUnite in self.dictUnites[IDactivite]["unites"] :
                label = nomUnite
                niveauUnite = self.AppendItem(niveauActivite, label, ct_type=1)
                self.SetPyData(niveauUnite, {"type" : "depot", "ID" : IDunite, "label" : label})
                if IDunite in listeCoches :
                    self.CheckItem(niveauUnite)
                    self.CheckItem(niveauActivite)

            # Coche toutes les branches enfants
            if self.IsItemChecked(niveauActivite) == False :
                self.EnableChildren(niveauActivite, False)
            self.Expand(niveauActivite)

    def Importation(self):
        dictUnites = {}
        DB = GestionDB.DB()
        req = """SELECT IDunite, unites.nom, ordre, unites.IDactivite, activites.nom, activites.date_debut, activites.date_fin
        FROM unites
        LEFT JOIN activites ON activites.IDactivite = unites.IDactivite
        LEFT JOIN inscriptions ON inscriptions.IDactivite = activites.IDactivite
        WHERE inscriptions.statut='ok' AND IDindividu=%d
        ORDER BY unites.IDactivite, ordre;""" % self.IDindividu
        DB.ExecuterReq(req)
        listeDonnees = DB.ResultatReq()
        DB.Close()
        for IDunite, nomUnite, ordre, IDactivite, nomActivite, date_debut, date_fin in listeDonnees :
            if date_debut != None : date_debut = DateEngEnDateDD(date_debut)
            if date_fin != None : date_fin = DateEngEnDateDD(date_fin)

            if (IDactivite in dictUnites) == False :
                dictUnites[IDactivite] = {"nom" : nomActivite, "date_debut" : date_debut, "date_fin" : date_fin, "unites" : []}
            dictUnites[IDactivite]["unites"].append((ordre, IDunite, nomUnite))

        return dictUnites

class CTRL_Saisie_prog(wx.Panel):
    def __init__(self, parent, IDtransport=None, IDindividu=None):
        wx.Panel.__init__(self, parent, id=-1, style=wx.TAB_TRAVERSAL)
        self.parent = parent
        self.IDtransport = IDtransport
        self.IDindividu = IDindividu
        self.liste_jours = ("lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche")

        # Validité
        self.box_validite_staticbox = wx.StaticBox(self, -1, _(u"Validité"))
        self.label_date_debut = wx.StaticText(self, -1,u"Du :")
        self.ctrl_date_debut = CTRL_Saisie_date.Date2(self)
        self.label_date_fin = wx.StaticText(self, -1,_(u"Au :"))
        self.ctrl_date_fin = CTRL_Saisie_date.Date2(self)
        self.label_actif = wx.StaticText(self, -1,_(u"Actif :"))
        self.ctrl_actif = wx.CheckBox(self, -1, u"")
        self.ctrl_actif.SetValue(True)

        # Conditions
        self.box_conditions_staticbox = wx.StaticBox(self, -1, _(u"Conditions"))

        # Périodes scolaires
        self.label_periodes_scolaires = wx.StaticText(self, -1,_(u"Périodes scolaires :"))
        self.check_scolaire_lundi = wx.CheckBox(self, -1,u"L")
        self.check_scolaire_mardi = wx.CheckBox(self, -1,u"M")
        self.check_scolaire_mercredi = wx.CheckBox(self, -1,u"M")
        self.check_scolaire_jeudi = wx.CheckBox(self, -1,u"J")
        self.check_scolaire_vendredi = wx.CheckBox(self, -1,u"V")
        self.check_scolaire_samedi = wx.CheckBox(self, -1,u"S")
        self.check_scolaire_dimanche = wx.CheckBox(self, -1,u"D")
        self.CheckJours("scolaire")

        # Périodes de vacances
        self.label_periodes_vacances = wx.StaticText(self, -1,_(u"Périodes de vacances :"))
        self.check_vacances_lundi = wx.CheckBox(self, -1,u"L")
        self.check_vacances_mardi = wx.CheckBox(self, -1,u"M")
        self.check_vacances_mercredi = wx.CheckBox(self, -1,u"M")
        self.check_vacances_jeudi = wx.CheckBox(self, -1,u"J")
        self.check_vacances_vendredi = wx.CheckBox(self, -1,u"V")
        self.check_vacances_samedi = wx.CheckBox(self, -1,u"S")
        self.check_vacances_dimanche = wx.CheckBox(self, -1,u"D")
        self.CheckJours("vacances")

        # Unités
        self.label_unites = wx.StaticText(self, -1,_(u"Unités de consommation :"))
        self.ctrl_unites = CTRL_Choix_unites(self, IDindividu=self.IDindividu)

        self.__set_properties()
        self.__do_layout()

        # Importation
        if self.IDtransport != None :
            self.Importation()

    def __set_properties(self):
        self.check_scolaire_lundi.SetToolTip(wx.ToolTip(_(u"Lundi")))
        self.check_scolaire_mardi.SetToolTip(wx.ToolTip(_(u"Mardi")))
        self.check_scolaire_mercredi.SetToolTip(wx.ToolTip(_(u"Mercredi")))
        self.check_scolaire_jeudi.SetToolTip(wx.ToolTip(_(u"Jeudi")))
        self.check_scolaire_vendredi.SetToolTip(wx.ToolTip(_(u"Vendredi")))
        self.check_scolaire_samedi.SetToolTip(wx.ToolTip(_(u"Samedi")))
        self.check_scolaire_dimanche.SetToolTip(wx.ToolTip(_(u"Dimanche")))
        self.check_vacances_lundi.SetToolTip(wx.ToolTip(_(u"Lundi")))
        self.check_vacances_mardi.SetToolTip(wx.ToolTip(_(u"Mardi")))
        self.check_vacances_mercredi.SetToolTip(wx.ToolTip(_(u"Mercredi")))
        self.check_vacances_jeudi.SetToolTip(wx.ToolTip(_(u"Jeudi")))
        self.check_vacances_vendredi.SetToolTip(wx.ToolTip(_(u"Vendredi")))
        self.check_vacances_samedi.SetToolTip(wx.ToolTip(_(u"Samedi")))
        self.check_vacances_dimanche.SetToolTip(wx.ToolTip(_(u"Dimanche")))

    def __do_layout(self):
        grid_sizer_base = wx.FlexGridSizer(rows=3, cols=1, vgap=10, hgap=10)

        # Validité
        box_validite = wx.StaticBoxSizer(self.box_validite_staticbox, wx.VERTICAL)
        grid_sizer_validite = wx.FlexGridSizer(rows=3, cols=2, vgap=5, hgap=5)
        grid_sizer_validite.Add(self.label_date_debut, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
        grid_sizer_validite.Add(self.ctrl_date_debut, 0, 0, 0)
        grid_sizer_validite.Add(self.label_date_fin, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
        grid_sizer_validite.Add(self.ctrl_date_fin, 0, 0, 0)
        grid_sizer_validite.Add(self.label_actif, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
        grid_sizer_validite.Add(self.ctrl_actif, 0, 0, 0)
        box_validite.Add(grid_sizer_validite, 1, wx.ALL|wx.EXPAND, 10)
        grid_sizer_base.Add(box_validite, 1, wx.EXPAND, 0)

        # Conditions
        box_conditions = wx.StaticBoxSizer(self.box_conditions_staticbox, wx.VERTICAL)
        grid_sizer_conditions = wx.FlexGridSizer(rows=6, cols=1, vgap=5, hgap=5)

        # Périodes scolaires
        grid_sizer_conditions.Add(self.label_periodes_scolaires, 0, 0, 0)

        grid_sizer_scolaire = wx.FlexGridSizer(rows=1, cols=7, vgap=5, hgap=5)
        grid_sizer_scolaire.Add(self.check_scolaire_lundi, 0, 0, 0)
        grid_sizer_scolaire.Add(self.check_scolaire_mardi, 0, 0, 0)
        grid_sizer_scolaire.Add(self.check_scolaire_mercredi, 0, 0, 0)
        grid_sizer_scolaire.Add(self.check_scolaire_jeudi, 0, 0, 0)
        grid_sizer_scolaire.Add(self.check_scolaire_vendredi, 0, 0, 0)
        grid_sizer_scolaire.Add(self.check_scolaire_samedi, 0, 0, 0)
        grid_sizer_scolaire.Add(self.check_scolaire_dimanche, 0, 0, 0)
        grid_sizer_conditions.Add(grid_sizer_scolaire, 1, wx.EXPAND, 0)

        # Périodes de vacances
        grid_sizer_conditions.Add(self.label_periodes_vacances, 0, wx.TOP, 10)

        grid_sizer_vacances = wx.FlexGridSizer(rows=1, cols=7, vgap=5, hgap=5)
        grid_sizer_vacances.Add(self.check_vacances_lundi, 0, 0, 0)
        grid_sizer_vacances.Add(self.check_vacances_mardi, 0, 0, 0)
        grid_sizer_vacances.Add(self.check_vacances_mercredi, 0, 0, 0)
        grid_sizer_vacances.Add(self.check_vacances_jeudi, 0, 0, 0)
        grid_sizer_vacances.Add(self.check_vacances_vendredi, 0, 0, 0)
        grid_sizer_vacances.Add(self.check_vacances_samedi, 0, 0, 0)
        grid_sizer_vacances.Add(self.check_vacances_dimanche, 0, 0, 0)
        grid_sizer_conditions.Add(grid_sizer_vacances, 1, wx.EXPAND, 0)

        # Unités
        grid_sizer_conditions.Add(self.label_unites, 0, wx.TOP, 10)
        grid_sizer_conditions.Add(self.ctrl_unites, 1, wx.EXPAND, 0)

        grid_sizer_conditions.AddGrowableCol(0)
        grid_sizer_conditions.AddGrowableRow(5)

        box_conditions.Add(grid_sizer_conditions, 1, wx.ALL|wx.EXPAND, 10)
        grid_sizer_base.Add(box_conditions, 1, wx.EXPAND, 0)

        self.SetSizer(grid_sizer_base)
        grid_sizer_base.Fit(self)
        grid_sizer_base.AddGrowableRow(1)
        grid_sizer_base.AddGrowableCol(0)

    def CheckJours(self, periode="scolaire"):
        for jour in self.liste_jours[:5] :
            getattr(self, "check_%s_%s" % (periode, jour)).SetValue(True)

    def GetJours(self, periode="scolaire"):
        listeTemp = []
        index = 0
        for jour in self.liste_jours :
            etat = getattr(self, "check_%s_%s" % (periode, jour)).GetValue()
            if etat == True :
                listeTemp.append(str(index))
            index += 1
        texte = ";".join(listeTemp)
        return texte

    def SetJours(self, periode="scolaire", texteJours=""):
        listeJoursTemp = texteJours.split(";")
        listeJours = []
        for jour in listeJoursTemp :
            if jour != "" :
                listeJours.append(int(jour))
        index = 0
        for jour in self.liste_jours :
            if index in listeJours :
                etat = True
            else :
                etat = False
            getattr(self, "check_%s_%s" % (periode, jour)).SetValue(etat)
            index += 1

    def GetData(self):
        dictData = {}
        # Période
        dictData["date_debut"] = self.ctrl_date_debut.GetDate()
        dictData["date_fin"] = self.ctrl_date_fin.GetDate()
        # Actif
        dictData["actif"] = int(self.ctrl_actif.GetValue())
        # Périodes scolaires
        dictData["jours_scolaires"] = self.GetJours("scolaire")
        # Périodes vacances
        dictData["jours_vacances"] = self.GetJours("vacances")
        # Unités
        dictData["unites"] = self.ctrl_unites.GetTexteUnites()
        return dictData

    def Validation(self):
        dictData = self.GetData()
        if dictData["date_debut"] == None or self.ctrl_date_debut.Validation() == False :
                dlg = wx.MessageDialog(self, _(u"Vous devez obligatoirement saisir une date de début de période !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
                dlg.ShowModal()
                dlg.Destroy()
                self.ctrl_date_debut.SetFocus()
                return False
        date_fin = self.ctrl_date_fin.GetDate()
        if dictData["date_fin"] == None or self.ctrl_date_fin.Validation() == False :
                dlg = wx.MessageDialog(self, _(u"Vous devez obligatoirement saisir une date de fin de période !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
                dlg.ShowModal()
                dlg.Destroy()
                self.ctrl_date_fin.SetFocus()
                return False
        if len(dictData["jours_scolaires"]) == 0 and len(dictData["jours_vacances"]) == 0 :
                dlg = wx.MessageDialog(self, _(u"Vous devez cocher au moins un jour de la semaine !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
                dlg.ShowModal()
                dlg.Destroy()
                return False
        if len(dictData["unites"]) == 0 :
                dlg = wx.MessageDialog(self, _(u"Vous devez cocher au moins une unité de consommation !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
                dlg.ShowModal()
                dlg.Destroy()
                return False
        return True

    def Importation(self):
        """ Importation des données """
        # Importation
        DB = GestionDB.DB()
        req = """SELECT date_debut, date_fin, actif, jours_scolaires, jours_vacances, unites
        FROM transports
        WHERE IDtransport=%d;""" % self.IDtransport
        DB.ExecuterReq(req)
        listeValeurs = DB.ResultatReq()
        DB.Close()
        if len(listeValeurs) == 0 : return
        date_debut, date_fin, actif, jours_scolaires, jours_vacances, unites = listeValeurs[0]

        self.ctrl_date_debut.SetDate(date_debut)
        self.ctrl_date_fin.SetDate(date_fin)
        self.ctrl_actif.SetValue(actif)
        self.SetJours("scolaire", jours_scolaires)
        self.SetJours("vacances", jours_vacances)
        self.ctrl_unites.SetUnites(unites)

# -----------------------------------------------------------------------------------------------------------------------------------------------------------

class CTRL_Planning(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, id=-1, style=wx.TAB_TRAVERSAL)
        self.parent = parent
        self.liste_jours = ("lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche")

        # Période
        self.label_date_debut = wx.StaticText(self, -1,u"Du :")
        self.ctrl_date_debut = CTRL_Saisie_date.Date2(self)
        self.label_date_fin = wx.StaticText(self, -1,_(u"Au :"))
        self.ctrl_date_fin = CTRL_Saisie_date.Date2(self)

        # Périodes scolaires
        self.label_periodes_scolaires = wx.StaticText(self, -1,_(u"Périodes scolaires :"))
        self.check_scolaire_lundi = wx.CheckBox(self, -1,u"L")
        self.check_scolaire_mardi = wx.CheckBox(self, -1,u"M")
        self.check_scolaire_mercredi = wx.CheckBox(self, -1,u"M")
        self.check_scolaire_jeudi = wx.CheckBox(self, -1,u"J")
        self.check_scolaire_vendredi = wx.CheckBox(self, -1,u"V")
        self.check_scolaire_samedi = wx.CheckBox(self, -1,u"S")
        self.check_scolaire_dimanche = wx.CheckBox(self, -1,u"D")
        self.CheckJours("scolaire")

        # Périodes de vacances
        self.label_periodes_vacances = wx.StaticText(self, -1,_(u"Périodes de vacances :"))
        self.check_vacances_lundi = wx.CheckBox(self, -1,u"L")
        self.check_vacances_mardi = wx.CheckBox(self, -1,u"M")
        self.check_vacances_mercredi = wx.CheckBox(self, -1,u"M")
        self.check_vacances_jeudi = wx.CheckBox(self, -1,u"J")
        self.check_vacances_vendredi = wx.CheckBox(self, -1,u"V")
        self.check_vacances_samedi = wx.CheckBox(self, -1,u"S")
        self.check_vacances_dimanche = wx.CheckBox(self, -1,u"D")
        self.CheckJours("vacances")

        self.__set_properties()
        self.__do_layout()

    def __set_properties(self):
        self.check_scolaire_lundi.SetToolTip(wx.ToolTip(_(u"Lundi")))
        self.check_scolaire_mardi.SetToolTip(wx.ToolTip(_(u"Mardi")))
        self.check_scolaire_mercredi.SetToolTip(wx.ToolTip(_(u"Mercredi")))
        self.check_scolaire_jeudi.SetToolTip(wx.ToolTip(_(u"Jeudi")))
        self.check_scolaire_vendredi.SetToolTip(wx.ToolTip(_(u"Vendredi")))
        self.check_scolaire_samedi.SetToolTip(wx.ToolTip(_(u"Samedi")))
        self.check_scolaire_dimanche.SetToolTip(wx.ToolTip(_(u"Dimanche")))
        self.check_vacances_lundi.SetToolTip(wx.ToolTip(_(u"Lundi")))
        self.check_vacances_mardi.SetToolTip(wx.ToolTip(_(u"Mardi")))
        self.check_vacances_mercredi.SetToolTip(wx.ToolTip(_(u"Mercredi")))
        self.check_vacances_jeudi.SetToolTip(wx.ToolTip(_(u"Jeudi")))
        self.check_vacances_vendredi.SetToolTip(wx.ToolTip(_(u"Vendredi")))
        self.check_vacances_samedi.SetToolTip(wx.ToolTip(_(u"Samedi")))
        self.check_vacances_dimanche.SetToolTip(wx.ToolTip(_(u"Dimanche")))

    def __do_layout(self):
        grid_sizer_base = wx.FlexGridSizer(rows=7, cols=1, vgap=8, hgap=8)
        grid_sizer_base.Add( (5, 5), 1, wx.EXPAND, 0)

        # Période
        grid_sizer_date_debut = wx.FlexGridSizer(rows=1, cols=2, vgap=5, hgap=5)
        grid_sizer_date_debut.Add(self.label_date_debut, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
        grid_sizer_date_debut.Add(self.ctrl_date_debut, 0, 0, 0)
        grid_sizer_base.Add(grid_sizer_date_debut, 1, wx.EXPAND, 0)

        grid_sizer_date_fin = wx.FlexGridSizer(rows=1, cols=2, vgap=5, hgap=5)
        grid_sizer_date_fin.Add(self.label_date_fin, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
        grid_sizer_date_fin.Add(self.ctrl_date_fin, 0, 0, 0)
        grid_sizer_base.Add(grid_sizer_date_fin, 1, wx.EXPAND, 0)

        # Périodes scolaires
        grid_sizer_base.Add(self.label_periodes_scolaires, 0, wx.TOP, 10)

        grid_sizer_scolaire = wx.FlexGridSizer(rows=1, cols=7, vgap=5, hgap=5)
        grid_sizer_scolaire.Add(self.check_scolaire_lundi, 0, 0, 0)
        grid_sizer_scolaire.Add(self.check_scolaire_mardi, 0, 0, 0)
        grid_sizer_scolaire.Add(self.check_scolaire_mercredi, 0, 0, 0)
        grid_sizer_scolaire.Add(self.check_scolaire_jeudi, 0, 0, 0)
        grid_sizer_scolaire.Add(self.check_scolaire_vendredi, 0, 0, 0)
        grid_sizer_scolaire.Add(self.check_scolaire_samedi, 0, 0, 0)
        grid_sizer_scolaire.Add(self.check_scolaire_dimanche, 0, 0, 0)
        grid_sizer_base.Add(grid_sizer_scolaire, 1, wx.EXPAND, 0)

        # Périodes de vacances
        grid_sizer_base.Add(self.label_periodes_vacances, 0, wx.TOP, 10)

        grid_sizer_vacances = wx.FlexGridSizer(rows=1, cols=7, vgap=5, hgap=5)
        grid_sizer_vacances.Add(self.check_vacances_lundi, 0, 0, 0)
        grid_sizer_vacances.Add(self.check_vacances_mardi, 0, 0, 0)
        grid_sizer_vacances.Add(self.check_vacances_mercredi, 0, 0, 0)
        grid_sizer_vacances.Add(self.check_vacances_jeudi, 0, 0, 0)
        grid_sizer_vacances.Add(self.check_vacances_vendredi, 0, 0, 0)
        grid_sizer_vacances.Add(self.check_vacances_samedi, 0, 0, 0)
        grid_sizer_vacances.Add(self.check_vacances_dimanche, 0, 0, 0)
        grid_sizer_base.Add(grid_sizer_vacances, 1, wx.EXPAND, 0)

        self.SetSizer(grid_sizer_base)
        grid_sizer_base.Fit(self)
        grid_sizer_base.AddGrowableCol(0)

    def CheckJours(self, periode="scolaire"):
        for jour in self.liste_jours[:5] :
            getattr(self, "check_%s_%s" % (periode, jour)).SetValue(True)

    def GetJours(self, periode="scolaire"):
        listeTemp = []
        index = 0
        for jour in self.liste_jours :
            etat = getattr(self, "check_%s_%s" % (periode, jour)).GetValue()
            if etat == True :
                listeTemp.append(index)
            index += 1
        return listeTemp

    def GetData(self):
        dictData = {}
        # Période
        dictData["date_debut"] = self.ctrl_date_debut.GetDate()
        dictData["date_fin"] = self.ctrl_date_fin.GetDate()
        # Périodes scolaires
        dictData["jours_scolaires"] = self.GetJours("scolaire")
        # Périodes vacances
        dictData["jours_vacances"] = self.GetJours("vacances")
        return dictData

    def Validation(self):
        dictData = self.GetData()
        if dictData["date_debut"] == None or self.ctrl_date_debut.Validation() == False :
                dlg = wx.MessageDialog(self, _(u"Vous devez obligatoirement saisir une date de début de période !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
                dlg.ShowModal()
                dlg.Destroy()
                self.ctrl_date_debut.SetFocus()
                return False
        date_fin = self.ctrl_date_fin.GetDate()
        if dictData["date_fin"] == None or self.ctrl_date_fin.Validation() == False :
                dlg = wx.MessageDialog(self, _(u"Vous devez obligatoirement saisir une date de fin de période !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
                dlg.ShowModal()
                dlg.Destroy()
                self.ctrl_date_fin.SetFocus()
                return False
        if len(dictData["jours_scolaires"]) == 0 and len(dictData["jours_vacances"]) == 0 :
                dlg = wx.MessageDialog(self, _(u"Vous devez cocher au moins un jour de la semaine !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
                dlg.ShowModal()
                dlg.Destroy()
                return False
        return True

class CTRL_Mode_multiple(wx.Choicebook):
    def __init__(self, parent):
        wx.Choicebook.__init__(self, parent, id=-1)
        self.parent = parent
        #self.SetToolTip(wx.ToolTip(_(u"Sélectionnez ici une localisation")))

        self.listePanels = [
            ("CALENDRIER", _(u"Selon les dates sélectionnées"), CTRL_Calendrier.CTRL(self, afficheBoutonAnnuel=False) ),
            ("PLANNING", _(u"Selon le planning suivant"), CTRL_Planning(self) ),
            ]

        for code, label, ctrl in self.listePanels :
            self.AddPage(ctrl, label)

        # Sélection par défaut
        self.SetSelection(0)

    def GetData(self):
        dictData = {}
        if self.GetSelection() == 0 :
            # Mode Calendrier
            dictData["mode"] = "CALENDRIER"
            ctrl = self.listePanels[self.GetSelection()][2]
            listeDates = ctrl.GetSelections()
            dictData["dates"] = listeDates
        else :
            # Mode Planning
            dictData["mode"] = "PLANNING"
            ctrl = self.listePanels[self.GetSelection()][2]
            dictData = MelangeDictionnaires(dictData, ctrl.GetData())
        return dictData

    def Validation(self):
        dictData = self.GetData()
        if dictData["mode"] == "CALENDRIER" :
            if dictData["dates"] == None or len(dictData["dates"]) == 0 :
                dlg = wx.MessageDialog(self, _(u"Vous n'avez sélectionné aucune date dans le calendrier !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
                dlg.ShowModal()
                dlg.Destroy()
                return False
        if dictData["mode"] == "PLANNING" :
            ctrl = self.listePanels[self.GetSelection()][2]
            if ctrl.Validation() == False :
                return False
        return True

#------------------------------------------------------------------------------------------------------

class CTRL_Choix_activite(wx.Choice):
    def __init__(self, parent, IDindividu=None):
        wx.Choice.__init__(self, parent, -1, size=(-1, -1))
        self.parent = parent
        self.IDindividu = IDindividu
        self.MAJ()
        self.SetToolTip(wx.ToolTip(_(u"Sélectionnez ici une activité")))

    def MAJ(self):
        listeItems = self.GetListeDonnees()
        self.SetItems(listeItems)
        if len(listeItems) == 0 :
            self.Enable(False)
        else:
            self.Enable(True)
            self.Select(0)

    def GetListeDonnees(self):
        db = GestionDB.DB()
        req = """SELECT activites.IDactivite, activites.nom
        FROM activites
        LEFT JOIN inscriptions ON inscriptions.IDactivite = activites.IDactivite
        WHERE inscriptions.statut='ok' AND IDindividu=%d
        ORDER BY activites.date_fin DESC;""" % self.IDindividu
        db.ExecuterReq(req)
        listeDonnees = db.ResultatReq()
        db.Close()
        listeItems = []
        self.dictDonnees = {}
        index = 0
        for IDactivite, nom in listeDonnees :
            self.dictDonnees[index] = { "ID" : IDactivite, "nom " : nom}
            listeItems.append(nom)
            index += 1
        return listeItems

    def SetID(self, ID=0):
        if ID == None :
            self.SetSelection(0)
        for index, values in self.dictDonnees.items():
            if values["ID"] == ID :
                 self.SetSelection(index)

    def GetID(self):
        index = self.GetSelection()
        if index == -1 : return None
        return self.dictDonnees[index]["ID"]

class CTRL_Saisie_multiple(wx.Panel):
    def __init__(self, parent, IDindividu=None):
        wx.Panel.__init__(self, parent, id=-1, style=wx.TAB_TRAVERSAL)
        self.parent = parent
        self.IDindividu = IDindividu

        # Mode
        self.box_mode_staticbox = wx.StaticBox(self, -1, _(u"Mode de saisie"))
        self.radio_unique = wx.RadioButton(self, -1, _(u"Saisie unique"), style=wx.RB_GROUP)
        self.radio_multiple = wx.RadioButton(self, -1, _(u"Saisie multiple"))

        # Saisie multiple
        self.box_multiple_staticbox = wx.StaticBox(self, -1, _(u"Saisie multiple"))
        self.ctrl_multiple = CTRL_Mode_multiple(self)

        # Options
        self.box_options_staticbox = wx.StaticBox(self, -1, _(u"Options"))
        self.check_feries = wx.CheckBox(self, -1, _(u"Inclure les jours fériés"))
        self.check_activite = wx.CheckBox(self, -1, _(u"Uniquement si individu inscrit sur l'activité :"))
        self.ctrl_activite = CTRL_Choix_activite(self, IDindividu=self.IDindividu)

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_RADIOBUTTON, self.OnChoixMode, self.radio_unique)
        self.Bind(wx.EVT_RADIOBUTTON, self.OnChoixMode, self.radio_multiple)
        self.Bind(wx.EVT_CHECKBOX, self.OnCheckActivite, self.check_activite)

        # Init contrôles
        self.OnChoixMode(None)

    def __set_properties(self):
        self.radio_unique.SetToolTip(wx.ToolTip(_(u"Sélectionnez ce mode pour saisir un seul transport")))
        self.radio_multiple.SetToolTip(wx.ToolTip(_(u"Sélectionnez ce mode pour saisir plusieurs transports à la fois")))
        self.check_feries.SetToolTip(wx.ToolTip(_(u"Cochez cette case pour saisir également des transports sur les jours fériés")))
        self.check_activite.SetToolTip(wx.ToolTip(_(u"Cochez cette case pour saisir ce transport uniquement les jours sur lesquels l'individu est inscrit sur une activité donnée")))
        self.ctrl_activite.SetToolTip(wx.ToolTip(_(u"Sélectionnez une activité")))

    def __do_layout(self):
        grid_sizer_base = wx.FlexGridSizer(rows=3, cols=1, vgap=10, hgap=10)

        # Mode de saisie
        box_mode = wx.StaticBoxSizer(self.box_mode_staticbox, wx.VERTICAL)
        grid_sizer_mode = wx.FlexGridSizer(rows=2, cols=2, vgap=20, hgap=20)
        grid_sizer_mode.Add(self.radio_unique, 0, 0, 0)
        grid_sizer_mode.Add(self.radio_multiple, 0, 0, 0)
        box_mode.Add(grid_sizer_mode, 1, wx.ALL|wx.EXPAND, 10)
        grid_sizer_base.Add(box_mode, 1, wx.EXPAND, 0)

        # Saisie multiple
        box_multiple = wx.StaticBoxSizer(self.box_multiple_staticbox, wx.VERTICAL)
        box_multiple.Add(self.ctrl_multiple, 1, wx.ALL|wx.EXPAND, 10)
        grid_sizer_base.Add(box_multiple, 1, wx.EXPAND, 0)

        # Options
        box_options = wx.StaticBoxSizer(self.box_options_staticbox, wx.VERTICAL)
        grid_sizer_options = wx.FlexGridSizer(rows=3, cols=1, vgap=5, hgap=5)
        grid_sizer_options.Add(self.check_feries, 0, 0, 0)
        grid_sizer_options.Add(self.check_activite, 0, 0, 0)
        grid_sizer_options.Add(self.ctrl_activite, 0, wx.LEFT|wx.EXPAND, 20)
        grid_sizer_options.AddGrowableCol(0)
        box_options.Add(grid_sizer_options, 1, wx.ALL|wx.EXPAND, 10)

        grid_sizer_base.Add(box_options, 1, wx.EXPAND, 0)
        self.SetSizer(grid_sizer_base)
        grid_sizer_base.Fit(self)
        grid_sizer_base.AddGrowableRow(1)
        grid_sizer_base.AddGrowableCol(0)

    def OnChoixMode(self, event):
        etat =  self.radio_multiple.GetValue()
        self.ctrl_multiple.Enable(etat)
        self.check_feries.Enable(etat)
        self.check_activite.Enable(etat)
        self.OnCheckActivite(None)
        # Affiche ou non les dates de saisie
        self.parent.AffichageDates(not etat)

    def OnCheckActivite(self, event):
        if self.radio_multiple.GetValue() == True and self.check_activite.GetValue() == True :
            self.ctrl_activite.Enable(True)
        else :
            self.ctrl_activite.Enable(False)

    def GetData(self):
        dictData = None
        if self.radio_multiple.GetValue() == True :
            dictData = {}

            # Récupération paramètres multiples
            dictData = self.ctrl_multiple.GetData()

            # Récupération paramètres Options
            dictData["feries"] = self.check_feries.GetValue()
            dictData["activite"] = None
            if self.check_activite.GetValue() == True :
                dictData["activite"] = self.ctrl_activite.GetID()

        return dictData

    def Validation(self):
        if self.radio_multiple.GetValue() == True :
            # Validation Paramètres multiples
            if self.ctrl_multiple.Validation() == False :
                return False
            # Validation Options
            if self.check_activite.GetValue() == True and self.ctrl_activite.GetID() == None :
                dlg = wx.MessageDialog(self, _(u"Vous n'avez sélectionné aucune activité !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
                dlg.ShowModal()
                dlg.Destroy()
                self.ctrl_activite.SetFocus()
                return False
        return True

class Dialog_prog(wx.Dialog):
    def __init__(self, parent, IDtransport=None, IDindividu=None):
        wx.Dialog.__init__(self, parent, -1, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.MAXIMIZE_BOX|wx.MINIMIZE_BOX)
        self.parent = parent
        self.IDtransport = IDtransport
        self.IDindividu = IDindividu

        # Bandeau
        titre = _(u"Programmation d'un transport")
        intro = _(u"Vous pouvez ici programmer un transport. Celui-ci sera ainsi créé automatiquement par Noethys à chaque fois qu'une consommation sera saisie pour cet individu en fonction des paramètres que vous aurez précisé ci-dessous.")
        self.SetTitle(titre)
        self.ctrl_bandeau = CTRL_Bandeau.Bandeau(self, titre=titre, texte=intro, hauteurHtml=30, nomImage="Images/32x32/Transport.png")

        # Contenu
        self.ctrl_saisie = CTRL_Saisie_transport.CTRL(self, IDtransport=IDtransport, IDindividu=IDindividu)
        self.ctrl_saisie_prog = CTRL_Saisie_prog(self, IDtransport=IDtransport, IDindividu=IDindividu)

        # Boutons
        self.bouton_aide = CTRL_Bouton_image.CTRL(self, texte=_(u"Aide"), cheminImage="Images/32x32/Aide.png")
        self.bouton_ok = CTRL_Bouton_image.CTRL(self, texte=_(u"Ok"), cheminImage="Images/32x32/Valider.png")
        self.bouton_annuler = CTRL_Bouton_image.CTRL(self, id=wx.ID_CANCEL, texte=_(u"Annuler"), cheminImage="Images/32x32/Annuler.png")

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.OnBoutonOk, self.bouton_ok)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonAide, self.bouton_aide)

        # Init contrôles
        self.AffichageDates(False)

    def __set_properties(self):
        self.bouton_aide.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour obtenir de l'aide")))
        self.bouton_ok.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour valider")))
        self.bouton_annuler.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour annuler")))
        self.SetMinSize((800, 660))

    def __do_layout(self):
        grid_sizer_base = wx.FlexGridSizer(rows=3, cols=1, vgap=10, hgap=10)
        grid_sizer_base.Add(self.ctrl_bandeau, 1, wx.EXPAND, 0)

        grid_sizer_contenu = wx.FlexGridSizer(rows=1, cols=2, vgap=20, hgap=20)
        grid_sizer_contenu.Add(self.ctrl_saisie_prog, 1, wx.EXPAND, 0)
        grid_sizer_contenu.Add(self.ctrl_saisie, 1, wx.EXPAND|wx.TOP, 10)
        grid_sizer_contenu.AddGrowableCol(1)
        grid_sizer_contenu.AddGrowableRow(0)
        grid_sizer_base.Add(grid_sizer_contenu, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 10)

        grid_sizer_boutons = wx.FlexGridSizer(rows=1, cols=4, vgap=10, hgap=10)
        grid_sizer_boutons.Add(self.bouton_aide, 0, 0, 0)
        grid_sizer_boutons.Add((20, 20), 0, wx.EXPAND, 0)
        grid_sizer_boutons.Add(self.bouton_ok, 0, 0, 0)
        grid_sizer_boutons.Add(self.bouton_annuler, 0, 0, 0)
        grid_sizer_boutons.AddGrowableCol(1)
        grid_sizer_base.Add(grid_sizer_boutons, 1, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, 10)
        grid_sizer_base.AddGrowableCol(0)
        grid_sizer_base.AddGrowableRow(1)
        self.SetSizer(grid_sizer_base)
        grid_sizer_base.Fit(self)
        self.Layout()
        self.CenterOnScreen()

    def OnBoutonAide(self, event):
        from Utils import UTILS_Aide
        UTILS_Aide.Aide("Transports1")

    def OnBoutonOk(self, event):
        # Validation des données
        if self.Validation() == False :
            return False

        # Sauvegardes des données
        parametres = self.GetData()

        # Sauvegarde
        resultat = self.ctrl_saisie.Sauvegarde(mode="prog", parametres=parametres)
        if resultat == True :
            self.EndModal(wx.ID_OK)

    def GetListeDictDonnees(self):
        listedictDonnees = self.ctrl_saisie.listeDonneesSauvegardees
        return listedictDonnees

    def GetData(self):
        dictData = {}
        dictData = self.ctrl_saisie_prog.GetData()
        return dictData

    def Validation(self):
        if self.ctrl_saisie_prog.Validation() == False :
            return False
        if self.ctrl_saisie.Validation() == False :
            return False
        return True

    def AffichageDates(self, etat=True):
        self.ctrl_saisie.AffichageDates(etat)

class Dialog_multiple(wx.Dialog):
    def __init__(self, parent, IDindividu=None):
        wx.Dialog.__init__(self, parent, -1, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.MAXIMIZE_BOX|wx.MINIMIZE_BOX)
        self.parent = parent
        self.IDindividu = IDindividu

        # Bandeau
        titre = _(u"Saisie d'un ou plusieurs transports")
        intro = _(u"Vous pouvez ici sélectionner toutes les caractéristiques du ou des transports à créer. Pour saisir un lot de transports identiques sur un ensemble de dates, sélectionnez le mode Saisie multiple.")
        self.SetTitle(titre)
        self.ctrl_bandeau = CTRL_Bandeau.Bandeau(self, titre=titre, texte=intro, hauteurHtml=30, nomImage="Images/32x32/Transport.png")

        # Contenu
        self.ctrl_saisie = CTRL_Saisie_transport.CTRL(self, IDtransport=None, IDindividu=IDindividu)
        self.ctrl_saisie_multiple = CTRL_Saisie_multiple(self, IDindividu=IDindividu)

        # Boutons
        self.bouton_aide = CTRL_Bouton_image.CTRL(self, texte=_(u"Aide"), cheminImage="Images/32x32/Aide.png")
        self.bouton_ok = CTRL_Bouton_image.CTRL(self, texte=_(u"Ok"), cheminImage="Images/32x32/Valider.png")
        self.bouton_annuler = CTRL_Bouton_image.CTRL(self, id=wx.ID_CANCEL, texte=_(u"Annuler"), cheminImage="Images/32x32/Annuler.png")

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.OnBoutonOk, self.bouton_ok)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonAide, self.bouton_aide)

    def __set_properties(self):
        self.bouton_aide.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour obtenir de l'aide")))
        self.bouton_ok.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour valider")))
        self.bouton_annuler.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour annuler")))
        self.SetMinSize((800, 660))

    def __do_layout(self):
        grid_sizer_base = wx.FlexGridSizer(rows=3, cols=1, vgap=10, hgap=10)
        grid_sizer_base.Add(self.ctrl_bandeau, 1, wx.EXPAND, 0)

        grid_sizer_contenu = wx.FlexGridSizer(rows=1, cols=2, vgap=20, hgap=20)
        grid_sizer_contenu.Add(self.ctrl_saisie_multiple, 1, wx.EXPAND, 0)
        grid_sizer_contenu.Add(self.ctrl_saisie, 1, wx.EXPAND|wx.TOP, 10)
        grid_sizer_contenu.AddGrowableCol(1)
        grid_sizer_contenu.AddGrowableRow(0)
        grid_sizer_base.Add(grid_sizer_contenu, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 10)

        grid_sizer_boutons = wx.FlexGridSizer(rows=1, cols=4, vgap=10, hgap=10)
        grid_sizer_boutons.Add(self.bouton_aide, 0, 0, 0)
        grid_sizer_boutons.Add((20, 20), 0, wx.EXPAND, 0)
        grid_sizer_boutons.Add(self.bouton_ok, 0, 0, 0)
        grid_sizer_boutons.Add(self.bouton_annuler, 0, 0, 0)
        grid_sizer_boutons.AddGrowableCol(1)
        grid_sizer_base.Add(grid_sizer_boutons, 1, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, 10)
        grid_sizer_base.AddGrowableCol(0)
        grid_sizer_base.AddGrowableRow(1)
        self.SetSizer(grid_sizer_base)
        grid_sizer_base.Fit(self)
        self.Layout()
        self.CenterOnScreen()

    def OnBoutonAide(self, event):
        from Utils import UTILS_Aide
        UTILS_Aide.Aide("Transports1")

    def OnBoutonOk(self, event):
        # Validation des données
        if self.Validation() == False :
            return False

        # Sauvegardes des données
        parametres = self.GetData()
        if parametres == None :
            mode = "unique"
        else :
            mode = "multiple"

        # Sauvegarde
        resultat = self.ctrl_saisie.Sauvegarde(mode=mode, parametres=parametres)
        if resultat == True :
            self.EndModal(wx.ID_OK)

    def GetListeDictDonnees(self):
        listedictDonnees = self.ctrl_saisie.listeDonneesSauvegardees
        return listedictDonnees

    def GetData(self):
        dictData = {}
        dictData = self.ctrl_saisie_multiple.GetData()
        return dictData

    def Validation(self):
        if self.ctrl_saisie_multiple.Validation() == False :
            return False
        if self.ctrl_saisie.Validation() == False :
            return False
        return True

    def AffichageDates(self, etat=True):
        self.ctrl_saisie.AffichageDates(etat)

class Dialog(wx.Dialog):
    def __init__(self, parent, IDtransport=None, IDindividu=None, modeVirtuel=False, dictDonnees={}, verrouilleBoutons=False):
        wx.Dialog.__init__(self, parent, -1, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.MAXIMIZE_BOX|wx.MINIMIZE_BOX)
        self.parent = parent
        self.IDindividu = IDindividu
        self.IDtransport = IDtransport
        self.modeVirtuel = modeVirtuel
        self.dictDonnees = dictDonnees # Pour le mode virtuel

        # Bandeau
        if IDtransport == None :
            titre = _(u"Saisie d'un transport")
        else:
            titre = _(u"Modification d'un transport")
        intro = _(u"Vous pouvez ici sélectionner toutes les caractéristiques du transport.")
        self.SetTitle(titre)
        self.ctrl_bandeau = CTRL_Bandeau.Bandeau(self, titre=titre, texte=intro, hauteurHtml=30, nomImage="Images/32x32/Transport.png")

        # Contenu
        self.ctrl_saisie = CTRL_Saisie_transport.CTRL(self, IDtransport=IDtransport, IDindividu=IDindividu, dictDonnees=self.dictDonnees, verrouilleBoutons=verrouilleBoutons)

        # Boutons
        self.bouton_aide = CTRL_Bouton_image.CTRL(self, texte=_(u"Aide"), cheminImage="Images/32x32/Aide.png")
        self.bouton_ok = CTRL_Bouton_image.CTRL(self, texte=_(u"Ok"), cheminImage="Images/32x32/Valider.png")
        self.bouton_annuler = CTRL_Bouton_image.CTRL(self, id=wx.ID_CANCEL, texte=_(u"Annuler"), cheminImage="Images/32x32/Annuler.png")

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.OnBoutonOk, self.bouton_ok)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonAide, self.bouton_aide)

    def __set_properties(self):
        self.bouton_aide.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour obtenir de l'aide")))
        self.bouton_ok.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour valider")))
        self.bouton_annuler.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour annuler")))
        self.SetMinSize((450, 660))

    def __do_layout(self):
        grid_sizer_base = wx.FlexGridSizer(rows=3, cols=1, vgap=10, hgap=10)
        grid_sizer_base.Add(self.ctrl_bandeau, 1, wx.EXPAND, 0)
        grid_sizer_base.Add(self.ctrl_saisie, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 10)
        grid_sizer_boutons = wx.FlexGridSizer(rows=1, cols=4, vgap=10, hgap=10)
        grid_sizer_boutons.Add(self.bouton_aide, 0, 0, 0)
        grid_sizer_boutons.Add((20, 20), 0, wx.EXPAND, 0)
        grid_sizer_boutons.Add(self.bouton_ok, 0, 0, 0)
        grid_sizer_boutons.Add(self.bouton_annuler, 0, 0, 0)
        grid_sizer_boutons.AddGrowableCol(1)
        grid_sizer_base.Add(grid_sizer_boutons, 1, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, 10)
        grid_sizer_base.AddGrowableCol(0)
        grid_sizer_base.AddGrowableRow(1)
        self.SetSizer(grid_sizer_base)
        grid_sizer_base.Fit(self)
        self.Layout()
        self.CenterOnScreen()

    def OnBoutonAide(self, event):
        from Utils import UTILS_Aide
        UTILS_Aide.Aide("Transports1")

    def OnBoutonOk(self, event):
        # Validation des données
        if self.Validation() == False :
            return False

        # Fermeture sans sauvegarde
        if self.modeVirtuel == True :
            self.EndModal(wx.ID_OK)
            return

        # Sauvegarde
        resultat = self.ctrl_saisie.Sauvegarde(mode="unique", )
        if resultat == True :
            self.EndModal(wx.ID_OK)

    def GetDictDonnees(self):
        dictDonnees = self.ctrl_saisie.GetDictDonnees()
        dictDonnees["IDtransport"] = self.GetIDtransport()
        return dictDonnees

    def GetIDtransport(self):
        return self.ctrl_saisie.GetIDtransport()

    def SetDateHeure(self, datedt=None):
        # Règle la date et l'heure de départ
        ctrl_date_heure = self.ctrl_saisie.GetControle("date_heure", "depart")
        ctrl_date_heure.SetDateTime(datedt)
        # Règle la date et l'heure d'arrivée
        ctrl_date_heure = self.ctrl_saisie.GetControle("date_heure", "arrivee")
        ctrl_date_heure.SetDateTime(datedt)

    def SetDateObligatoire(self, date=None):
        ctrl_date_heure = self.ctrl_saisie.GetControle("date_heure", "depart")
        ctrl_date_heure.SetDate(date)
        ctrl_date_heure.ctrl_date.Enable(False)
        ctrl_date_heure = self.ctrl_saisie.GetControle("date_heure", "arrivee")
        ctrl_date_heure.SetDate(date)
        ctrl_date_heure.ctrl_date.Enable(False)

    def VerrouilleBoutonsGestion(self):
        """ Verrouille l'accès aux boutons de gestion """
        self.ctrl_saisie.VerrouilleBoutonsGestion()

    def Validation(self):
        # Validation de la saisie
        resultat = self.ctrl_saisie.Validation()
        return resultat

if __name__ == "__main__":
    app = wx.App(0)
    #wx.InitAllImageHandlers()
    dialog_1 = Dialog_prog(None, IDtransport=1, IDindividu=46) # Pour une saisie multiple
    # dialog_1 = Dialog_multiple(None, IDindividu=46) # Pour une saisie multiple
    # dialog_1 = Dialog(None, IDtransport=None, IDindividu=46) # Pour une saisie unique
    app.SetTopWindow(dialog_1)
    dialog_1.ShowModal()
    app.MainLoop()


import pygame
from config import SCREEN_HEIGHT, SCREEN_WIDTH

BAR_WIDTH = 200
BAR_HEIGHT = 20

class HealthContainer(pygame.sprite.Sprite):
    def __init__(self):
        super(HealthContainer, self).__init__()
        self.surf = pygame.Surface((BAR_WIDTH, BAR_HEIGHT))
        self.surf.fill((100, 116, 139))
        self.rect = self.surf.get_rect()
        self.rect.left = SCREEN_WIDTH - BAR_WIDTH - 10
        self.rect.bottom = SCREEN_HEIGHT - 10

class HealthBar(pygame.sprite.Sprite):
    def __init__(self):
        super(HealthBar, self).__init__()
        self.update(1)

    def update(self, health):
        self.surf = pygame.Surface((BAR_WIDTH * health, BAR_HEIGHT))
        if health > 0.8:  # green
            self.surf.fill((22, 168, 74))
        elif health > 0.25:  # blue
            self.surf.fill((37, 99, 235))
        else:  # color bar in red
            self.surf.fill((225, 29, 72))

        self.rect = self.surf.get_rect()
        self.rect.left = SCREEN_WIDTH - BAR_WIDTH - 10
        self.rect.bottom = SCREEN_HEIGHT - 10