from __future__ import absolute_import, division, print_function
from cctbx import miller
from cctbx import crystal
from cctbx import sgtbx
from cctbx import uctbx
from cctbx.array_family import flex
import sys

import boost_adaptbx.boost.python as bp
from six.moves import range
dtrek_ext = bp.import_ext("iotbx_dtrek_ext")

class reflnlist(object):

  def __init__(self, file, header_only=False):
    self.file = file
    self.line_no = 0
    line_1 = self.next_line().split()
    assert len(line_1) in (3,4)
    line_1 = [int(field) for field in line_1]
    if (len(line_1) == 3):
      line_1.append(0)
    self.NumInts = line_1[0]
    assert self.NumInts >= 3
    self.NumFloats = line_1[1]
    self.NumStrings = line_1[2]
    self.NumInfoLines = line_1[3]
    self.InfoLines = []
    for i in range(self.NumInfoLines):
      self.InfoLines.append(self.next_line().strip())
    self.column_info = []
    num_columns = self.NumInts + self.NumFloats + self.NumStrings
    self.column_names = []
    for i in range(num_columns):
      column_name = self.next_line().strip()
      assert len(column_name) > 1
      assert column_name[0] in "nfs"
      if (i < self.NumInts):
        assert column_name[0] == "n"
      elif (i < self.NumInts + self.NumFloats):
        assert column_name[0] == "f"
      else:
        assert column_name[0] == "s"
      self.column_names.append(column_name)
    assert "fIntensity" in self.column_names
    assert "fSigmaI" in self.column_names
    assert self.column_names[:3] == ["nH", "nK", "nL"]
    if (header_only):
      self.miller_indices = None
      self.column_dict = None
    else:
      self.miller_indices = flex.miller_index()
      self.column_dict = {}
      column_list = [None, None, None]
      for i in range(3, num_columns):
        if (i < self.NumInts):
          column_list.append(flex.int())
        elif (i < self.NumInts + self.NumFloats):
          column_list.append(flex.double())
        else:
          column_list.append(flex.std_string())
        self.column_dict[self.column_names[i]] = column_list[-1]
      while 1:
        line = self.next_line()
        if (line is None):
          break
        data_values = line.split()
        assert len(data_values) == num_columns, "Line no. %d" % self.line_no
        h = [int(v) for v in data_values[:3]]
        self.miller_indices.append(h)
        offset = 3
        for i in range(offset, self.NumInts):
          v = int(data_values[i])
          column_list[i].append(v)
        offset = self.NumInts
        for i in range(offset, offset+self.NumFloats):
          v = float(data_values[i])
          column_list[i].append(v)
        offset += self.NumFloats
        for i in range(offset, num_columns):
          column_list[i].append(data_values[i])
    del self.file
    del self.line_no

  def next_line(self):
    line = self.file.readline()
    if (line == ""): return None
    self.line_no += 1
    return line

  def space_group_info(self):
    for info_line in self.InfoLines:
      if (info_line.upper().startswith("CRYSTAL_SPACEGROUP=")):
        assert info_line[-1] == ";"
        space_group_number = info_line[:-1].split("=", 1)[1]
        return sgtbx.space_group_info(symbol=space_group_number)
    return None

  def unit_cell(self):
    for info_line in self.InfoLines:
      if (info_line.upper().startswith("CRYSTAL_UNIT_CELL=")):
        assert info_line[-1] == ";"
        unit_cell = info_line[:-1].split("=", 1)[1]
        return uctbx.unit_cell(unit_cell)
    return None

  def crystal_symmetry(self):
    return crystal.symmetry(
      unit_cell=self.unit_cell(),
      space_group_info=self.space_group_info())

  def show_summary(self, out=None, prefix=""):
    if (out is None): out = sys.stdout
    self.crystal_symmetry().show_summary(f=out, prefix=prefix)
    print(prefix + "Column names:", " ".join(self.column_names[3:]), file=out)
    print(prefix + "Number of reflections:", self.miller_indices.size(), file=out)

  def as_miller_arrays(self,
        crystal_symmetry=None,
        force_symmetry=False,
        merge_equivalents=True,
        base_array_info=None,
        anomalous=None):
    crystal_symmetry_from_file = self.crystal_symmetry()
    crystal_symmetry = crystal_symmetry_from_file.join_symmetry(
      other_symmetry=crystal_symmetry,
      force=force_symmetry)
    if (base_array_info is None):
      base_array_info = miller.array_info(source_type="dtrek_reflnlist")
    miller_arrays = []
    sigmas=self.column_dict["fSigmaI"]
    miller_arrays.append(miller.array(
      miller_set=miller.set(
        crystal_symmetry=crystal_symmetry,
        indices=self.miller_indices,
        anomalous_flag=False),
      data=self.column_dict["fIntensity"],
      sigmas=sigmas)
      .select(sigmas > 0)
      .set_info(base_array_info.customized_copy(
        labels=["Intensity", "SigmaI"],
        crystal_symmetry_from_file=crystal_symmetry_from_file))
      .set_observation_type_xray_intensity())
    if ("fIntensity+" in self.column_dict):
      assert "fSigmaI+" in self.column_dict
      assert "fIntensity-" in self.column_dict
      assert "fSigmaI-" in self.column_dict
      if (crystal_symmetry.space_group_info() is None):
        space_group = sgtbx.space_group() # P 1
      else:
        space_group = crystal_symmetry.space_group()
      ac = dtrek_ext.anomalous_combined(
        space_group,
        self.miller_indices,
        self.column_dict["fIntensity+"],
        self.column_dict["fSigmaI+"],
        self.column_dict["fIntensity-"],
        self.column_dict["fSigmaI-"])
      miller_arrays.append(miller.array(
        miller_set=miller.set(
          crystal_symmetry=crystal_symmetry,
          indices=ac.miller_indices(),
          anomalous_flag=True),
        data=ac.data(),
        sigmas=ac.sigmas())
        .set_info(base_array_info.customized_copy(
          labels=["Intensity+-", "SigmaI+-"],
          crystal_symmetry_from_file=crystal_symmetry_from_file))
        .set_observation_type_xray_intensity())
    for column_name in self.column_names:
      if (column_name in ("nH", "nK", "nL",
                          "fSigmaI", "fIntensity",
                          "fIntensity+", "fSigmaI+",
                          "fIntensity-", "fSigmaI-")):
        continue
      miller_arrays.append(miller.array(
        miller_set=miller.set(
          crystal_symmetry=crystal_symmetry,
          indices=self.miller_indices,
          anomalous_flag=False),
        data=self.column_dict[column_name])
        .set_info(base_array_info.customized_copy(
          labels=[column_name[1:]],
          crystal_symmetry_from_file=crystal_symmetry_from_file)))
    return miller_arrays


def string_mal(str1,str2):
    a = []
    b = []

    for x in range(len(str1)):
        if str1[x]!="#":
            a.append(str1[x])
        else:
            if a!=[]:
                a.pop()

    for y in range(len(str2)):
        if str2[y]!="#":
            b.append(str2[y])
        else:
            if b!=[]:
                b.pop()

    return a==b

x = string_mal("ab#c","ad#c")
print(x)


def extract_tar(url, target_dir, additional_compression="", remove_common_prefix=False, overwrite=False):
    """ extract a targz and install to the target directory """
    try:
        if not os.path.exists(target_dir):
            os.makedirs(target_dir)
        tf = tarfile.TarFile.open(fileobj=download_to_bytesio(url))
        if not os.path.exists(target_dir):
            os.makedirs(target_dir)
        common_prefix = os.path.commonprefix(tf.getnames())
        if not common_prefix.endswith('/'):
            common_prefix += "/"
        for tfile in tf.getmembers():
            if remove_common_prefix:
                tfile.name = tfile.name.replace(common_prefix, "", 1)
            if tfile.name != "":
                target_path = os.path.join(target_dir, tfile.name)
                if target_path != target_dir and os.path.exists(target_path):
                    if overwrite:
                        remove_path(target_path)
                    else:
                        continue
                tf.extract(tfile, target_dir)
    except OSError:
        e = sys.exc_info()[1]
        raise ExtractException(str(e))
    except IOError:
        e = sys.exc_info()[1]
        raise ExtractException(str(e))


import cnpj
from random import randint

print("--Verificador de CNPJ--")
print("Informe todos os 13 números do CNPJ para verificar sua validade")
print("Sua validade não quer dizer que o mesmo existe, mas sim, que é matematicamente válido")

print("Opção 1 : Digitar um CNPJ para ser verificado")
print("Opção 2 : Gerar um CNPJ aleatoriamente ")
print("Opção 3 : Sair do programa ")

while True:
    option = input("Digite a opção escolhida: ")

    if option == '1':
        aux = input('Digite um CNPJ: ')
        cnpj.valida(aux, option)
    elif option == '2':
        cpfaux = str((randint(10000000000000, 99999999999999)))
        print(f"O CNPJ gerado automaticamente foi {cpfaux}")
        cnpj.valida(cpfaux, option)
    elif option == '3':
        break
    else:
        print("Opção inválida")


adapters = [0]
with open("10.txt") as file:
    for line in file:
        adapters.append(int(line.strip()))

adapters.sort()
adapters.append(adapters[-1] + 3)
differences = {"1": 0, "3": 0}
for i in range(len(adapters) - 1):
    if abs(adapters[i] - adapters[i+1]) == 1:
        differences["1"] += 1
    elif abs(adapters[i] - adapters[i+1]) == 3:
        differences["3"] += 1
print(differences["1"]*differences["3"])

paths = {}
for i in range(-1, adapters[-1] + 1):
    paths[i] = 0
paths[0] = 1
paths[1] = 1

for i in range(2, len(adapters)):
    paths[adapters[i]] = paths[adapters[i] - 1] + paths[adapters[i] - 2] + paths[adapters[i] - 3]
print(paths[adapters[-1]])


import re
file = '/Users/atunin/Downloads/python/pyneg-tasks/exercises/15_module_re/sh_ip_int_br.txt'
def parse_sh_ip_int_br(filename):
    with open(filename) as f:
        result = re.finditer(r'(\S+) +'
                        r'(\S+) +'
                        r'\S+ +'
                        r'\S+ +'
                        r'(up|down|administratively down) +'
                        r'(up|down)',f.read())
    groups = []
    for match in result:
        groups.append(match.groups())

    print(groups)
    return groups

if __name__ == "__main__":
    parse_sh_ip_int_br(file)


import glob
import math

import os

import helpers
import settings

import tensorflow as tf
AUTOTUNE = tf.data.experimental.AUTOTUNE

assert tf.test.is_built_with_cuda()
assert tf.test.is_gpu_available()

def run():
    # Training data
    training_image_generator = tf.keras.preprocessing.image.ImageDataGenerator(
        rescale=1./255,
        brightness_range=[0.2, 1.0],
        rotation_range=20,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.2,
        zoom_range=0.1,
        # horizontal_flip=True,
        fill_mode='nearest',
    )
    training_generator = training_image_generator.flow_from_directory(
        settings.TRAINING_DIRECTORY,
        target_size=(settings.TARGET_IMAGE_HEIGHT, settings.TARGET_IMAGE_WIDTH),
        batch_size=settings.TRAINING_BATCH_SIZE,
        class_mode='binary',
        # classes=list(settings.CLASS_NAMES),
    )

    # helpers.show_generator_batch(training_generator)

    # Validation data
    validation_image_generator = tf.keras.preprocessing.image.ImageDataGenerator(
        rescale=1./255
    )
    validation_generator = validation_image_generator.flow_from_directory(
        settings.VALIDATION_DIRECTORY,
        target_size=(settings.TARGET_IMAGE_HEIGHT, settings.TARGET_IMAGE_WIDTH),
        batch_size=settings.VALIDATION_BATCH_SIZE,
        class_mode='binary',
        # classes=list(settings.CLASS_NAMES),
    )

    use_latest_model_file = False
    if use_latest_model_file:
        model = tf.keras.models.load_model(settings.MODEL_FILE)
    else:
        model = tf.keras.models.Sequential([
            # This is the first convolution
            tf.keras.layers.Conv2D(16, (3, 3), activation='relu', input_shape=(settings.TARGET_IMAGE_HEIGHT, settings.TARGET_IMAGE_WIDTH, 3)),
            # tf.keras.layers.BatchNormalization(),
            tf.keras.layers.MaxPooling2D(2, 2),
            # tf.keras.layers.Dropout(0.2),

            # The second convolution
            tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),
            # tf.keras.layers.BatchNormalization(),
            tf.keras.layers.MaxPooling2D(2, 2),
            # tf.keras.layers.Dropout(0.2),

            # The third convolution
            tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
            # tf.keras.layers.BatchNormalization(),
            tf.keras.layers.MaxPooling2D(2, 2),
            # tf.keras.layers.Dropout(0.2),

            # The fourth convolution
            tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
            # tf.keras.layers.BatchNormalization(),
            tf.keras.layers.MaxPooling2D(2, 2),
            # tf.keras.layers.Dropout(0.2),

            # The fifth convolution
            tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
            # tf.keras.layers.BatchNormalization(),
            tf.keras.layers.MaxPooling2D(2, 2),
            # tf.keras.layers.Dropout(0.2),

            # Flatten the results to feed into a DNN
            tf.keras.layers.Flatten(),

            # 512 neuron hidden layer
            tf.keras.layers.Dense(512, activation='relu'),

            # Only 1 output neuron. It will contain a value from 0-1 where 0 for 1 class ('false') and 1 for the other ('true')
            tf.keras.layers.Dense(1, activation='sigmoid')
        ])

    model.summary()

    model.compile(
        loss='binary_crossentropy',
        optimizer=tf.keras.optimizers.RMSprop(),
        metrics=['acc']
    )

    callbacks = [
        tf.keras.callbacks.EarlyStopping(
            monitor='val_loss',
            patience=5,
            verbose=1,
        ),
        tf.keras.callbacks.ReduceLROnPlateau(
            monitor='val_acc',
            patience=2,
            verbose=1,
            factor=0.5,
            min_lr=0.00001,
        ),
        tf.keras.callbacks.ModelCheckpoint(
            # Path where to save the model
            filepath=settings.CHECKPOINT_FILE,
            # The two parameters below mean that we will overwrite
            # the current checkpoint if and only if
            # the `val_loss` score has improved.
            save_best_only=True,
            monitor='val_loss',
            verbose=1,
        ),
        tf.keras.callbacks.TensorBoard(
            log_dir=settings.LOG_DIRECTORY,
            histogram_freq=1
        )
    ]

    model.fit_generator(
        training_generator,
        # steps_per_epoch=steps_per_epoch,
        epochs=20000,
        verbose=2 if 'PYCHARM_HOSTED' in os.environ else 1,
        validation_data=validation_generator,
        # validation_steps=validation_steps,
        callbacks=callbacks,

        # use_multiprocessing=True,
        workers=8,
    )

    model.save(settings.FULL_MODEL_FILE)

if __name__ == '__main__':
    run()


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

# ref: https://leetcode.com/problems/split-bst/solutions/2996704/python-with-pictures/?orderBy=most_votes

class Solution:
    def splitBST(self, root: Optional[TreeNode], target: int) -> List[Optional[TreeNode]]:
        def cut(node):
            if not node:
                return None, None

            if node.val <= target:
                left, right = cut(node.right)
                node.right = left
                return node, right

            elif node.val > target:
                left, right = cut(node.left)
                node.left = right
                return left, node

        return cut(root)


from flask import Flask
import pandas as pd
import numpy as np
from flask import jsonify
from recomendacion import recomendations
from buscador_principal import buscador_principal
from filtraje import filtraje
from flask import jsonify
from flask import request
#base de datos
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow, Schema, fields
from sqlalchemy.orm import relationship, backref
from sqlalchemy import create_engine, ForeignKey, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
import json
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy_serializer import SerializerMixin
from marshmallow_sqlalchemy.fields import Nested
from sqlalchemy import and_, or_

app= Flask(__name__)
#app.config['SQLALCHEMY_DATABASE_URI']='mysql+pymysql://root@localhost/laravel'
#app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False
app.config['SQLALCHEMY_DATABASE_URI']='mysql+pymysql://u398984712_founduss:Siliconvalley1@45.93.101.52/u398984712_founduss'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False
#engine = create_engine('mysql+pymysql://root@localhost/laravel', echo = True)
engine = create_engine('mysql+pymysql://u398984712_founduss:Siliconvalley1@45.93.101.52/u398984712_founduss', echo = True)
Base = declarative_base()
Session = sessionmaker(bind = engine)
session = Session()

db=SQLAlchemy(app)
ma=Marshmallow(app)

class Bank(db.Model, SerializerMixin):
    __tablename__ = 'banks'
    serialize_only = ('id', 'name', 'description')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(70),unique=True)
    description = db.Column(db.Text)

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

product_image = db.Table('product_image',
    db.Column('product_id', db.Integer, db.ForeignKey('products.id'), primary_key=True),
    db.Column('image_id', db.Integer, db.ForeignKey('images.id'), primary_key=True)
)
factory_product = db.Table('factory_product',
    db.Column('product_id', db.Integer, db.ForeignKey('products.id'), primary_key=True),
    db.Column('factory_id', db.Integer, db.ForeignKey('factories.id'), primary_key=True)
)
mark_product = db.Table('mark_product',
    db.Column('product_id', db.Integer, db.ForeignKey('products.id'), primary_key=True),
    db.Column('mark_id', db.Integer, db.ForeignKey('marks.id'), primary_key=True)
)
subcategory_product = db.Table('subcategory_product',
    db.Column('product_id', db.Integer, db.ForeignKey('products.id'), primary_key=True),
    db.Column('subcategory_id', db.Integer, db.ForeignKey('subcategories.id'), primary_key=True)
)

class Product(db.Model, SerializerMixin):
    __tablename__ = 'products'
    serialize_only = ('id', 'name', 'description', 'images')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(250),unique=True)
    description = db.Column(db.Text)
    images = relationship("Image", secondary=product_image)
    factories = relationship("Factory", secondary=factory_product)
    marks = relationship("Mark", secondary=mark_product)
    subcategories = relationship("Subcategory", secondary=subcategory_product)

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

class Image(db.Model, SerializerMixin):
    __tablename__ = 'images'
    serialize_only = ('id', 'src')

    id = db.Column(db.Integer, primary_key=True)
    src = db.Column(db.Text)

    def __init__(self,src):
        self.src = src
class Factory(db.Model, SerializerMixin):
    __tablename__ = 'factories'
    serialize_only = ('id', 'name')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(250),unique=True)

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

class Mark(db.Model, SerializerMixin):
    __tablename__ = 'marks'
    serialize_only = ('id', 'name')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(250),unique=True)

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

class Category(db.Model, SerializerMixin):
    __tablename__ = 'categories'
    serialize_only = ('id', 'name')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(250),unique=True)

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

class Subcategory(db.Model, SerializerMixin):
    __tablename__ = 'subcategories'
    serialize_only = ('id', 'name')

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(250),unique=True)
    category_id = db.Column(db.Integer, ForeignKey('categories.id'))
    category = relationship("Category")

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

class Bankchema(ma.SQLAlchemySchema):
    class Meta:
        model =Bank
    id = ma.auto_field()
    name = ma.auto_field()
    description = ma.auto_field()

bank_schema= Bankchema()
bank_schema= Bankchema(many=True)

class ImageSchema(ma.SQLAlchemySchema):
    class Meta:
        model =Image
    src = ma.auto_field()

images_schema= ImageSchema()
images_schema= ImageSchema(many=True)

class FactorySchema(ma.SQLAlchemySchema):
    class Meta:
        model =Factory
    name = ma.auto_field()

factories_schema= FactorySchema()
factories_schema= FactorySchema(many=True)

class MarkSchema(ma.SQLAlchemySchema):
    class Meta:
        model =Factory
    name = ma.auto_field()

marks_schema= MarkSchema()
marks_schema= MarkSchema(many=True)

class CategorySchema(ma.SQLAlchemySchema):
    class Meta:
        model =Category
    name = ma.auto_field()

categories_schema= CategorySchema()
categories_schema= CategorySchema(many=True)

class SubcategorySchema(ma.SQLAlchemySchema):
    class Meta:
        model =Subcategory
    name = ma.auto_field()
    category_id = ma.auto_field()
    category = Nested(CategorySchema)

subcategories_schema= SubcategorySchema()
subcategories_schema= SubcategorySchema(many=True)

class ProductSchema(ma.SQLAlchemySchema):
    class Meta:
        model =Product
    id = ma.auto_field()
    name = ma.auto_field()
    description = ma.auto_field(dump_only=False)
    images = Nested(ImageSchema,many=True)
    factories = Nested(FactorySchema,many=True)
    marks = Nested(MarkSchema,many=True)
    subcategories = Nested(SubcategorySchema,many=True)

products_schema= ProductSchema()
products_schema= ProductSchema(many=True)

@app.route("/")
def home():
    return 'La pagina esta funcionando bien'

@app.route('/products')
def getProducts():
    return 'datos'

@app.route('/products/<string:product_name>')
def getProduct(product_name):

    return 'nada'

@app.route('/products',methods=['POST'])
def postProducts():
    all_products=Bank.query.all()
    lista_productos= bank_schema.dump(all_products)
    producto_buscar={
        "name":request.json['name'],
        "description":request.json['description'],
    }
    lista_productos_json=json.dumps(lista_productos)

    datos=recomendations(producto_buscar,lista_productos_json)
    datos_recomendacion=json.dumps(datos)
    return datos_recomendacion
#buscador_python
@app.route('/search/products',methods=['POST'])
def postSearchProducts():
    #listas de filtros
    lista_marca_json=request.json['marks']
    lista_subcategoria_json=request.json['subcategories']
    lista_factories_json=request.json['factories']
    lista_categories_json=request.json['categories']

    filter_group = filtraje(lista_marca_json,lista_subcategoria_json,lista_factories_json,lista_categories_json,Mark,Subcategory,Factory,Category,Product)

    #filtraje por join
    all_products=session.query(Product)\
        .join(Subcategory, Product.subcategories) \
        .join(Mark, Product.marks) \
        .join(Factory, Product.factories) \
        .join(Category, Subcategory.category) \
        .filter(and_(*filter_group)
        )\
        .all()

    #return json.dumps(all_products)
    #array=[]
    #for x in all_products:
     #   for y in x.images:
      #      array.append(y)

    lista_productos= products_schema.dump(all_products)
    #return  json.dumps(lista_productos)

    producto_buscar={
        "name":request.json['name'],
    }
    lista_productos_json=json.dumps(lista_productos)

    datos=buscador_principal(producto_buscar,lista_productos_json)

    datos_buscador=json.dumps(datos)

    return datos_buscador

    the_rock_movies = session.query(Product) \
    .join(Image, Product.images) \
    .all()
    print('###########################################')
    for product in the_rock_movies:
        print(f'el producto es in {product.images}')
        for image in product.images:
             print(f'la imagen es in {image.src}')
        print('')
    lista_productos= products_schema.dump(the_rock_movies)
    return  json.dumps(lista_productos)

if __name__=='__main__':
    app.run()


#First load Mat to get

firstN = 5
from scipy import io
from scipy import linalg
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
cfd_datas = io.loadmat("date0.mat")
print(io.whosmat("date0.mat"))

print(cfd_datas.keys())

state_matrix = cfd_datas['p']
print(state_matrix.shape)

nSnapShot = state_matrix.shape[0]
nX = state_matrix.shape[1]
nY = state_matrix.shape[2]
#Perform an Proper orthogonal decomposition

operating_matrix = state_matrix.reshape(nSnapShot,nX*nY)
print(operating_matrix.shape)

u,s,Vh = linalg.svd(operating_matrix)
#Output the firstN modes.
for i in range(firstN):
    ColumnVec = Vh[i].reshape(nX,nY).T
    plt.imshow(ColumnVec)
    plt.savefig("Mode{}.png".format(i))
#Perform an superposition of u s Vh to get the approximated flow

print(u.shape)
print(s.shape)
print(Vh.shape)
#Now test the mutiply of two matrix:
mat1 = np.array([[1,0],[0,1],[0,0]])
print(mat1.shape)
vec1 = np.array([[0],[1]])
print(vec1.shape)
print(mat1.dot(vec1))

fig,ax = plt.subplots(2,1)

ims = []
ax[0].set_title("CDF result")
ax[1].set_title("First {} mode superposition".format(firstN))
for j in range(nSnapShot):
    im0 = ax[0].imshow(state_matrix[j].T,animated=True)
    MatrixVec = operating_matrix[j]
    super = np.zeros_like(MatrixVec)
    for i in range(firstN):
        ColumnVec = Vh[i]
        imagnitude = sum(ColumnVec * MatrixVec)
        super  = super + ColumnVec * imagnitude
    super = super.reshape(nX,nY).T
    #plt.imshow(super)
    #plt.savefig("Snap{}".format(j))
    im1 = ax[1].imshow(super,animated=True)
    ims.append([im0,im1])

#Generating movie and gif
# ani = animation.ArtistAnimation(fig,ims,interval=150,blit=True, repeat_delay=1000)
# ani.save("movie.mp4")
# ani.save("ani.gif",writer='pillow',fps=10)
#Plot EigenValue related

fig,axes = plt.subplots(1,2)
#Left is the eigenvalue
x_axis = np.arange(138)
axes[0].set_yscale('log')
axes[0].plot(x_axis,s)
axes[0].set_title("Eigen value")

axes[1].set_title("Accumulated Energy")
total_Energy = sum(s*s)
accum_Energy = np.zeros_like(x_axis,dtype=float)

for i in range(0,nSnapShot):
    accum_Energy[i] = accum_Energy[i-1] + float(s[i]*s[i]/total_Energy)
#accum_Energy = accum_Energy/total_Energy

axes[1].plot(x_axis,accum_Energy)

plt.savefig("energy.png")


import sqlalchemy as sql
import pandas as pd
from rssa.utils.constants import *
class MySql:
    def __init__(self):
        self.connection = sql.create_engine('mysql+mysqlconnector://{0}:{1}@{2}/{3}'.
                                            format(SQL_USERNAME, SQL_PASSWORD,
                                                   SQL_HOSTNAME, SQL_DBNAME))
    def read(self, tablename, columns = None):
        selection = "*"
        if columns is not None:
            selection = ",".join(columns)
        query = "select " + selection + " from {}".format(tablename)
        df = pd.read_sql(query, con=self.connection)
        return df

    def read_latest_ts(self, tablename):
        query = "select * from {} where ts = (select MAX(ts) from {})".format(tablename, tablename)
        df = pd.read_sql(query, con=self.connection)
        return df

    def write(self, df, tablename):
        df.to_sql(name=tablename, con=self.connection, index=False, if_exists='append')


'''
    문제설명
        백준 11404 (플로이드 와샬 알고리즘 이용)
        모든 도시의 쌍 (A, B)에 대해서 A에서 B로 가는데 필요한 비용의 최솟값을 구하라.
    해결전략
        최단경로를 구하는 알고리즘은 크게 다익스트라 알고리즘과 플로이드 알고리즘이 있다.
        한 정점에서의 최단경로를 구할 떄는 다익스트라를 이용하고 모든 정점 쌍에 대해 최단경로를 구할 때는 플로이드를 이용한다.
        플로이드 와샬 알고리즘의 시간복잡도는 O(N^3)이다.
        2차원 리스트 dis에서 dis[i][j]는 i에서 j까지 가는데 드는 최소비용이다. 처음에는 모든 원소를 가능한 최대 비용으로 초기화한다.
        그 이후에 자기 자신으로 가는 비용은 0이므로 dis[i][i]를 0으로 초기화한다.
        그리고 버스 노선 정보를 차례로 읽으며 그래프 인접행렬을 초기화하듯이 도시 사이의 연결관계와 간선의 가중치를 표시한다.
        두 노드 사이의 간선은 두 개 이상일 수 있지만 최소비용을 구하는 경우에는 가중치가 작은 간선만 이용하므로 그 값으로 초기화한다.
        플로이드 알고리즘은 거쳐가는 노드, 시작 노드, 도착 노드의 순으로 3중 for문을 이용한다.
        i에서 j로 가는데 기존 방식과 k를 거쳐서 가는 방식을 비교해서 더 비용이 적은 방법을 선택해서 dis 리스트의 값을 갱신한다.
        따라서 기존 인접행렬과 유사한 dis 리스트를 도시 1을 거쳐 갈 때로 갱신하고, 도시 2를 거쳐갈 때로 갱신하고 이렇게 차례로 적용한다.
        출력할 때는 i에서 j로 갈 수 없는 경우 dis[i][j] 값이 처음 초기화된 값 INF에서 변하지 않았을 것이므로 0으로 출력하고 나머지는 dis[i][j] 값을 출력한다.
'''
import sys
INF = 100000 * 100
n = int(sys.stdin.readline())
m = int(sys.stdin.readline())
dis = [[INF]*(n+1) for _ in range(n+1)]
for i in range(1, n+1):
    dis[i][i] = 0
for i in range(m):
    a, b, c = map(int, sys.stdin.readline().split())
    dis[a][b] = min(dis[a][b], c)
for k in range(1, n+1):
    for i in range(1, n+1):
        for j in range(1, n+1):
            dis[i][j] = min(dis[i][j], dis[i][k]+dis[k][j])
for i in range(1, n+1):
    for j in range(1, n+1):
        if dis[i][j] == INF:
            print(0, end=' ')
        else:
            print(dis[i][j], end = ' ')
    print()


import random

from direct.gui.DirectGui import (
    DGG,
    DirectButton,
    DirectFrame,
    DirectLabel,
)
from panda3d.core import TransparencyAttrib

from gui import MechanicDesc
from gui.widgets import GUI_PIC, RUST_COL
from utils import take_random

class Scenario:
    """The game scenario orchestrator.

    Tracks on which part of the scenario the player is, controls
    the next scenario steps and performs choice consequences effects.

    One scenario chapter includes a situation in which the player
    has to make a decision. Decision will have consequences, positive
    or negative, but in any case the player will become one step
    closer to figuring out the way to survive the Stench. After
    every chapter the player will also get a note written in a
    diary fashion. The note will give the player more info about
    the Stench, Captain, the Adjutant and how the cataclysm
    started to destroy the World.

    Args:
        current_chapter (int): The chapter number to start with.
    """

    def __init__(self, current_chapter=None):
        if current_chapter is not None:  # saved game
            self.current_chapter = current_chapter
        else:  # game start
            self.current_chapter = -1

        self._list = DirectFrame(
            frameSize=(-0.73, 0.73, -0.9, 0.9),
            frameTexture=GUI_PIC + "paper1.png",
            state=DGG.NORMAL,
        )
        self._list.setDepthTest(False)
        self._list.setTransparency(TransparencyAttrib.MAlpha)
        self._list.hide()

        self._name = DirectLabel(
            parent=self._list,
            text="",
            text_font=base.main_font,  # noqa: F821
            frameSize=(0.4, 0.4, 0.4, 0.4),
            text_scale=0.05,
            pos=(-0.4, 0, 0.7),
        )
        self._type = DirectLabel(
            parent=self._list,
            text=base.labels.SCENARIO_LABELS[1],  # noqa: F821
            text_font=base.main_font,  # noqa: F821
            frameSize=(0.4, 0.4, 0.4, 0.4),
            text_scale=0.035,
            pos=(-0.13, 0, 0.699),
        )
        self._desc = DirectLabel(
            parent=self._list,
            text="",
            text_font=base.main_font,  # noqa: F821
            frameSize=(0.6, 0.6, 0.6, 0.6),
            text_scale=0.037,
            pos=(0, 0, 0.55),
        )

        self._buts = []
        z_coor = -0.6
        for _ in range(3):
            self._buts.append(
                DirectButton(
                    parent=self._list,
                    text="Text",
                    text_font=base.main_font,  # noqa: F821
                    text_fg=RUST_COL,
                    text_shadow=(0, 0, 0, 1),
                    frameColor=(0, 0, 0, 0),
                    frameSize=(-9, 9, -0.3, 0.7),
                    scale=(0.047, 0, 0.047),
                    clickSound=base.main_menu.click_snd,  # noqa: F821
                    pos=(0, 0, z_coor),
                )
            )
            z_coor -= 0.08

        self._done_but = DirectButton(
            parent=self._list,
            text=base.labels.DISTINGUISHED[6],  # noqa: F821
            text_font=base.main_font,  # noqa: F821
            text_fg=RUST_COL,
            text_shadow=(0, 0, 0, 1),
            frameColor=(0, 0, 0, 0),
            frameSize=(-9, 9, -0.3, 0.7),
            scale=(0.05, 0, 0.05),
            clickSound=base.main_menu.click_snd,  # noqa: F821
            pos=(0, 0, -0.8),
            command=self.hide_chapter,
        )

    def _choose_variant(self, var):
        """Process the player's choice and do consequences.

        Args:
            var (str): Variant id.
        """
        consequences = base.labels.SCENARIO[self.current_chapter][  # noqa: F821
            "variants"
        ][var]
        for but in self._buts:
            but.hide()

        self._desc["text"] = consequences["desc"]
        for effect in consequences["effects"]:
            getattr(self, effect[0])(*effect[1])

        base.journal.add_page(self.current_chapter)  # noqa: F821
        self._done_but.show()
        base.res_gui.update_resource(  # noqa: F821
            "places_of_interest", str(self.current_chapter + 1) + "/10"
        )

        base.decisions["decision_" + str(self.current_chapter)] = {  # noqa: F821
            "decision": var,
            "goodness": consequences["goodness"],
        }

    def finish_game(self):
        """Completely finish the game."""
        self.hide_chapter()
        taskMgr.doMethodLater(  # noqa: F821
            1, base.effects_mgr.fade_out_screen, "fade_out"  # noqa: F821
        )
        taskMgr.doMethodLater(  # noqa: F821
            4, base.main_menu.show_credits, "show_credits",  # noqa: F821
        )
        taskMgr.doMethodLater(  # noqa: F821
            4.5, base.effects_mgr.fade_in_screen, "fade_in"  # noqa: F821
        )
        taskMgr.doMethodLater(  # noqa: F821
            76, base.restart_game, "restart_game", extraArgs=[]  # noqa: F821
        )
        base.train.ctrl.unset_controls()  # noqa: F821
        base.effects_mgr.stench_effect.stop()  # noqa: F821

        for task in (
            "update_physics",
            "sun_look_at_train",
            "collide_mouse",
            "move_camera_with_mouse",
            "update_speed_indicator",
            "disease",
            "show_teaching_note",
            "calc_cohesion",
            "track_ambient_sounds",
            "stench_step",
            "check_train_contacts",
            "change_sun_color",
        ):
            base.taskMgr.remove(task)  # noqa: F821

        base.sound_mgr.disable()  # noqa: F821
        base.world.drown_ambient_snds()  # noqa: F821

    def do_build_camp_effect(self):
        """Do effects for building a camp for orphans choice."""
        base.helped_children = True  # noqa: F821

    def do_spend_cohesion(self, value):
        """Do effect of decreasing the crew cohesion.

        Args:
            value (int): The amount of the cohesion change.
        """
        base.team.spend_cohesion(value)  # noqa: F821

    def do_get_money(self, money):
        """Get or lose the given amount of money.

        Args:
            money (int): Money amount to get/lose.
        """
        base.dollars += money  # noqa: F821

    def do_plus_resource(self, name, value):
        """Change the given resource amount.

        Args:
            name (str): Resource name.
            value (int): Amount delta.
        """
        base.plus_resource(name, value)  # noqa: F821

    def do_enemy_inc_effect(self):
        """Make enemy stronger effect."""
        base.world.enemy.score += 3  # noqa: F821

    def do_character_effect(self, char, effect):
        """Do choice consequences effect to the given character.

        Args:
            char (units.crew.character.Character):
                The character to do effect to.
            effect (dict): The effect description.
        """
        for key, value in effect.items():
            setattr(char, key, getattr(char, key) + value)

    def do_characters_effect(self, effect, to_one=False):
        """Do choice consequences effects to the crew.

        Args:
            effect (dict): Effect description.
            to_one (bool): Effect targets only one random character.
        """
        if to_one:
            self.do_character_effect(
                random.choice(list(base.team.chars.values())), effect  # noqa: F821
            )
            return

        for char in base.team.chars.values():  # noqa: F821
            self.do_character_effect(char, effect)

    def do_locomotive_damage(self, damage):
        """Do some damage to the Adjutant.

        Args:
            damage (int): Amount of damage to do.
        """
        base.train.get_damage(damage)  # noqa: F821

    def do_no_effect(self):
        """No choice consequences method."""
        pass

    def do_stench_moves_effect(self, steps):
        """Move the Stench frontier several miles deeper into the Silewer.

        Args:
            steps (int): Number of miles to cover with the Stench.
        """
        for _ in range(steps):
            base.world.make_stench_step()  # noqa: F821

    def do_transfusion_effect(self):
        """Do blood transfusion effect of Chapter 9."""
        char = None
        chars = list(base.team.chars.values())  # noqa: F821

        if chars:
            char = take_random(chars)
            char.health -= 30

        if chars:
            take_random(chars).health -= 30
        elif char:
            char.health -= 30

    def do_medicine_save(self):
        """Do save with medicines effect of Chapter 9."""
        if base.resource("medicine_boxes"):  # noqa: F821
            base.plus_resource("medicine_boxes", -1)  # noqa: F821
        else:
            chars = list(base.team.chars.values())  # noqa: F821
            if chars:
                take_random(chars).energy -= 40

    def hide_chapter(self):
        """Hide the scenario GUI."""
        if self.current_chapter == 4:
            MechanicDesc("SCP")

        self._list.hide()

    def start_chapter(self, task):
        """Start a new scenario chapter."""
        self.current_chapter += 1

        base.train.ctrl.set_controls(base.train)  # noqa: F821
        base.camera_ctrl.enable_ctrl_keys()  # noqa: F821

        base.world.outings_mgr.hide_outing()  # noqa: F821
        base.traits_gui.hide()  # noqa: F821

        if self.current_chapter <= 9:
            self.show_chapter_situation()  # noqa: F821

            base.world.drop_place_of_interest()  # noqa: F821

        if self.current_chapter in (1, 3, 4):
            base.add_scp_page()  # noqa: F821
            if self.current_chapter in (4, 7):
                base.world.meet_scp = True  # noqa: F821

        return task.done

    def show_chapter_situation(self):
        """Show the situation description and the possible variants."""
        self._done_but.hide()
        self._name["text"] = base.labels.SCENARIO_LABELS[0] + str(  # noqa: F821
            self.current_chapter + 1
        )
        self._desc["text"] = base.labels.SCENARIO[self.current_chapter][  # noqa: F821
            "intro"
        ]

        if (
            len(base.labels.SCENARIO[self.current_chapter]["variants"])  # noqa: F821
            == 3
        ):
            for index, var in enumerate(
                base.labels.SCENARIO[self.current_chapter]["variants"]  # noqa: F821
            ):
                self._buts[index]["text"] = var
                self._buts[index]["extraArgs"] = [var]
                self._buts[index]["command"] = self._choose_variant
                self._buts[index].show()
        else:
            self._buts[0].hide()
            self._buts[1].hide()

            for var in base.labels.SCENARIO[self.current_chapter][  # noqa: F821
                "variants"
            ]:
                self._buts[2]["text"] = var
                self._buts[2]["extraArgs"] = [var]
                self._buts[2]["command"] = self._choose_variant
                self._buts[2].show()

            self._done_but["command"] = self.finish_game

        self._list.show()


from DatabaseControllers.FirebaseConfig import db
# import FirebaseConfig

# db = FirebaseConfig.db

emptyQuestion = {
    "subject":"",
    "level":"",
    "questionText":"",
    "optionA":"",
    "optionB":"",
    "optionC":"",
    "optionD":"",
    "correctAnswer":"",
}

class QuestionDB:
    def add_question(self,subject,level,question):
        db.child("questions").child(subject).child(level).push(question)

    def get_questions(self, subject, level):
        questionList = db.child("questions").child(subject).child(level).get()
        return questionList.val()

    def get_all_questions(self):

        temp ={}

        questionList = db.child("questions").get()
        questiondb =  questionList.val()

        for subject in questiondb:
            #print(subject)
            for level in questiondb[subject]:
                #print(level)
                for question_id in questiondb[subject][level]:
                    #print(question_id)
                    temp[question_id] = questiondb[subject][level][question_id]

        return temp

    def get_single_question(self,questionID):
        db = QuestionDB()
        temp = db.get_all_questions()

        return temp[f'{questionID}']

    # db.child("users").child("Morty").update({"name": "Mortiest Morty"})
    def update_questions(self, subject, level, questionID, newQuestion):
        db.child("questions").child(subject).child(
            level).child(questionID).update(newQuestion)

    def delete_questions(self, questionID):
        db.child("questions").child(questionID).remove()

if __name__ == "__main__":

    data = {
    "subject": "algebra",
    "level": "level 1",
    "questionText": "2+1+2+8+1-1=x",
    "optionA": "2",
    "optionB": "3",
    "optionC": "5",
    "optionD": "14",
    "correctAnswer": "2",
}

    test = QuestionDB()
    print(test.get_single_question("-MoI_Crd-AGYfoiRcifX"))


# -*-coding:utf-8-*-
from main_app import app
from flask import render_template, jsonify, request
import json
from package_mix_ratio import result_package_new, package_best
from initial_screen import main_initial
from deep_model_strength.strength_prediction import presiction, load_torch_model
from main_util import change_joption_jprice
from mix_ratio_optimization import main_mix_ratio_optimization

model_strength = load_torch_model()  # 让模型一直在内存中
model_strength.eval()

# 设置route
@app.route('/')
@app.route('/index', methods=['GET', 'POST'])
def index():
    ip = request.remote_addr
    return render_template('index.html', user_ip=ip)

# 请求配合比
@app.route('/mixratio', methods=['POST'])
def create_task_test():
    data = json.loads(request.get_data())
    joption = data["option"]
    jprice = data["price"]
    # 获取石和砂是否使用、价格和位置等信息
    joption, jprice = change_joption_jprice(joption, jprice)
    lrecord = main_initial(joption)[:10]
    jresult = result_package_new(joption, jprice, lrecord)
    if len(jresult["result"]) > 0:
        best_record, best_apparent_density, best_unit_price = main_mix_ratio_optimization(joption, jprice, lrecord, model=model_strength)
        if best_record != None:
            jdata = package_best(joption, best_record, best_apparent_density, best_unit_price)  # 优化之后打包
            jresult["result"].insert(0, jdata)  # 优化后的数据插入到最前面
        else:
            print("生成数据失败!")
    return jsonify(jresult), 201

# 混凝土强度预测
@app.route('/mixratio/strength', methods=['POST'])
def strength_prediction():
    data = json.loads(request.get_data())
    jresult = presiction(data, model=model_strength)
    return jsonify(jresult), 201


import os
import time
import random
from gtts import gTTS
import pygame
import tkinter as tk
from tkinter import Listbox, Button, Checkbutton, simpledialog
import json
import threading
from pydub import AudioSegment
from pydub.playback import play
import openai
import requests
import datetime
import configparser
import re
from playsound import playsound
import emoji
from itertools import zip_longest

pygame.mixer.init()

# Load the configuration
config = configparser.ConfigParser()
config.read('config.ini')

# Access the configuration settings in the code
api_base = config['DEFAULT']['api_base']
openai_api_key = config['OpenAI']['api_key']
openweather_api_key = config['OpenWeatherMap']['api_key']
city = config['OpenWeatherMap']['city']

song_intro_prompt = config['Prompts']['song_intro']
comedy_skit_prompt = config['Prompts']['comedy_skit']
weather_forecast_prompt = config['Prompts']['weather_forecast']

# Load emoji to sound effect mappings from JSON file
with open("emoji_sound_mappings.json", "r", encoding='utf-8') as f:
    emoji_sound_mappings = json.load(f)

class LogBook:
    def __init__(self, filename="log_book.txt"):
        self.filename = filename

    def write_entry(self, entry_type, content):
        timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        with open(self.filename, "a", encoding='utf-8') as f:
            f.write(f"{timestamp} - {entry_type}: {content}\n")

import pygame.mixer
import time
import os

import threading
import queue
import os

import threading
import queue
import time
from gtts import gTTS
import os

class TTSManager:
    def __init__(self, playback_manager):
        self.text_queue = queue.Queue()
        self.audio_files = {}
        self.lock = threading.Lock()
        self.thread = threading.Thread(target=self._run, daemon=True)
        self.thread.start()
        self.playback_manager = playback_manager
        self.audio_files_directory = "tts_audio"  # Set the

    def _run(self):
        while True:
            text, filename = self.text_queue.get()
            if text is None:
                break
            audio_file = self.generate_voice_announcement(text, filename)
            with self.lock:
                self.audio_files[filename] = audio_file

    def generate_tts(self, text):
        filename = f"tts_audio/{int(time.time() * 1000)}.mp3"
        self.text_queue.put((text, filename))
        return filename

    def get_audio_file(self, filename):
        with self.lock:
            return self.audio_files.pop(filename, None)

    def shutdown(self):
        self.text_queue.put((None, None))  # Stop the thread

    def generate_voice_announcement(self, text, filename):
        tts = gTTS(text=text, lang='en', slow=False)
        tts.save(filename)
        return filename

    def play_text_with_effects(self, text):
        # Split the text into segments and emojis
        emoji_pattern = re.compile('[\U0001F600-\U0001F64F\U0001F300-\U0001F5FF\U0001F680-\U0001F6FF'
                                    '\U0001F700-\U0001F77F\U0001F780-\U0001F7FF\U0001F800-\U0001F8FF'
                                    '\U0001F900-\U0001F9FF\U0001FA00-\U0001FA6F\U0001FA70-\U0001FAFF'
                                    '\U00002702-\U000027B0]+', flags=re.UNICODE)
        segments = emoji_pattern.split(text)
        emojis = emoji_pattern.findall(text)

        # Play each segment and its following emoji
        for segment, emoji in zip_longest(segments, emojis, fillvalue=''):
            if segment:
                filename = self.generate_tts(segment)
                audio_file_path = os.path.join(self.audio_files_directory, filename)
                self.playback_manager.play_audio(audio_file_path)
            if emoji:
                self.playback_manager.play_sound_effect(emoji)

        def preload_tts(self, text):
            emoji_pattern = re.compile('[\U0001F600-\U0001F64F\U0001F300-\U0001F5FF\U0001F680-\U0001F6FF'
                                        '\U0001F700-\U0001F77F\U0001F780-\U0001F7FF\U0001F800-\U0001F8FF'
                                        '\U0001F900-\U0001F9FF\U0001FA00-\U0001FA6F\U0001FA70-\U0001FAFF'
                                        '\U00002702-\U000027B0]+', flags=re.UNICODE)
            segments = emoji_pattern.split(text)

        # Pre-generate TTS audio files for each text segment
        for segment in segments:
            if segment:
                self.generate_tts(segment)

class PlaybackManager:
    def __init__(self):
        self.queue = []
        self.currently_playing = None
        pygame.mixer.init()
        with open('emoji_sound_mappings.json', encoding='utf-8') as f:
            self.emoji_sound_mappings = json.load(f)

    def add_to_queue(self, filepath):
        self.queue.append(filepath)
        if not self.currently_playing:
            self.play_next()

    def play_next(self):
        if self.queue:
            self.currently_playing = self.queue.pop(0)
            self.play_audio(self.currently_playing)
            if self.currently_playing.startswith("tts_audio/"):
                self.delete_file(self.currently_playing)
            self.play_next()
        else:
            self.currently_playing = None

    def play_audio(self, filepath):
        sound = pygame.mixer.Sound(filepath)
        sound.play()
        time.sleep(sound.get_length())  # Wait for the sound to finish playing
        pass

    def delete_file(self, filepath):
        os.remove(filepath)

    def play_sound_effect(self, emoji):
        if emoji in self.emoji_sound_mappings:
            sound_effect_path = self.emoji_sound_mappings[emoji]
            print(f"Playing sound effect for emoji: {emoji}, path: {sound_effect_path}")
            try:
                self.play_audio(sound_effect_path)  # This assumes full paths are stored in the JSON file
            except Exception as e:
                print(f"Error playing sound effect: {e}")
        else:
            print(f"No sound effect found for emoji: {emoji}")

class OpenAI:
    def __init__(self):
        pass

    @staticmethod
    def Completion_create(model, prompt, max_tokens, n, stop, temperature, api_base):
        response = openai.Completion.create(
            model=model,
            prompt=prompt,
            max_tokens=max_tokens,
            n=n,
            stop=stop,
            temperature=temperature,
            api_base=api_base
        )
        return response

class MusicDirectoryWatcher:
    def __init__(self, directory):
        self.directory = directory
        self.last_played = None

    def get_random_song(self):
        all_songs = [f for f in os.listdir(self.directory) if f.endswith(".mp3")]
        if len(all_songs) == 1:
            return all_songs[0]
        selectable_songs = [song for song in all_songs if song != self.last_played]
        selected_song = random.choice(selectable_songs)
        self.last_played = selected_song
        return selected_song

def generate_voice_announcement(text, filename=None, lang="en"):
    if filename is None:
        timestamp = str(int(time.time() * 1000))
        filename = "tts_audio/{}.mp3".format(timestamp)
    tts = gTTS(text=text, lang=lang, slow=False)
    tts.save(filename)
    return filename

def play_audio_file(audio_file_path):
    audio_segment = AudioSegment.from_file(audio_file_path, format="mp3")
    play(audio_segment)

import re

class QueueItem:
    def __init__(self, voice_intro_text, playback_manager, tts_manager):
        self.voice_intro_text = voice_intro_text
        self.playback_manager = playback_manager
        self.tts_manager = tts_manager

    def play(self):
        self.tts_manager.play_text_with_effects(self.voice_intro_text)

class SongItem(QueueItem):
    def __init__(self, voice_intro_text, song_file, playback_manager, tts_manager):
        super().__init__(voice_intro_text, playback_manager, tts_manager)
        self.song_file = song_file

    def play(self):
        # First, play the voice introduction
        super().play()
        # Then, play the song
        play_audio_file(self.song_file)

class ComedySkitItem(QueueItem):
    def __init__(self, voice_intro_text, playback_manager, tts_manager):
        super().__init__(voice_intro_text, playback_manager, tts_manager)
        # other initializations if needed

class WeatherForecastItem(QueueItem):
    def __init__(self, voice_intro_text, playback_manager, tts_manager):
        super().__init__(voice_intro_text, playback_manager, tts_manager)
        # other initializations if needed

def generate_comedy_skit():
    prompt = "Create a short, funny comedy skit for the radio audience."
    response = openai_api.Completion_create(
        model="gpt-4-32k",
        prompt=comedy_skit_prompt,
        max_tokens=150,
        n=1,
        stop=None,
        temperature=0.7,
        api_base=api_base
    )
    skit_text = response["choices"][0]["text"]
    skit_data = {
        "Voice Introduction Text": skit_text,
        "Type": "Comedy Skit"
    }
    song_queue.append(ComedySkitItem(skit_text, playback_manager, tts_manager))  # Pass tts_manager here
    log_book.write_entry("Comedy Skit", skit_text)
    listbox_commands.insert(tk.END, "Queued: Comedy Skit")

# The rest of the code remains unchanged

def on_add_song():
    global playback_manager
    next_song = watcher.get_random_song()
    song_intro_prompt = f"Co-Host: Introduce the next song titled '{next_song[:-4]}' to the audience. Only say the name in a funny sentence. Announcer:"
    response = openai_api.Completion_create(
        model="gpt-4-32k",
        prompt=song_intro_prompt.format(song_name=next_song[:-4]),
        max_tokens=2000,
        n=1,
        stop=None,
        temperature=0.7,
        api_base=api_base
    )
    song_intro = response["choices"][0]["text"]
    song_path = os.path.join(watcher.directory, next_song)
    song_queue.append(SongItem(song_intro, song_path, playback_manager, tts_manager))  # Pass playback_manager here
    log_book.write_entry("Song Intro", song_intro)
    listbox_commands.insert(tk.END, f"Queued: {next_song}")

is_playing = False
play_lock = threading.Lock()

def play_from_queue():
    global is_playing

    with play_lock:
        if is_playing:
            print("Already playing, please wait...")
            return
        is_playing = True

    if not song_queue:
        with play_lock:
            is_playing = False
        return

    item = song_queue.pop(0)

    try:
        item.play()
    finally:
        with play_lock:
            is_playing = False

        listbox_commands.delete(0)

        # Check if auto_play_next is True and play next item if available
        if auto_play_next.get() and song_queue:
            window.after(1000, threaded_play_from_queue)  # Delay of 1 second before next play

def threaded_play_from_queue():
    threading.Thread(target=play_from_queue).start()

def move_up():
    index = listbox_commands.curselection()
    if not index:
        return
    index = index[0]
    if index == 0:
        return
    song_queue[index], song_queue[index-1] = song_queue[index-1], song_queue[index]
    listbox_commands.insert(index-1, listbox_commands.get(index))
    listbox_commands.delete(index+1)
    listbox_commands.selection_set(index-1)

def move_down():
    index = listbox_commands.curselection()
    if not index:
        return
    index = index[0]
    if index == len(song_queue) - 1:
        return
    song_queue[index], song_queue[index+1] = song_queue[index+1], song_queue[index]
    listbox_commands.insert(index+2, listbox_commands.get(index))
    listbox_commands.delete(index)
    listbox_commands.selection_set(index+1)

def toggle_auto_play():
    if auto_play_next.get():
        btn_toggle_auto_play.config(text="Auto-Play: ON")
    else:
        btn_toggle_auto_play.config(text="Auto-Play: OFF")

def fetch_weather():
    base_url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={openweather_api_key}&units=metric"
    response = requests.get(base_url)
    data = response.json()

    if 'main' not in data:
        print(f"Error fetching weather data: {data}")
        return None, None

    temperature = data["main"]["temp"]
    description = data["weather"][0]["description"]
    return temperature, description

def on_generate_weather_forecast():
    temperature, description = fetch_weather()
    if temperature is None or description is None:
        print("Failed to fetch weather data.")
        return

    prompt = weather_forecast_prompt.format(city=city, temperature=temperature, description=description)
    response = openai_api.Completion_create(
        model="gpt-4-32k",
        prompt=prompt,
        max_tokens=2000,
        n=1,
        stop=None,
        temperature=0.7,
        api_base=api_base
    )

    forecast_text = response["choices"][0]["text"]
    song_queue.append(WeatherForecastItem(forecast_text, playback_manager, tts_manager))  # Pass playback_manager here
    listbox_commands.insert(tk.END, "Queued: Weather Forecast")
    log_book.write_entry("Weather Forecast", forecast_text)

class SongItem(QueueItem):
    def __init__(self, voice_intro_text, song_path, playback_manager, tts_manager):
        super().__init__(voice_intro_text, playback_manager, tts_manager)
        self.song_path = song_path

    def play(self):
        print("Playing item:", self.voice_intro_text)
        super().play()
        play_audio_file(self.song_file)

def open_settings():
    settings_window = tk.Toplevel(window)
    settings_window.title("Settings")

    tk.Label(settings_window, text="API Base:").pack(pady=5)
    api_base_entry = tk.Entry(settings_window, width=40)
    api_base_entry.insert(0, api_base)
    api_base_entry.pack(pady=5)

    tk.Label(settings_window, text="OpenAI API Key:").pack(pady=5)
    openai_api_key_entry = tk.Entry(settings_window, width=40)
    openai_api_key_entry.insert(0, openai_api_key)
    openai_api_key_entry.pack(pady=5)

    tk.Label(settings_window, text="OpenWeatherMap API Key:").pack(pady=5)
    openweather_api_key_entry = tk.Entry(settings_window, width=40)
    openweather_api_key_entry.insert(0, openweather_api_key)
    openweather_api_key_entry.pack(pady=5)

    tk.Label(settings_window, text="City:").pack(pady=5)
    city_entry = tk.Entry(settings_window, width=40)
    city_entry.insert(0, city)
    city_entry.pack(pady=5)

    tk.Label(settings_window, text="Song Intro Prompt:").pack(pady=5)
    song_intro_prompt_entry = tk.Entry(settings_window, width=40)
    song_intro_prompt_entry.insert(0, song_intro_prompt)
    song_intro_prompt_entry.pack(pady=5)

    tk.Label(settings_window, text="Comedy Skit Prompt:").pack(pady=5)
    comedy_skit_prompt_entry = tk.Entry(settings_window, width=40)
    comedy_skit_prompt_entry.insert(0, comedy_skit_prompt)
    comedy_skit_prompt_entry.pack(pady=5)

    tk.Label(settings_window, text="Weather Forecast Prompt:").pack(pady=5)
    weather_forecast_prompt_entry = tk.Entry(settings_window, width=40)
    weather_forecast_prompt_entry.insert(0, weather_forecast_prompt)
    weather_forecast_prompt_entry.pack(pady=5)

    def save_settings():
        config.set('OpenAI', 'api_key', openai_api_key_entry.get())
        config.set('DEFAULT', 'api_base', api_base_entry.get())
        config.set('OpenWeatherMap', 'api_key', openweather_api_key_entry.get())
        config.set('OpenWeatherMap', 'city', city_entry.get())
        config.set('Prompts', 'song_intro', song_intro_prompt_entry.get())
        config.set('Prompts', 'comedy_skit', comedy_skit_prompt_entry.get())
        config.set('Prompts', 'weather_forecast', weather_forecast_prompt_entry.get())
        with open('config.ini', 'w', encoding='utf-8') as configfile:
            config.write(configfile)

        # Update the global variables
        global api_base, openai_api_key, openweather_api_key, city
        global song_intro_prompt, comedy_skit_prompt, weather_forecast_prompt
        api_base = api_base_entry.get()
        openai_api_key = openai_api_key_entry.get()
        openweather_api_key = openweather_api_key_entry.get()
        city = city_entry.get()
        song_intro_prompt = song_intro_prompt_entry.get()
        comedy_skit_prompt = comedy_skit_prompt_entry.get()
        weather_forecast_prompt = weather_forecast_prompt_entry.get()

        settings_window.destroy()

    tk.Button(settings_window, text="Save", command=save_settings).pack(pady=20)

def on_custom_intro():
    custom_intro_text = tk.simpledialog.askstring("Custom Introduction", "Enter the introduction text:")
    if custom_intro_text:
        item = QueueItem(custom_intro_text, playback_manager, tts_manager)  # Ensure playback_manager is passed here
        song_queue.append(item)
        print("Added to queue:", item.voice_intro_text)  # Add this line
        listbox_commands.insert(tk.END, "Queued: Custom Introduction")

window = tk.Tk()
window.title("Radio Host")

song_queue = []
auto_play_next = tk.BooleanVar(value=False)

frame_left = tk.Frame(window)
frame_left.pack(side=tk.LEFT, padx=20, pady=20)

btn_add_song = Button(frame_left, text="Add Song", command=on_add_song)
btn_add_song.pack(pady=10)

btn_generate_skit = Button(frame_left, text="Generate Comedy Skit", command=generate_comedy_skit)
btn_generate_skit.pack(pady=10)

btn_custom_intro = Button(frame_left, text="Add Custom Intro", command=on_custom_intro)
btn_custom_intro.pack(pady=10)

btn_play_next = Button(frame_left, text="Play Next", command=threaded_play_from_queue)
btn_play_next.pack(pady=10)

btn_move_up = Button(frame_left, text="Move Up", command=move_up)
btn_move_up.pack(pady=10)

btn_move_down = Button(frame_left, text="Move Down", command=move_down)
btn_move_down.pack(pady=10)

btn_toggle_auto_play = Checkbutton(frame_left, text="Auto-Play: OFF", variable=auto_play_next, command=toggle_auto_play)
btn_toggle_auto_play.pack(pady=10)

btn_generate_weather = Button(frame_left, text="Generate Weather Forecast", command=on_generate_weather_forecast)
btn_generate_weather.pack(pady=10)

btn_settings = Button(frame_left, text="Settings", command=open_settings)
btn_settings.pack(pady=10)

frame_right = tk.Frame(window)
frame_right.pack(side=tk.RIGHT, padx=20, pady=20)

listbox_commands = Listbox(frame_right)
listbox_commands.pack(pady=10)

if __name__ == "__main__":
    music_dir = "./music_folder"
    openai_api = OpenAI()
    openai.api_key = openai_api_key  # Setting the OpenAI API key
    tts_manager = TTSManager(PlaybackManager)
    watcher = MusicDirectoryWatcher(music_dir)
    log_book = LogBook()  # Create an instance of LogBook here
    playback_manager = PlaybackManager()
    window.mainloop()
    tts_manager.shutdown()


import numpy as np
from catalyst.constants import LOG_LEVEL
from catalyst.protocol import Portfolio, Positions, Position
from logbook import Logger

log = Logger('ExchangePortfolio', level=LOG_LEVEL)

class ExchangePortfolio(Portfolio):
    """
    Since the goal is to support multiple exchanges, it makes sense to
    include additional stats in the portfolio object. This fills the role
    of Blotter and Portfolio in live mode.

    Instead of relying on the performance tracker, each exchange portfolio
    tracks its own holding. This offers a separation between tracking an
    exchange and the statistics of the algorithm.
    """

    def __init__(self, start_date, starting_cash=None):
        self.capital_used = 0.0
        self.starting_cash = starting_cash
        self.portfolio_value = starting_cash
        self.pnl = 0.0
        self.returns = 0.0
        self.cash = starting_cash
        self.positions = Positions()
        self.start_date = start_date
        self.positions_value = 0.0
        self.open_orders = dict()

    def create_order(self, order):
        """
        Create an open order and store in memory.

        Parameters
        ----------
        order: Order

        """
        log.debug('creating order {}'.format(order.id))

        open_orders = self.open_orders[order.asset] \
            if order.asset is self.open_orders else []

        open_orders.append(order)

        self.open_orders[order.asset] = open_orders

        order_position = self.positions[order.asset] \
            if order.asset in self.positions else None

        if order_position is None:
            order_position = Position(order.asset)
            self.positions[order.asset] = order_position

        order_position.amount += order.amount
        log.debug('open order added to portfolio')

    def _remove_open_order(self, order):
        try:
            open_orders = self.open_orders[order.asset]
            if order in open_orders:
                open_orders.remove(order)

        except Exception:
            raise ValueError(
                'unable to clear order not found in open order list.'
            )

    def execute_order(self, order, transaction):
        """
        Update the open orders and positions to apply an executed order.

        Unlike with backtesting, we do not need to add slippage and fees.
        The executed price includes transaction fees.

        Parameters
        ----------
        order: Order
        transaction: Transaction

        """
        log.debug('executing order {}'.format(order.id))
        self._remove_open_order(order)

        order_position = self.positions[order.asset] \
            if order.asset in self.positions else None

        if order_position is None:
            raise ValueError(
                'Trying to execute order for a position not held:'
                ' {}'.format(order.id)
            )

        self.capital_used += order.amount * transaction.price

        if order.amount > 0:
            if order_position.cost_basis > 0:
                order_position.cost_basis = np.average(
                    [order_position.cost_basis, transaction.price],
                    weights=[order_position.amount, order.amount]
                )
            else:
                order_position.cost_basis = transaction.price

        log.debug('updated portfolio with executed order')

    def remove_order(self, order):
        """
        Removing an open order.

        Parameters
        ----------
        order: Order

        """
        log.info('removing cancelled order {}'.format(order.id))
        self._remove_open_order(order)

        order_position = self.positions[order.asset] \
            if order.asset in self.positions else None

        if order_position is None:
            raise ValueError(
                'Trying to remove order for a position not held: %s' % order.id
            )

        order_position.amount -= order.amount

        log.debug('removed order from portfolio')


from agents import Prover, Checker, CoqEvaluator

prover = Prover('Prove the fundamental theorem of calculus.')
checker = Checker()
evaluator = CoqEvaluator()

feedback = None
accepted = False
steps = 0
explanations = []

while not accepted and steps < 3:
    explanation, coq = prover.step(input=feedback)
    coq_output, coq_success = evaluator.evaluate(coq)

    if not coq_success:
        feedback = f"Coq error: {coq_output}. \nCheck the Coq code for syntax errors, and try again."
        explanations.append(checker.check(explanation))
    else:
        feedback, accepted = checker.check(explanation)
        explanations.append((feedback, accepted))

    print("\033[92m" + feedback + "\033[0m")
    if accepted: break

    steps += 1

for i, thing in enumerate(explanations):
    print(i)
    print(thing)


from collections import Counter
class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        cl = list(Counter(nums).items())
        ret=[[]]
        return foo(0,cl,ret)

def foo(idx, cnt, ret):
        if idx==len(cnt): return ret
        new_ret=ret.copy()
        num=cnt[idx][0]
        rng=cnt[idx][1]
        #print('idx {} ret {} num {} rng {}'.format(idx,ret,num,rng))

        if idx==0:
                for i in range(1,rng+1):
                        new_ret.append([num]*i)
        else:
                for i in range(1,rng+1):
                        to_app=[num]*i
                        for r in ret:
                                row=r.copy()
                                row.extend(to_app)
                                new_ret.append(row)
        return foo(idx+1,cnt,new_ret)


#! /usr/bin/env python

#!/usr/bin/env python
#
# Filename      : averages.py
# Author        : Yuhang Ming
# Date          : Feb 2021
# Description   : Command line script to display averages of some numbers.

from averages import mode

import sys
import math
import argparse

def compute_mean(vals):
    sum = 0.
    num = len(vals)
    for v in vals:
        sum = sum + v
    avg_mean = sum / num
    print("Mean: ", avg_mean)

def compute_median(vals):
    num = len(vals)
    # Buble sorting
    for i in range(num-1):
        for j in range(num-i-1):
            if vals[j] > vals[j+1] :
                vals[j], vals[j+1] = vals[j+1], vals[j]
    half = math.ceil(num/2.)
    print("Median: ", vals[half-1])

def compute_mod(vals):
    val_dict = {}
    for v in vals:
        if v in val_dict.keys():
            val_dict[v] = val_dict[v] + 1
        else:
            val_dict[v] = 1
    max_count = max(val_dict.values())
    print("Mod: ", end=' ')
    for val, count in val_dict.items():
        if count == max_count:
            print(val, ", ", end=' ')
    print("")

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Take averages of a set of integers.')
    parser.add_argument('integers', metavar='N', type=int, nargs='*',
                        help='integers to be averaged')
    parser.add_argument('--mean', dest='mean', action='store_true', default=False,
                        help='take the mean')
    parser.add_argument('--mode', dest='mod', action='store_true', default=False,
                        help='take the mode')
    parser.add_argument('--median', dest='median', action='store_true', default=False,
                        help='find the median')
    parser.add_argument('--file', dest='file_name', default="",
                        help='take the average from a file')
    args = parser.parse_args()

    if len(args.file_name) > 0 and len(args.integers) > 0:
        print("ERROR: expected one non-flag input when -file is specified")
        exit(1)

    elif len(args.file_name) > 0 and len(args.integers) == 0:
        print("Reading from ", args.file_name)
        with open(args.file_name) as f:
            array = []
            for line in f: # read rest of lines
                array.append([int(x) for x in line.split()])
        vals = [j for sub in array for j in sub]
        if len(vals) == 0:
            print("ERROR: no integers given.")
            exit(1)

    elif len(args.file_name) == 0 and len(args.integers) > 0:
        print("Reading from command line.")
        vals = args.integers
        if len(args.integers) > 8:
            print("ERROR: expected max 8 integer data points.")
            exit(1)

    else:
        print("ERROR: no file or integers given.")
        exit(1)

    if not args.mean and not args.mod and not args.median:
        compute_mean(vals)
        compute_median(vals)
        compute_mod(vals)

    if args.mean:
        compute_mean(vals)

    if args.median:
        compute_median(vals)

    if args.mod:
        compute_mod(vals)

    mode(vals)


# 키로거
# 소요시간 12분
import sys
input = sys.stdin.readline

T = int(input())

for _ in range(T):
    script = list(input().strip())
    left  = []
    right = []
    for cmd in script:

        if cmd == '-':
            if not left:
                continue
            left.pop()

        elif cmd == '<':
            if not left:
                continue
            x = left.pop()
            right.append(x)

        elif cmd == '>':
            if not right:
                continue
            x = right.pop()
            left.append(x)
        else:
            left.append(cmd)

    print(''.join(left+right[::-1]))


from airflow import DAG
from airflow.operators.python_operator import PythonOperator
from datetime import datetime, timedelta
from test_python_transformation import test_clean_amount,test_clean_Date

default_args = {
    'owner': 'airflow',
    'start_date': datetime(2023, 8, 28),
    'retries': 1,
    'retry_delay': timedelta(seconds=2),
}

with DAG('Unit_Test_Dag', default_args=default_args, schedule_interval=timedelta(days=1), catchup=False) as dag:

    # Task 2 : transformation et création du nouveau fichier
    t1 = PythonOperator(
        task_id='UnitTestAmount',
        python_callable=test_clean_amount,
    )

     # Task 4 : création de la table Postgres
    t2 = PythonOperator(
        task_id='UnitTestCleanDate',
        python_callable=test_clean_Date,
    )

    # Les deux tâches seront faîtes simultanéments
    [t1,t2]


from pydantic import BaseModel
from openai import OpenAI
import json
from nlp_toolkit.llms.openai import OpenAIRequest

class PydanticTool:

    def __init__(self, model:BaseModel):

        if not issubclass(model, BaseModel):
            raise ValueError("Model should be a valid pydantic BaseModel")
        self.model = model

    @property
    def tool_spec(self):
        schema = self.model.schema()
        return {
            "type":"function",
            "function":{
                "name":schema['title'],
                "description":schema['description'],
                "parameters": {
                    "type": "object",
                    "properties":{k: {kk:vv for kk, vv in v.items() if kk!= 'title'}
                                for k, v in schema['properties'].items()}
                }
            }
        }

    def __call__(self, **kwargs):
        return self.model(**kwargs)

class StructuredExtraction:

    def __init__(self, client:"OpenAI", response_model:BaseModel, system_prompt:str = None, **kwargs):
        self.client = client
        self.tool = PydanticTool(response_model)
        if system_prompt is None:
            self.system_prompt = 'you are a nlp bot, that helps to extract entities from texts'
        else:
            self.system_prompt = system_prompt

    def __call__(self, input):

        openai_request = OpenAIRequest(
            client = self.client,
            model = "gpt-3.5-turbo-0613",
            messages = [{'role':'system','content':self.system_prompt}],
            tools = [self.tool.tool_spec],
            tool_choice = 'auto'
        )

        response = openai_request(input)
        args = json.loads(response.choices[0].message.tool_calls[0].function.arguments)
        return self.tool(**args)


from django.contrib import admin

from instaparser.models import TaskForParse, Data, InstagramAccount

class TaskForParseAdmin(admin.ModelAdmin):
    """Выводить модель TaskForParse"""

    list_display = ['id', 'user', 'user_to_scrape', 'count_parse_data', 'status', 'file',
                    'next_max_id', 'type_of_parse']
    list_editable = ['status', 'file']

class InstagramAccountAdmin(admin.ModelAdmin):
    """Выводить модель InstagramAccount"""

    list_display = ['id', 'username', 'is_used', 'used_at', 'enc_password']
    list_editable = ['is_used', ]

class DataAdmin(admin.ModelAdmin):
    """Выводить модель TaskForParse"""

    list_display = [
        'id',
        'task_for_parse',
        'username',
        'full_name',
        'biography',
        'is_private',
        'follower_count',
        'following_count',
        'following_tag_count',
        'media_count',
        'usertags_count',
        'contact_phone_number',
        'public_email',
        'whatsapp_number',
        'business_contact_method',
        'instagram_location_id',
    ]

admin.site.register(TaskForParse, TaskForParseAdmin)
admin.site.register(Data, DataAdmin)
admin.site.register(InstagramAccount, InstagramAccountAdmin)


# -*- coding: utf-8 -*-
# @Time    : 2023/3/17 18:33
# @Author  : Flora.Chen
# @File    : conftest.py
# @Software: PyCharm
# @Desc:

# 标准库导入
# 第三方库导入
import pytest
import allure
from loguru import logger
# 本地应用/模块导入
from config.settings import RunConfig
from case_utils.get_driver import GetDriver

@pytest.fixture(scope="function", autouse=True)
def case_skip(request):
    """处理跳过用例"""
    # 使用 request.getfixturevalue() 方法来获取测试用例函数的参数值
    # 注意这里的"case"需要与@pytest.mark.parametrize("case", cases)中传递的保持一致
    case = request.getfixturevalue("case")
    if case.get("run") is None or case.get("run") is False:
        reason = f"{case.get('title')}: 标记了该用例为false，不执行\\n"
        logger.warning(f"{reason}")
        pytest.skip(reason)

def pytest_collection_modifyitems(config, items):
    for item in items:
        # 注意这里的"case"需要与@pytest.mark.parametrize("case", cases)中传递的保持一致
        parameters = item.callspec.params["case"]
        # print(f"测试参数：{type(parameters)}     {parameters}")
        if parameters and parameters.get("severity"):
            if parameters["severity"].upper() == "TRIVIAL":
                item.add_marker(allure.severity(allure.severity_level.TRIVIAL))
            elif parameters["severity"].upper() == "MINOR":
                item.add_marker(allure.severity(allure.severity_level.MINOR))
            elif parameters["severity"].upper() == "CRITICAL":
                item.add_marker(allure.severity(allure.severity_level.CRITICAL))
            elif parameters["severity"].upper() == "BLOCKER":
                item.add_marker(allure.severity(allure.severity_level.BLOCKER))
            else:
                item.add_marker(allure.severity(allure.severity_level.NORMAL))
        else:
            item.add_marker(allure.severity(allure.severity_level.NORMAL))

# ------------------------------------- START: 配置浏览器驱动 ---------------------------------------#
@pytest.fixture(scope="session")
def init_drivers():
    # logger.debug(f"此时的driver类型:{RunConfig.driver_type}")
    drivers = GetDriver(drivers_type=RunConfig.driver_type).get_driver()
    RunConfig.drivers = drivers
    yield drivers
    for driver in drivers:
        driver.close()
        driver.quit()
# ------------------------------------- END: 配置浏览器驱动 ---------------------------------------#


import math
import torch
import torch.nn as nn
import torch.distributions as D
import numpy as np
import json

class gaussian:
    """
    This is a simple Gaussian prior used for initializing mixture model means
    """

    def __init__(self, dim, mean, stddev):
        self.dim = dim
        self.mean = mean
        self.stddev = stddev
        self.g = torch.distributions.normal.Normal(mean, stddev)

    def sample(self, n):
        return self.g.sample((n, self.dim))

    def log_prob(self, x):
        return self.g.log_prob(x)

class softball:
    """
    Almost uniform prior for the m-dimensional ball.
    Logistic function makes a soft (differentiable) boundary.
    Returns a prior function and a sample function.
    The prior takes a tensor with a batch of z
    vectors (last dim) and returns a tensor of prior log-probabilities.
    The sample function returns n samples from the prior (approximate
    samples uniform from the m-ball). NOTE: APPROXIMATE SAMPLING.
    """

    def __init__(self, dim, radius, a=1):
        self.dim = dim
        self.radius = radius
        self.a = a
        self.norm = math.lgamma(1 + dim * 0.5) - dim * (
            math.log(radius) + 0.5 * math.log(math.pi)
        )

    def sample(self, n):
        # Return n random samples
        # Approximate: We sample uniformly from n-ball
        with torch.no_grad():
            # Gaussian sample
            sample = torch.randn((n, self.dim))
            # n random directions
            sample.div_(sample.norm(dim=-1, keepdim=True))
            # n random lengths
            local_len = self.radius * torch.pow(torch.rand((n, 1)), 1.0 / self.dim)
            sample.mul_(local_len.expand(-1, self.dim))
        return sample

    def log_prob(self, z):
        # Return log probabilities of elements of tensor (last dim assumed to be z vectors)
        return self.norm - torch.log(
            1 + torch.exp(self.a * (z.norm(dim=-1) / self.radius - 1))
        )

class GaussianMixture(nn.Module):
    def __init__(
        self,
        Nmix,
        dim,
        type="diagonal",
        alpha=1,
        mean_init=(1.0, 1.0),
        sd_init=[1.0, 1.0],
    ):
        """
        A mixture of multi-variate Gaussians

        Nmix is the number of components in the mixture
        dim is the dimension of the space
        type can be "fixed", "isotropic" or "diagonal", which refers to the covariance matrices
        mean_prior is a prior class with a log_prob and sample function
            - Standard normal if not specified.
            - Other option is ('softball',<radius>,<hardness>)
        If there is no mean_prior specified, a default Gaussian will be chosen with
            - mean_init[0] as mean and mean_init[1] as standard deviation
        logbeta_prior is a prior class for the negative log variance of the mixture components
            - logbeta = log (1/sigma^2)
            - If it is not specified, we make this prior a Gaussian from sd_init parameters
            - For the sake of interpretability, the sd_init parameters represent the desired mean and (approximately) sd of the standard deviation
            - the difference btw giving a prior beforehand and giving only init values is that with a given prior, the logbetas will be sampled from it, otherwise they will be initialized the same
        alpha determines the Dirichlet prior on mixture coefficients
        Mixture coefficients are initialized uniformly
        Other parameters are sampled from prior
        """
        super(GaussianMixture, self).__init__()
        self.dim = dim
        self.Nmix = Nmix
        # self.init = init

        # Means with shape: Nmix,dim
        self.mean = nn.Parameter(torch.empty(Nmix, dim), requires_grad=True)
        self.mean_prior = softball(self.dim, mean_init[0], mean_init[1])

        # Dirichlet prior on mixture
        self.alpha = alpha
        self.dirichlet_constant = math.lgamma(Nmix * alpha) - Nmix * math.lgamma(alpha)

        # Log inverse variance with shape (Nmix,dim) or (Nmix,1)
        self.sd_init = sd_init
        self.sd_init[0] = 0.2 * (mean_init[0] / self.Nmix)
        self.betafactor = dim * 0.5  # rename this!
        self.bdim = 1  # If 'diagonal' the dimension of lobbeta is = dim
        if type == "fixed":
            # No gradient needed for training
            # This is a column vector to be correctly broadcastet in std dev tensor
            self.logbeta = nn.Parameter(
                torch.empty(Nmix, self.bdim), requires_grad=False
            )
            self.logbeta_prior = None
        else:
            if type == "diagonal":
                self.betafactor = 0.5
                self.bdim = dim
            elif type != "isotropic":
                raise ValueError(
                    "type must be 'isotropic' (default), 'diagonal', or 'fixed'"
                )

            self.logbeta = nn.Parameter(
                torch.empty(Nmix, self.bdim), requires_grad=True
            )

        # Mixture coefficients. These are weights for softmax
        self.weight = nn.Parameter(torch.empty(Nmix), requires_grad=True)
        self.init_params()

        # -dim*0.5*log(2pi)
        self.pi_term = -0.5 * self.dim * math.log(2 * math.pi)

    def init_params(self):
        with torch.no_grad():
            # Means are sampled from the prior
            self.mean.copy_(self.mean_prior.sample(self.Nmix))
            self.logbeta.fill_(-2 * math.log(self.sd_init[0]))
            self.logbeta_prior = gaussian(
                self.bdim, -2 * math.log(self.sd_init[0]), self.sd_init[1]
            )

            # Weights are initialized to 1, corresponding to uniform mixture coeffs
            self.weight.fill_(1)

    def forward(self, x, label=None):
        # The beta values are obtained from logbeta
        halfbeta = 0.5 * torch.exp(self.logbeta)

        # y = logp =  - 0.5*log (2pi) -0.5*beta(x-mean[i])^2 + 0.5*log(beta)
        # sum terms for each component (sum is over last dimension)
        # y is one-dim with length Nmix
        # x is unsqueezed to (nsample,1,dim), so broadcasting of mean (Nmix,dim) works
        y = (
            self.pi_term
            - (x.unsqueeze(-2) - self.mean).square().mul(halfbeta).sum(-1)
            + self.betafactor * self.logbeta.sum(-1)
        )
        # For each component multiply by mixture probs
        y += torch.log_softmax(self.weight, dim=0)
        y = torch.logsumexp(y, dim=-1)
        y = y + self.prior()  # += gives cuda error

        return y

    def log_prob(self, x):  # Add label?
        self.forward(x)

    def mixture_probs(self):
        return torch.softmax(self.weight, dim=-1)

    def covariance(self):
        return torch.exp(-self.logbeta)

    def prior(self):
        """Calculate log prob of prior on mean, logbeta, and mixture coeff"""
        # Mixture
        p = self.dirichlet_constant  # /self.Nmix
        if self.alpha != 1:
            p = p + (self.alpha - 1.0) * (
                self.mixture_probs().log().sum()
            )  # /self.Nmix
        # Means
        p = p + self.mean_prior.log_prob(self.mean).sum()  # /self.Nmix
        # logbeta
        if self.logbeta_prior is not None:
            p = (
                p + self.logbeta_prior.log_prob(self.logbeta).sum()
            )  # /(self.Nmix*self.dim)
        return p

    def Distribution(self):
        with torch.no_grad():
            mix = D.Categorical(probs=torch.softmax(self.weight, dim=-1))
            comp = D.Independent(D.Normal(self.mean, torch.exp(-0.5 * self.logbeta)), 1)
            return D.MixtureSameFamily(mix, comp)

    def sample(self, nsample):
        with torch.no_grad():
            gmm = self.Distribution()
            return gmm.sample(torch.tensor([nsample]))

    def component_sample(self, nsample):
        """Returns a sample from each component. Tensor shape (nsample,nmix,dim)"""
        with torch.no_grad():
            comp = D.Independent(D.Normal(self.mean, torch.exp(-0.5 * self.logbeta)), 1)
            return comp.sample(torch.tensor([nsample]))

    def sample_probs(self, x):
        halfbeta = 0.5 * torch.exp(self.logbeta)
        y = (
            self.pi_term
            - (x.unsqueeze(-2) - self.mean).square().mul(halfbeta).sum(-1)
            + self.betafactor * self.logbeta.sum(-1)
        )
        y += torch.log_softmax(self.weight, dim=0)
        return torch.exp(y)

    """This section is for learning new data points"""

    def sample_new_points(self, n_points, option="random", n_new=1):
        """
        Generates samples for each new data point
            - n_points defines the number of new data points to learn
            - option defines which of 2 schemes to use
                - random: sample n_new vectors from each component
                    -> Nmix * n_new values per new point
                - mean: take the mean of each component as initial representation values
                    -> Nmix values per new point
        The order of repetition in both options is [a,a,a, b,b,b, c,c,c] on data point ID.
        """
        self.new_samples = n_new
        multiplier = self.Nmix
        if option == "random":
            out = self.component_sample(n_points * n_new)
            multiplier *= n_new

        elif option == "mean":
            with torch.no_grad():
                out = torch.repeat_interleave(
                    self.mean.clone().cpu().detach().unsqueeze(0), n_points, dim=0
                )
        else:
            print(
                "Please specify how to initialize new representations correctly \nThe options are 'random' and 'mean'."
            )
        return out.view(n_points * self.new_samples * self.Nmix, self.dim)

    def reshape_targets(self, y, y_type="true"):
        """
        Since we have multiple representations for the same new data point,
        we need to reshape the output a little to calculate the losses
        Depending on the y_type, y can be
            - the true targets (y_type: 'true')
            - the model predictions (y_type: 'predicted') (can also be used for rep.z in dataloader loop)
            - the 4-dimensional representation or the loss (y_type: 'reverse')
        """

        if y_type == "true":
            if len(y.shape) > 2:
                raise ValueError(
                    "Unexpected shape in input to function reshape_targets. Expected 2 dimensions, got "
                    + str(len(y.shape))
                )
            return (
                y.unsqueeze(1).unsqueeze(1).expand(-1, self.new_samples, self.Nmix, -1)
            )
        elif y_type == "predicted":
            if len(y.shape) > 2:
                raise ValueError(
                    "Unexpected shape in input to function reshape_targets. Expected 2 dimensions, got "
                    + str(len(y.shape))
                )
            n_points = int(
                torch.numel(y) / (self.new_samples * self.Nmix * y.shape[-1])
            )
            return y.view(n_points, self.new_samples, self.Nmix, y.shape[-1])
        elif "reverse":
            if len(y.shape) < 4:
                # this case is for when the losses are of shape (n_points,self.new_samples,self.Nmix)
                return y.view(y.shape[0] * self.new_samples * self.Nmix)
            else:
                return y.view(y.shape[0] * self.new_samples * self.Nmix, y.shape[-1])
        else:
            raise ValueError(
                "The y_type in function reshape_targets was incorrect. Please choose between 'true' and 'predicted'."
            )

    def choose_best_representations(self, x, losses):
        """
        Selects the representation for each new datapoint that maximizes the objective
            - x are the newly learned representations
            - x and losses have to have the same shape in the first dimension
              make sure that the losses are only summed over the output dimension
        Outputs new representation values
        """
        n_points = int(torch.numel(losses) / (self.new_samples * self.Nmix))

        best_sample = torch.argmin(
            losses.view(-1, self.new_samples * self.Nmix), dim=1
        ).squeeze(-1)
        best_rep = x.view(n_points, self.new_samples * self.Nmix, self.dim)[
            range(n_points), best_sample
        ]
        # best_rep = torch.diagonal(x.view(n_points,self.new_samples*self.Nmix,self.dim)[:,best_sample],dim1=0,dim2=1).transpose(0,1)

        return best_rep

    def choose_old_or_new(self, z_new, loss_new, z_old, loss_old):
        if (len(z_new.shape) == 2) and (len(z_old.shape) == 2):
            z_conc = torch.cat((z_new.unsqueeze(1), z_old.unsqueeze(1)), dim=1)
        else:
            raise ValueError(
                "Unexpected shape in input to function choose_old_or_new. Expected 2 dimensions for z_new and z_old, got "
                + str(len(z_new.shape))
                + " and "
                + str(len(z_old.shape))
            )

        len_loss_new = len(loss_new.shape)
        for l in range(3 - len_loss_new):
            loss_new = loss_new.unsqueeze(1)
        len_loss_old = len(loss_old.shape)
        for l in range(3 - len_loss_old):
            loss_old = loss_old.unsqueeze(1)
        losses = torch.cat((loss_new, loss_old), dim=1)

        best_sample = torch.argmin(losses, dim=1).squeeze(-1)
        # print(str(best_sample.sum().item())+' out of '+str(z_new.shape[0])+' samples were resampled.')

        best_rep = z_conc[range(z_conc.shape[0]), best_sample]

        return best_rep, round((best_sample.sum().item() / z_new.shape[0]) * 100, 2)

    def clustering(self, z):
        """compute the cluster assignment (as int) for each sample"""
        return torch.argmax(self.sample_probs(torch.tensor(z)), dim=-1).to(torch.int16)

    @classmethod
    def load(cls, save_dir="./"):
        # get saved hyper-parameters
        with open(save_dir + "dgd_hyperparameters.json", "r") as fp:
            param_dict = json.load(fp)

        gmm = cls(
            Nmix=param_dict["n_components"],
            dim=param_dict["latent"],
            type="diagonal",
            alpha=param_dict["dirichlet_a"],
            mean_init=(param_dict["mp_scale"], param_dict["hardness"]),
            sd_init=[param_dict["sd_mean"], param_dict["sd_sd"]],
        )

        device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
        gmm.load_state_dict(
            torch.load(save_dir + param_dict["name"] + "_gmm.pt", map_location=device)
        )
        return gmm

class GaussianMixtureSupervised(GaussianMixture):
    def __init__(
        self,
        Nclass,
        dim,
        Ncpc=1,
        type="diagonal",
        alpha=1,
        mean_init=(1.0, 1.0),
        sd_init=(1.0, 1.0),
    ):
        super(GaussianMixtureSupervised, self).__init__(
            Ncpc * Nclass,
            dim,
            type=type,
            alpha=alpha,
            mean_init=mean_init,
            sd_init=sd_init,
        )
        self.dim = dim

        self.Nclass = Nclass
        self.Ncpc = Ncpc

    def forward(self, x, label=None):
        if label is None:
            y = super().forward(x)
            return y

        if 999 in label:
            # first get normal loss
            idx_unsup = [i for i in range(len(label)) if label[i] == 999]
            y_unsup = super().forward(x[idx_unsup])
            # Otherwise use the component corresponding to the label
            idx_sup = [i for i in range(len(label)) if label[i] != 999]
            halfbeta = 0.5 * torch.exp(self.logbeta)
            # Pick only the Nclc components belonging class
            # y_sup = self.pi_term - (x.unsqueeze(-2).unsqueeze(-2) - self.mean.view(self.Nclass,self.Ncpc,-1)).square().mul(halfbeta.unsqueeze(-2))[label[idx_sup]].sum(-1).sum(-1) + self.betafactor*self.logbeta.view(self.Nclass,self.Ncpc,-1).sum(-1).sum(-1)
            y_sup = (
                self.pi_term
                - (
                    x.unsqueeze(-2).unsqueeze(-2)
                    - self.mean.view(self.Nclass, self.Ncpc, -1)
                )
                .square()
                .mul(halfbeta.unsqueeze(-2))
                .sum(-1)
                + (self.betafactor * self.logbeta.view(self.Nclass, self.Ncpc, -1)).sum(
                    -1
                )
            )
            y_sup += torch.log_softmax(self.weight.view(self.Nclass, self.Ncpc), dim=-1)
            y_sup = y_sup.sum(-1)
            y_sup = torch.abs(
                y_sup[(idx_sup, label[idx_sup])] * self.Nclass
            )  # this is replacement for logsumexp of supervised samples
            # put together y
            y = torch.empty((x.shape[0]), dtype=torch.float32).to(x.device)
            y[idx_unsup] = y_unsup
            y[idx_sup] = y_sup
        else:
            halfbeta = 0.5 * torch.exp(self.logbeta)
            # Pick only the Nclc components belonging class
            y = (
                self.pi_term
                - (
                    x.unsqueeze(-2).unsqueeze(-2)
                    - self.mean.view(self.Nclass, self.Ncpc, -1)
                )
                .square()
                .mul(halfbeta.unsqueeze(-2))
                .sum(-1)
                + (self.betafactor * self.logbeta.view(self.Nclass, self.Ncpc, -1)).sum(
                    -1
                )
            )
            y += torch.log_softmax(self.weight.view(self.Nclass, self.Ncpc), dim=-1)
            y = y.sum(-1)
            # y = torch.abs(y[(np.arange(y.shape[0]),label)] * self.Nclass) # this is replacement for logsumexp of supervised samples
            y = (
                y[(np.arange(y.shape[0]), label)] * self.Nclass
            )  # this is replacement for logsumexp of supervised samples

        y = y + super().prior()
        return y

    def log_prob(self, x, label=None):
        self.forward(x, label=label)

    def label_mixture_probs(self, label):
        return torch.softmax(self.weight[label], dim=-1)