#!/usr/bin/env python

import sys
import commands
import string

import datetime
import logging
import logging.handlers

from optparse import OptionParser
from random import choice

def print_error(ret, do_exit=False, msg=""):
    """
    ret is the tuple returned by commands.getstatusoutput. If ret[0] is not 0,
    then msg (if passed) or ret[1] is printed as an error. If do_exit is True,
    the program also exits
    """
    if ret[0] != 0:
        if not msg:
            msg = ret[1]
        logging.error("Check the following information:")
        logging.error(msg)
        if do_exit:
            sys.exit(ret[0])

def check_lcg_ce(ce):
    """Do the tests for a lcg-CE"""
    # I will not waste much effort on this, since lcg-CE are condemned
    # to disappear.
    rets = []

    ce, queue = ce.split("/", 1)

    logging.info("\t\tchecking globus-job-run to ce")
    cmd = "globus-job-run %s /bin/hostname" % ce
    logging.debug("Executing '%s'", cmd)
    ret = commands.getstatusoutput(cmd)
    print_error(ret)
    rets.append(ret)

    logging.info("\t\tchecking globus-job-run to fork")
    cmd = "globus-job-run %s/jobmanager-fork /bin/pwd" % ce
    logging.debug("Executing '%s'", cmd)
    ret = commands.getstatusoutput(cmd)
    print_error(ret)
    rets.append(ret)

    logging.info("\t\tchecking globus-job-run to queue")
    queue = queue.split("-")
    cmd = "globus-job-run %s/%s-%s -queue %s /bin/pwd" % tuple([ce] + queue)
    logging.debug("Executing '%s'", cmd)
    ret = commands.getstatusoutput(cmd)
    print_error(ret)
    rets.append(ret)

    return rets

def check_cream_ce(ce):
    """Do the tests for a CREAM CE"""
    rets = []

    ce_hostport, dummy = ce.split("/", 1)

    logging.info("\t\tchecking glite-ce-allowed-submission")
    cmd = "glite-ce-allowed-submission -n %s" % ce_hostport
    logging.debug("Executing '%s'", cmd)
    ret = commands.getstatusoutput(cmd)
    print_error(ret)
    rets.append(ret)

    logging.info("\t\tchecking glite-ce-job-submit")
    cmd = "glite-ce-job-submit -n -a -r %s test_submission.jdl" % ce  # XXX
    logging.debug("Executing '%s'", cmd)
    ret = commands.getstatusoutput(cmd)
    print_error(ret)
    rets.append(ret)
    if ret[0] == 0:
        url = ret[1].splitlines()[-1]
    else:
        return  # XXX
    logging.info("\t\t\tJob ID: %s", url)
    while True:
        cmd = "glite-ce-job-status -n %s" % url
        logging.debug("Executing '%s'", cmd)
        ret = commands.getstatusoutput(cmd)
        if "[DONE-OK]" in ret[1]:
            logging.info("\t\tsubmission ok, check the following job " + \
                    "id for further details %s", url)
            break
        elif "[DONE-FAILED]" in ret[1]:
            ret = (1, ret[1])
            print_error(ret)
            break
    print_error(ret)
    rets.append(ret)

    return rets

def check_gridftp(host):
    """Check gridftp on host"""
    cmd = "uberftp %s ls" % host
    logging.debug("Executing '%s'", cmd)
    ret = commands.getstatusoutput(cmd)
    if ret[0] != 0:
        print_error(ret)
    else:
        logging.info("\t\tGridFTP OK")

def check_ces(bdii, vo):
    """Query the bdii for the available CE for VO vo, then check them"""

    logging.info("Checking Computing Elements")
    logging.info("\tQuerying the BDII for the CEs")

    cmd = "lcg-info --list-ce --bdii %(bdii)s --sed --vo %(vo)s" % locals()
    logging.debug("Executing '%s'", cmd)
    ret = commands.getstatusoutput(cmd)
    print_error(ret, do_exit=True)

    ces = ret[-1].splitlines()

    logging.info("\t\tFound: " + ",\n\t\t\t".join(ces))

    checked = []
    for ce in ces:
        if ce in checked:
            continue

        rets = []
        checked.append(ce)

        ce_host = ce.split(":")[0]
        logging.info("\tChecking %s", ce_host)

        # Check the GridFTP
        check_gridftp(ce_host)

        if "8443" in ce:
            rets.extend(check_cream_ce(ce))
        else:
            # lcf-CE
            rets.extend(check_lcg_ce(ce))

        if not any([i[0] for i in rets]):
            logging.info("\t\tJob submission seems OK")
        else:
            logging.critical("\t\tJob submission has problems, check errors")

def filter_and_join_ldap(data, query):
    """Filter results to only those of query and join
line breaks from ldapsearch."""
    got = False
    aux = []
    for i in data.splitlines():
        if i.startswith(query):
            got = True
            aux.append([i.split(":", 1)[-1].strip()])
        elif i.startswith(" ") and got:
            aux[-1].append(i.strip())
        elif got:
            got = False
    return ["".join(i) for i in aux]

def check_ses(bdii, vo):
    """Query the bdii for the available SE for VO, then check them"""
    logging.info("Checking Storage Elements")
    logging.info("\tQuerying the BDII for the SEs")

    cmd = "lcg-info --list-se --bdii %(bdii)s --sed --vo VO:%(vo)s" % locals()
    logging.debug("Executing '%s'", cmd)
    ret = commands.getstatusoutput(cmd)
    print_error(ret, do_exit=True)

    ses = ret[-1].splitlines()
    logging.info("\t\tFound: " + ",\n\t\t\t".join(ses))

    checked = ["gridce05.ifca.es"]
    for se in ses:
        if se in checked:
            continue

        rets = []
        checked.append(se)

        logging.info("\tChecking %s", se)
        cmd = "uberftp %s ls" % se
        logging.debug("Executing '%s'", cmd)
        ret = commands.getstatusoutput(cmd)
        if ret[0] != 0:
            print_error(ret)
        else:
            logging.info("\t\tGridFTP is up")
        rets.append(ret)

        cmd = "ldapsearch -x -LLL -H ldap://%(bdii)s -b o=grid \
                '(&(objectClass=GlueSATop) \
                (GlueVOInfoAccessControlBaseRule=VO:%(vo)s) \
                (GlueChunkKey=GlueSEUniqueID=%(se)s))' \
                GlueVOInfoPath" % locals()
        logging.debug("Executing '%s'", cmd)
        ret = commands.getstatusoutput(cmd)
        print_error(ret)
        rets.append(ret)

        se_paths = filter_and_join_ldap(ret[1], "GlueVOInfoPath")

        cmd = "ldapsearch -x -LLL -H ldap://%(bdii)s -b o=grid \
                '(&(objectClass=GlueSEControlProtocol) \
                (GlueChunkKey=GlueSEUniqueID=%(se)s) \
                (GlueSEControlProtocolType=SRM) \
                (GlueSEControlProtocolVersion=2.2.0))' \
                GlueSEControlProtocolEndpoint" % locals()

        logging.debug("Executing '%s'", cmd)
        ret = commands.getstatusoutput(cmd)
        print_error(ret)
        rets.append(ret)

        endpt = [i.replace("httpg", "srm") for i in filter_and_join_ldap(
            ret[1], "GlueSEControlProtocolEndpoint")]

        for endpoint in endpt:
            for se_path in se_paths:
                logging.info("\t\tUploading to %(endpoint)s/%(se_path)s",
                        locals())
                randfile = ''.join([choice(string.letters + string.digits) \
                        for i in range(15)])
                cmd = "lcg-cp -v -b --vo %(vo)s -D srmv2 file:/etc/issue \
                        %(endpoint)s/\?SFN=%(se_path)s/%(randfile)s" % locals()
                logging.debug("Executing '%s'", cmd)
                ret = commands.getstatusoutput(cmd)
                print_error(ret)
                rets.append(ret)

                if ret[0] == 0:
                    logging.info("\t\tRemoving uploaded file")
                    cmd = "lcg-del -l -v -b --vo %(vo)s -D srmv2 \
                            %(endpoint)s/\?SFN=%(se_path)s/%(randfile)s" % \
                            locals()
                    logging.debug("Executing '%s'", cmd)
                    ret = commands.getstatusoutput(cmd)
                    print_error(ret)
                    rets.append(ret)

        if not any([i[0] for i in rets]):
            logging.info("\t\tData management seems OK")
        else:
            logging.critical("\t\tData management has problems, check errors")

def check_bdii(bdii):
    """Check bdii for correctness"""
    logging.info("Checking BDII '%s' information (TBD)", bdii)

def get_proxy():
    """Check for proxy validity and return VO"""
    ret = commands.getstatusoutput("voms-proxy-info -exists")
    print_error(ret, do_exit=True, msg="VOMS: No valid proxy found!")

    ret = commands.getstatusoutput("voms-proxy-info -vo")
    print_error(ret, do_exit=True)

    vo = ret[1]
    return vo

def set_logging(level=logging.INFO):
    """Set up logging"""

    outfile = "%s.log" % datetime.datetime.now().strftime("%Y%m%d_%H%M%S.%f")

    logging.basicConfig(level=logging.DEBUG,
            format="%(asctime)s %(levelname)-8s %(message)s",
            datefmt="%m-%d %H:%M",
            filename=outfile,
            filemode="w")

    console = logging.StreamHandler()
    console.setLevel(level)
    formatter = logging.Formatter('%(levelname)-8s %(message)s')
    console.setFormatter(formatter)
    logging.getLogger('').addHandler(console)

    logging.info("Detailed output for this run will be on '%s'", outfile)

def main():
    """Main program"""
    usage = """%prog [options] <siteBDII host>:<port>"""
    parser = OptionParser(usage=usage)
#    parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
#            default="False", help="Print verbose results")
    parser.add_option("-c", "--ces", dest="onlyce", action="store_true",
            default=False, help="Check only Computing Elements")
    parser.add_option("-s", "--ses", dest="onlyse", action="store_true",
            default=False, help="Check only Storage Elements")

    (opts, args) = parser.parse_args()

    if opts.onlyse and opts.onlyce:
        parser.error("-s and -c options are mutually exclusive")
    elif opts.onlyse or opts.onlyse:
        all_ = False
    else:
        all_ = True

    if len(args) != 1:
        parser.error("Error, you have to specify one (and only one) siteBDII")

    set_logging()

    vo = get_proxy()

    logging.info("Checking with VO '%s'", vo)

    bdii = args[-1]
    check_bdii(bdii)

    if all_ or opts.onlyce:
        check_ces(bdii, vo)
    if all_ or opts.onlyse:
        check_ses(bdii, vo)

if __name__ == "__main__":
    main()
sys.exit(0)


from sqlwrapper import gensql, dbget, dbput
import json
import datetime
def HOTEL_FD_POST_UPDATE_CheckinGuestArrivals(request):

   d = request.json
   res_id = d.get("Res_id")
   unique_id = d.get("Res_unique_id")
   pf_id = d.get("pf_id")
   a = {}
   RES_Log_Time = datetime.datetime.utcnow()+datetime.timedelta(hours=5, minutes=30)
   RES_Log_Time = RES_Log_Time.time().strftime("%H:%M:%S")
   print(RES_Log_Time)
   RES_Log_Date = datetime.datetime.utcnow().date()
   print(RES_Log_Date)
   RES_Log_Date = str(RES_Log_Date)
   arrival = dbget("select res_arrival, res_adults,res_room from reservation.res_reservation where res_id = '"+res_id+"' and pf_id = '"+pf_id+"' and res_unique_id = '"+unique_id+"'")

   arrival = json.loads(arrival)
   print(arrival)
   print(arrival[0]['res_arrival'],type(arrival[0]['res_arrival']))
   today_arrival = (arrival[0]['res_arrival'])
   adult = arrival[0]['res_adults']
   room = arrival[0]['res_room']
   print(room,type(room))

   print(today_arrival)
   if RES_Log_Date == today_arrival:
       p = {}
       p['res_id'] = res_id
       p['res_unique_id'] = unique_id
       sql_value = gensql('select','room_management.rm_queue_room','rm_queue',p)
       sql_value = json.loads(sql_value)

       if len(sql_value) != 0:
          psql = dbput("delete from room_management.rm_queue_room where res_id = '"+res_id+"' and res_unique_id = '"+unique_id+"'")
          print(psql)
       else:
          pass
       e = {}
       e['Res_id'] = res_id
       e['pf_id'] = pf_id
       e['res_unique_id'] = unique_id
       a['Res_guest_status'] = "checkin"

       sql_value = gensql('update','reservation.res_reservation',a,e)
       print(sql_value)
       res_id = e.get("Res_id")
       Emp_Id = '121'
       Emp_Firstname = "daisy"
       s = {}
       s['Emp_Id'] = Emp_Id
       s['Emp_Firstname'] = Emp_Firstname

       s['RES_Log_Date'] = RES_Log_Date
       s['RES_Log_Time'] = RES_Log_Time
       s['RES_Action_Type'] = "Checkin a guest"
       s['RES_Description'] = "Checked in a guest"
       s['Res_id'] = res_id
       sql_value = gensql('insert','reservation.res_activity_log',s)
       fo_status = "occupied"
       res_status = "checkin"
       sql_value = dbput("update room_management.rm_room_list set rm_fo_status = '"+fo_status+"',rm_reservation_status = '"+res_status+"',rm_fo_person = "+str(adult)+" where rm_room in ("+str(room)+")")

       print(sql_value)
       alertcount = json.loads(dbget("select count(*) from reservation.res_alert where res_id = '"+str(res_id)+"' \
                                      and res_unique_id = '"+str(unique_id)+"'"))
       print(alertcount)
       if alertcount[0]['count'] !=0:
          alertvalue = json.loads(dbget("select * from reservation.res_alert where res_id = '"+str(res_id)+"' \
                                      and res_unique_id = '"+str(unique_id)+"'"))
          return(json.dumps({'Status': 'Success', 'StatusCode': '200', 'alertvalue':alertvalue,'Return': 'Alert Got Successfully','ReturnCode':'AGS'}, sort_keys=True, indent=4))
       else:

         return(json.dumps({'Status': 'Success', 'StatusCode': '200','Return': 'Record Updated Successfully','ReturnCode':'RUS'}, sort_keys=True, indent=4))

   else:
      return(json.dumps({'Status': 'Success', 'StatusCode': '200','Return': 'Checkin a Today Guest arrivals only','ReturnCode':'CTG'}, sort_keys=True, indent=4))


from ...robot import Robot

from stt_watson.SttWatsonLogListener import SttWatsonLogListener
from recording.Record import Record
from watson_client.Client import Client
from utils.SignalHandler import SignalHandler

import threading
import signal
import os

class WatsonRobot(Robot):
    def __init__(self, config, speaker, actions):
        super(WatsonRobot, self).__init__(config, speaker, actions)
        config['audio-chunk'] = 8000
        config['audio-rate'] = 44100
        config['channels'] = 1

        self.listeners = []
        sttWatsonLogListener = SttWatsonLogListener()
        self.listeners.append(sttWatsonLogListener)
        self.stopper = threading.Event()
        self.record = Record(config, self.stopper)
        self.workers = [self.record]
        self.watsonClient = Client(config)
        self.handler = SignalHandler(self.stopper, self.workers)
        signal.signal(signal.SIGINT, self.handler)

    def name(self):
        return 'Watson'

    def listen(self):
        audioFd, writer = os.pipe()
        self.record.setWriter(writer)
        self.record.start()
        self.watsonClient.setListeners(self.listeners)
        self.watsonClient.startStt(audioFd)


from asyncio import sleep

from discord import Forbidden
from discord.ext import commands

from Utils.domain_tester import get_domain_embed
from Utils.file_tester import get_file_embed

class DmCommands(commands.Cog, name="Dm Commands"):
    """
    Cog including all Commands that are dm only
    """

    def __init__(self, b):
        self.b = b
        print("Dm Commands succesfully added to the bot!")

    @commands.command(name="check",
                      help="Takes given Input and runs a test over it. Only Dm Channels. Accepts URLs",
                      brief="Checks Input", aliases=["test"])
    async def check(self, ctx, *arg):
        if ctx.guild is not None:
            try:
                await ctx.message.delete()
                await ctx.author.send("Only DM Available")
            except Forbidden:
                await ctx.reply("Only DM Available! Warning! The Above message might be milicious. "
                                "Dont click the file/url until you trust it! (for some reason i cant delete it)")
            return
        if arg is None and not ctx.message.attachments:
            await ctx.send("Missing an url")
            return
        if ctx.message.attachments:
            await ctx.reply("Starting testing of files. This takes some time")
            for i in ctx.message.attachments:
                msgn = await ctx.reply("Stand by...")
                await msgn.edit(content=None, embed=await get_file_embed(i, ctx))
                await sleep(30)
        if len(arg) > 0:
            domain = arg[0]
            await ctx.reply(embed=get_domain_embed(domain, ctx))


from collections import Counter

class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        # anagram: str with same histgram

        res = []

        lp = len(p) -1
        ls = len(s)
        pCount = Counter(p)
        mCount = Counter(s[:lp]) # from 0 to lp - 2

        for i in range(lp, ls):
            mCount[s[i]]+=1
            if mCount == pCount:
                res.append(i-lp)
            mCount[s[i-lp]]-=1
            if mCount[s[i-lp]] == 0:
                del mCount[s[i-lp]]

        return res


import torch
from torch import nn
from torch.autograd import Variable
import numpy as np
from util import get_data
from torch.utils.data import DataLoader
from torch.nn import functional as F
from torch.optim import Adam
from variables import*
from matplotlib import pyplot as plt

class MnistRegression(object):
    def __init__(self, train_data, test_data):
        self.train_data = train_data
        self.test_data = test_data
        self.model = self.MnistModel()

    class MnistModel(nn.Module):
        def __init__(self):
            super().__init__()
            self.linear = nn.Linear(
                    in_features=input_shape,
                    out_features=output_shape
                    )

        def forward(self, x):
            x = x.reshape(-1, input_shape)
            x = self.linear(x)
            x = F.log_softmax(x, dim=1)
            return x

    def loss_fnc(self, Ypred, Y):
        return F.cross_entropy(Ypred, Y)

    def optimizer(self, learning_rate=0.1):
        return Adam(self.model.parameters(), lr=learning_rate)

    def evaluate(self, Y, Ypred):
        P = torch.argmax(Ypred, dim=1).numpy()
        Y = Y.numpy()
        return np.sum(Y == P)

    def train(self, num_epochs=100):
        opt = self.optimizer()
        total_train_loss = []
        total_test_loss = []
        for i in range(1,num_epochs+1):
            n_correct = 0
            n_total = 0
            for X, Y in self.train_data:
                Y = Y.to(dtype=torch.int64)
                Ypred = self.model(X)
                loss = self.loss_fnc(Ypred, Y)
                loss.backward() # calculate gradients
                total_train_loss.append(loss.item())

                n_correct += self.evaluate(Y, Ypred)
                n_total += batch_size

                opt.step() # update parameters using claculated gradients
                opt.zero_grad() # use to avoid accumilating the gradients

            train_acc = round(n_correct/n_total, 3)

            with torch.no_grad():
                n_correct = 0
                n_total = 0
                for X, Y in self.test_data:
                    Y = Y.to(dtype=torch.int64)
                    Ypred = self.model(X)
                    loss = self.loss_fnc(Ypred, Y)
                    total_test_loss.append(loss.item())

                    n_correct += self.evaluate(Y, Ypred)
                    n_total += batch_size

                test_acc = round(n_correct/n_total, 3)

            print("Train Acc : {} Test Acc : {}".format(train_acc, test_acc))

        plt.plot(total_train_loss, label='Train loss')
        plt.plot(total_test_loss , label='Test loss')
        plt.legend()
        plt.show()

if __name__ == "__main__":
    train_data, test_data = get_data()
    model = MnistRegression(train_data, test_data)
    model.train()


#! /bin/python

import os
import sys
import json

import luigi
import numpy as np
import nifty.tools as nt

import nifty
import nifty.graph.rag as nrag
from vigra.analysis import relabelConsecutive
from elf.segmentation.clustering import mala_clustering, agglomerative_clustering

import cluster_tools.utils.volume_utils as vu
import cluster_tools.utils.function_utils as fu
from cluster_tools.cluster_tasks import SlurmTask, LocalTask, LSFTask

#
# Agglomerate Tasks
#

# TODO it would be nice to be able to change the block shape compared to ws task
# so that we can agglomerate block boundaries.
# However, I am not sure how this interacts with the id-offsets, so haven't
# implemented this yet.
class AgglomerateBase(luigi.Task):
    """ Agglomerate base class
    """

    task_name = 'agglomerate'
    src_file = os.path.abspath(__file__)

    # input and output volumes
    input_path = luigi.Parameter()
    input_key = luigi.Parameter()
    output_path = luigi.Parameter()
    output_key = luigi.Parameter()
    have_ignore_label = luigi.BoolParameter()
    dependency = luigi.TaskParameter()

    def requires(self):
        return self.dependency

    @staticmethod
    def default_task_config():
        # parameter:
        # use_mala_agglomeration: whether to use thresholding based mala agglomeration
        #                         or element number based agglomerative clustering
        # threshold: threshold up to which to agglomerate (mala) or fraction of nodes
        #            after agglomeration (agglomerative clustering)
        # size_regularizer: size regularizer in agglomerative clustering (wardness)
        # invert_inputs: do we need to invert the inputs?
        # offsets: offsets for affinities, set to None for boundaries
        config = LocalTask.default_task_config()
        config.update({'use_mala_agglomeration': True, 'threshold': .9,
                       'size_regularizer': .5, 'invert_inputs': False,
                       'offsets': None})
        return config

    def clean_up_for_retry(self, block_list):
        super().clean_up_for_retry(block_list)
        # TODO remove any output of failed blocks because it might be corrupted

    def run_impl(self):
        # get the global config and init configs
        shebang, block_shape, roi_begin, roi_end = self.global_config_values()
        self.init(shebang)

        # get shape and make block config
        shape = vu.get_shape(self.input_path, self.input_key)
        if len(shape) == 4:
            shape = shape[1:]

        # load the agglomerate config
        config = self.get_task_config()

        # update the config with input and output paths and keys
        # as well as block shape
        config.update({'input_path': self.input_path, 'input_key': self.input_key,
                       'output_path': self.output_path, 'output_key': self.output_key,
                       'block_shape': block_shape, 'have_ignore_label': self.have_ignore_label})

        if self.n_retries == 0:
            block_list = vu.blocks_in_volume(shape, block_shape, roi_begin, roi_end)
        else:
            block_list = self.block_list
            self.clean_up_for_retry(block_list)

        self._write_log('scheduling %i blocks to be processed' % len(block_list))
        n_jobs = min(len(block_list), self.max_jobs)

        # prime and run the jobs
        self.prepare_jobs(n_jobs, block_list, config)
        self.submit_jobs(n_jobs)

        # wait till jobs finish and check for job success
        self.wait_for_jobs()
        self.check_jobs(n_jobs)

class AgglomerateLocal(AgglomerateBase, LocalTask):
    """
    Agglomerate on local machine
    """
    pass

class AgglomerateSlurm(AgglomerateBase, SlurmTask):
    """
    Agglomerate on slurm cluster
    """
    pass

class AgglomerateLSF(AgglomerateBase, LSFTask):
    """
    Agglomerate on lsf cluster
    """
    pass

#
# Implementation
#

def _agglomerate_block(blocking, block_id, ds_in, ds_out, config):
    fu.log("start processing block %i" % block_id)
    have_ignore_label = config['have_ignore_label']
    use_mala_agglomeration = config.get('use_mala_agglomeration', True)
    threshold = config.get('threshold', 0.9)
    size_regularizer = config.get('size_regularizer', .5)
    invert_inputs = config.get('invert_inputs', False)
    offsets = config.get('offsets', None)

    bb = vu.block_to_bb(blocking.getBlock(block_id))
    # load the segmentation / output
    seg = ds_out[bb]

    # check if this block is empty
    if np.sum(seg) == 0:
        fu.log_block_success(block_id)
        return

    # load the input data
    ndim_in = ds_in.ndim
    if ndim_in == 4:
        assert offsets is not None
        assert len(offsets) <= ds_in.shape[0]
        bb_in = (slice(0, len(offsets)),) + bb
        input_ = vu.normalize(ds_in[bb_in])
    else:
        assert offsets is None
        input_ = vu.normalize(ds_in[bb])

    if invert_inputs:
        input_ = 1. - input_

    id_offset = int(seg[seg != 0].min())

    # relabel the segmentation
    _, max_id, _ = relabelConsecutive(seg, out=seg, keep_zeros=True, start_label=1)
    seg = seg.astype('uint32')

    # construct rag
    rag = nrag.gridRag(seg, numberOfLabels=max_id + 1,
                       numberOfThreads=1)

    # extract edge features
    if offsets is None:
        edge_features = nrag.accumulateEdgeMeanAndLength(rag, input_, numberOfThreads=1)
    else:
        edge_features = nrag.accumulateAffinityStandartFeatures(rag, input_, offsets,
                                                                numberOfThreads=1)
    edge_features, edge_sizes = edge_features[:, 0], edge_features[:, -1]
    uv_ids = rag.uvIds()
    # set edges to ignore label to be maximally repulsive
    if have_ignore_label:
        ignore_mask = (uv_ids == 0).any(axis=1)
        edge_features[ignore_mask] = 1

    # build undirected graph
    n_nodes = rag.numberOfNodes
    graph = nifty.graph.undirectedGraph(n_nodes)
    graph.insertEdges(uv_ids)

    if use_mala_agglomeration:
        node_labels = mala_clustering(graph, edge_features,
                                      edge_sizes, threshold)
    else:
        node_ids, node_sizes = np.unique(seg, return_counts=True)
        if node_ids[0] != 0:
            node_sizes = np.concatenate([np.array([0]), node_sizes])
        n_stop = int(threshold * n_nodes)
        node_labels = agglomerative_clustering(graph, edge_features,
                                               node_sizes, edge_sizes,
                                               n_stop, size_regularizer)

    # run clusteting
    node_labels, max_id, _ = relabelConsecutive(node_labels, start_label=1, keep_zeros=True)

    fu.log("reduced number of labels from %i to %i" % (n_nodes, max_id + 1))

    # project node labels back to segmentation
    seg = nrag.projectScalarNodeDataToPixels(rag, node_labels, numberOfThreads=1)
    seg = seg.astype('uint64')
    # add offset back to segmentation
    seg[seg != 0] += id_offset

    ds_out[bb] = seg
    # log block success
    fu.log_block_success(block_id)

def agglomerate(job_id, config_path):
    fu.log("start processing job %i" % job_id)
    fu.log("reading config from %s" % config_path)
    with open(config_path, 'r') as f:
        config = json.load(f)

    # read the input cofig
    input_path = config['input_path']
    input_key = config['input_key']
    shape = list(vu.get_shape(input_path, input_key))
    if len(shape) == 4:
        shape = shape[1:]

    block_shape = list(config['block_shape'])
    block_list = config['block_list']

    # read the output config
    output_path = config['output_path']
    output_key = config['output_key']

    # get the blocking
    blocking = nt.blocking([0, 0, 0], shape, block_shape)

    # submit blocks
    with vu.file_reader(input_path, 'r') as f_in, vu.file_reader(output_path) as f_out:
        ds_in = f_in[input_key]
        assert ds_in.ndim in (3, 4)
        ds_out = f_out[output_key]
        assert ds_out.ndim == 3
        for block_id in block_list:
            _agglomerate_block(blocking, block_id, ds_in, ds_out, config)

    # log success
    fu.log_job_success(job_id)

if __name__ == '__main__':
    path = sys.argv[1]
    assert os.path.exists(path), path
    job_id = int(os.path.split(path)[1].split('.')[0].split('_')[-1])
    agglomerate(job_id, path)


from setuptools import setup

import dorm

with open("README.md", "r") as readme:
    long_description = readme.read()

setup(
    name="dorm",
    version=dorm.version,
    description="A tiny SQLite ORM for Python.",
    long_description=long_description,
    long_description_content_type="text/markdown",
    author="Dan Watson",
    author_email="dcwatson@gmail.com",
    url="https://github.com/dcwatson/dorm",
    license="MIT",
    py_modules=["dorm"],
    entry_points={"console_scripts": ["dorm=dorm:main"]},
    classifiers=[
        "Development Status :: 2 - Pre-Alpha",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 3",
        "Topic :: Database",
    ],
)


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

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('student', '0002_userinfo_grade'),
    ]

    operations = [
        migrations.CreateModel(
            name='Events',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('name', models.CharField(max_length=80)),
                ('date', models.DateTimeField()),
                ('cost', models.DecimalField(max_digits=6, decimal_places=2)),
            ],
        ),
        migrations.AddField(
            model_name='userinfo',
            name='balance',
            field=models.DecimalField(default=0.0, max_digits=6, decimal_places=2),
            preserve_default=False,
        ),
    ]


import pandas as pd
import networkx as nx
import json

hierarchy_df = pd.read_csv('hierarchy_table.csv', index_col=0, dtype=str)

graph_network = nx.from_pandas_edgelist(
    hierarchy_df,
    source='Parent',
    target='Child',
)

json_graph = json.dumps(graph_network, default=nx.node_link_data)

# Using a JSON string
with open('json_graph.json', 'w') as outfile:
    outfile.write(json_graph)


#!/usr/bin/python

import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate

a=0.7
b=0.6

X = np.arange(0,2.4,0.2)
Y = np.arange(0,2.4,0.2)
m,p =  np.meshgrid(X,Y)
mdot = np.divide(1,1+np.square(p))- np.multiply(b,m)
pdot = np.subtract(m,np.multiply(a,p))

fig, ax = plt.subplots()
q=ax.quiver(p,m,pdot,mdot)
ax.quiverkey(q,X=0.3,Y=2.4, U=5,
             label='Quiver key, length = 5', labelpos='E')
ax.plot(p,np.multiply(a,p))
ax.plot(p, np.divide( 1, np.multiply(b,(1+np.square(p)))))
ax.set_xlabel('p')
ax.set_ylabel('m')

def dydt_autoinhib(t,y,a,b):
    y1,y2=y
    dy1 = 1/(1+y2**2)-b*y1
    dy2 = y1-a*y2
    return (dy1,dy2)

# lambda trick so we can pass the right function into the solver
dydt_params = lambda t,y: dydt_autoinhib(t,y,a,b)

solution1 = scipy.integrate.solve_ivp(dydt_params, t_span=(0,20),y0=(2,2), method='RK45')
t1_ode45 = solution1.t
m1_ode45 = solution1.y[0]
p1_ode45 = solution1.y[1]
ax.plot(p1_ode45,m1_ode45)
plt.show()


from django import template
from django.urls import NoReverseMatch, reverse

from utilities.utils import get_viewname, prepare_cloned_fields

register = template.Library()

#
# Instance buttons
#

@register.inclusion_tag('buttons/clone.html')
def clone_button(instance):
    url = reverse(get_viewname(instance, 'add'))

    # Populate cloned field values
    param_string = prepare_cloned_fields(instance).urlencode()
    if param_string:
        url = f'{url}?{param_string}'

    return {
        'url': url,
    }

@register.inclusion_tag('buttons/edit.html')
def edit_button(instance):
    viewname = get_viewname(instance, 'edit')
    url = reverse(viewname, kwargs={'pk': instance.pk})

    return {
        'url': url,
    }

@register.inclusion_tag('buttons/delete.html')
def delete_button(instance):
    viewname = get_viewname(instance, 'delete')
    url = reverse(viewname, kwargs={'pk': instance.pk})

    return {
        'url': url,
    }

#
# List buttons
#

@register.inclusion_tag('buttons/add.html')
def add_button(model, action='add'):
    try:
        url = reverse(get_viewname(model, action))
    except NoReverseMatch:
        url = None

    return {
        'url': url,
    }

@register.inclusion_tag('buttons/import.html')
def import_button(model, action='import'):
    try:
        url = reverse(get_viewname(model, action))
    except NoReverseMatch:
        url = None

    return {
        'url': url,
    }

@register.inclusion_tag('buttons/bulk_edit.html')
def bulk_edit_button(model, action='bulk_edit', query_params=None):
    try:
        url = reverse(get_viewname(model, action))
        if query_params:
            url = f'{url}?{query_params.urlencode()}'
    except NoReverseMatch:
        url = None

    return {
        'url': url,
    }

@register.inclusion_tag('buttons/bulk_delete.html')
def bulk_delete_button(model, action='bulk_delete', query_params=None):
    try:
        url = reverse(get_viewname(model, action))
        if query_params:
            url = f'{url}?{query_params.urlencode()}'
    except NoReverseMatch:
        url = None

    return {
        'url': url,
    }


import torch
import torch.nn as nn
import torch.nn.functional as F

def normalize_l2(x):
    """
    Expects x.shape == [N, C, H, W]
    """
    norm = torch.norm(x.view(x.size(0), -1), p=2, dim=1)
    norm = norm.unsqueeze(-1).unsqueeze(-1).unsqueeze(-1)
    return x / norm

def pair_cos_dist(x, y):
    cos = nn.CosineSimilarity(dim=-1, eps=1e-6)
    c = torch.clamp(1 - cos(x, y), min=0)
    return c

class Feature_Targets(nn.Module):
    def __init__(self, epsilon, num_steps, step_size, data_min = -1.0, data_max = 1.0, grad_sign=True, random_start = True):
        super().__init__()
        self.epsilon = epsilon
        self.num_steps = num_steps
        self.step_size = step_size
        self.grad_sign = grad_sign
        self.data_min = data_min
        self.data_max = data_max
        self.random_start = random_start

    def forward(self, model, bx, by, target_bx):
        """
        :param model: the classifier's forward method
        :param bx: batch of images
        :param by: true labels
        :return: perturbed batch of images
        """
        adv_bx = bx.detach().clone()
        target = target_bx.detach().clone()
        if self.random_start:
            adv_bx += torch.zeros_like(adv_bx).uniform_(-self.epsilon, self.epsilon)
            adv_bx = adv_bx.clamp(self.data_min, self.data_max)

        target_feature, target_logits = model(target)

        for i in range(self.num_steps):
            adv_bx.requires_grad_()
            with torch.enable_grad():
                feature, logits = model(adv_bx)
                loss = pair_cos_dist(feature, target_feature).mean()
            grad = torch.autograd.grad(loss, adv_bx, only_inputs=True)[0]

            if self.grad_sign:
                adv_bx = adv_bx.detach() + self.step_size * torch.sign(grad.detach())
            else:
                grad = normalize_l2(grad.detach())
                adv_bx = adv_bx.detach() + self.step_size * grad

            adv_bx = torch.min(torch.max(adv_bx, bx - self.epsilon), bx + self.epsilon).clamp(self.data_min, self.data_max)

        return adv_bx


import json
from .db_utils import conn as db_conn
from enum import Enum

class NotificationType(Enum):
    questionEndorse = 'question_endorsed'
    answerEndorse = 'answer_endorsed'
    answerUser = 'answer_user'
    answerSaved = 'answer_saved'

NOTIFICATION_TEXT_BY_TYPE = {
    NotificationType.questionEndorse: "endorsed your question",
    NotificationType.answerEndorse: "endorsed your answer",
    NotificationType.answerUser: "answered your question",
    NotificationType.answerSaved: "answered a question you saved"
}

DATA_FIELDS_BY_TYPE = {
    NotificationType.questionEndorse: set(['question_id']),
    NotificationType.answerEndorse: set(['question_id', 'answer_id']),
    NotificationType.answerUser: set(['question_id', 'answer_id']),
    NotificationType.answerSaved: set(['question_id', 'answer_id'])
}

def push_notification(user_id, notif_type, data):
    cur = db_conn.cursor()
    if set(data.keys()) != DATA_FIELDS_BY_TYPE[notif_type]:
        raise ArgumentError("Invalid data fields for notification type {}; expected {}".format(data.keys(), DATA_FIELDS_BY_TYPE[notif_type]))
    cur.execute("INSERT INTO notifications (user_id, type, data) VALUES (%s, %s, %s)", (user_id, notif_type.value, json.dumps(data)))


#!/usr/bin/python2.4

import base64
import hmac

from google.appengine.api import urlfetch
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

import hashlib

class PlacesHandler(webapp.RequestHandler):
  """Handles requests to /places."""

  def post(self):
    """Handles posts."""
    self.response.headers['Content-Type'] = 'application/json'
    action = self.request.get('action')

    CLIENT_ID = None
    PRIVATE_KEY = None

    # These are required to work
    if not CLIENT_ID and not PRIVATE_KEY:
      self.response.out.write('{}')
      return

    places_url = None

    if action == 'search':
      location = self.request.get('location')
      radius = self.request.get('radius')

      url_to_sign = ('/maps/api/place/search/json?location=%s&radius=%s&client='
                     '%s&sensor=true') % (location, radius, CLIENT_ID)

      decoded_key = base64.urlsafe_b64decode(PRIVATE_KEY)
      signature = hmac.new(decoded_key, url_to_sign, hashlib.sha1)
      encoded_signature = base64.urlsafe_b64encode(signature.digest())

      places_url = ('http://maps.google.com/maps/api/place/search/json?'
                    'location=%s&radius=%s&client=%s&sensor=true&'
                    'signature=%s') % (location, radius, CLIENT_ID,
                                       encoded_signature)

    if places_url:
      self.response.out.write(urlfetch.fetch(places_url).content)

if __name__ == '__main__':
  application = webapp.WSGIApplication([('/places[/]?', PlacesHandler)],
                                       debug=True)
  run_wsgi_app(application)


import csv
import getopt, sys
from moviepy.editor import VideoFileClip, concatenate_videoclips

folder = '/Videos/'
# file name of the video and config file
event = '20221002 PREECNLBVA'

output_file = None # Create a file for each segment
#output_file = 'check' # Compile the clips with a check flag
output_file = 'highlight' # Compile the clips with a highligh flag
#output_file = '20221002 EYF Segments.mp4' # compile all segments in the config file

# --input
mp4_file = folder + '/' + event + '.mp4'
    # --config
config_file = folder + '/' + event + '.csv'
# --output

def return_filename(desc, prefix, suffix):
    return str(prefix or '') + str(desc or '') + str(suffix or '') + '.mp4'

def main():
    global folder
    global event
    global output_file
    global mp4_file
    global config_file

    argumentList = sys.argv[1:]

    options = "i:c:o:"

    long_options = ["input=","config=","output="]

    try:
        arguments, values = getopt.getopt(argumentList, options, long_options)
        for currentArgument, currentValue in arguments:
            if currentArgument in ("-i", "--input"):
                mp4_file = currentValue
                # print ("File: ", currentValue)
            if currentArgument in ("-o", "--output"):
                output_file = currentValue
            if currentArgument in ("-c", "--config"):
                config_file = currentValue
                # print ("Config: ", currentValue)
    except getopt.error as err:
        print (str(err))

    if mp4_file is None:
        # If mp4 file is not provided, use config file name
        mp4_file = config_file.replace(".csv", ".mp4")

    # Read the config file
    rows = csv.DictReader(open(config_file))

    first = True
    for row in rows:
        if row['source'] == 'video':
            min = int(row['min'])
            sec = int(row['sec'])

            if min > 0:
                start_seconds = min * 60 + sec
            else:
                start_seconds = sec
            length_in_sec = int(row['length_in_sec'])
            end_seconds = start_seconds + length_in_sec
            if start_seconds and end_seconds:
                if output_file is None:
                    # MODE = Split the segments into separate files
                    clip = VideoFileClip(mp4_file).subclip(start_seconds, end_seconds)
                    file_name = return_filename(row['desc'], row['filename_prefix'], row['filename_suffix'])
                    clip.write_videofile(file_name)
                else:
                    # MODE = Concatenate the segments into a single file
                    if (output_file == 'check' and row['filename_suffix'] == 'check') or \
                        (output_file == 'highlight' and row['filename_suffix'] == 'highlight') or \
                            (output_file != 'check' and output_file != 'highlight'):
                        # Save only if check or highlight or if all clips
                        if first:
                            final_clip = VideoFileClip(mp4_file).subclip(start_seconds, end_seconds)
                            first = False
                        else:
                            clip = VideoFileClip(mp4_file).subclip(start_seconds, end_seconds)
                            final_clip = concatenate_videoclips([final_clip,clip])
            else:
                print(f'Error with config settings for: {row}')

    if output_file:
        # Save the final clip
        if output_file == 'check':
            output_file = event + ' check.mp4'
        elif output_file == 'highlight':
            output_file = event + ' highlight.mp4'
        final_clip.write_videofile(output_file)

if __name__ == "__main__":
    main()


"""
This question is asked by Apple. Given two binary strings
(strings containing only 1s and 0s) return their sum (also as a binary string).
Note: neither binary string will contain leading 0s unless the string itself is 0

Ex: Given the following binary strings...

"100" + "1", return "101"
"11" + "1", return "100"
"1" + "0", return  "1"
"""
from collections import deque

def addBinary(number1:str, number2: str) -> str:
  # Time: O(n) -> where "n" is the number of bits of the final sum
  # Space: O(n) or O(1) if we don't consider the output

  n1Pointer = len(number1)-1
  n2Pointer = len(number2)-1

  output = deque()
  carry = 0

  while n1Pointer >= 0 or n2Pointer >= 0:
    n1Digit = 0 if n1Pointer < 0 else int(number1[n1Pointer])
    n2Digit = 0 if n2Pointer < 0 else int(number2[n2Pointer])

    currDigitSum = n1Digit + n2Digit + carry
    carry = 1 if currDigitSum >= 2 else 0

    if currDigitSum == 2:
      currDigitSum = 0
    elif currDigitSum == 3:
      currDigitSum = 1

    output.appendleft(str(currDigitSum)) # O(1)
    n1Pointer -= 1
    n2Pointer -= 1

  if carry:
    output.appendleft(str(carry)) # O(1)

  return "".join(output) # O(n)

assert addBinary("100", "1") == "101"
assert addBinary("11", "1") == "100"
assert addBinary("1", "0") == "1"

print("Passed all testes!")


import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
from scipy.optimize import minimize
from sklearn.metrics import mean_squared_error as mse

def SIR():

    def prediction(beta, gamma, population, i0, r0, d0, time_predict):
        def SIR_model(y, t, beta, gamma, population):
            s, i, r = y
            dSdt = -beta * s * i / population
            dIdt = beta * s * i / population - gamma * i
            dRdt = gamma * i
            return [dSdt, dIdt, dRdt]

        s0 = population - i0 - r0 - d0
        y_0 = [s0, i0, r0]
        sol = odeint(SIR_model, y_0, time_predict, args=(beta, gamma, population))
        sol = np.transpose(sol)
        return sol

    def error_model(point, cases, population, infected_0, recovered_0, dead_0):
        beta, gamma = point

        def SIR_model(y, t, beta, gamma, population):
            s, i, r = y
            dSdt = -beta * s * i / population
            dIdt = beta * s * i / population - gamma * i
            dRdt = gamma * i
            return [dSdt, dIdt, dRdt]

        suscepted_0 = population - infected_0 - recovered_0 - dead_0
        y0 = [suscepted_0, infected_0, recovered_0]
        sol = odeint(SIR_model, y0, np.arange(1, len(cases) + 1), args=(beta, gamma, population))
        sol = np.transpose(sol)
        error = mse(cases, sol[1])
        return error

    def trainer(cases, population, infected_0, recovered_0, dead_0):
        optimal = minimize(error_model, np.array([0.001, 0.001]), args=(cases, population, infected_0, recovered_0, dead_0),
                           method='L-BFGS-B', bounds=[(0.000001, 1.0), (0.000001, 1.0)])
        beta, gamma = optimal.x
        return beta, gamma

    def plot(s, i, r, initials_state, city_name, period_predict, time_predict, population):
        plt.figure()
        plt.title('Projeção do total de habitantes sucetíveis, infectados e recuperados em ' + city_name + '/' +
                  initials_state[0], fontsize=20)
        plt.xlabel('Meses', fontsize=15)
        plt.xticks(np.linspace(15, period_predict + 15, 7)[:-1], ('Abril', 'Maio', 'Junho', 'Julo', 'Agosto', 'Setembro'))
        plt.ylabel('Número de habitantes', fontsize=15)
        plt.yticks(np.arange(0, population, step=population * 0.03))
        plt.plot(time_predict, s, label='Sucetíveis')
        plt.plot(time_predict, i, label='Infectados')
        plt.plot(time_predict, r, label='Recuperados')
        plt.legend(loc='center left', bbox_to_anchor=(1.002, 0.7), fontsize=14)
        plt.rcParams["figure.figsize"] = (20, 10)
        plt.show()


import numpy as np
import matplotlib.pyplot as plt
from scipy import fftpack, signal

# 고주파 성분만 날리는 fft
# def get_filtered_data(in_data, filter_value=0.004):
def del_high_freq(in_data, filter_value=0.004):
    """
    :param in_data: 대상 시계열 신호
    :param filter_value: filter_value이상의 주파수를 가지는 신호를 날림
    :return: fft 결과
    """
    sig_fft = fftpack.fft(in_data)
    sample_freq = fftpack.fftfreq(in_data.size)
    high_freq_fft = sig_fft.copy()

    high_freq_fft[np.abs(sample_freq) > filter_value] = 0
    filtered_data = fftpack.ifft(high_freq_fft)

    return filtered_data

# 고주파, 저주파 성분을 날리는 fft
def del_high_and_low_freq(in_data, high_filter_value, low_filter_value):
    """
    :param in_data: 대상 시계열 신호
    :param high_filter_value: fft를 수행할 최대값, low_filter_value ~ high_filter_value값 사이의 신호를 fft
    :param low_filter_value: fft를 수행할 최소값
    :return: fft 결과
    """
    sig_fft = fftpack.fft(in_data)
    sample_freq = fftpack.fftfreq(in_data.size)
    high_freq_fft = sig_fft.copy()

    low_value1 = np.max(high_freq_fft)
    high_freq_fft[np.abs(sample_freq) > high_filter_value] = 0
    high_freq_fft[np.abs(sample_freq) < low_filter_value] = 0

    low_value2 = np.max(high_freq_fft)
    filtered_data = fftpack.ifft(high_freq_fft)

    return filtered_data, low_value1, low_value2

def fft(pupil_list, minu=None, quar=None):
    global section_frames, time

    # 데이터에서 0, -1인 부분 제거
    while 0 in pupil_list:
        pupil_list.remove(0)
    while -1 in pupil_list:
        pupil_list.remove(-1)

    if minu is not None:
        time = minu * 1800
        section_frames = len(pupil_list) // time

    if quar is not None:
        time = len(pupil_list) // quar
        section_frames = quar

    y = np.array(pupil_list)

    # fft
    # filtered_sig = del_high_freq(y, filter_value=0.005)  # 고주파 필터링
    filtered_sig, _, _ = del_high_and_low_freq(y, 0.0048, 0.0035)  # 저주파, 고주파 필터링
    filtered_sig = filtered_sig.astype(np.float)

    # zero-crossing point
    zero_crossings = np.where(np.diff(np.sign(np.diff(filtered_sig))))[0]
    zero_crossings = np.insert(zero_crossings, 0, 0)
    zero_crossings = np.append(zero_crossings, len(filtered_sig) - 1)

    # 변화 속도 계산
    change_rates_list = [[] for _ in range(section_frames)]
    for section in range(section_frames):
        # zero-crossing points 기준으로 원하는 위치(섹션) 가져오기
        section_zero_crossing = zero_crossings[np.where(zero_crossings <= (section + 1) * time)]
        section_zero_crossing = section_zero_crossing[np.where(section * time < section_zero_crossing)]
        # 변화 속도 계산
        for j in range(len(section_zero_crossing) - 1):
            change_rate = abs((filtered_sig[section_zero_crossing[j + 1]] - filtered_sig[section_zero_crossing[j]]) / (
                        section_zero_crossing[j + 1] - section_zero_crossing[j]))
            change_rates_list[section].append(change_rate)

    return filtered_sig, zero_crossings, section_frames, change_rates_list

# fft를 수행한 결과 그래프 그리기
def draw_fft_graph(y, filtered_sig, zero_crossings, section_frames, savepath, minu=None, quar=None):
    global time
    x = np.arange(0, len(y))
    if minu is not None:
        time = minu * 1800
        section_frames = len(y) // time

    if quar is not None:
        time = len(y) // quar
        section_frames = quar

    fig = plt.figure(dpi=150)

    # plt.figure(figsize=(6, 5))
    plt.rcParams["font.family"] = 'Malgun Gothic'
    plt.figure(figsize=(14, 6))
    plt.plot(x, y, label='Original signal')
    plt.plot(x, filtered_sig, linewidth=2, label='Filtered signal')
    # plt.plot(zero_crossings, filtered_sig[zero_crossings], marker='o', color='red', linestyle='--')
    plt.legend(loc='upper right')

    # 섹션 나눠진거 표시
    for section in range(section_frames):
        plt.axvline(x=section * time, ymin=0, ymax=1.0, color='r')
        plt.axvline(x=(section + 1) * time, ymin=0, ymax=1.0, color='r')

    # plt.xlim(0, 1800)
    plt.title('동공크기 변화율')
    plt.xlabel('Frame')
    plt.ylabel('Pupil size')
    plt.savefig(f'{savepath}')
    plt.show()

# 2차식 추세선 그리기, 히스토그램 그래프 저장
def draw_trendline_fft(data, title, y_lim, y_label, savepath, quar = None, avg = False):
    results = {}

    # 추세선
    x = np.arange(0, len(data))
    y = []
    for idx, value in enumerate(data):
        y.append(value)
    y = np.array(y)  # 10개 구간에 해당하는 특징(깜빡임 횟수)

    fit = np.polyfit(x, y, 2)
    a = fit[0]
    b = fit[1]
    c = fit[2]
    fit_equation = a * np.square(x) + b * x + c
    results['coeffs'] = fit.tolist()

    # r-squared
    p = np.poly1d(fit)

    # fit values, and mean
    yhat = p(x)
    ybar = np.sum(y) / len(y)
    ssreg = np.sum((yhat - ybar) ** 2)
    sstot = np.sum((y - ybar) ** 2)
    results['r-squared'] = ssreg / sstot
    r_squared = str(round(results['r-squared'], 3))  # 출력하기 위해 문자열로 변환
    a = str(round(results['coeffs'][0], 3))
    b = str(round(results['coeffs'][1], 3))
    c = str(round(results['coeffs'][2], 3))
    # print("R 제곱값: ", round(results['r-squared'], 3))
    # print("추세선: "+"Y="+a+"xX^2 + "+b+"xX + "+c)

    period = ['0~3분', '3~6분', '6~9분', '9~12분', '12~15분', '15~18분', '18~21분', '21~24분', '24~27분', '27~30분', '30~33분']
    plt.rcParams["font.family"] = 'Malgun Gothic'

    fig = plt.figure(dpi=150)
    ax = fig.add_subplot(1, 1, 1)

    for idx2, value2 in enumerate(data):
        ax.bar(period[idx2], value2, color='b', alpha=0.5)
    ax.plot(x, fit_equation, color='r', alpha=0.5, label='Polynomial fit', linewidth=3.0)
    # ax.scatter(x, y, s = 5, color = 'b', label = 'Data points')  # 추세선 예측에 사용한 좌표 그리기

    # Plotting
    plt.xticks(rotation=20)
    plt.title(f'{title}')
    plt.ylim(0, y_lim)
    plt.xlabel('구간')
    plt.ylabel(f'{y_label}')

    # 동공 크기 변화율 출력할 때 위치 조정
    if not avg:
        plt.text(3.2, 0.055, "추세선: " + r'$y = $' + a + r'$x^2 + ($' + b + r'$)x + $' + c, fontdict={'size': 12})
        plt.text(7.5, 0.05, r'$R^2 =$' + r_squared, fontdict={'size': 12})

    # 평균 동공크기 변화율 출력할 때 위치 조정
    else:
        plt.text(3.2, 0.027, "추세선: " + r'$y = $' + a + r'$x^2 + ($' + b + r'$)x + $' + c, fontdict={'size': 12})
        plt.text(7.5, 0.025, r'$R^2 =$' + r_squared, fontdict={'size': 12})

    plt.tight_layout()
    fig.canvas.draw()
    img = np.array(fig.canvas.renderer._renderer)
    spl = title.split('.')[0]
    plt.savefig(f'{savepath}')
    plt.imshow(img)
    plt.show()  # 그래프 잘 나오는지 띄우기


import re
#import CMUTweetTagger
#import cPickle
from collections import defaultdict
import pickle
from nltk.corpus import wordnet as wn
from itertools import product
import spacy
from spacy.symbols import *
from nltk import Tree
import nltk

nlp=spacy.load('en')
np_labels=set(['nsubj','dobj','pobj','iobj','conj','nsubjpass','appos','nmod','poss','parataxis','advmod','advcl'])
subj_labels=set(['nsubj','nsubjpass'])
need_verb_list=['need','require','want','lack']
send_verb_list=['send','give','donate','transfer','distribute','aid','help','procure']
common_resource=['food','water','medicine','tent','clothes','communication','transport','infrastructure','shelter','internet','sanitation','hospital','donations']
modifiers=['nummod','compound','amod','punct']
after_clause_modifier=['relcl','acl','ccomp','xcomp','acomp','punct']#,'nn','quantmod','nmod','hmod','infmod']
verb_count={}
resource_array=[]
modified_array=[]
# nepal_stop_list=['nepal','earthquake','quake','nepalese']
nepal_stop_list=[]
tel_no="([+]?[0]?[1-9][0-9\s]*[-]?[0-9\s]+)"
email="([a-zA-Z0-9]?[a-zA-Z0-9_.]+[@][a-zA-Z]*[.](com|net|edu|in|org|en))"
web_url="http:[a-zA-Z._0-9/]+[a-zA-Z0-9]"
entity_type_list=['NORP','ORG','GPE','PERSON']
quant_no="([0-9]*[,.]?[0-9]+[k]?)"

need_send_verb_list=['need','require','want','lack','send','give','donate','transfer','distribute','aid','help','support','procure']
# def quant_no(resource):
# 	return [i for re.findall(quant_no,resource)]

def modifier_word(word):
	modified_word=word.orth_
	while word.n_lefts+word.n_rights==1 and word.dep_.lower() in modifiers:
		word=[child for child in word.children][0]
		modified_word=word.orth_+" "+modified_word
	return modified_word

def tok_format(tok):
	return "_".join([tok.orth_, tok.dep_,tok.ent_type_])

def to_nltk_tree(node):
	if node.n_lefts + node.n_rights > 0:
		return Tree(tok_format(node), [to_nltk_tree(child) for child in node.children])
	else:
		return tok_format(node)

def get_children(word,resource_array,modified_array):
	#print(word,word.dep_)
	for child in word.children:
		if child.dep_.lower() in modifiers:
			get_word=modifier_word(child)+" "+word.orth_+"<_>"+word.dep_
			modified_array.append(get_word)
		if child.dep_.lower()=='prep' or child.dep_.lower()=='punct':
			get_children(child,resource_array,modified_array)
		if child.dep_.lower() in after_clause_modifier:
			#print(child, child.dep_)
			get_children(child,resource_array,modified_array)
		if child.dep_.lower() in np_labels:
			get_children(child,resource_array,modified_array)
			resource_array.append(child.orth_+"<_>"+child.dep_)
		else:
			if get_verb_similarity_score(child.orth_,common_resource)>0.7 :
				get_children(child,resource_array,modified_array)

def get_verb_similarity_score(word,given_list):
	max_verb_similarity=0
	if word.lower() in given_list:
		max_verb_similarity=1
	else:
		current_verb_list=wn.synsets(word.lower())
		for verb in given_list:
			related_verbs=wn.synsets(verb)
			for a,b in product(related_verbs,current_verb_list):
				d=wn.wup_similarity(a,b)
				try:
					if d> max_verb_similarity:
						max_verb_similarity=d
				except:
					continue
	return max_verb_similarity

def resource_in_list(resource):
	related_resources=wn.synsets(resource)
	max_similarity=0
	chosen_word=""
	if resource.lower() in common_resource:
		return 1,resource
	for word in common_resource:
		related_words=wn.synsets(word)
		#print(word,related_words)
		for a,b in product(related_words,related_resources):
			d=wn.wup_similarity(a,b)
			try:
				if d> max_similarity:
					max_similarity=d
					chosen_word=word
			except:
				continue
	return max_similarity,chosen_word

def get_resource(text):
	doc=nlp(text)
	# try:
	# 	[to_nltk_tree(sent.root).pretty_print() for sent in doc.sents]
	# except:
	# 	print("Exception here")
	org_list=[]
	prev_word=""
	prev_word_type=""
	for word in doc:
		if word.ent_type_ in entity_type_list:
			org_list.append(word.orth_+"<_>"+word.ent_type_)
		else:
			org_list.append("<_>")

	resource_array=[]
	modified_array=[]
	for word in doc:
		if  get_verb_similarity_score(word.orth_,need_send_verb_list)>0.8 or word.dep_=='ROOT':
			get_children(word,resource_array,modified_array)

		if word.dep_=='cc' and word.n_lefts+word.n_rights==0:
			ancestor=word.head.orth_
			#print(ancestor)
			if get_verb_similarity_score(ancestor,common_resource)>0.6:
				get_children(word.head,resource_array,modified_array)

	#print(resource_array)
	#print(modified_array)
	last_word=[]
	# for resource in modified_array:
	# 	print(resource)
	# 	print(resource, resource_in_list(resource.lower()))
	# for word in modified_array:
	# 	last_word.append(word.split(' ')[-1])

	final_resource={}
	modified_array_2=[]
	resource_array_2=[]
	n_subj_list=[]

	for i in modified_array:
		modified_array_2.append(i[:(i.index("<_>"))])

	for i in resource_array:
		resource_array_2.append(i[:(i.index("<_>"))])

	for resources in modified_array_2:
		max_val_resource=0
		val_type=""
		resource_list=resources.rstrip().split(" ")
		for resource in resource_list:
			pres_res_val,pres_res_type=resource_in_list(resource)
			if pres_res_val> max_val_resource:
				val_type=pres_res_type
				max_val_resource=pres_res_val
		if max_val_resource > 0.6:
			final_resource[resources]=val_type

	for resource in resource_array_2:
		#print(resource)
		pres_res_val,pres_res_type=resource_in_list(resource)
		if pres_res_val> 0.6:
			if resource not in final_resource:
				final_resource[resource]=pres_res_type

	final_resource_keys=list(final_resource.keys())

	prev_word_type=""
	prev_word=""
	org_list_2=[]
	poss_places=[]
	for i in org_list:
		index=i.index("<_>")
		if i[index+3:]=='GPE' and i[:index] in final_resource_keys:

			#final_resource_keys.remove(i[:index])
			poss_places.append(i[:index])

		if i[index+3:]=="ORG" and prev_word_type=="ORG":
			prev_word=prev_word+" "+i[:index]
		elif i[index+3:]=="PERSON" and prev_word_type=="PERSON":
			prev_word=prev_word+" "+i[:index]

		else:
			if prev_word !='':
				org_list_2.append(prev_word+"<_>"+prev_word_type)
			prev_word_type=i[index+3:]
			prev_word=i[:index]

	quantity_dict={}
	for i in final_resource:
		for j in re.findall(quant_no,i):
			quantity_dict[i]=j

	source_list=[]
	org_person_list=[]

	for i in org_list_2:
		tag=i[i.index("<_>")+3:]
		j=i[:i.index("<_>")]

		if tag=="ORG" or tag=="PERSON":
			if j.lower() not in nepal_stop_list:
				org_person_list.append(j)
		elif j.lower() not in nepal_stop_list and j not in quantity_dict.keys():
			source_list.append(j)
		else:
			continue

	for i in modified_array:
		pos_res=i[:i.index("<_>")]
		pos_tag=i[i.index("<_>")+3:]
		if pos_tag in subj_labels:
			if pos_res not in source_list and pos_res not in final_resource_keys and pos_res.lower() not in  nepal_stop_list:
				#print(pos_tag,pos_res)
				source_list.append(pos_res)

	for i in resource_array:
		pos_res=i[:i.index("<_>")]
		pos_tag=i[i.index("<_>")+3:]
		if pos_tag in subj_labels:
			if pos_res not in source_list and pos_res not in final_resource_keys and pos_res.lower() not in  nepal_stop_list:
				#print(pos_tag,pos_res)
				source_list.append(pos_res)

	return quantity_dict,final_resource_keys,source_list,poss_places,org_person_list

def get_contact(text):
	numbers=re.findall(tel_no,text)
	print("Contact Information")
	for i in numbers:
		if len(i)>=7:
			print(i)
			#test_file.write(str(i)+",")

	#test_file.write('\nMail:')
	mails= re.findall(email,text)
	for i in mails:
		print("Mail: "+i)
		#test_file.write(str(i)+",")


import psycopg2

DBNAME = "news"

def fetch_all(query, params):
    """
    execute a query and fetch all result from it
    :param query: the query to execute
    :param params: parameters of the query
    :return: result of this query
    """
    # it's kind time consuming every time we open and close a connection
    db = psycopg2.connect(database=DBNAME)
    c = db.cursor()
    c.execute(query, params)
    ret = c.fetchall()
    db.close()
    return ret

def article_views(cnt=None):
    """
    statistics about article views, article is consider a view if exists
    a http request for the article path with GET method and 200 status code
    :param cnt: int, optional
        max number of articles
    :return:
        list of (article name, view_cnt) pair ordered by views in desc order
    """
    query = """
    select title, view_cnt
    from articles, view_stat
    where concat('/article/', slug) = path
    order by view_cnt desc
    """
    if cnt is not None:
        query += "limit (%s)"
        params = (cnt,)
    else:
        params = ()
    return fetch_all(query, params)

def author_views(cnt=None):
    """
    statistics about author's all articles views
    :param cnt: int, optional
        max number of authors
    :return:
        list of (author name, view_cnt) pair ordered by views in desc order
    """
    query = """
    select name, sum(view_cnt) as view_cnt
    from articles, view_stat, authors
    where concat('/article/', slug) = path
      and articles.author = authors.id
    group by authors.id
    order by view_cnt desc
    """
    if cnt is not None:
        query += "limit (%s)"
        params = (cnt,)
    else:
        params = ()
    return fetch_all(query, params)

def error_stat(threshold):
    """
    error rate stat by day, error rate is defined as total number of failed
    requests(status is not 200) divided by the total number of requests a day.
    if a day don't have any requests it will be ignored
    :param threshold: double
        error rate bigger or equal threshold will be returned
    :return: list of (date, error rate)
    """
    query = """
    select date(time) as stat_date,
        sum(cast(status != '200 OK' as integer))
        / cast(count(*) as real) as error_rate
    from log
    group by stat_date
    having
        sum(cast(status != '200 OK' as integer))
        / cast(count(*) as real) >= (%s);
    """
    return fetch_all(query, (threshold,))


import cv2

#Reading Image
img = cv2.imread('img46_gray_noise.png')

#Aplying filter
median = cv2.medianBlur(img,3)

#Showing image
cv2.imshow("Noised Image", img)
cv2.imshow("median", median)
cv2.waitKey()
cv2.destroyAllWindows()

#Save result
cv2.imwrite("denoised_image.png", median)


import sqlite3

with open("C:\\Users\Asmaa Samir\Desktop\Project\data.txt", "w") as myFile:
    my_tuple1 = ('google.com ', '198.188.3.2 ', '255.255.255.0', '11:01 ')
    my_tuple2 = ('youtube.com', '199.588.35.22', '255.255.255.0', '1:01')
    my_tuple3 = ('google.com', '198.155.66.1', '255.255.255.0', '7:55')

    myFile.writelines(my_tuple1)
    myFile.writelines(my_tuple2)
    myFile.writelines(my_tuple3)

db = sqlite3.connect("data.db")  # create database and connect
cr = db.cursor()  # تفعيل

# noinspection SqlNoDataSourceInspection
cr.execute("CREATE TABLE  Analysis (User Name text, IP , MAC ,URLs being visited ,TIME) ")

cr.execute("insert into Analysis values(?, ?, ?, ?, ?)", my_tuple1)  # insert data

cr.execute("insert into skills values(?, ?, ?, ?, ?)", my_tuple2)

cr.execute("insert into skills values(?, ?, ?, ? , ?)", my_tuple3)

db.commit()  # save
db.close()  # close


import pika, json

def upload(f, fs, channel, access):
	# put file into mongodb database
	try:
		# get file if success
		fid = fs.put(f)
	except Exception as err:
		return "internal server error", 500

	# create message
	message = {
		"video_fid": str(fid),
		"mp3_fid": None,
		# who owns the file
		"username": access["username"],
	}
	# put message in queue
	try:
		channel.basic_publish(
			exchange="",
			routing_key="video",
			# convert python object to json string
			body=json.dumps(message),
			properties=pika.BasicProperties(
				# make messages persistent
				delivery_mode=pika.PERSISTENT_DELIVERY_MODE
			),
		)
	# if message unsuccesfully added to the queue
	except:
		# delete file, because it's not connected to any message
		fs.delete(fid)
		return "internal server error", 500


from __future__ import annotations

import dataclasses
import typing

from randovania.game_description.db.resource_node import ResourceNode
from randovania.game_description.requirements.requirement_and import RequirementAnd
from randovania.game_description.requirements.resource_requirement import ResourceRequirement
from randovania.game_description.resources.node_resource_info import NodeResourceInfo

if typing.TYPE_CHECKING:
    from randovania.game_description.db.node import Node, NodeContext
    from randovania.game_description.requirements.base import Requirement
    from randovania.game_description.resources.resource_info import ResourceGain

def _all_nodes_in_network(context: NodeContext, network_name: str) -> typing.Iterator[TeleporterNetworkNode]:
    for node in context.node_provider.iterate_nodes():
        if isinstance(node, TeleporterNetworkNode) and node.network == network_name:
            yield node

@dataclasses.dataclass(frozen=True, slots=True)
class TeleporterNetworkNode(ResourceNode):
    """
    Represents a node that belongs to a set, where you can freely move between if some conditions are satisfied.
    - can only teleport *to* if `is_unlocked` is satisfied
    - can only teleport *from* if the node has been activated

    A TeleporterNetworkNode being activated is implemented as being collected, with this class being a ResourceNode.
    There are three methods of activating a TeleporterNetworkNode:

    Method 1:
    - Be the starting node

    Method 2:
    - Collecting a TeleporterNetworkNode also collects all other nodes in the same network with satisfied `is_unlocked`

    Method 3:
    - Collect the node normally by reaching it, with `is_unlocked` satisfied and one of:
      - `requirement_to_activate` is satisfied
      - this node was already collected
    """

    is_unlocked: Requirement
    network: str
    requirement_to_activate: Requirement

    def requirement_to_leave(self, context: NodeContext) -> Requirement:
        return RequirementAnd([self.is_unlocked, ResourceRequirement.simple(self.resource(context))])

    def resource(self, context: NodeContext) -> NodeResourceInfo:
        return NodeResourceInfo.from_node(self, context)

    def can_collect(self, context: NodeContext) -> bool:
        resources = context.current_resources
        req = self.requirement_to_activate

        if resources.has_resource(self.resource(context)) or req.satisfied(resources, 0, context.database):
            return not self.is_collected(context)
        else:
            return False

    def is_collected(self, context: NodeContext) -> bool:
        current_resources = context.current_resources
        return all(
            context.has_resource(node.resource(context))
            for node in _all_nodes_in_network(context, self.network)
            if node.is_unlocked.satisfied(current_resources, 0, context.database)
        )

    def resource_gain_on_collect(self, context: NodeContext) -> ResourceGain:
        for node in _all_nodes_in_network(context, self.network):
            if node.is_unlocked.satisfied(context.current_resources, 0, context.database):
                yield node.resource(context), 1

    def connections_from(self, context: NodeContext) -> typing.Iterator[tuple[Node, Requirement]]:
        for node in _all_nodes_in_network(context, self.network):
            if node != self:
                yield node, node.is_unlocked


""" VirtualMachineHandler provides remote access to VirtualMachineDB

    The following methods are available in the Service interface:

    - insertInstance
    - declareInstanceSubmitted
    - declareInstanceRunning
    - instanceIDHeartBeat
    - declareInstanceHalting
    - getInstancesByStatus
    - declareInstancesStopping
    - getUniqueID( instanceID ) return cloud manager uniqueID form VMDIRAC instanceID

"""

from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import os
from subprocess import Popen, PIPE
import six

# DIRAC
from DIRAC import gLogger, S_ERROR, S_OK
from DIRAC.Core.DISET.RequestHandler import RequestHandler
from DIRAC.Core.Utilities.ThreadScheduler import gThreadScheduler
from DIRAC.ConfigurationSystem.Client.Helpers.Operations import Operations

# VMDIRAC
from VMDIRAC.WorkloadManagementSystem.DB.VirtualMachineDB import VirtualMachineDB
from VMDIRAC.Security import VmProperties
from VMDIRAC.Resources.Cloud.Utilities import STATE_MAP
from VMDIRAC.Resources.Cloud.ConfigHelper import getVMTypeConfig, getVMTypes
from VMDIRAC.Resources.Cloud.EndpointFactory import EndpointFactory
from VMDIRAC.WorkloadManagementSystem.Utilities.Utils import getProxyFileForCE

__RCSID__ = '$Id$'

# This is a global instance of the VirtualMachineDB class
gVirtualMachineDB = False

def initializeVirtualMachineManagerHandler(_serviceInfo):

  global gVirtualMachineDB

  gVirtualMachineDB = VirtualMachineDB()
  haltStalledInstances()
  checkStalledInstances()

  if gVirtualMachineDB._connected:
    gThreadScheduler.addPeriodicTask(60 * 15, checkStalledInstances)
    return S_OK()

  return S_ERROR()

def haltStalledInstances():

  result = gVirtualMachineDB.getInstancesByStatus('Stalled')
  if not result['OK']:
    return result

  uList = []
  for image in result['Value']:
    uList += result['Value'][image]

  stallingList = []
  for uID in uList:
    result = gVirtualMachineDB.getInstanceID(uID)
    if not result['OK']:
      continue
    stallingList.append(result['Value'])
  return haltInstances(stallingList)

def getCEInstances(siteList=None, ceList=None, vo=None):

  result = getVMTypes(siteList=siteList, ceList=ceList, vo=vo)
  if not result['OK']:
    return S_ERROR('Failed to get images from the CS')
  imageDict = result['Value']
  ceList = []
  for site in imageDict:
    for ce in imageDict[site]:
      result = EndpointFactory().getCE(site, ce)
      if not result['OK']:
        continue
      ceList.append((site, ce, result['Value']))

  nodeDict = {}
  for site, ceName, ce in ceList:
    result = ce.getVMNodes()
    if not result['OK']:
      continue
    for node in result['Value']:
      if not node.name.startswith('DIRAC'):
        continue
      ip = (node.public_ips[0] if node.public_ips else 'None')
      nodeState = node.state.upper() if not isinstance(node.state, six.integer_types) else STATE_MAP[node.state]
      nodeDict[node.id] = {"Site": site,
                           "CEName": ceName,
                           "NodeName": node.name,
                           "PublicIP": ip,
                           "State": nodeState}
  return S_OK(nodeDict)

def checkStalledInstances():
  """
   To avoid stalling instances consuming resources at cloud endpoint,
   attempts to halt the stalled list in the cloud endpoint
  """

  result = gVirtualMachineDB.declareStalledInstances()
  if not result['OK']:
    return result

  stallingList = result['Value']

  return haltInstances(stallingList)

def stopInstance(site, endpoint, nodeID):

  result = getVMTypeConfig(site, endpoint)
  if not result['OK']:
    return result
  ceParams = result['Value']
  ceFactory = EndpointFactory()
  result = ceFactory.getCEObject(parameters=ceParams)
  if not result['OK']:
    return result

  ce = result['Value']
  result = ce.stopVM(nodeID)
  return result

def createEndpoint(uniqueID):

  result = gVirtualMachineDB.getEndpointFromInstance(uniqueID)
  if not result['OK']:
    return result
  site, endpoint = result['Value'].split('::')

  result = getVMTypeConfig(site, endpoint)
  if not result['OK']:
    return result
  ceParams = result['Value']
  ceFactory = EndpointFactory()
  result = ceFactory.getCEObject(parameters=ceParams)
  return result

def haltInstances(vmList):
  """
   Common haltInstances for Running(from class VirtualMachineManagerHandler) and
   Stalled(from checkStalledInstances periodic task) to Halt
  """

  failed = {}
  successful = {}

  for instanceID in vmList:
    instanceID = int(instanceID)
    result = gVirtualMachineDB.getUniqueID(instanceID)
    if not result['OK']:
      gLogger.error('haltInstances: on getUniqueID call: %s' % result['Message'])
      continue
    uniqueID = result['Value']

    result = createEndpoint(uniqueID)
    if not result['OK']:
      gLogger.error('haltInstances: on createEndpoint call: %s' % result['Message'])
      continue

    endpoint = result['Value']

    # Get proxy to be used to connect to the cloud endpoint
    authType = endpoint.parameters.get('Auth')
    if authType and authType.lower() in ['x509', 'voms']:
      siteName = endpoint.parameters['Site']
      ceName = endpoint.parameters['CEName']
      gLogger.verbose("Getting cloud proxy for %s/%s" % (siteName, ceName))
      result = getProxyFileForCE(endpoint)
      if not result['OK']:
        continue
      endpoint.setProxy(result['Value'])

    result = endpoint.stopVM(uniqueID)
    if result['OK']:
      gVirtualMachineDB.recordDBHalt(instanceID, 0)
      successful[instanceID] = True
    else:
      failed[instanceID] = result['Message']

  return S_OK({"Successful": successful, "Failed": failed})

def getPilotOutput(pilotRef):

  if not pilotRef.startswith('vm://'):
    return S_ERROR('Invalid pilot reference %s' % pilotRef)

  # Get the VM public IP
  diracID, nPilot = os.path.basename(pilotRef).split(':')
  result = gVirtualMachineDB.getUniqueIDByName(diracID)
  if not result['OK']:
    return result
  uniqueID = result['Value']
  result = gVirtualMachineDB.getInstanceID(uniqueID)
  if not result['OK']:
    return result
  instanceID = result['Value']
  result = gVirtualMachineDB.getInstanceParameter("PublicIP", instanceID)
  if not result['OK']:
    return result
  publicIP = result['Value']

  op = Operations()
  privateKeyFile = op.getValue('/Cloud/PrivateKey', '')
  diracUser = op.getValue('/Cloud/VMUser', '')

  ssh_str = '%s@%s' % (diracUser, publicIP)
  cmd = ['ssh', '-i', privateKeyFile, ssh_str,
         "cat /etc/joboutputs/vm-pilot.%s.log" % nPilot]
  inst = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
  output, stderr = inst.communicate()
  if inst.returncode:
    return S_ERROR('Failed to get pilot output: %s' % stderr)
  else:
    return S_OK(output)

class VirtualMachineManagerHandler(RequestHandler):

  def initialize(self):

    credDict = self.getRemoteCredentials()
    self.rpcProperties = credDict['properties']

  @staticmethod
  def __logResult(methodName, result):
    '''
    Method that writes to log error messages
    '''
    if not result['OK']:
      gLogger.error('%s: %s' % (methodName, result['Message']))

  types_getCEInstances = [(list, type(None)), (list, type(None)), six.string_types]

  def export_getCEInstances(self, siteList, ceList, vo):

    if not siteList:
      siteList = None
    return getCEInstances(siteList=siteList, ceList=ceList, vo=vo)

  types_stopInstance = [six.string_types, six.string_types, six.string_types]

  def export_stopInstance(self, site, endpoint, nodeID):

    return stopInstance(site, endpoint, nodeID)

  types_getPilotOutput = [six.string_types]

  def export_getPilotOutput(self, pilotReference):

    return getPilotOutput(pilotReference)

  types_checkVmWebOperation = [six.string_types]

  def export_checkVmWebOperation(self, operation):
    """
    return true if rpc has VM_WEB_OPERATION
    """
    if VmProperties.VM_WEB_OPERATION in self.rpcProperties:
      return S_OK('Auth')
    return S_OK('Unauth')

  types_insertInstance = [six.string_types, six.string_types, six.string_types, six.string_types, six.string_types]

  def export_insertInstance(self, uniqueID, imageName, instanceName, endpoint, runningPodName):
    """
    Check Status of a given image
    Will insert a new Instance in the DB
    """
    res = gVirtualMachineDB.insertInstance(uniqueID, imageName, instanceName, endpoint, runningPodName)
    self.__logResult('insertInstance', res)

    return res

  types_getUniqueID = [six.string_types]

  def export_getUniqueID(self, instanceID):
    """
    return cloud manager uniqueID from VMDIRAC instanceID
    """
    res = gVirtualMachineDB.getUniqueID(instanceID)
    self.__logResult('getUniqueID', res)

    return res

  types_getUniqueIDByName = [six.string_types]

  def export_getUniqueIDByName(self, instanceName):
    """
    return cloud manager uniqueID from VMDIRAC name
    """
    result = gVirtualMachineDB.getUniqueIDByName(instanceName)
    self.__logResult('getUniqueIDByName', result)

    return result

  types_setInstanceUniqueID = [six.integer_types, six.string_types]

  def export_setInstanceUniqueID(self, instanceID, uniqueID):
    """
    Check Status of a given image
    Will insert a new Instance in the DB
    """
    res = gVirtualMachineDB.setInstanceUniqueID(instanceID, uniqueID)
    self.__logResult('setInstanceUniqueID', res)

    return res

  types_declareInstanceSubmitted = [six.string_types]

  def export_declareInstanceSubmitted(self, uniqueID):
    """
    After submission of the instance the Director should declare the new Status
    """
    res = gVirtualMachineDB.declareInstanceSubmitted(uniqueID)
    self.__logResult('declareInstanceSubmitted', res)

    return res

  types_declareInstanceRunning = [six.string_types, six.string_types]

  def export_declareInstanceRunning(self, uniqueID, privateIP):
    """
    Declares an instance Running and sets its associated info (uniqueID, publicIP, privateIP)
    Returns S_ERROR if:
      - instanceName does not have a "Submitted" entry
      - uniqueID is not unique
    """
    gLogger.info('Declare instance Running uniqueID: %s' % (uniqueID))
    if VmProperties.VM_RPC_OPERATION not in self.rpcProperties:
      return S_ERROR("Unauthorized declareInstanceRunning RPC")

    publicIP = self.getRemoteAddress()[0]
    gLogger.info('Declare instance Running publicIP: %s' % (publicIP))

    res = gVirtualMachineDB.declareInstanceRunning(uniqueID, publicIP, privateIP)
    self.__logResult('declareInstanceRunning', res)

    return res

  types_instanceIDHeartBeat = [six.string_types, float, six.integer_types,
                               six.integer_types, six.integer_types]

  def export_instanceIDHeartBeat(self, uniqueID, load, jobs,
                                 transferredFiles, transferredBytes, uptime=0):
    """
    Insert the heart beat info from a running instance
    It checks the status of the instance and the corresponding image
    Declares "Running" the instance and the image
    It returns S_ERROR if the status is not OK
    """
    if VmProperties.VM_RPC_OPERATION not in self.rpcProperties:
      return S_ERROR("Unauthorized declareInstanceIDHeartBeat RPC")

    try:
      uptime = int(uptime)
    except ValueError:
      uptime = 0

    res = gVirtualMachineDB.instanceIDHeartBeat(uniqueID, load, jobs,
                                                transferredFiles, transferredBytes, uptime)
    self.__logResult('instanceIDHeartBeat', res)

    return res

  types_declareInstancesStopping = [list]

  def export_declareInstancesStopping(self, instanceIdList):
    """
    Declares "Stopping" the instance because the Delete button of Browse Instances
    The instanceID is the VMDIRAC VM id
    When next instanceID heat beat with stopping status on the DB the VM will stop the job agent and terminates properly
    It returns S_ERROR if the status is not OK
    """
    if VmProperties.VM_WEB_OPERATION not in self.rpcProperties:
      return S_ERROR("Unauthorized VM Stopping")

    for instanceID in instanceIdList:
      gLogger.info('Stopping DIRAC instanceID: %s' % (instanceID))
      result = gVirtualMachineDB.getInstanceStatus(instanceID)
      if not result['OK']:
        self.__logResult('declareInstancesStopping on getInstanceStatus call: ', result)
        return result
      state = result['Value']
      gLogger.info('Stopping DIRAC instanceID: %s, current state %s' % (instanceID, state))

      if state == 'Stalled':
        result = gVirtualMachineDB.getUniqueID(instanceID)
        if not result['OK']:
          self.__logResult('declareInstancesStopping on getUniqueID call: ', result)
          return result
        uniqueID = result['Value']
        result = gVirtualMachineDB.getEndpointFromInstance(uniqueID)
        if not result['OK']:
          self.__logResult('declareInstancesStopping on getEndpointFromInstance call: ', result)
          return result
        endpoint = result['Value']

        result = self.export_declareInstanceHalting(uniqueID, 0)
      elif state == 'New':
        result = gVirtualMachineDB.recordDBHalt(instanceID, 0)
        self.__logResult('declareInstanceHalted', result)
      else:
        # this is only aplied to allowed trasitions
        result = gVirtualMachineDB.declareInstanceStopping(instanceID)
        self.__logResult('declareInstancesStopping: on declareInstanceStopping call: ', result)

    return result

  types_declareInstanceHalting = [six.string_types, float]

  def export_declareInstanceHalting(self, uniqueID, load):
    """
    Insert the heart beat info from a halting instance
    The VM has the uniqueID, which is the Cloud manager VM id
    Declares "Halted" the instance and the image
    It returns S_ERROR if the status is not OK
    """
    if VmProperties.VM_RPC_OPERATION not in self.rpcProperties:
      return S_ERROR("Unauthorized declareInstanceHalting RPC")

    endpoint = gVirtualMachineDB.getEndpointFromInstance(uniqueID)
    if not endpoint['OK']:
      self.__logResult('declareInstanceHalting', endpoint)
      return endpoint
    endpoint = endpoint['Value']

    result = gVirtualMachineDB.declareInstanceHalting(uniqueID, load)
    if not result['OK']:
      if "Halted ->" not in result["Message"]:
        self.__logResult('declareInstanceHalting on change status: ', result)
        return result
      else:
        gLogger.info("Bad transition from Halted to something, will assume Halted")

    haltingList = []
    instanceID = gVirtualMachineDB.getInstanceID(uniqueID)
    if not instanceID['OK']:
      self.__logResult('declareInstanceHalting', instanceID)
      return instanceID
    instanceID = instanceID['Value']
    haltingList.append(instanceID)

    return haltInstances(haltingList)

  types_getInstancesByStatus = [six.string_types]

  def export_getInstancesByStatus(self, status):
    """
    Get dictionary of Image Names with InstanceIDs in given status
    """

    res = gVirtualMachineDB.getInstancesByStatus(status)
    self.__logResult('getInstancesByStatus', res)
    return res

  types_getAllInfoForUniqueID = [six.string_types]

  def export_getAllInfoForUniqueID(self, uniqueID):
    """
    Get all the info for a UniqueID
    """
    res = gVirtualMachineDB.getAllInfoForUniqueID(uniqueID)
    self.__logResult('getAllInfoForUniqueID', res)

    return res

  types_getInstancesContent = [dict, (list, tuple),
                               six.integer_types, six.integer_types]

  def export_getInstancesContent(self, selDict, sortDict, start, limit):
    """
    Retrieve the contents of the DB
    """
    res = gVirtualMachineDB.getInstancesContent(selDict, sortDict, start, limit)
    self.__logResult('getInstancesContent', res)

    return res

  types_getHistoryForInstanceID = [six.integer_types]

  def export_getHistoryForInstanceID(self, instanceId):
    """
    Retrieve the contents of the DB
    """
    res = gVirtualMachineDB.getHistoryForInstanceID(instanceId)
    self.__logResult('getHistoryForInstanceID', res)

    return res

  types_getInstanceCounters = [six.string_types, dict]

  def export_getInstanceCounters(self, groupField, selDict):
    """
    Retrieve the contents of the DB
    """
    res = gVirtualMachineDB.getInstanceCounters(groupField, selDict)
    self.__logResult('getInstanceCounters', res)

    return res

  types_getHistoryValues = [int, dict]

  def export_getHistoryValues(self, averageBucket, selDict, fields2Get=None, timespan=0):
    """
    Retrieve the contents of the DB
    """
    if not fields2Get:
      fields2Get = []
    res = gVirtualMachineDB.getHistoryValues(averageBucket, selDict, fields2Get, timespan)
    self.__logResult('getHistoryValues', res)

    return res

  types_getRunningInstancesHistory = [int, int]

  def export_getRunningInstancesHistory(self, timespan, bucketSize):
    """
    Retrieve number of running instances in each bucket
    """
    res = gVirtualMachineDB.getRunningInstancesHistory(timespan, bucketSize)
    self.__logResult('getRunningInstancesHistory', res)

    return res

  types_getRunningInstancesBEPHistory = [int, int]

  def export_getRunningInstancesBEPHistory(self, timespan, bucketSize):
    """
    Retrieve number of running instances in each bucket by End-Point History
    """
    res = gVirtualMachineDB.getRunningInstancesBEPHistory(timespan, bucketSize)
    self.__logResult('getRunningInstancesBEPHistory', res)

    return res

  types_getRunningInstancesByRunningPodHistory = [int, int]

  def export_getRunningInstancesByRunningPodHistory(self, timespan, bucketSize):
    """
    Retrieve number of running instances in each bucket by Running Pod History
    """
    res = gVirtualMachineDB.getRunningInstancesByRunningPodHistory(timespan, bucketSize)
    self.__logResult('getRunningInstancesByRunningPodHistory', res)

    return res

  types_getRunningInstancesByImageHistory = [int, int]

  def export_getRunningInstancesByImageHistory(self, timespan, bucketSize):
    """
    Retrieve number of running instances in each bucket by Running Pod History
    """
    res = gVirtualMachineDB.getRunningInstancesByImageHistory(timespan, bucketSize)
    self.__logResult('getRunningInstancesByImageHistory', res)

    return res


import os
import shutil
import zipfile
from base64 import b64decode
from utils.config import config
import requests

root_path = os.getcwd()
gat = (
    "Z2l0aHViX3BhdF8xMUJBQkhHNkEwa1JRZEM1dFByczhVXzU0cERCS21URXRGYm"
    "FYRElUWE5KVUk4VkUxVTdjb0dHbElMSWdhVnI2Qkc3QzVCN0lCWlhWdDJMOUo2"
)

def download_and_extract_zip(url, root_path):
    zip_file_path = os.path.join(root_path, "repository.zip")
    response = requests.get(url, stream=True)
    response.raise_for_status()
    total_size = int(response.headers.get("Content-Length", 0))
    if total_size == 0:
        print("下载失败！")
        return 0
    block_size = 1024  # 每次下载的块大小
    progress = 0
    with open(zip_file_path, "wb") as file:
        for data in response.iter_content(block_size):
            progress += len(data)
            file.write(data)

            # 计算下载进度并显示进度条
            percent = (progress / total_size) * 100
            progress_bar = "=" * int(percent // 5) + ">"
            print(f"下载进度: {percent:.2f}% [{progress_bar:<20}] ", end="\r")

    print("\n下载完成！")
    # 解压ZIP文件
    with zipfile.ZipFile(zip_file_path, "r") as zip_ref:
        zip_ref.extractall(root_path)

    os.remove(zip_file_path)  # 删除ZIP文件
    return 1

def sync_github_repo(repo_url, root_path):
    # 构建API URL
    api_url = f"https://api.github.com/repos/{repo_url}/zipball/main"

    # 检查保存路径是否存在，如果不存在则创建
    os.makedirs(root_path, exist_ok=True)

    # 下载并解压ZIP文件
    return download_and_extract_zip(api_url, root_path)

def get_latest_branch_sha(repo_url):
    url = f"https://api.github.com/repos/{repo_url}/branches"
    headers = {
        "Accept": "application/vnd.github.v3+json",
        "Authorization": b64decode(gat).decode("utf-8"),
    }
    try:
        response = requests.get(url, headers=headers, timeout=3)
    except:
        return None
    if response.status_code == 200:
        branches = response.json()
        if branches:
            latest_branch = branches[0]
            return latest_branch["commit"]["sha"]
    else:
        return None

def copy_folder_contents(source_folder, destination_folder):
    # 检查目标文件夹是否存在，如果不存在则创建
    if not os.path.exists(destination_folder):
        os.makedirs(destination_folder)

    # 遍历源文件夹中的所有文件和子文件夹
    for item in os.listdir(source_folder):
        source = os.path.join(source_folder, item)
        destination = os.path.join(destination_folder, item)

        if os.path.isfile(source):
            # 如果源项是文件，则直接复制并覆盖同名文件
            shutil.copy2(source, destination)
        elif os.path.isdir(source):
            # 如果源项是文件夹，则递归地调用复制函数
            copy_folder_contents(source, destination)

def update_map(force=False):
    repo_url = "CHNZYX/maps"
    # 获取远端sha
    remote_sha = get_latest_branch_sha(repo_url)
    if remote_sha is None:
        print("远端地图sha获取失败, 请检查网络连接")
        return "远端地图sha获取失败, 请检查网络连接", "red"
    print("远端地图sha: " + remote_sha)
    # 获取本地sha
    local_sha = config.map_sha
    print("本地地图sha: " + local_sha)
    # 判断是否需要更新
    if remote_sha == local_sha:
        print("map无需更新")
        return "地图已是最新版本", "green"
    map_path = os.path.join(root_path, "imgs\\maps")
    print("Map path: " + map_path)
    # 下载map仓库并解压
    status = sync_github_repo(repo_url, root_path)
    if status == 0:
        return "下载失败", "red"
    print("下载完成")
    # 找出下载的map文件夹
    t = os.listdir(root_path)
    chn_folders = [item for item in t if item.startswith("CHNZYX")]
    downloaded_map_path = os.path.join(os.path.join(root_path, chn_folders[0]), "maps")
    print("download_map_path: " + downloaded_map_path)
    print("解压中...")
    # 删除原有map文件夹，复制新的map文件夹
    if force:
        shutil.rmtree(map_path)
        shutil.copytree(downloaded_map_path, map_path)
    else:
        copy_folder_contents(downloaded_map_path, map_path)
    shutil.rmtree(os.path.dirname(downloaded_map_path))
    # 更新sha
    config.map_sha = remote_sha
    config.save()
    print("更新完成")
    return "更新完成", "green"


import datetime as dt
import random

import pytest

from scheduler import Scheduler, SchedulerError
from scheduler.base.definition import JobType
from scheduler.threading.job import Job

from ...helpers import DELETE_NOT_SCHEDULED_ERROR, foo

@pytest.mark.parametrize(
    "n_jobs",
    [
        1,
        2,
        3,
        10,
    ],
)
def test_delete_job(n_jobs):
    sch = Scheduler()
    assert len(sch.jobs) == 0

    jobs = []
    for _ in range(n_jobs):
        jobs.append(sch.once(dt.datetime.now(), foo))
    assert len(sch.jobs) == n_jobs

    job = random.choice(jobs)
    sch.delete_job(job)
    assert job not in sch.jobs
    assert len(sch.jobs) == n_jobs - 1

    # test error if the job is not scheduled
    with pytest.raises(SchedulerError, match=DELETE_NOT_SCHEDULED_ERROR):
        sch.delete_job(job)

@pytest.mark.parametrize(
    "empty_set",
    [
        False,
        True,
    ],
)
@pytest.mark.parametrize(
    "any_tag",
    [
        None,
        False,
        True,
    ],
)
@pytest.mark.parametrize(
    "n_jobs",
    [
        0,
        1,
        2,
        3,
        10,
    ],
)
def test_delete_jobs(n_jobs, any_tag, empty_set):
    sch = Scheduler()
    assert len(sch.jobs) == 0

    for _ in range(n_jobs):
        sch.once(dt.datetime.now(), foo)
    assert len(sch.jobs) == n_jobs

    if empty_set:
        if any_tag is None:
            num_del = sch.delete_jobs()
        else:
            num_del = sch.delete_jobs(any_tag=any_tag)
    else:
        if any_tag is None:
            num_del = sch.delete_jobs(tags={})
        else:
            num_del = sch.delete_jobs(tags={}, any_tag=any_tag)

    assert len(sch.jobs) == 0
    assert num_del == n_jobs

@pytest.mark.parametrize(
    "job_tags, delete_tags, any_tag, n_deleted",
    [
        [[{"a", "b"}, {"1", "2", "3"}, {"a", "1"}], {"a", "1"}, True, 3],
        [[{"a", "b"}, {"1", "2", "3"}, {"a", "2"}], {"b", "1"}, True, 2],
        [[{"a", "b"}, {"1", "2", "3"}, {"b", "1"}], {"3"}, True, 1],
        [[{"a", "b"}, {"1", "2", "3"}, {"b", "2"}], {"2", "3"}, True, 2],
        [[{"a", "b"}, {"1", "2", "3"}, {"a", "1"}], {"a", "1"}, False, 1],
        [[{"a", "b"}, {"1", "2", "3"}, {"a", "2"}], {"b", "1"}, False, 0],
        [[{"a", "b"}, {"1", "2", "3"}, {"b", "1"}], {"1", "3"}, False, 1],
        [[{"a", "b"}, {"1", "2", "3"}, {"b", "2"}], {"2", "3"}, False, 1],
    ],
)
def test_delete_tagged_jobs(job_tags, delete_tags, any_tag, n_deleted):
    sch = Scheduler()

    for tags in job_tags:
        sch.once(dt.timedelta(), lambda: None, tags=tags)

    assert sch.delete_jobs(tags=delete_tags, any_tag=any_tag) == n_deleted


import json
import frappe
from frappe.model.document import Document
from frappe.utils.safe_exec import get_safe_globals, safe_exec
from frappe.integrations.utils import make_post_request
from frappe.desk.form.utils import get_pdf_link
from frappe.utils.background_jobs import enqueue

def validate(self, method):
	if self.channel == "WhatsApp":
		fields = frappe.get_doc("DocType", self.document_type).fields
		fields += frappe.get_all(
			"Custom Field",
			filters={"dt": self.document_type},
			fields=["fieldname"]
		)
		# if not any(field.fieldname == self.custom_receiver_mobile for field in fields): # noqa
		# 	frappe.throw(f"Field name {self.custom_receiver_mobile} does not exists")

def on_trash(self, method):
	pass
	# if self.channel == "WhatsApp":
	# 	if self.notification_type == "Scheduler Event":
	# 		frappe.delete_doc("Scheduled Job Type", self.name)

	# 	frappe.cache().delete_value("whatsapp_notification_map")

def after_insert(self, method):
	pass
	# if self.channel == "WhatsApp":
	# 	if self.notification_type == "Scheduler Event":
	# 		method = f"whatsapp_erpnext.utils.trigger_whatsapp_notifications_{self.event_frequency.lower().replace(' ', '_')}" # noqa
	# 		job = frappe.get_doc(
	# 			{
	# 				"doctype": "Scheduled Job Type",
	# 				"method": method,
	# 				"frequency": self.event_frequency
	# 			}
	# 		)

	# 		job.insert()

def format_number(self, number):
	if (number.startswith("+")):
		number = number[1:len(number)]

	return number

def send_scheduled_message(self) -> dict:
	safe_exec(
		self.condition, get_safe_globals(), dict(doc=self)
	)
	language_code = frappe.db.get_value(
		"WhatsApp Templates", self.template,
		fieldname='language_code'
	)
	if language_code:
		for contact in self._contact_list:
			data = {
				"messaging_product": "whatsapp",
				"to": self.format_number(contact),
				"type": "template",
				"template": {
					"name": self.template,
					"language": {
						"code": language_code
					},
					"components": []
				}
			}

			self.notify(data)
	# return _globals.frappe.flags

def send_template_message(self, doc: Document, contact_no = None):
	"""Specific to Document Event triggered Server Scripts."""
	if not self.enabled:
		return

	doc_data = doc.as_dict()
	if self.condition:
		# check if condition satisfies
		if not frappe.safe_eval(
			self.condition, get_safe_globals(), dict(doc=doc_data)
		):
			return

	template = frappe.db.get_value(
		"WhatsApp Templates", self.custom_whatsapp_template,
		fieldname='*'
	)

	if template:
		for row in self.recipients:
			if row.receiver_by_document_field != "owner":
				if not contact_no:
					contact_no = doc.get(row.receiver_by_document_field)
				if contact_no:
					data = {
						"messaging_product": "whatsapp",
						"to": contact_no,
						"type": "template",
						"template": {
							"name": self.custom_whatsapp_template,
							"language": {
								"code": template.language_code
							},
							"components": []
						}
					}

					# Pass parameter values
					if self.fields:
						parameters = []
						for field in self.fields:
							parameters.append({
								"type": "text",
								"text": doc.get_formatted(field.field_name)
							})

						data['template']["components"] = [{
							"type": "body",
							"parameters": parameters
						}]

					if self.attach_print:
						key = doc.get_document_share_key()
						frappe.db.commit()

						link = get_pdf_link(
							doc_data['doctype'],
							doc_data['name'],
							print_format=self.print_format or "Standard"
						)

						filename = f'{doc_data["name"]}.pdf'
						url = f'{frappe.utils.get_url()}{link}&key={key}'

						data['template']['components'].append({
							"type": "header",
							"parameters": [{
								"type": "document",
								"document": {
									"link": url,
									"filename": filename
								}
							}]
						})
						label = f"{doc_data['doctype']} - {doc_data['name']}"

					notify(self, data, label)

def notify(self, data, label = None):
	"""Notify."""
	settings = frappe.get_doc(
		"WhatsApp Settings", "WhatsApp Settings",
	)
	token = settings.get_password("token")

	headers = {
		"authorization": f"Bearer {token}",
		"content-type": "application/json"
	}
	try:
		response = make_post_request(
			f"{settings.url}/{settings.version}/{settings.phone_id}/messages",
			headers=headers, data=json.dumps(data)
		)

		message_id = response['messages'][0]['id']
		enqueue(save_whatsapp_log, data = data, message_id = message_id, label = label)

		frappe.msgprint("WhatsApp Message Triggered", indicator="green", alert=True)

	except Exception as e:
		response = frappe.flags.integration_request.json()['error']
		error_message = response.get('Error', response.get("message"))
		frappe.msgprint(
			f"Failed to trigger whatsapp message: {error_message}",
			indicator="red",
			alert=True
		)
	finally:
		status_response = frappe.flags.integration_request.json().get('error')
		frappe.get_doc({
			"doctype": "Integration Request",
			"integration_request_service": self.custom_whatsapp_template,
			"output": str(frappe.flags.integration_request.json()),
			"status": "Failed" if status_response else "Completed"
		}).insert(ignore_permissions=True)

def format_number(self, number):
	if (number.startswith("+")):
		number = number[1:len(number)]

	return number

@frappe.whitelist()
def send_notification(notification, ref_doctype, ref_docname, mobile_no = None):
	noti_doc = frappe.get_doc("Notification", notification)

	ref_doc = frappe.get_doc(ref_doctype, ref_docname)

	send_template_message(noti_doc, ref_doc, mobile_no)

def save_whatsapp_log(data, message_id, label = None):
	frappe.get_doc({
			"doctype": "WhatsApp Message",
			"type": "Outgoing",
			"message": str(data['template']),
			"to": data['to'],
			"message_type": "Template",
			"message_id": message_id,
			"content_type": "document",
			"label": label
		}).save(ignore_permissions=True)