"""Sagemaker InvokeEndpoint API."""
import io
import json
from abc import abstractmethod
from typing import Any, Dict, Generic, Iterator, List, Mapping, Optional, TypeVar, Union

from langchain_core.callbacks import CallbackManagerForLLMRun
from langchain_core.language_models.llms import LLM
from langchain_core.pydantic_v1 import Extra, root_validator

from langchain_community.llms.utils import enforce_stop_tokens

INPUT_TYPE = TypeVar("INPUT_TYPE", bound=Union[str, List[str]])
OUTPUT_TYPE = TypeVar("OUTPUT_TYPE", bound=Union[str, List[List[float]], Iterator])

class LineIterator:
    """
    A helper class for parsing the byte stream input.

    The output of the model will be in the following format:

    b'{"outputs": [" a"]}\n'
    b'{"outputs": [" challenging"]}\n'
    b'{"outputs": [" problem"]}\n'
    ...

    While usually each PayloadPart event from the event stream will
    contain a byte array with a full json, this is not guaranteed
    and some of the json objects may be split acrossPayloadPart events.

    For example:

    {'PayloadPart': {'Bytes': b'{"outputs": '}}
    {'PayloadPart': {'Bytes': b'[" problem"]}\n'}}

    This class accounts for this by concatenating bytes written via the 'write' function
    and then exposing a method which will return lines (ending with a '\n' character)
    within the buffer via the 'scan_lines' function.
    It maintains the position of the last read position to ensure
    that previous bytes are not exposed again.

    For more details see:
    https://aws.amazon.com/blogs/machine-learning/elevating-the-generative-ai-experience-introducing-streaming-support-in-amazon-sagemaker-hosting/
    """

    def __init__(self, stream: Any) -> None:
        self.byte_iterator = iter(stream)
        self.buffer = io.BytesIO()
        self.read_pos = 0

    def __iter__(self) -> "LineIterator":
        return self

    def __next__(self) -> Any:
        while True:
            self.buffer.seek(self.read_pos)
            line = self.buffer.readline()
            if line and line[-1] == ord("\n"):
                self.read_pos += len(line)
                return line[:-1]
            try:
                chunk = next(self.byte_iterator)
            except StopIteration:
                if self.read_pos < self.buffer.getbuffer().nbytes:
                    continue
                raise
            if "PayloadPart" not in chunk:
                # Unknown Event Type
                continue
            self.buffer.seek(0, io.SEEK_END)
            self.buffer.write(chunk["PayloadPart"]["Bytes"])

class ContentHandlerBase(Generic[INPUT_TYPE, OUTPUT_TYPE]):
    """A handler class to transform input from LLM to a
    format that SageMaker endpoint expects.

    Similarly, the class handles transforming output from the
    SageMaker endpoint to a format that LLM class expects.
    """

    """
    Example:
        .. code-block:: python

            class ContentHandler(ContentHandlerBase):
                content_type = "application/json"
                accepts = "application/json"

                def transform_input(self, prompt: str, model_kwargs: Dict) -> bytes:
                    input_str = json.dumps({prompt: prompt, **model_kwargs})
                    return input_str.encode('utf-8')

                def transform_output(self, output: bytes) -> str:
                    response_json = json.loads(output.read().decode("utf-8"))
                    return response_json[0]["generated_text"]
    """

    content_type: Optional[str] = "text/plain"
    """The MIME type of the input data passed to endpoint"""

    accepts: Optional[str] = "text/plain"
    """The MIME type of the response data returned from endpoint"""

    @abstractmethod
    def transform_input(self, prompt: INPUT_TYPE, model_kwargs: Dict) -> bytes:
        """Transforms the input to a format that model can accept
        as the request Body. Should return bytes or seekable file
        like object in the format specified in the content_type
        request header.
        """

    @abstractmethod
    def transform_output(self, output: bytes) -> OUTPUT_TYPE:
        """Transforms the output from the model to string that
        the LLM class expects.
        """

class LLMContentHandler(ContentHandlerBase[str, str]):
    """Content handler for LLM class."""

class SagemakerEndpoint(LLM):
    """Sagemaker Inference Endpoint models.

    To use, you must supply the endpoint name from your deployed
    Sagemaker model & the region where it is deployed.

    To authenticate, the AWS client uses the following methods to
    automatically load credentials:
    https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html

    If a specific credential profile should be used, you must pass
    the name of the profile from the ~/.aws/credentials file that is to be used.

    Make sure the credentials / roles used have the required policies to
    access the Sagemaker endpoint.
    See: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html
    """

    """
    Args:

        region_name: The aws region e.g., `us-west-2`.
            Fallsback to AWS_DEFAULT_REGION env variable
            or region specified in ~/.aws/config.

        credentials_profile_name: The name of the profile in the ~/.aws/credentials
            or ~/.aws/config files, which has either access keys or role information
            specified. If not specified, the default credential profile or, if on an
            EC2 instance, credentials from IMDS will be used.

        client: boto3 client for Sagemaker Endpoint

        content_handler: Implementation for model specific LLMContentHandler

    Example:
        .. code-block:: python

            from langchain_community.llms import SagemakerEndpoint
            endpoint_name = (
                "my-endpoint-name"
            )
            region_name = (
                "us-west-2"
            )
            credentials_profile_name = (
                "default"
            )
            se = SagemakerEndpoint(
                endpoint_name=endpoint_name,
                region_name=region_name,
                credentials_profile_name=credentials_profile_name
            )

        #Use with boto3 client
            client = boto3.client(
                        "sagemaker-runtime",
                        region_name=region_name
                    )

            se = SagemakerEndpoint(
                endpoint_name=endpoint_name,
                client=client
            )

    """
    client: Any = None
    """Boto3 client for sagemaker runtime"""

    endpoint_name: str = ""
    """The name of the endpoint from the deployed Sagemaker model.
    Must be unique within an AWS Region."""

    region_name: str = ""
    """The aws region where the Sagemaker model is deployed, eg. `us-west-2`."""

    credentials_profile_name: Optional[str] = None
    """The name of the profile in the ~/.aws/credentials or ~/.aws/config files, which
    has either access keys or role information specified.
    If not specified, the default credential profile or, if on an EC2 instance,
    credentials from IMDS will be used.
    See: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html
    """

    content_handler: LLMContentHandler
    """The content handler class that provides an input and
    output transform functions to handle formats between LLM
    and the endpoint.
    """

    streaming: bool = False
    """Whether to stream the results."""

    """
     Example:
        .. code-block:: python

        from langchain_community.llms.sagemaker_endpoint import LLMContentHandler

        class ContentHandler(LLMContentHandler):
                content_type = "application/json"
                accepts = "application/json"

                def transform_input(self, prompt: str, model_kwargs: Dict) -> bytes:
                    input_str = json.dumps({prompt: prompt, **model_kwargs})
                    return input_str.encode('utf-8')

                def transform_output(self, output: bytes) -> str:
                    response_json = json.loads(output.read().decode("utf-8"))
                    return response_json[0]["generated_text"]
    """

    model_kwargs: Optional[Dict] = None
    """Keyword arguments to pass to the model."""

    endpoint_kwargs: Optional[Dict] = None
    """Optional attributes passed to the invoke_endpoint
    function. See `boto3`_. docs for more info.
    .. _boto3: <https://boto3.amazonaws.com/v1/documentation/api/latest/index.html>
    """

    class Config:
        """Configuration for this pydantic object."""

        extra = Extra.forbid

    @root_validator()
    def validate_environment(cls, values: Dict) -> Dict:
        """Dont do anything if client provided externally"""
        if values.get("client") is not None:
            return values

        """Validate that AWS credentials to and python package exists in environment."""
        try:
            import boto3

            try:
                if values["credentials_profile_name"] is not None:
                    session = boto3.Session(
                        profile_name=values["credentials_profile_name"]
                    )
                else:
                    # use default credentials
                    session = boto3.Session()

                values["client"] = session.client(
                    "sagemaker-runtime", region_name=values["region_name"]
                )

            except Exception as e:
                raise ValueError(
                    "Could not load credentials to authenticate with AWS client. "
                    "Please check that credentials in the specified "
                    "profile name are valid."
                ) from e

        except ImportError:
            raise ImportError(
                "Could not import boto3 python package. "
                "Please install it with `pip install boto3`."
            )
        return values

    @property
    def _identifying_params(self) -> Mapping[str, Any]:
        """Get the identifying parameters."""
        _model_kwargs = self.model_kwargs or {}
        return {
            **{"endpoint_name": self.endpoint_name},
            **{"model_kwargs": _model_kwargs},
        }

    @property
    def _llm_type(self) -> str:
        """Return type of llm."""
        return "sagemaker_endpoint"

    def _call(
        self,
        prompt: str,
        stop: Optional[List[str]] = None,
        run_manager: Optional[CallbackManagerForLLMRun] = None,
        **kwargs: Any,
    ) -> str:
        """Call out to Sagemaker inference endpoint.

        Args:
            prompt: The prompt to pass into the model.
            stop: Optional list of stop words to use when generating.

        Returns:
            The string generated by the model.

        Example:
            .. code-block:: python

                response = se("Tell me a joke.")
        """
        _model_kwargs = self.model_kwargs or {}
        _model_kwargs = {**_model_kwargs, **kwargs}
        _endpoint_kwargs = self.endpoint_kwargs or {}

        body = self.content_handler.transform_input(prompt, _model_kwargs)
        content_type = self.content_handler.content_type
        accepts = self.content_handler.accepts

        if self.streaming and run_manager:
            try:
                resp = self.client.invoke_endpoint_with_response_stream(
                    EndpointName=self.endpoint_name,
                    Body=body,
                    ContentType=self.content_handler.content_type,
                    **_endpoint_kwargs,
                )
                iterator = LineIterator(resp["Body"])
                current_completion: str = ""
                for line in iterator:
                    resp = json.loads(line)
                    resp_output = resp.get("outputs")[0]
                    if stop is not None:
                        # Uses same approach as below
                        resp_output = enforce_stop_tokens(resp_output, stop)
                    current_completion += resp_output
                    run_manager.on_llm_new_token(resp_output)
                return current_completion
            except Exception as e:
                raise ValueError(f"Error raised by streaming inference endpoint: {e}")
        else:
            try:
                response = self.client.invoke_endpoint(
                    EndpointName=self.endpoint_name,
                    Body=body,
                    ContentType=content_type,
                    Accept=accepts,
                    **_endpoint_kwargs,
                )
            except Exception as e:
                raise ValueError(f"Error raised by inference endpoint: {e}")

            text = self.content_handler.transform_output(response["Body"])
            if stop is not None:
                # This is a bit hacky, but I can't figure out a better way to enforce
                # stop tokens when making calls to the sagemaker endpoint.
                text = enforce_stop_tokens(text, stop)

            return text


# Emote Trainer Wrapper / Mass Analyzer
# Command line interface for mass analysis for Emote, and to train Emote's classification system using TextBlob's API
# Note: Training features have not yet been implemented yet
# All that's really working is mass analyzing text files through the CLI

#!/usr/bin/python
# -*- coding: utf-8-*-
encoding = "utf-8"
import os
import sys
from emote import emote
import time
import gc
import re
import csv
import os
from nltk.tokenize import sent_tokenize

data = ""
trainingFile = ""
trainingData = []
testData = {}

openingCSV = False
openingText = False
openingPDF = False

csvOutputData = False

csvData = []
csvTextData = []
csvResults = []
csvFile = {}

massResults = []
sentences = []

def startInterface():
    global openingCSV
    global openingText
    global openingPDF
    print("\n\tNow starting Emote Mass Analyzer..")
    option = input("\n\tTo analyze a file with Emote, enter in the type name ('PDF', 'Text', or 'CSV'), or enter 'Train' or 'Test': ")
    option = option.lower()
    if option == 'pdf':
        # print("PDF file input.")
        openingPDF = True
        openPDF(path, data)
    elif option == 'text':
        # print("Text file input.")
        openingText = True
        openFile(path, data)
    elif option == 'csv':
        # print("CSV file input.")
        openingCSV = True
        parseCSV(path, csvData, csvTextData)
    elif option == 'train':
        addToDatabase(trainingFile, trainingData)
    elif option == 'test':
        testEmote(testData)
    else:
        print("\n\tBad command entered. Please try again.")
        startInterface()

def openFile(path, data):
    global csvOutputData
    path = input("\n\tEnter the name of the text and extension of the text, CSV, or PDF file (has to be in directory 'texts') to be mass analyzed in Emote: ")
    try:
        p = os.getcwd()
        p = os.path.join(p, 'texts', path)
        print(p)
        file = open(p, 'r')
        data = file.read()
        text = data
        split_into_sentences(text)
        return data
    except IOError as err:
        print("Error opening path to file.")
        # self.openFile(path, data)
            # print("\n\tI/O error({0}): {1}".format(errno, strerror))
    option = input("\n\tOutput classification results to CSV file? (Yes / No)")
    option = option.lower()
    if option == 'yes':
        csvOutputData = True
    elif option == 'no':
        csvOutputData = False
    else:
        ("Commad not understood!")
        startInterface()
    return

def parseText(path):
    csvData = []
    csvTextData = []
    file = open(path, 'r')
    csv_file = csv.reader(file, delimiter = ",")
    for row in csv_file:
        csvData.append(row[0])
        csvTextData.append(row[1])
    file.close()
    analyzeCSV(csvData, csvTextData, massResults, csvFile)
    print("\n\t", csvData)
    print("\n\t", csvTextData)
    return csvData, csvTextData

def analyzeText(csvData, csvTextData, csvFile):
    print("\n\t",csvTextData)
    print("\n\t", csvData)
    global massResults
    massResults = []
    csvResults = {}
    csvFile = {}
    for i in range(len(csvTextData)):
        emote.getInput(csvTextData[i])
        # print(emote.normalizedProbValues)
        massResults.append(emote.normalizedProbValues)
    csvFile = open('static/results.csv', 'w', newline='')
    for i in range(len(massResults)):
        # with open('static/results.csv', 'w', newline='') as csvFile:
        csvIndRowList = []
        csvResults = csv.writer(csvFile, delimiter = ',')
        csvIndRowList.append(csvData[i])
        csvIndRowList.append(csvTextData[i])
        csvIndRowList.append(massResults[i][0])
        csvIndRowList.append(massResults[i][1])
        csvIndRowList.append(massResults[i][2])
        csvIndRowList.append(massResults[i][3])
        csvIndRowList.append(massResults[i][4])
        csvIndRowList.append(massResults[i][5])
        print("\n\tROW LIST", csvIndRowList)
        csvResults.writerow(csvIndRowList)
    csvFile.close()
    return csvResults, csvFile

def openPDF(path, data):
    return

# def openCSV(path, data):
#     path = input("\n\tEnter the name of the text and extension of the text, CSV, or PDF file (has to be in same directory) to be mass analyzed in Emote: ")
#     try:
#         with open(path) as csvfile:
#             reader = csv.reader(csvfile, dialect='excel', quoting=csv.QUOTE_NONNUMERIC)
#             datalist = []
#             datalist = list(reader)
#             return datalist
#     except IOError as err:
#         print("Error opening path to file.")
#     startInterface()
#     return

def split_into_sentences(text):
    print("CLASSIFYING MULTIPLE SENTENCES")
    global sentences
    sentences = []
    # Code below splits sentences without NLTK Tokenizer
    # START
    # caps = "([A-Z])"
    # prefixes = "(Mr|St|Mrs|Ms|Dr)[.]"
    # suffixes = "(Inc|Ltd|Jr|Sr|Co)"
    # starters = "(Mr|Mrs|Ms|Dr|He\s|She\s|It\s|They\s|Their\s|Our\s|We\s|But\s|However\s|That\s|This\s|Wherever)"
    # acronyms = "([A-Z][.][A-Z][.](?:[A-Z][.])?)"
    # websites = "[.](com|net|org|io|gov)"
    # digits = "([0-9])"
    # print("\n\tTaking input file, converting to text, and splitting it up into sentences..")
    # text = " " + text + "  "
    # text = text.replace("\n"," ")
    # text = re.sub(prefixes,"\\1<prd>",text)
    # text = re.sub(websites,"<prd>\\1",text)
    # if "Ph.D" in text: text = text.replace("Ph.D.","Ph<prd>D<prd>")
    # text = re.sub("\s" + caps + "[.] "," \\1<prd> ",text)
    # text = re.sub(acronyms+" "+starters,"\\1<stop> \\2",text)
    # text = re.sub(caps + "[.]" + caps + "[.]" + caps + "[.]","\\1<prd>\\2<prd>\\3<prd>",text)
    # text = re.sub(caps + "[.]" + caps + "[.]","\\1<prd>\\2<prd>",text)
    # text = re.sub(" "+suffixes+"[.] "+starters," \\1<stop> \\2",text)
    # text = re.sub(" "+suffixes+"[.]"," \\1<prd>",text)
    # text = re.sub(" " + caps + "[.]"," \\1<prd>",text)
    # text = re.sub(digits + "[.]" + digits,"\\1<prd>\\2",text)
    # if '"' in text: text = text.replace('."','".')
    # if "\"" in text: text = text.replace(".\"","\".")
    # if "!" in text: text = text.replace("!\"","\"!")
    # if "?" in text: text = text.replace("?\"","\"?")
    # text = text.replace(".",".<stop>")
    # text = text.replace("?","?<stop>")
    # text = text.replace("!","!<stop>")
    # text = text.replace("<prd>",".")
    # sentences = text.split("<stop>")
    # sentences = sentences[:-1]
    # sentences = [s.strip() for s in sentences]
    # END
    sentences = sent_tokenize(text)
    print("\n\tSENTENCES", sentences)
    sendToEmote()
    # return sentences

def sendToEmote():
    # pickledData = pickle.load(open("base_corpus.pickle", "wb"))
    # print(emote.objectToPickle)
    # print(sentences)
    global sentences
    global massResults
    massResults = []
    print("""\n\n\tEach sentence found in the text will now be output with the strongest classification associated with it on screen.""")
    print("""\n\tEmote will classify: """ + str(len(sentences)) + " detected sentences.")
    countSentences = int(len(sentences))
    print("COUNT: ", countSentences)
    # sentences = []
    # for num, sent in enumerate(sentences):
    for m in sentences:
        print("\n\t", m)
        # print("\n\tMESSAGE, message")
        # gc.disable()
        # print("\n\tI", i)
        emote.getInput(m)
        # print("\n")
        # print("\n\tH1", message)
        # print("\n\tH2", emote.normalizedProbValues)
        # print("\n"+emote.pre_result)
        # gc.enable()
        # return emote.normalizedProbVals
        massResults.append(emote.normalizedProbValues)
    # massResult.append(emote.result)
    print("\n\tMASS:" , massResults)
    # returnAsCSV(massresults)
    # timeTotal = time.time() - timeToClassify
    # m, s = divmod(s,  60)
    # timeTotal = m + " :" + s + " "
    # print("""\n\n\n\tEmote took """ + str(timeTotal) + " time to classify the text of " + sentences.length + " detected sentences.")
    # outputOption(massResults)
    # return massResults

# Code below is not functional
def outputOption(massResults):
    option = input("\n\tOutput results into data for 'training' or 'spreadsheet' (enter one): ")
    option = option.lower()
    if option == 'training':
        print("\n\tOutputting data into traininable format.")
        outputTraining(massResults)
    elif option == 'spreadsheet':
        print("\n\tOutputting data into CSV with full results.")
        outputSpreadsheet(massResults)
    else:
        print("\n\tCommand not understood!")
        outputOption(massResults)

def outputTraining(massResults):
    startInterfaCe()

def outputSpreadsheet(massResults):
    startInterfaCe()

# Code below is not functional
def addToDatabase(trainingFile, trainingData):

    # USING SHELF
    try:
        pickledData = shelve.open('base_corpus.db', writeback = True)
        train = pickledData["base"]
        # train = pickle.load(open("base_corpus.pickle", "rb" ) )
        # cl = NaiveBayesClassifier(train)
        print("\n\tLoaded pickled default database corpus.")
        # pickledData.close()
    except IOError as err:
        # print("\n\tI/O error({0}): {1}".format(errno, strerror))
        print("\n\tError training pickle file.. system will exit. Go into the directory, delete the corrupt pickle file, and retry this script to train a new copy.")
        # sys.exit()
    trainingFile = raw_input("\n\tEnter the directory / name of the text file to train (with extension): ")
    with open(trainingFile, "rb") as fp:
        for i in fp.readlines():
            # tmp = i.decode('string_escape')
            # tmp = i.decode('utf-8').strip()
            tmp = i.strip()
            # tmp = i.replace('\r', ' ').replace('\n', '')
            # tmp = i.replace('\\', ' ').replace('\'', '')
            # tmp = i.replace('\\', ' ').replace('\"', '')
            # i = i.strip()
            tmp = tmp.split(",")
            try:
                trainingData.append((str(tmp[0]), str(tmp[1])))
            except:
                pass
    for data in trainingData:
        try:
            pickledData["base"].append(data)
        except:
            pass
    pickledData.sync()
    pickledData.close()
    print("\n\tTraining data added to the default database corpus.")
    startInterface()

# Code below is not functional
def testEmote(testData):
    testFileLoc = input("Enter the file name of the text you would like to test against Emote for accuracy (Must be in the same directory and labelled as .txt):")
    try:
        print(str(testFileLoc))
    except:
        print("Did not find the text file.")
        startInterface()
    # for line in open (str(testFileLoc)):
        # print(str(testFileLoc))
        # testDataTemp = line.split()
        # testDataTemp = str(testDataTemp)
        # print(testDataTemp)
        # testData.append(testDataTemp)
        # print(testData)
    # print(testData)
    with open(str(testFileLoc)) as testData:
        print(testData)
        emote.testAccuracy(testData)
    print("\n\n\t\tTesting done.")
    startInterfaCe()

        # print("\n\tNo test data file found.")
        # startInterface()

if __name__ == '__main__':
    path = ""
    data = ""
    trainingFile = ""
    trainingData = []
    csvData = []
    csvTextData = []
    csvResults = []
    csvIndRowList = []
    testData = {}
    csvFile = {}
    massResults = []
    sentences = []
    startInterface()
else:
    path = ""
    data = ""
    trainingFile = ""
    trainingData = []
    csvData = []
    csvTextData = []
    csvResults = []
    csvIndRowList = []
    testData = {}
    csvFile = {}
    massResults = []
    sentences = []


import pytest
from Pages.findPage import findPage
from Utilities.readProperties import ReadConfig
from Utilities.customLogger import LogGen
from Utilities import Xutils
import time

class Test_002_DDT_find():
    baseURL = ReadConfig.getApplicationURL()
    path = "C:\\Users\\lijin\\PycharmProjects\\Redfin\\TestData\\Redfindata.xlsx"
    #logger = LogGen.loggen()  # Logger
    #integer="25"
    #integernew="3"

    def test_find_ddt(self,setup):
        self.driver = setup
        self.driver.get(self.baseURL)
        self.driver.maximize_window()
        self.fp = findPage(self.driver)

        self.rows = Xutils.getRowCount(self.path,'Sheet1')
        print('Number of rows...',self.rows)

        for r in range(2,self.rows+1):
            self.City = Xutils.readData(self.path,'Sheet1',r,1)
            self.integer=Xutils.readData(self.path,'Sheet1',r,2)
            self.integernew = Xutils.readData(self.path, 'Sheet1', r, 3)
            self.fp.clickPlace(self.City)
            time.sleep(2)
            self.fp.clickPopup()
            time.sleep(2)
            #act_title=self.driver.title
            #exp_title="Sunnyvale Homes for Sale: Sunnyvale, CA Real Estate | Redfin"
            self.fp.clickPrice()
            self.fp.clickMinPrice(self.integer)
            self.driver.execute_script("document.getElementsByClassName('option')[" + self.integer + "].click();")
            time.sleep(2)
            self.fp.clickMaxPrice(self.integernew)
            self.driver.execute_script("document.getElementsByClassName('option')[" + self.integernew + "].click();")
            time.sleep(2)
            self.fp.clickDone()
            self.fp.clickTotal()
            self.fp.clickCity()


import pandas as pd
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from keras.models import Sequential
from keras.layers import Layer, Dropout, Input, Dense
from sklearn.metrics import accuracy_score, confusion_matrix, ConfusionMatrixDisplay

url = 'C:/Users/johnn/OneDrive/Documentos/Deep Learning/Deep Learning com Python de A a Z - O Curso Completo/base_dados/wdbc.data'
cancer = datasets.load_breast_cancer()
dados = pd.read_csv(url, header=None)

entradas = dados.iloc[:,2:]
entradas.columns = cancer.feature_names
saidas = dados.iloc[:,1]

X = dados.iloc[:,2:].values
y = dados.iloc[:,1].replace('M', 1).replace('B', 0).values

# Divisão da base de dados em treino e teste
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=0)

# Rede Neural
classificador = Sequential()
classificador.add(Input(shape=30, name='Camada_entrada'))
classificador.add(Dense(units=16, activation='relu', kernel_initializer='uniform', name='Camada_oculta0'))
classificador.add(Dropout(rate=0.2, name='Camada_dropout0'))
classificador.add(Dense(units=1, activation='sigmoid', name='Camada_saida'))

classificador.compile(optimizer='adam', loss='binary_crossentropy', metrics=['binary_accuracy'])

classificador.fit(X_train, y_train, batch_size=10, epochs=100)
previsoes = classificador.predict(X_test) > 0.7
previsoes = previsoes.astype(int)

# Métricas de avaliação
accuracia1 = classificador.evaluate(X_test, y_test)
accuracia2 = accuracy_score(y_test, previsoes)

grafico = ConfusionMatrixDisplay(confusion_matrix(y_test, previsoes))
grafico.plot()


import os
import argparse
from PIL import Image
from tqdm import tqdm

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import Dataset
from torchvision.models import inception_v3
from torchvision import transforms
from torch.utils.data import DataLoader

class ImageDataset(Dataset):
    def __init__(self, directory, transform=None):
        self.directory = directory
        self.image_paths = sorted(os.listdir(directory))
        self.transform = transform

    def __len__(self):
        return len(self.image_paths)

    def __getitem__(self, index):
        image_path = os.path.join(self.directory, self.image_paths[index])
        image = Image.open(image_path).convert("RGB")

        if self.transform is not None:
            image = self.transform(image)

        return image

# Inception Scoreの計算
def compute_inception_score(generated_loader, inception_model, device):
    scores = []
    for batch in tqdm(generated_loader):
        batch = batch.to(device)
        batch = preprocess(batch)
        with torch.no_grad():
            # Inception Scoreの計算
            logits = inception_model(batch)
            probabilities = F.softmax(logits, dim=1)
            kl_divergence = torch.mean(
                torch.sum(
                    probabilities
                    * (
                        torch.log(probabilities)
                        - torch.log(torch.mean(probabilities, dim=0, keepdim=True))
                    ),
                    dim=1,
                )
            )
            score = torch.exp(kl_divergence)
            scores.append(score)

    scores = torch.stack(scores, dim=0)
    return scores.mean(), scores.std()

if __name__ == "__main__":
    parser = argparse.ArgumentParser()

    parser.add_argument(
        "--img_dir", type=str, required=True, help="img directory for evaluation"
    )
    args = parser.parse_args()

    # 生成された画像の確率分布を評価するためのデータセット
    # img_dir = "results/trans/trans64_dir_404to817_t500_run0"
    img_dir = args.img_dir
    generated_dataset = ImageDataset(directory=img_dir, transform=transforms.ToTensor())

    # Inceptionモデルの読み込みと前処理
    inception_model = inception_v3(pretrained=True, transform_input=False)
    inception_model.eval()
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    inception_model.to(device)

    # データローダーの設定
    batch_size = 64  # 適宜調整してください
    num_workers = 1  # 適宜調整してください
    generated_loader = DataLoader(
        generated_dataset, batch_size=batch_size, shuffle=False, num_workers=num_workers
    )

    # 画像の前処理
    preprocess = transforms.Compose(
        [
            transforms.Resize(299),
            # transforms.ToTensor(),
        ]
    )

    # Inception Scoreの計算結果の取得
    inception_score, inception_score_std = compute_inception_score(
        generated_loader, inception_model, device
    )
    print(
        "Inception Score: {:.2f} +/- {:.2f}".format(
            inception_score, inception_score_std
        )
    )


"""
The web application which will interact with users and control the underlying hardware
# https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d
"""
import datetime

from flask import Flask, render_template

from relay import Relay
from tempsensor import TemperatureSensor

flaskApp = Flask("JitterServer")

class JitterServer:
    _indexHtmlPath = "index.html"
    def __init__(self,
                heaterSensor: TemperatureSensor,
                heaterRelay: Relay,
                pump1Relay: Relay,
                pump2Relay: Relay):
        self._heaterSensor = heaterSensor
        self._heaterRelay = heaterRelay
        self._pump1Relay = pump1Relay
        self._pump2Relay = pump2Relay

    def index(self):
        now = datetime.datetime.now()
        timeString = now.strftime("%Y-%m-%d %H:%M:%S")
        templateData = {
                "title": "Jitter Server",
                "time": timeString,
                "isPump1On": self._pump1Relay.isRunning(),
        }
        return render_template(self._indexHtmlPath, **templateData)

class GlobalContainer:
    jitterServer = None

@flaskApp.route("/")
def index():
    return GlobalContainer.jitterServer.index()

@flaskApp.route("/pump1/startcycle", methods=["GET", "POST"])
def pump1StartCycle():
    didStart = GlobalContainer.jitterServer._pump1Relay.startCycle()
    return index()

@flaskApp.route("/pump1/killcycle", methods=["GET", "POST"])
def pump1KillCycle():
    didKill = GlobalContainer.jitterServer._pump1Relay.killCycle()
    return index()

def runJitterServer(heaterSensor, heaterRelay, pump1Relay, pump2Relay,
        port, shouldDebug):
    GlobalContainer.jitterServer = JitterServer(heaterSensor, heaterRelay,
            pump1Relay, pump2Relay)
    localhost = "0.0.0.0"
    flaskApp.run(debug=shouldDebug, port=port, host=localhost)


import msvcrt
from turtle import *

shape('turtle');
speed(0);
color('red');
def cuad():
	for i in range(4):
		forward(100);
		right(90);

def square():
	for i in range(60):

		right(5);

		cuad();

square();

msvcrt.getch();


from typing import List, Optional

from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session

from app.api.depends import get_db
from app.schemas.appointments import Appointments, AppointmentsCreate, AppointmentsUpdate, AppointmentsRequest
from app.service import appointments_service, medcard_service

router = APIRouter()

@router.get("/", response_model=List[Appointments])
def get_all_appointments(db: Session = Depends(get_db)):
    appointments = appointments_service.get_all_appointments(db=db)
    return appointments

@router.get("/{appointment_id}", response_model=Optional[Appointments])
def get_appointment_by_id(appointment_id: int, db: Session = Depends(get_db)):
    appointmetns = appointments_service.get_appointment_by_id(db=db, appointment_id=appointment_id)
    return appointmetns

@router.post("/", response_model=Appointments)
def create_appointment(appointment_request: AppointmentsRequest, db: Session = Depends(get_db)):
    medcard = medcard_service.get_medcard_by_passport_number(db=db, passportNumber=appointment_request.passportNumber)
    appointment_create = AppointmentsCreate(
        medcard_id=medcard.id,
        user_id=appointment_request.user_id,
        date=appointment_request.date,
        time=appointment_request.time,
        email=appointment_request.email
    )
    appointment = appointments_service.create_appointment(db=db, appointment_create=appointment_create)
    return appointment

@router.delete("/{appointment_id}", response_model=Appointments)
def delete_appointment(appointment_id: int, db: Session = Depends(get_db)):
    appointment = appointments_service.delete_appointment(db=db, appointment_id=appointment_id)
    return appointment


from __future__ import annotations

from logging import getLogger
from typing import Any, Dict, List, Mapping, Optional, Sequence, Set, Union

from buildarr.config import RemoteMapEntry
from buildarr.types import NonEmptyStr
from pydantic import Field, validator
from typing_extensions import Annotated, Self

from ...api import api_delete, api_get, api_post, api_put
from ...secrets import SonarrSecrets
from ..types import SonarrConfigBase

logger = getLogger(__name__)

class QualityGroup(SonarrConfigBase):
    """
    Quality group.

    Allows groups of quality definitions to be given the same prorioty in qualtity profiles.
    """

    name: NonEmptyStr
    members: Set[NonEmptyStr] = Field(..., min_items=1)

    def encode(self, group_id: int, quality_definitions: Mapping[str, Any]) -> Dict[str, Any]:
        return {
            "id": group_id,
            "name": self.name,
            "allowed": True,
            "items": [
                _encode_quality_str(quality_definitions, member, True) for member in self.members
            ],
        }

class QualityProfile(SonarrConfigBase):
    """
    The main things to consider when creating a quality profile are
    what quality settings to enable, and how to prioritise each.

    ```yaml
    ...
      quality_profiles:
        SDTV:
          upgrades_allowed: true
          upgrade_until: "Bluray-1080p"
          qualities:
          - "Bluray-480p"
          - "DVD"
          - name: "WEB 480p"
            members:
              - "WEBDL-480p"
              - "WEBRip-480p"
          - "SDTV"
    ```

    In Buildarr, the quality listed first (at the top) is given the highest priority, with
    subsequent qualities given lower priority. Qualities not explicitly defined are
    disabled (not downloaded).

    Sonarr supports grouping multiple qualities together to give them the same priority.
    In Buildarr, these are expressed by giving a `name` to the group, and listing the qualities
    under the `members` attribute.

    For more insight into reasonable values for quality profiles,
    refer to these guides from [WikiArr](https://wiki.servarr.com/sonarr/settings#quality-profiles)
    and TRaSH-Guides ([WEB-DL](https://trash-guides.info/Sonarr/Sonarr-Release-Profile-RegEx/),
    [anime](https://trash-guides.info/Sonarr/Sonarr-Release-Profile-RegEx-Anime/)).
    """

    upgrades_allowed: bool = False
    """
    Enable automatic upgrading if a higher quality version of the media file becomes available.

    If disabled, media files will not be upgraded after they have been downloaded.
    """

    qualities: Annotated[List[Union[NonEmptyStr, QualityGroup]], Field(min_items=1)]
    """
    The qualities to enable downloading episodes for. The order determines the priority
    (highest priority first, lowest priority last).

    Individual qualities can be specified using the name (e.g. `Bluray-480p`).

    Qualities can also be grouped together in a structure to give them the same
    priority level. A new version of the episode will not be downloaded if it is
    at least one of the qualities listed in the group, until a higher quality
    version is found.

    ```yaml
    ...
      qualities:
        - name: "WEB 480p"
          members:
            - "WEBDL-480p"
            - "WEBRip-480p"
    ```

    At least one quality must be specified.
    """

    upgrade_until: Optional[NonEmptyStr] = None
    """
    The maximum quality level to upgrade an episode to.
    For a quality group, specify the group name.

    Once this quality is reached Sonarr will no longer download episodes.

    This attribute is required if `upgrades_allowed` is set to `True`.
    """

    @validator("qualities")
    def validate_qualities(
        cls,
        value: List[Union[str, QualityGroup]],
    ) -> List[Union[str, QualityGroup]]:
        quality_name_map: Dict[str, Union[str, QualityGroup]] = {}
        for quality in value:
            for name in quality.members if isinstance(quality, QualityGroup) else [quality]:
                if name in quality_name_map:
                    error_message = f"duplicate entries of quality value '{name}' exist ("
                    other = quality_name_map[name]
                    if isinstance(quality, str) and isinstance(quality, str):
                        error_message += "both are non-grouped quality values"
                    else:
                        error_message += (
                            f"one as part of quality group '{quality.name}', "
                            if isinstance(quality, QualityGroup)
                            else "one as a non-grouped quality value, "
                        )
                        error_message += (
                            f"another as part of quality group '{other.name}'"
                            if isinstance(other, QualityGroup)
                            else "another as a non-grouped quality value"
                        )
                    error_message += ")"
                    raise ValueError(error_message)
                quality_name_map[name] = quality
        return value

    @validator("upgrade_until")
    def validate_upgrade_until(
        cls,
        value: Optional[str],
        values: Dict[str, Any],
    ) -> Optional[str]:
        try:
            upgrades_allowed: bool = values["upgrades_allowed"]
            qualities: Sequence[Union[str, QualityGroup]] = values["qualities"]
        except KeyError:
            return value
        # If `upgrades_allowed` is `False`, set `upgrade_until` to `None`
        # to make sure Buildarr ignores whatever it is currently set to
        # on the remote instance.
        if not upgrades_allowed:
            return None
        # Subsequent checks now assume that `upgrades_allowed` is `True`,
        # this parameter is required and defined to a valid value.
        if not value:
            raise ValueError("required if 'upgrades_allowed' is True")
        for quality in qualities:
            quality_name = quality.name if isinstance(quality, QualityGroup) else quality
            if value == quality_name:
                break
        else:
            raise ValueError("must be set to a value enabled in 'qualities'")
        return value

    @classmethod
    def _get_remote_map(
        cls,
        quality_definitions: Mapping[str, Mapping[str, Any]] = {},
        group_ids: Mapping[str, int] = {},
    ) -> List[RemoteMapEntry]:
        return [
            ("upgrades_allowed", "upgradeAllowed", {}),
            (
                "upgrade_until",
                "cutoff",
                {
                    "root_decoder": lambda vs: cls._upgrade_until_decoder(
                        items=vs["items"],
                        cutoff=vs["cutoff"],
                    ),
                    "root_encoder": lambda vs: cls._upgrade_until_encoder(
                        quality_definitions=quality_definitions,
                        group_ids=group_ids,
                        qualities=vs.qualities,
                        upgrade_until=vs.upgrade_until,
                    ),
                },
            ),
            (
                "qualities",
                "items",
                {
                    "decoder": lambda v: _decode_qualities(v),
                    "encoder": lambda v: _encode_qualities(quality_definitions, group_ids, v),
                },
            ),
        ]

    @classmethod
    def _upgrade_until_decoder(
        cls,
        items: Sequence[Mapping[str, Any]],
        cutoff: int,
    ) -> str:
        for quality_item in items:
            quality: Mapping[str, Any] = (
                quality_item  # Quality group
                if "id" in quality_item
                else quality_item["quality"]  # Quality definition (singular)
            )
            if quality["id"] == cutoff:
                return quality["name"]
        raise RuntimeError(
            "Inconsistent Sonarr instance state: "
            f"'cutoff' quality ID {cutoff} not found in 'items': {items}",
        )

    @classmethod
    def _upgrade_until_encoder(
        cls,
        quality_definitions: Mapping[str, Mapping[str, Any]],
        group_ids: Mapping[str, int],
        qualities: Sequence[Union[str, QualityGroup]],
        upgrade_until: Optional[str],
    ) -> int:
        if not upgrade_until:
            quality = qualities[0]
            return (
                group_ids[quality.name]
                if isinstance(quality, QualityGroup)
                else quality_definitions[quality]["id"]
            )
        return (
            group_ids[upgrade_until]
            if upgrade_until in group_ids
            else quality_definitions[upgrade_until]["id"]
        )

    @classmethod
    def _from_remote(cls, remote_attrs: Mapping[str, Any]) -> Self:
        return cls(**cls.get_local_attrs(cls._get_remote_map(), remote_attrs))

    def _create_remote(
        self,
        tree: str,
        secrets: SonarrSecrets,
        profile_name: str,
        quality_definitions: Mapping[str, Mapping[str, Any]],
    ) -> None:
        group_ids: Dict[str, int] = {
            quality_group.name: (1000 + i)
            for i, quality_group in enumerate(
                [q for q in self.qualities if isinstance(q, QualityGroup)],
                1,
            )
        }
        api_post(
            secrets,
            "/api/v3/qualityprofile",
            {
                "name": profile_name,
                **self.get_create_remote_attrs(
                    tree,
                    self._get_remote_map(quality_definitions, group_ids),
                ),
            },
        )

    def _update_remote(
        self,
        tree: str,
        secrets: SonarrSecrets,
        remote: Self,
        profile_id: int,
        profile_name: str,
        quality_definitions: Mapping[str, Mapping[str, Any]],
    ) -> bool:
        group_ids: Dict[str, int] = {
            quality_group.name: (1000 + i)
            for i, quality_group in enumerate(
                [q for q in self.qualities if isinstance(q, QualityGroup)],
                1,
            )
        }
        changed, remote_attrs = self.get_update_remote_attrs(
            tree,
            remote,
            self._get_remote_map(quality_definitions, group_ids),
            check_unmanaged=True,
            set_unchanged=True,
        )
        if changed:
            api_put(
                secrets,
                f"/api/v3/qualityprofile/{profile_id}",
                {"id": profile_id, "name": profile_name, **remote_attrs},
            )
            return True
        return False

    def _delete_remote(self, secrets: SonarrSecrets, profile_id: int) -> None:
        api_delete(secrets, f"/api/v3/qualityprofile/{profile_id}")

class SonarrQualityProfilesSettingsConfig(SonarrConfigBase):
    """
    Configuration parameters for controlling how Buildarr handles quality profiles.
    """

    delete_unmanaged: bool = False
    """
    Automatically delete quality profiles not defined in Buildarr.

    Out of the box Sonarr provides some pre-defined quality profiles.
    Take care when enabling this option, as those will also be deleted.
    """

    definitions: Dict[str, QualityProfile] = {}
    """
    Define quality profiles to configure on Sonarr here.

    If there are no quality profiles defined and `delete_unmanaged` is `False`,
    Buildarr will not modify existing quality profiles, but if `delete_unmanaged` is `True`,
    **Buildarr will delete all existing profiles. Be careful when using `delete_unmanaged`.**
    """

    @classmethod
    def from_remote(cls, secrets: SonarrSecrets) -> Self:
        return cls(
            definitions={
                profile["name"]: QualityProfile._from_remote(profile)
                for profile in api_get(secrets, "/api/v3/qualityprofile")
            },
        )

    def update_remote(
        self,
        tree: str,
        secrets: SonarrSecrets,
        remote: Self,
        check_unmanaged: bool = False,
    ) -> bool:
        changed = False
        profile_ids: Dict[str, int] = {
            profile_json["name"]: profile_json["id"]
            for profile_json in api_get(secrets, "/api/v3/qualityprofile")
        }
        quality_definitions: Dict[str, Dict[str, Any]] = {
            quality_json["title"]: quality_json["quality"]
            for quality_json in sorted(
                api_get(secrets, "/api/v3/qualitydefinition"),
                key=lambda q: q["weight"],
                reverse=True,
            )
        }
        for profile_name, profile in self.definitions.items():
            profile_tree = f"{tree}.definitions[{profile_name!r}]"
            if profile_name not in remote.definitions:
                profile._create_remote(
                    tree=profile_tree,
                    secrets=secrets,
                    profile_name=profile_name,
                    quality_definitions=quality_definitions,
                )
                changed = True
            elif profile._update_remote(
                tree=profile_tree,
                secrets=secrets,
                remote=remote.definitions[profile_name],
                profile_id=profile_ids[profile_name],
                profile_name=profile_name,
                quality_definitions=quality_definitions,
            ):
                changed = True
        return changed

    def delete_remote(self, tree: str, secrets: SonarrSecrets, remote: Self) -> bool:
        changed = False
        profile_ids: Dict[str, int] = {
            profile_json["name"]: profile_json["id"]
            for profile_json in api_get(secrets, "/api/v3/qualityprofile")
        }
        for profile_name, profile in remote.definitions.items():
            if profile_name not in self.definitions:
                profile_tree = f"{tree}.definitions[{profile_name!r}]"
                if self.delete_unmanaged:
                    logger.info("%s: (...) -> (deleted)", profile_tree)
                    profile._delete_remote(
                        secrets=secrets,
                        profile_id=profile_ids[profile_name],
                    )
                    changed = True
                else:
                    logger.debug("%s: (...) (unmanaged)", profile_tree)
        return changed

def _decode_qualities(value: Sequence[Mapping[str, Any]]) -> List[Union[str, QualityGroup]]:
    return [
        (
            QualityGroup(
                name=quality["name"],
                members=[member["quality"]["name"] for member in quality["items"]],
            )
            if quality["items"]
            else quality["quality"]["name"]
        )
        for quality in reversed(value)
        if quality["allowed"]
    ]

def _encode_qualities(
    quality_definitions: Mapping[str, Mapping[str, Any]],
    group_ids: Mapping[str, int],
    qualities: List[Union[str, QualityGroup]],
) -> List[Dict[str, Any]]:
    qualities_json: List[Dict[str, Any]] = []
    enabled_qualities: Set[str] = set()

    for quality in qualities:
        if isinstance(quality, QualityGroup):
            qualities_json.append(quality.encode(group_ids[quality.name], quality_definitions))
            for member in quality.members:
                enabled_qualities.add(member)
        else:
            qualities_json.append(_encode_quality_str(quality_definitions, quality, True))
            enabled_qualities.add(quality)

    for quality_name in quality_definitions.keys():
        if quality_name not in enabled_qualities:
            qualities_json.append(_encode_quality_str(quality_definitions, quality_name, False))

    return list(reversed(qualities_json))

def _encode_quality_str(
    quality_definitions: Mapping[str, Mapping[str, Any]],
    quality_name: str,
    allowed: bool,
) -> Dict[str, Any]:
    return {"quality": quality_definitions[quality_name], "items": [], "allowed": allowed}


from django.shortcuts import render

# Create your views here.
from re import I
from django.shortcuts import render

# Create your views here.
import json
from os import stat
from urllib import response
from django.shortcuts import render

import facilities

# Create your views here.
from .serializers import *
from rest_framework.permissions import IsAuthenticated

from authen.models import User
from .models import *
from .serializers import *
from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.shortcuts import get_object_or_404
from facilities.models import Facility

class CountryView(APIView):
    permission_classes = (IsAuthenticated,)

    def post(self, request):
        query_set=CountryConfig.objects.all()
        print(len(query_set))
        if(len(query_set)>0):
            return Response("Country exist",status=status.HTTP_400_BAD_REQUEST)
        else:
            serializer =   countrySerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def get(self, request):
        country = CountryConfig.objects.all()
        serializer =  countrySerializer(country, many=True)
        return Response(serializer.data)

    def put(self, request, ):
        id=request.data["id"]
        country = get_object_or_404(CountryConfig, id=id)
        serializer =  countrySerializer(country, data=request.data)
        if serializer.is_valid():
            serializer.save()
            code=serializer.data["codecountry"]
            fac=Facility.objects.filter(id=1)[0]
            fac.code=code+"0100001"
            fac.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, *args, **kwargs):
        id=request.data["id"]
        country = get_object_or_404(CountryConfig, id=id)
        country.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
class LevelView(APIView):
    permission_classes = (IsAuthenticated,)

    def post(self, request):
        level=0
        country=CountryConfig.objects.all()
        #check country levels
        for i in country:
            x=countrySerializer(i,many=False)
            level=x.data["levels"]
        count=len(LevelConfig.objects.all())
        if(count==level):
            return Response("Level is greater than country level",status=status.HTTP_400_BAD_REQUEST)

        else:
            serializer =   levelSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def get(self, request):
        level = LevelConfig.objects.all()
        serializer =  levelSerializer(level, many=True)
        x=sorted(serializer.data, key=lambda k: k['id'])
        return Response(x)

    def put(self, request, *args, **kwargs):
        # rows=request.data["rows"]
        # print(rows)
        res=[]
        for x in request.data:
            # print(x)
            level = get_object_or_404(LevelConfig, id=x["id"])
            serializer =  levelSerializer(level, data=x)
            if serializer.is_valid():
                serializer.save()
                res.append(serializer.data)
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        return Response(res,status=status.HTTP_200_OK)

    def delete(self, request, *args, **kwargs):
        id=request.data["id"]
        level = get_object_or_404(LevelConfig, id=id)
        level.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


import sys
import time
from typing import cast
from cryptography import x509
import requests

from getssl.log import LoggerBase, DebugLogger, ConfigBase, Actor, StrDict
from getssl.certManager import CertManager, CertManagerConfig, KeyType
from getssl.dnspod import DNSPodClient, DNSPodConfig
from getssl.acme import ACMEClient, ACMEConfig
from getssl.typing import JsonDict, PrivateKeyTypes

class Config(ConfigBase, CertManagerConfig, DNSPodConfig, ACMEConfig):
  def __init__(self, path: str, logger: LoggerBase):
    super().__init__(path, logger)

    raw = self._raw
    self._wd = raw['workingDir']
    # CA
    self._ca         = raw['ca']
    self._allMethods: StrDict = requests.get(self._ca).json()
    self._accountKey = raw['accountKey']
    logger("CA url={}, accountKey={}", self._ca, self._accountKey)
    # dnspod
    self._dnspod       = raw['dnspod']
    self._dnspodToken  = raw['dnspodToken']
    self._baseDomain   = raw['baseDomain']
    logger("dnspod url={}, baseDomain={}", self._dnspod, self._baseDomain)

  @property
  def wd(self): return self._wd

  @property
  def recordList(self): return self._dnspod + '/Record.List'

  @property
  def recordCreate(self): return self._dnspod + '/Record.Create'

  @property
  def recordDelete(self): return self._dnspod + '/Record.Remove'

  @property
  def dnspodToken(self): return self._dnspodToken

  @property
  def baseDomain(self): return self._baseDomain

  @property
  def newAccount(self): return self._allMethods['newAccount']

  @property
  def newNonce(self): return self._allMethods['newNonce']

  @property
  def newOrder(self): return self._allMethods['newOrder']

  @property
  def accountKey(self): return self._accountKey

class GetSSL(Actor):
  def __init__(self, configPath: str, domain: str):
    self.domain = domain
    self.logger = DebugLogger(True)
    self.config = Config(configPath, self.logger)
    self.acme   = ACMEClient(self.config, self.logger)
    self.dnspod = DNSPodClient(self.config, self.logger)
    self.certManager = CertManager(self.config, self.logger)
    self.certManager.domain = domain

  def waitForStatusValid(self, url: str, expect: str, sleep: int=1, retry: int=5):
    self.logger("wait for {} to be {}", url, expect)
    while True:
      obj = cast(JsonDict, self.acme.getAsPost(url))
      retry -= 1
      status = cast(str, obj['status'])
      if status == expect:
        return obj
      elif status not in ( 'valid', 'pending', 'ready', 'processing' ):
        raise RuntimeError("wait object valid failed url={}, status={}, details={}".format(url, status, obj))
      elif retry <= 0:
        raise RuntimeError("wait object valid timeout url={}, status={}, details={}".format(url, status, obj))
      time.sleep(sleep)

  def saveSSL(self, priv: PrivateKeyTypes, csr: x509.CertificateSigningRequest, cert: str):
    keyType = KeyType.getType(priv)
    self.certManager.savePriv(priv)
    self.certManager.saveCSR(csr, keyType)
    self.certManager.saveCert(cert, keyType)

  def getSSL(self, dnsWait: int=5):
    orderURL, order = self.acme.newOrder(self.domain)
    authURL = order['authorizations'][0]
    self.logger("new order location={}, auth={}", orderURL, authURL)

    challengeURL, challengeDomain, challengeValue = self.acme.getChallenge(authURL)
    challengeRecord = self.dnspod.recordFromDomain(challengeDomain)
    try:
      self.dnspod.ensureTxtRecord(challengeRecord, challengeValue)
      self.logger("challenge record written domain={}", challengeDomain)
      self.logger("sleep {} secs for DNS", dnsWait)
      time.sleep(dnsWait)

      priv, csr = self.certManager.getCSR(KeyType.RSA)

      self.acme.signAndSend(challengeURL, {})
      order = self.waitForStatusValid(authURL, 'valid')
      order = self.waitForStatusValid(orderURL, 'ready')
      finalURL = cast(str, order['finalize'])
    except Exception as ex:
      raise ex from None
    finally:
      self.dnspod.deleteRecord(challengeRecord)
    self.logger("order ready finalize={}", finalURL)

    self.acme.finalize(finalURL, csr)
    order = self.waitForStatusValid(orderURL, 'valid')
    certURL = cast(str, order['certificate'])
    self.logger("cert issued url={}", certURL)

    cert = self.acme.getAsPost(certURL, True)
    return priv, csr, cast(str, cert)

  def run(self):
    self.acme.register()
    priv, csr, cert = self.getSSL()
    self.saveSSL(priv, csr, cert)

if __name__ == '__main__':
  if len(sys.argv) <= 2:
    raise ValueError('Must provide config file and domain')
  GetSSL(sys.argv[1], sys.argv[2]).run()


import pandas as pd
import plotly.graph_objects as go
import plotly.subplots as sp
import webbrowser
import os

# Path to the dataset
file_path_ufos = "/Users/maz/Desktop/UFOs/ufo_sighting_data.csv"

# Read the dataset
df = pd.read_csv(file_path_ufos, low_memory=False)

# Convert the 'latitude' column to numeric
df['latitude'] = pd.to_numeric(df['latitude'], errors='coerce')

# Filter the dataset for triangle UFO sightings
triangle_ufos = df[df['UFO_shape'] == 'triangle']

# Create the base map
fig = sp.make_subplots(rows=1, cols=1, subplot_titles=["Triangle UFO Sightings by Latitude"])

# Add the triangle UFO sightings to the map
fig.add_trace(go.Scattergeo(
    lon=triangle_ufos['longitude'],
    lat=triangle_ufos['latitude'],
    mode='markers',
    marker=dict(color='yellow', opacity=0.5),
    hoverinfo='text',
    hovertext=triangle_ufos['city'] + ', ' + triangle_ufos['state/province'] + '
' + triangle_ufos['date_documented'] + '
' + triangle_ufos['description']
))

# Add a shaded region for the predominant latitudinal range
fig.add_trace(go.Scattergeo(
    lon=[-180, 180, 180, -180, -180],
    lat=[39, 39, 53, 53, 39],
    mode='none',
    fill='toself',
    fillcolor='blue',
    opacity=0.5
))

# Update the layout to show a world map with country borders
fig.update_geos(
    showcoastlines=True,
    coastlinecolor="White",
    showland=True,
    landcolor="Black",
    showcountries=True,
    countrycolor="Grey",
    projection_type="natural earth"
)

fig.update_layout(title_text='Triangle UFO Sightings by Latitude', template='plotly_dark')

# Save the figure as an HTML file
file_path = "/Users/maz/Desktop/UFOs/triangle_ufo_map.html"
fig.write_html(file_path)

# Open the saved HTML file in the default web browser
webbrowser.open('file://' + os.path.realpath(file_path))


from app.services import bucket_service, resolve_bucket_key
from app.services.bucket import S3Bucket
from app.services.utils import cfg

def test_resolve_bucket_key(monkeypatch):
    file_name = "myfile.jpg"
    bucket_subfolder = "my/bucket/subfolder"

    # Same if the bucket folder is specified
    assert resolve_bucket_key(file_name, bucket_subfolder) == f"{bucket_subfolder}/{file_name}"

    # Check that bucket folder is prepended in bucket key if set
    origin_value = cfg.BUCKET_MEDIA_FOLDER
    monkeypatch.setattr(cfg, "BUCKET_MEDIA_FOLDER", bucket_subfolder)
    assert resolve_bucket_key(file_name) == f"{bucket_subfolder}/{file_name}"

    # Check that it returns the same thing when bucket folder is not set
    monkeypatch.setattr(cfg, "BUCKET_MEDIA_FOLDER", None)
    assert resolve_bucket_key(file_name) == file_name
    monkeypatch.setattr(cfg, "BUCKET_MEDIA_FOLDER", origin_value)

def test_bucket_service():
    assert isinstance(bucket_service, S3Bucket)


import serial
import numpy as np
import matplotlib.pyplot as plt
import time as t
import paho.mqtt.client as paho

serdev = '/dev/ttyUSB0'

s = serial.Serial(serdev, 9600)

mqttc = paho.Client()

host = "localhost"

port = 1883

# MQTT Callbacks

def on_connect(self, mosq, obj, rc):

    print("Connected rc: " + str(rc))

def on_message(mosq, obj, msg):

    print("[Received] Topic: " + msg.topic + ", Message: " + str(msg.payload) + "\n");

def on_subscribe(mosq, obj, mid, granted_qos):

    print("Subscribed OK")

def on_unsubscribe(mosq, obj, mid, granted_qos):

    print("Unsubscribed OK")

# Set callbacks

mqttc.on_message = on_message

mqttc.on_connect = on_connect

mqttc.on_subscribe = on_subscribe

mqttc.on_unsubscribe = on_unsubscribe

# Connect and subscribe to MQTT

print("Connecting to " + host )

mqttc.connect(host, port=1883, keepalive=60)
mqttc.subscribe("X", 0)
mqttc.subscribe("Y", 0)
mqttc.subscribe("Z", 0)
mqttc.subscribe("tilt", 0)
mqttc.subscribe("plot", 0)

# Variables for accel value

num_time=np.arange(0,10)
velo = np.arange(0,10,dtype=float)
a=0 #the index

#xbee settings

s.write("+++".encode())

char = s.read(2)

print("Enter AT mode.")

print(char.decode())

s.write("ATMY 0x140\r\n".encode())

char = s.read(3)

print("Set MY 0x140.")

print(char.decode())

s.write("ATDL 0x240\r\n".encode())

char = s.read(3)

print("Set DL 0x240.")

print(char.decode())

s.write("ATID 0x1\r\n".encode())

char = s.read(3)

print("Set PAN ID 0x1.")

print(char.decode())

s.write("ATWR\r\n".encode())

char = s.read(3)

print("Write config.")

print(char.decode())

s.write("ATMY\r\n".encode())

char = s.read(4)

print("MY :")

print(char.decode())

s.write("ATDL\r\n".encode())

char = s.read(4)

print("DL : ")

print(char.decode())

s.write("ATCN\r\n".encode())

char = s.read(3)

print("Exit AT mode.")

print(char.decode())

print("start sending RPC")

s.write(bytes("\r", 'UTF-8'))

line=s.readline()

print(line)

line=s.readline()

print(line)

t.sleep(1)

for i in range(0, 10):
    s.write(bytes("/getData/run\n", 'UTF-8'))
    line=s.readline()
    print(line)
    line=s.readline()
    print(line)

    velo[i] = float(line)
    print("velo[i]="+str(velo[i]))
    t.sleep(1)

for i in range(0,10):
    print(velo[i])
for i in range(0,10):
    print("mqtt publish")
    mqttc.publish("velocity", velo[i])
    print("send velo"+str(velo[i]))
    t.sleep(0.1)


import json
import os, signal
import psutil
import time
from cilantro_ee.cli.utils import restart
from cilantro_ee.cli.start import start_mongo

def check_pid(pid):
    """ Check For the existence of a unix pid. """
    try:
        #signal 0 just checks for pid status
        os.kill(pid, 0)
    except OSError:
        return False
    else:
        return True

def find_pid(name):
    try:
        PNAME = name
        for proc in psutil.process_iter():
            # check whether the process name matches
            if proc.name() == PNAME:
                return proc.pid
    except BaseException as err:
        print("Node Setup not finished")
        print("Error: {}".format(err))
        return -1

def main():

    mpid = find_pid(name='mongod')
    cpid = find_pid(name='cil')

    if -1 in {mpid, cpid}:
        return

    while (True):
        time.sleep(10)
        m_status = check_pid(mpid)
        c_status = check_pid(cpid)

        if False in {c_status, m_status}:
            try:
                os.kill(mpid, signal.SIGTERM)
                os.kill(cpid, signal.SIGTERM)
            except BaseException as err:
                print("Error: {}".format(err))

            # start mongo
            start_mongo()

            # restart node from config
            restart()

if __name__ == "__main__":
    # execute only if run as a script
    main()


from lstore.table import Table, Record
from lstore.index import Index
from datetime import datetime
from lstore.config import *

class Query:
    """
    # Creates a Query object that can perform different queries on the specified table
    Queries that fail must return False
    Queries that succeed should return the result or True
    Any query that crashes (due to exceptions) should return False
    """
    def __init__(self, table):
        self.table = table
        self.index = Index(table)

    """
    # internal Method
    # Read a record with specified key
    # Returns True upon succesful deletion
    # Return False if record doesn't exist or is locked due to 2PL
    """

    def delete(self, key):
        rid = self.table.key_RID[key]
        del self.table.key_RID[key]
        del self.table.page_directory[rid]
        return True

    """
    # Insert a record with specified columns
    # Return True upon succesful insertion
    # Returns False if insert fails for whatever reason
    """
    def insert(self, *columns):
        key = columns[self.table.key_column]
        if key in self.table.key_RID.keys():
            return False;

        self.table.new_record.acquire()
        schema_encoding = '0' * self.table.num_columns
        indirection = MAX_INT
        rid = self.table.num_records
        time = datetime.now().strftime("%Y%m%d%H%M%S")
        base_id = rid
        meta_data = [rid, int(time), schema_encoding, indirection, base_id]
        columns = list(columns)
        meta_data.extend(columns)

        # self.table.lock_manager[key].acquire_wlock()
        self.table.base_write(meta_data)
        # self.table.lock_manager[key].release_wlock()
        self.table.new_record.release()
        return True

    """
    # Read matching record with specified search key
    # :param search_key: the value you want to search based on
    # :param search_key_index: the column index you want to search based on
    # :param projected_columns_index: what columns to return. array of 1 or 0 values.
    # Returns a list of Record objects upon success
    # Returns False if record locked by TPL
    # Assume that select will never be called on a key that doesn't exist
    """
    def find_column_bufferID(self, column):
        buffer_rid = []
        num_base = self.table.num_records - self.table.num_updates
        num_page_range = num_base % RECORD_PER_PAGERANGE + 1
        num_base_page = num_base % RECORD_PER_PAGE + 1
        for page_range in range(num_page_range):
            for base_page in range(num_base_page):
                buffer_id = (self.table.table_path, "base", str(column), str(page_range), str(base_page))
                buffer_rid.append(buffer_id)

        return buffer_rid

    def select(self, search_key, search_key_index, projected_columns_index):
        records = []
        column = []
        rids = []

        if search_key_index == self.table.key_column:
            if search_key in self.table.key_RID.keys():
                rids.append(self.table.key_RID[search_key])
        elif self.table.index.has_index(search_key_index):
            rids = self.table.index.locate(search_key_index, search_key)
        else:
            rids = self.table.find_value_rid(search_key_index, search_key)

        if len(rids) == 0:
                return []

        for rid in rids:
            result = self.table.find_record(rid)
            # print(result)
            column = result[DEFAULT_PAGE:DEFAULT_PAGE + self.table.num_columns + 1]

            # if record has update record
            if result[INDIRECTION] != MAX_INT:
            # use indirection of base record to find tail record
                rid_tail = result[INDIRECTION]

                result_tail = self.table.find_record(rid_tail)
                updated_column = result_tail[DEFAULT_PAGE:DEFAULT_PAGE + self.table.num_columns + 1]
                encoding = result[SCHEMA_ENCODING]
                encoding = self.find_changed_col(encoding)
                for i, value in enumerate(encoding):
                    if value == 1:
                        column[i] = updated_column[i]

            # take columns that is requested
            for i in range(self.table.num_columns):
                if projected_columns_index[i] == 0:
                    column[i] = None
            record = Record(rid, search_key, column)
            records.append(record)

        return records

    # helper function to find which columns have updated
    def find_changed_col(self, encoding):
        count = self.table.num_columns
        result = [0 for _ in range(count)]
        if encoding == 0:
            return result
        while encoding != 0:
            if encoding % 10 == 1:
                result[count - 1] = 1
            encoding = encoding // 10
            count -= 1
        return result

    """
    # Read matching record with specified search key
    # :param search_key: the value you want to search based on
    # :param search_key_index: the column index you want to search based on
    # :param projected_columns_index: what columns to return. array of 1 or 0 values.
    # :param relative_version: the relative version of the record you need to retreive.
    # Returns a list of Record objects upon success
    # Returns False if record locked by TPL
    # Assume that select will never be called on a key that doesn't exist
    """
    def select_version(self, search_key, search_key_index, projected_columns_index, relative_version):
        pass

    """
    # Update a record with specified key and columns
    # Returns True if update is succesful
    # Returns False if no records exist with given key or if the target record cannot be accessed due to 2PL locking
    """
    def update(self, primary_key, *columns):

        columns = list(columns)

        if primary_key not in self.table.key_RID.keys():
            return False
        if columns[self.table.key_column] in self.table.key_RID.keys():
            return False
        if columns[self.table.key_column] != None:
            return False

        self.table.update_record.acquire()
        tail_rid = self.table.num_records
        time = datetime.now().strftime("%Y%m%d%H%M%S")
        rid = self.table.key_RID[primary_key]
        base_id = rid
        result = self.table.find_record(rid)
        indirection = result[INDIRECTION]
        new_encoding = ''
        location_base = self.table.page_directory[rid]

        # first time update
        if indirection == MAX_INT:
            tail_indirect = rid
            for i, value in enumerate(columns):
                if value == None:
                    new_encoding += '0'
                    columns[i] = MAX_INT
                else:
                    new_encoding += '1'
        else:
            latest_tail = self.table.find_record(indirection)
            tail_indirect = latest_tail[RID]
            encoding = latest_tail[SCHEMA_ENCODING]
            encoding = self.find_changed_col(encoding)
            for i, value in enumerate(encoding):
                if columns[i] != None:
                    new_encoding += '1'
                else:
                    columns[i] = latest_tail[i + DEFAULT_PAGE]
                    if latest_tail[i + DEFAULT_PAGE] != MAX_INT:
                        new_encoding += '1'
                    else:
                        new_encoding += '0'

        # update base record
        self.table.update_value(INDIRECTION, location_base, tail_rid)
        self.table.update_value(SCHEMA_ENCODING, location_base, new_encoding)

        meta_data = [tail_rid, int(time), new_encoding, tail_indirect, base_id]
        meta_data.extend(columns)
        self.table.tail_write(meta_data)

        self.table.update_record.release()

        # for merge
        # location = self.table.page_directory[tail_rid]
        # self.table.merge_trigger(location)
        return True

    """
    :param start_range: int         # Start of the key range to aggregate
    :param end_range: int           # End of the key range to aggregate
    :param aggregate_columns: int  # Index of desired column to aggregate
    # this function is only called on the primary key.
    # Returns the summation of the given range upon success
    # Returns False if no record exists in the given range
    """
    def sum(self, start_range, end_range, aggregate_column_index):
        total_sum = 0
        column_index = aggregate_column_index + DEFAULT_PAGE
        for key in range(start_range, end_range + 1):
            if key in self.table.key_RID.keys():
                rid = self.table.key_RID[key]
                record = self.table.find_record(rid)
                # never been updated
                if record[INDIRECTION] == MAX_INT:
                    total_sum += record[column_index]
                else:
                # have been updated
                    tail_rid = record[INDIRECTION]
                    tail_record = self.table.find_record(tail_rid)
                    updated_column = tail_record[DEFAULT_PAGE:DEFAULT_PAGE + self.table.num_columns + 1]
                    encoding = tail_record[SCHEMA_ENCODING]
                    encoding = self.find_changed_col(encoding)
                    # print(updated_column)
                    # print(tail_record)
                    if encoding[aggregate_column_index] == 1:
                        total_sum += updated_column[aggregate_column_index]
                    else:
                        total_sum += record[column_index]

        return total_sum

    """
    :param start_range: int         # Start of the key range to aggregate
    :param end_range: int           # End of the key range to aggregate
    :param aggregate_columns: int  # Index of desired column to aggregate
    :param relative_version: the relative version of the record you need to retreive.
    # this function is only called on the primary key.
    # Returns the summation of the given range upon success
    # Returns False if no record exists in the given range
    """
    def sum_version(self, start_range, end_range, aggregate_column_index, relative_version):
        pass

    """
    incremenets one column of the record
    this implementation should work if your select and update queries already work
    :param key: the primary of key of the record to increment
    :param column: the column to increment
    # Returns True is increment is successful
    # Returns False if no record matches key or if target record is locked by 2PL.
    """
    def increment(self, key, column):
        r = self.select(key, self.table.key_column, [1] * self.table.num_columns)[0]
        if r is not False:
            updated_columns = [None] * self.table.num_columns
            updated_columns[column] = r[column] + 1
            u = self.update(key, *updated_columns)
            return u
        return False


#!/usr/bin/python3

import asyncio
import json
import os
import re
import subprocess
from abc import ABC
from configparser import ConfigParser
from ipaddress import IPv4Address
from os import getpid
from pathlib import Path
from pprint import pp
from tempfile import TemporaryDirectory
from typing import ClassVar, Optional, Self

from pydantic import BaseModel, Field, ConfigDict

def fd_change2(from_fd: int, to_fd: int) -> int:
    """替换文件描述符并确保其可继承"""

    if from_fd != to_fd:
        os.dup2(from_fd, to_fd)
        os.close(from_fd)
    os.set_inheritable(to_fd, True)
    return to_fd

def fd_pipe(child_fd: int, parent_fd: int, child_mode: str) -> None:
    """打开文件描述符作为 pipe"""

    if child_mode == "w":
        cfd, pfd = os.pipe()
    elif child_mode == "r":
        pfd, cfd = os.pipe()
    else:
        raise ValueError(f"unsupport child mode {child_mode}")

    fd_change2(cfd, child_fd)
    fd_change2(pfd, parent_fd)

async def readline_pipe(self, fd: int) -> str:
    loop = asyncio.get_running_loop()
    stream_reader = asyncio.StreamReader(loop=loop)
    transport, protocol = await loop.connect_read_pipe(
        lambda: asyncio.StreamReaderProtocol(stream_reader, loop=loop),
        os.fdopen(fd, "rb"),
    )
    stream_reader.set_transport(transport)
    data = await stream_reader.readline()
    return data.decode("utf-8")

def table_to_dict(table_str: str):
    """将表示 lua 中 table 的字符串转为 Python 中的 dict"""

    s = table_str.replace("=", ":").replace('["', '"').replace('"]', '"')
    s = re.sub(r"(?P<key>[\w.]+)(?=\s*?:)", r'"\g<key>"', s)  # 键加双引号
    s = re.sub(r",(?=\s*?[}|\]])", r"", s)  # 去列表尾逗号
    return json.loads(s if s else "{}")

def extract_lua_data(path: Path):
    """提取存档文件中易识别的 lua 数据"""

    raw_str = path.read_text(encoding="utf-8")
    table_str = raw_str[raw_str.find("{") : raw_str.find("\x00")]
    return table_to_dict(table_str)

class ClusterMisc(BaseModel):
    """集群杂项配置"""

    max_snapshots: int = 6
    console_enabled: bool = True

class ClusterShard(BaseModel):
    """集群分片配置"""

    shard_enabled: bool = False
    bind_ip: IPv4Address = IPv4Address("127.0.0.1")
    master_ip: IPv4Address = IPv4Address("127.0.0.1")
    master_port: int = 10888
    cluster_key: str = "defaultPass"

class ClusterSteam(BaseModel):
    """集群 Steam 配置"""

    steam_group_only: bool = False
    steam_group_id: int = 0
    steam_group_admins: bool = False

class ClusterNetwork(BaseModel):
    """集群网络配置"""

    cluster_name: str = ""
    cluster_password: str = ""
    cluster_description: str = ""
    tick_rate: int = 15
    offline_cluster: bool = False
    lan_only_cluster: bool = False
    autosaver_enabled: bool = True
    whitelist_slots: int = 0
    cluster_language: str = "en"

class ClusterGameplay(BaseModel):
    """集群游戏配置"""

    max_players: int = 16
    pvp: bool = False
    pause_when_empty: bool = True
    vote_enabled: bool = True

class ServerShard(BaseModel):
    """服务端分片配置"""

    is_master: bool = True
    name: str = "[SHDMASTER]"
    id: int = 1

class ServerSteam(BaseModel):
    """服务端 Steam 配置"""

    authentication_port: int = 8766
    master_server_port: int = 27016

class ServerNetwork(BaseModel):
    """服务端网络配置"""

    server_port: int = 10999

class ServerAccount(BaseModel):
    """服务端账户配置"""

    encode_user_path: bool = False

class IniModel(BaseModel, ABC):
    @classmethod
    def load(cls, ini_path: Path) -> Self:
        """加载 ini 配置"""

        parser = ConfigParser()
        with ini_path.open(mode="r", encoding="utf-8") as f:
            parser.read_file(f)
        config_dict = {
            section: {k: v for k, v in parser.items(section) if v is not None}
            for section in parser.sections()
        }
        return cls.model_validate(config_dict)

    def save(self, ini_path: Path) -> None:
        """保存 ini 配置"""

        parser = ConfigParser()
        parser.read_dict(self.model_dump())
        ini_path.parent.mkdir(mode=0o755, parents=True, exist_ok=True)
        with ini_path.open(mode="w", encoding="utf-8") as f:
            parser.write(f)

class ClusterConfig(IniModel):
    """集群配置（cluster.ini）"""

    misc: ClusterMisc = Field(default_factory=ClusterMisc)
    shard: ClusterShard = Field(default_factory=ClusterShard)
    steam: ClusterSteam = Field(default_factory=ClusterSteam)
    network: ClusterNetwork = Field(default_factory=ClusterNetwork)
    gameplay: ClusterGameplay = Field(default_factory=ClusterGameplay)

class ServerConfig(IniModel):
    """服务端配置（server.ini）"""

    shard: ServerShard = Field(default_factory=ServerShard)
    steam: ServerSteam = Field(default_factory=ServerSteam)
    network: ServerNetwork = Field(default_factory=ServerNetwork)
    account: ServerAccount = Field(default_factory=ServerAccount)

class Shard(BaseModel):
    """分片"""

    model_config = ConfigDict(arbitrary_types_allowed=True)

    cluster: "Cluster"

    name: str = "Master"
    config: Optional[ServerConfig] = None
    process: Optional[asyncio.subprocess.Process] = None

    @property
    def path(self) -> Path:
        """分片文件夹路径"""

        return self.cluster.path / self.name

    @property
    def ini_path(self) -> Path:
        """ini 配置文件路径"""

        return self.path / "server.ini"

    @property
    def console_path(self) -> Path:
        """控制台管道文件路径"""

        return self.path / "console"

    @property
    def modoverrides_path(self) -> Path:
        """modoverrides.lua 路径"""

        return self.path / "modoverrides.lua"

    @property
    def leveldataoverride_path(self) -> Path:
        """leveldataoverride.lua 路径"""

        return self.path / "leveldataoverride.lua"

    @property
    def server_temp_path(self) -> Path:
        """服务端临时文件路径"""

        return self.path / "save/server_temp/server_save"

    def load_config(self) -> None:
        """加载配置"""

        ini_path = self.ini_path
        if not ini_path.is_file():
            raise FileNotFoundError(ini_path)
        self.config = ServerConfig.load(ini_path)

    def save_config(self) -> None:
        """保存配置"""

        self.config.save(self.ini_path)

    async def start(
        self,
        *args: tuple[str],
        only_update_server_mods: bool = False,
        skip_update_server_mods: bool = True,
        cloudserver: bool = True,
    ) -> None:
        """启动分片"""

        cmd_list = self.cluster.cmd_list + ["-shard", self.name, *args]
        if only_update_server_mods:
            cmd_list.append("-only_update_server_mods")
        if skip_update_server_mods:
            cmd_list.append("-skip_update_server_mods")
        if cloudserver:
            cmd_list.append("-cloudserver")
            console_path = self.console_path
            if not console_path.is_fifo():
                console_path.unlink(missing_ok=True)
                os.mkfifo(console_path)
            fd3 = os.open(console_path, os.O_RDONLY)
            fd4 = os.open("fd4", os.O_WRONLY | os.O_CREAT | os.O_APPEND)
            fd5 = os.open("fd5", os.O_WRONLY | os.O_CREAT | os.O_APPEND)
            fd_change2(fd3, 3)
            fd_change2(fd4, 4)
            fd_change2(fd5, 5)

        self.process = await asyncio.create_subprocess_exec(
            cmd_list[0],
            *cmd_list[1:],
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            close_fds=False,
        )

        if cloudserver:
            os.close(3)
            os.close(4)
            os.close(5)

    async def stop(self) -> None:
        """停止分片"""

        if self.process:
            self.process.terminate()
            await self.process.communicate()

    async def _handle_log(self) -> None:
        """处理日志输出"""

        # TODO:
        queue = asyncio.Queue()

        while True:
            await self.process.stdout()

class Cluster(BaseModel):
    """集群"""

    root_path: ClassVar[Path] = Path("/")
    conf_dir: ClassVar[str] = "root"
    ugc_path: ClassVar[Path] = Path("/root/ugc")
    install_path: ClassVar[Path] = Path("/root/install")
    steamcmd_path: ClassVar[Path] = Path("/home/steam/steamcmd/steamcmd.sh")
    permission_files: ClassVar[tuple[str]] = (
        "adminlist.txt",
        "whitelist.txt",
        "blocklist.txt",
    )
    bin_mapping: ClassVar[dict[int, str]] = {
        32: "bin/dontstarve_dedicated_server_nullrenderer",
        64: "bin64/dontstarve_dedicated_server_nullrenderer_x64",
    }

    name: str = "Cluster_1"
    config: Optional[ClusterConfig] = None
    shards: list[Shard] = Field(default_factory=list)
    architecture: int = 64

    @classmethod
    def update_steam(cls) -> None:
        """更新 steam"""

        cmd_list = [
            str(cls.steamcmd_path),
            "+@ShutdownOnFailedCommand",
            "1",
            "+@NoPromptForPassword",
            "1",
            "+force_install_dir",
            str(cls.install_path),
            "+login",
            "anonymous",
            "+app_update",
            "343050",
            "validate",
            "+quit",
        ]
        sp = subprocess.run(
            cmd_list,
            check=True,
            encoding="utf-8",
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
        )

    @classmethod
    async def update_mods(cls) -> None:
        """更新模组"""

        with TemporaryDirectory(dir=cls.root_path / cls.conf_dir) as temp_dir:
            temp_path = Path(temp_dir)
            cluster = cls(name=temp_path.name, config=ClusterConfig())
            cluster.save_config()
            shard = Shard(cluster=cluster, config=ServerConfig())
            shard.save_config()
            await shard.start(
                only_update_server_mods=True, skip_update_server_mods=False
            )

    @property
    def path(self) -> Path:
        """集群文件夹路径"""

        return self.root_path / self.conf_dir / self.name

    @property
    def ini_path(self) -> Path:
        """ini 配置文件路径"""

        return self.path / "cluster.ini"

    @property
    def bin_path(self) -> Path:
        """服务端可执行文件路径"""

        return self.install_path / self.bin_mapping[self.architecture]

    @property
    def cmd_list(self) -> list[str]:
        """命令列表"""

        return [
            str(self.bin_path),
            "-monitor_parent_process",
            str(getpid()),
            "-persistent_storage_root",
            str(self.root_path),
            "-conf_dir",
            self.conf_dir,
            "-ugc_directory",
            str(self.ugc_path),
            "-cluster",
            self.name,
        ]

    def load_config(self, include_shards: bool = True) -> None:
        """加载配置"""

        ini_path = self.ini_path
        if not ini_path.is_file():
            raise FileNotFoundError(ini_path)
        self.config = ClusterConfig.load(ini_path)

        if include_shards:
            for shard in self.shards:
                shard.load_config()

    def save_config(self, include_shards: bool = True) -> None:
        """保存配置"""

        self.config.save(self.ini_path)

        if include_shards:
            for shard in self.shards:
                shard.save_config()

    def load_shards(self) -> list[Shard]:
        """加载分片"""

        for p in filter(lambda p: p.is_dir(), self.path.iterdir()):
            shard = Shard(cluster=self, name=p.name)
            self.shards.append(shard)

    def config_port(
        self,
    ) -> None:
        """配置端口"""

        # TODO:

    def ensure_files(self) -> None:
        """确保文件齐全"""

        for file_name in self.permission_files:
            file_path = self.path / file_name
            file_path.touch()

    async def start(self) -> None:
        """启动集群"""

        self.ensure_files()
        self.save_config()
        async with asyncio.TaskGroup() as tg:
            for shard in self.shards:
                tg.create_task(shard.start())

    async def stop(self) -> None:
        """停止集群"""

        async with asyncio.TaskGroup() as tg:
            for shard in self.shards:
                tg.create_task(shard.stop())

class Player(object):
    """玩家"""

    name: str
    kuid: str
    steam_id: int

if __name__ == "__main__":
    # cluster = Cluster(name="cluster")
    # cluster.load_shards()
    # asyncio.run(cluster.start())

    for i in range(1, 6):
        c = ClusterConfig()
        c.misc.max_snapshots = 10
        c.shard.shard_enabled = True
        c.shard.master_port = 10000 + i
        c.shard.cluster_key = "lst"
        c.network.cluster_name = f"LST-标准纯净-{i}"
        c.network.cluster_description = "QQ 频道：饥荒联机版"
        c.network.cluster_language = "zh"
        cluster = Cluster(name=str(i), config=c)

        fc = ServerConfig()
        fc.shard.name = "forest"
        fc.steam.authentication_port = 8700 + i
        fc.steam.master_server_port = 27000 + i
        fc.network.server_port = 11000 + i
        forest = Shard(cluster=cluster, name="forest", config=fc)

        cc = ServerConfig()
        cc.shard.is_master = False
        cc.shard.name = "cave"
        cc.shard.id = 2
        cc.steam.authentication_port = 8800 + i
        cc.steam.master_server_port = 28000 + i
        cc.network.server_port = 12000 + i
        cave = Shard(cluster=cluster, name="cave", config=cc)

        cluster.shards.extend((forest, cave))
        cluster.save_config()


from django.shortcuts import render

# Create your views here.
def contact(request):
    return render(request,'./first_app/index.html',{'courses': [
        {
            'id':1,'course':'C','teacher': 'Rahim'
        },
        {
            'id':2,'course':'C++','teacher': 'Kahim'
        },
        {
            'id':3,'course':'Pyhton','teacher': 'Rahim'
        }
    ]

    })


import re
from django import forms

from mongoengine import *

from mumblr.entrytypes import EntryType, Comment, markup

class HtmlComment(Comment):
    """An HTML-based entry, which will be converted from the markup language
    specified in the settings.
    """
    rendered_content = StringField(required=True)

class TextEntry(EntryType):
    """An HTML-based entry, which will be converted from the markup language
    specified in the settings.
    """
    content = StringField(required=True)
    rendered_content = StringField(required=True)

    type = 'Text'

    def save(self):
        """Convert any markup to HTML before saving.
        """
        self.rendered_content = markup(self.content)
        super(TextEntry, self).save()

    class AdminForm(EntryType.AdminForm):
        content = forms.CharField(widget=forms.Textarea)

class LinkEntry(EntryType):
    """A link-based entry - the title is a link to the specified url and the
    content is the optional description.
    """
    link_url = StringField(required=True)
    description = StringField()

    type = 'Link'

    def rendered_content(self):
        if self.description:
            return markup(self.description, no_follow=False)
        return '
Link: %s
' % (self.link_url,
                                                     self.link_url)

    class AdminForm(EntryType.AdminForm):
        link_url = forms.URLField()
        description = forms.CharField(widget=forms.Textarea, required=False)

class ImageEntry(EntryType):
    """An image-based entry - displays the image at the given url along with
    the optional description.
    """
    image_url = StringField(required=True)
    description = StringField()

    type = 'Image'

    def rendered_content(self):
        url = self.image_url
        html = '' % url
        if self.description:
            html += markup(self.description)
        return html

    class AdminForm(EntryType.AdminForm):
        image_url = forms.URLField()
        description = forms.CharField(widget=forms.Textarea, required=False)

class VideoEntry(EntryType):
    """An video-based entry - will try to embed the video if it is of
    and known type e.g. YouTube
    """
    video_url = StringField(required=True)
    description = StringField()

    type = 'Video'

    embed_codes = {
        'vimeo': (
            '<object width="600" height="338"><param name="allowfullscr'
            'een" value="true" /><param name="allowscriptaccess" value='
            '"always" /><param name="movie" value="http://vimeo.com/moo'
            'galoop.swf?clip_id={{!ID}}&server=vimeo.com&show_t'
            'itle=0&show_byline=0&show_portrait=0&color=59a'
            '5d1&fullscreen=1" /><embed src="http://vimeo.com/mooga'
            'loop.swf?clip_id={{!ID}}&server=vimeo.com&show_tit'
            'le=0&show_byline=0&show_portrait=0&color=59a5d'
            '1&fullscreen=1" type="application/x-shockwave-flash" a'
            'llowfullscreen="true" allowscriptaccess="always" width="60'
            '0" height="338"></embed></object>'
        ),
        'youtube': (
            '<object width="600" height="338">'
            '<param name="movie" value="{{!ID}}"></param>'
            '<param name="allowFullScreen" value="true"></param>'
            '<param name="allowscriptaccess" value="always"></param>'
            '<embed src="http://www.youtube.com/v/{{!ID}}&fs=1&rel=&'
            'hd=10&showinfo=0&iv_load_policy=3" '
            'type="application/x-shockwave-flash" '
            'allowscriptaccess="always" allowfullscreen="true" '
            'width="600" height="338"></embed></object>'
        )
    }

    embed_patterns = (
        ('youtube', r'youtube\.com\/watch\?v=([A-Za-z0-9._%-]+)[&\w;=\+_\-]*'),
        ('vimeo', r'vimeo\.com\/(\d+)'),
    )

    def rendered_content(self):
        video_url = self.video_url
        for source, pattern in VideoEntry.embed_patterns:
            id = re.findall(pattern, video_url)
            if id:
                embed = VideoEntry.embed_codes[source]
                html = embed.replace('{{!ID}}', id[0])
                break
        else:
            html = 'Video: %s' % video_url

        if self.description:
            html += markup(self.description)
        return html

    class AdminForm(EntryType.AdminForm):
        video_url = forms.URLField()
        description = forms.CharField(widget=forms.Textarea, required=False)

EntryType.register(TextEntry)
EntryType.register(LinkEntry)
EntryType.register(ImageEntry)
EntryType.register(VideoEntry)