#!/usr/bin/python3
import argparse
from lxml import etree
from pprint import pprint
#====================================
#====================================
if __name__=='__main__':
    parser=argparse.ArgumentParser(description='XML Parser')
    parser.add_argument('-menu','--menu',dest='menu',action='store_true',default=False,help='Display all the menu items')
    cmdlineopts=parser.parse_args()
    etree=etree.parse("sample.xml")
    breakfast_menu={}
    ###parse the xml file
    for food_ele in etree.xpath("//breakfast_menu/food"):
        btype=food_ele.get('type')
        if breakfast_menu.get('btype') is None:
            breakfast_menu[btype]={}
        bname=food_ele.find('name').text
#        print (bname)
        bprice=food_ele.find('price').text
        bdescription=food_ele.find('description').text
        bcalories=food_ele.find('calories').text
        breakfast_menu[btype][bname]={}
        breakfast_menu[btype][bname]['price']=bprice
        breakfast_menu[btype][bname]['description']=bdescription
        breakfast_menu[btype][bname]['calories']=bcalories
    ##
    pprint (breakfast_menu)
    ##get all the menu items
    if cmdlineopts.menu is True:
        for bt in breakfast_menu.keys():
            print ("MenuType:{},".format(bt))
            for bn in breakfast_menu[bt].keys():
                print ("MenuName:{},".format(bn))


from django.contrib.auth.forms import PasswordResetForm, UserCreationForm
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django import forms
from django.utils.translation import ugettext_lazy as _
from stepping_out.auth.tokens import REGISTRATION_TIMEOUT_DAYS
from stepping_out.auth.widgets import EmailInput
from stepping_out.mail.models import UserEmail
from random import choice
import datetime

class UserEmailPasswordResetForm(PasswordResetForm):
	def clean_email(self):
		"""
		Validates that a user exists with the given e-mail address.
		"""
		email = self.cleaned_data['email']
		self.users_cache = User.objects.filter(emails__email__iexact=email)
		if len(self.users_cache) == 0:
			raise forms.ValidationError(_("That e-mail address doesn't have an associated user account. Are you sure you've registered?"))
		return email

class PendUserCreationForm(UserCreationForm):
	email = forms.EmailField(widget=EmailInput)

	def __init__(self, *args, **kwargs):
		super(PendUserCreationForm, self).__init__(*args, **kwargs)
		self._messages = []

	def clean_email(self):
		email = self.cleaned_data['email']
		try:
			User.objects.get(emails__email=email)
		except User.DoesNotExist:
			return email
		raise forms.ValidationError(_("A user already exists with that email."))

	def clean_username(self):
		username = self.cleaned_data['username']
		try:
			user = User.objects.get(username=username)
		except User.DoesNotExist:
			return username

		# Consider the name free if more than the relevant number of days has passed.
		if not user.is_active and user.date_joined == user.last_login and (datetime.datetime.now() - user.date_joined).days > REGISTRATION_TIMEOUT_DAYS:
			user.delete()
			return username

		raise forms.ValidationError(_("A user with that username already exists."))

	def save(self, commit=True):
		user = super(PendUserCreationForm, self).save(commit=False)
		user.is_active = False
		user.email = self.cleaned_data['email']
		user.save()
		return user

class TestHumanityForm(forms.Form):
	HUMANITY_CHECKS = {
		'first-letter': ('What is the first letter of the English alphabet?', 'a'),
		'5-times-5': ('What is 5 times 5?', '25'),
		'fitzgerald': ('How many letters are in the name Fitzgerald?', '10'),
		'last-name': ("What was Duke Ellington's last name?", 'Ellington'),
		'sentence': ("This is a really silly question, but what is the fourth word in this sentence?", 'really'),
	}
	question = forms.CharField(max_length=20, widget=forms.HiddenInput)
	answer = forms.CharField(max_length=20, help_text="This is a (case-sensitive) question to make sure you're human. :-)")

	def __init__(self, *args, **kwargs):
		super(TestHumanityForm, self).__init__(*args, **kwargs)
		initial = choice(self.HUMANITY_CHECKS.keys())
		self.fields['question'].initial = initial

	def get_question(self):
		key = self['question'].data or self.fields['question'].initial
		return self.HUMANITY_CHECKS[key][0]

	def clean_question(self):
		question = self.cleaned_data['question']
		if question not in self.HUMANITY_CHECKS:
			raise ValidationError("Invalid question. This should only happen if you've been messing with the HTML. Please don't. Thanks!")
		return question

	def clean_answer(self):
		correct_answer = self.HUMANITY_CHECKS[self.cleaned_data['question']][1]
		answer = self.cleaned_data['answer']
		if answer != correct_answer:
			raise ValidationError("Wrong! Try again.")
		return answer


import numpy as np
import matplotlib.pyplot as plt
import os
import sys
from os import listdir
from os.path import isfile, join

PATH_TO_PROJECT = os.path.abspath(
    os.path.join(os.path.dirname(__file__), '..'))
sys.path.append(PATH_TO_PROJECT)

def plot_n_examples(data_path, subset_name="training", n_examples=3, plot_freq_hist=True):

    data = np.load(data_path)
    subset = data[subset_name]
    idx = np.random.randint(0, subset['n_sequences'], size=n_examples)
    for i in idx:
        plt.plot(subset["dense_time"][i],
                 subset["real_values"][i], '-o', ms=5, label="underlying_model")
        plt.plot(subset["time"][i],
                 subset["sequences"][i], '-o', ms=5, label="noisy_samples")
        #plt.errorbar(subset["time"][i], subset["sequences"][i], yerr=subset["noise"][i], fmt="o", ms=5, label="samples")
        plt.xlabel("time")
        plt.ylim([-1,1])
        plt.ylabel("amplitude")
        title = "amp: " + "{0:.2f}".format(subset["params"][i][0]) \
                + ", freq: " + "{0:.2f}".format(subset["params"][i][1]) \
                + ", period: " + "{0:.2f}".format(1 / subset["params"][i][1])
        plt.title(title)
        plt.grid(True)
        plt.legend()
        #plt.savefig("./plots/" + subset_name + "_" + self.seq_shape +
        #            "_" + self.noise_distr + "_sample" + str(i).zfill(3) + ".png")
        plt.show()
    if plot_freq_hist:
        a = []
        for i in range(subset['n_sequences']):
            a.append(subset["params"][i][1])
        plt.hist(a)
        plt.title('freq')
        plt.show()

        a = []
        for i in range(subset['n_sequences']):
            a.append(1/subset["params"][i][1])
        plt.hist(a)
        plt.title('period')
        plt.show()

        a=[]
        for i in range(subset['n_sequences']):
            a.append(subset["params"][i][0])
        plt.hist(a)
        plt.title('amplitude')
        plt.show()

def plot_n_examples_all_classes(data_path, subset_name="training", n_examples=3):
    filenames = [f for f in listdir(data_path) if isfile(join(data_path, f))]
    time_series_filenames = [s for s in filenames if "gaussian.pkl" in s]
    for time_series_filename in time_series_filenames:
        time_series_path = os.path.join(data_path, time_series_filename)
        plot_n_examples(time_series_path, subset_name=subset_name, n_examples=n_examples)

data_path = os.path.join(PATH_TO_PROJECT, 'data')
plot_n_examples_all_classes(data_path, subset_name='training', n_examples=5)


from itertools import permutations

t = int(input())

for _ in range(t):
    n = int(input())
    a = [int(x) for x in input().split()]
    b = [int(x) for x in input().split()]
    neighbors = [[] for _ in range(n)]
    nums = [_ for _ in range(1, len(a) + 1)]
    p = permutations(nums, 2)
    for u, v in p:
        if a[u - 1] - a[v - 1] >= b[u - 1] - b[v - 1]:
            neighbors[u - 1].append(v - 1)

    lengths = [len(lst) for lst in neighbors]
    strong = []
    i = 1
    for length in lengths:
        if length == n - 1:
            strong.append(str(i))
        i += 1
    print(len(strong))
    print(" ".join(strong))


from django.contrib import admin
from django.utils.html import format_html

from .models import TagAssociation
from .app_settings import mumble_active

class TagAssociationAdmin(admin.ModelAdmin):
    list_display = ['tag', 'enabled', '_groups']

    def _list_2_html_w_tooltips(self, my_items: list, max_items: int) -> str:
        """converts list of strings into HTML with cutoff and tooltip"""
        items_truncated_str = ', '.join(my_items[:max_items])
        if not my_items:
            result = None
        elif len(my_items) <= max_items:
            result = items_truncated_str
        else:
            items_truncated_str += ', (...)'
            items_all_str = ', '.join(my_items)
            result = format_html(
                '{}',
                items_all_str,
                items_truncated_str
            )
        return result

    def _groups(self, obj):
        my_groups = [x.name for x in obj.groups.order_by('name')]

        return self._list_2_html_w_tooltips(
            my_groups,
            10
        )

    _groups.short_description = 'groups'
    filter_horizontal = ['groups']

admin.site.register(TagAssociation, TagAssociationAdmin)


# code for sentiment analysis

from textblob import TextBlob
from textblob.sentiments import NaiveBayesAnalyzer

def getSentiments(text):
    blob = TextBlob(text, analyzer=NaiveBayesAnalyzer())
    print(blob.sentiment)

training_data = [('it is good 1', 'pos'), ('it is good 3', 'pos'),
                 ('it is good 2', 'pos'), ('it is good 4', 'pos')]

txt2 = 'Service robot implementation a theoretical framework and research agenda'
txt1 = 'He is really hateful hateful hateful'

getSentiments(txt2)
getSentiments(txt1)


import pathlib
import signal
import sqlite3
from datetime import datetime, timedelta, date

import pandas as pd
from rx.subject import Subject

from data_fetcher import DataFetcher

class BusinessHours:
    def __init__(self, start_hour, end_hour):
        self.start_hour = start_hour
        self.end_hour = end_hour

    @property
    def today_start_hour_time(self):
        return self.to_exact_hour_time(datetime.now(), self.start_hour)

    @property
    def today_end_hour_time(self):
        result = self.to_exact_hour_time(datetime.now(), self.end_hour)
        if self.start_hour > self.end_hour:
            result + timedelta(days=1)

        return result

    def is_closed(self, time):
        time_hour = time.hour
        if self.start_hour < self.end_hour:
            return not self.start_hour <= time_hour < self.end_hour
        else:
            return self.end_hour <= time_hour < self.start_hour

    def estimate_how_long_to_wait_open(self, current_time):
        today_open_time = self.to_exact_hour_time(current_time, self.start_hour)
        if today_open_time >= current_time:
            return today_open_time - current_time
        else:
            return today_open_time + timedelta(days=1) - current_time

    def to_exact_hour_time(self, time, hour):
        return time.replace(hour=hour, minute=0, second=0, microsecond=0)

TABLE_NAME = 'cmcsc_room_people_number'
DAY_DATA_QUERY = "SELECT * from " + TABLE_NAME + " WHERE date(`index`) = ?"
class DataService:
    def __init__(self, sport_center_business_hours, fetch_period_seces=5, write_to_storage_period_secs=60, error_delay_secs=3):
        self.io_loop = None

        self.data_fetcher = DataFetcher()
        sqlite_file_path = pathlib.Path(__file__).parent / 'data.sqlite'
        print('database path', sqlite_file_path)
        self.sql_connection = sqlite3.connect(str(sqlite_file_path))

        self.fetch_period_secs = fetch_period_seces
        self.error_delay_secs = error_delay_secs
        self.write_to_storage_period_secs = timedelta(seconds=write_to_storage_period_secs)
        self.business_hours = sport_center_business_hours
        self.last_write_to_database_time = datetime.now()
        self.data_cache = None

        self.live_subject = Subject()

    def append_datum(self, df):
        if self.data_cache is None:
            self.data_cache = df
            return

        self.data_cache.loc[df.index[0]] = df.iloc[0]

    def write_cache_to_database(self, current_time):
        self.data_cache.to_sql(TABLE_NAME, con=self.sql_connection, if_exists='append')
        self.last_write_to_database_time = current_time
        self.data_cache = self.data_cache.iloc[0:0]
        print(datetime.now().time(), 'write into DB')

    async def fetch_callback(self):
        try:
            data = await self.data_fetcher.fetch_data()
        except Exception as e:
            print(datetime.now().time(), 'error occur, retry', e)
            self.io_loop.call_later(self.error_delay_secs, self.fetch_callback)
            return

        df = data.current_number_of_people_df
        self.append_datum(df)
        self.live_subject.on_next(df)

        if self.should_write_to_storage(data.timestamp):
            self.write_cache_to_database(data.timestamp)

        self.io_loop.call_later(self.estimate_next_fetch_delay(data.timestamp), self.fetch_callback)

    def query_last_week_data(self):
        today = date.today()
        return self.query_week_data(today - timedelta(days=1) if datetime.now() <= self.business_hours.today_end_hour_time else today)

    # from Monday
    def query_week_data(self, end_day):
        week_data = [None] * 7
        for i in range(0, 7):
            queried_date = end_day - timedelta(days=i)
            week_data[queried_date.weekday()] = self.query_datetime_indexed_db(DAY_DATA_QUERY, (queried_date,))

        return week_data

    def should_write_to_storage(self, current_time):
        return current_time - self.last_write_to_database_time >= self.write_to_storage_period_secs

    def estimate_next_fetch_delay(self, current_time):
        if self.business_hours.is_closed(current_time):
            delay = self.business_hours.estimate_how_long_to_wait_open(current_time).seconds
            print('business closed, delay: {} secs'.format(delay))
            return delay

        return self.fetch_period_secs

    def subscribe(self, doc, on_next, on_error):
        disposable = self.live_subject.subscribe(on_next=on_next, on_error=on_error)
        def on_session_destroyed(session_context):
            disposable.dispose()
            print('observer disposed, observers: ', len(self.live_subject.observers))

        doc.on_session_destroyed(on_session_destroyed)
        today_df = self.query_datetime_indexed_db(DAY_DATA_QUERY, (date.today(),))

        return today_df.append(self.data_cache)

    def query_datetime_indexed_db(self, query_str, params=None):
        return pd.read_sql_query(query_str,
                          self.sql_connection,
                          params=params,
                          index_col='index',
                          parse_dates=['index'])

    def start(self, io_loop):
        self.io_loop = io_loop

        self.register_quit_signals()
        self.io_loop.call_later(self.estimate_next_fetch_delay(datetime.now()), self.fetch_callback)

    def register_quit_signals(self):
        # signal.signal(signal.SIGQUIT, self.shutdown)  # SIGQUIT is send by our supervisord to stop this server.
        signal.signal(signal.SIGABRT, self.shutdown)  # SIGQUIT is send by our supervisord to stop this server.
        signal.signal(signal.SIGTERM, self.shutdown)  # SIGTERM is send by Ctrl+C or supervisord's default.
        signal.signal(signal.SIGINT, self.shutdown)

    def shutdown(self):
        self.write_cache_to_database(datetime.now())
        print('data service shutdown')
        self.sql_connection.close()


import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'    # to give away the GPU warning in TF
from pandas import read_csv
from matplotlib import pyplot as plt
import numpy as np
import copy

my_path = os.path.dirname(os.path.realpath(__file__))  #gets current path of the file
filename = my_path + "/data.csv"   #gets path of the file
df = read_csv(filename, header = None)
#print(df)
print("DATAFRAME :")
print(df.shape)

images = df.loc[:, :783]
labels = df.loc[:, 784:]

clean_images = images.values
print("\nCLEAN IMAGES :")

print(type(clean_images))
print(clean_images.shape)

print("\n", type(images), type(labels))
print(images.shape)

# Visualize original images

for i in range(2):
    sample = clean_images[i, :]
    print(sample)
    sample = sample.reshape(28, 28)
    plt.gray()
    plt.imshow(sample)
    plt.show()
    print("Original image : ")
    print(sum(sum(sample)))
    print(784 - sum(sum(sample)))

# Add noise and visualize noisy images

N = clean_images.shape[1]
print("Dimension : ", N)
n = int(0.05 * N)  # no. of noisy pixels
print("Number of noisy pixels : ", n)
pixels = N
noisy_images = copy.deepcopy(clean_images)

# Generate noisy pixels
seed = 10
np.random.seed(seed)  # first call
random_pixels = np.random.randint(0, 784, size = n)
print("RANDOM PIXEL VALUES ", random_pixels)
seed += 1
s = 28  # set random value of seed so that it flips the same bits each time for the same image
examples = clean_images.shape[0]
print(examples)
for k in range(examples):
    for i in range(n):
        np.random.seed(s)  # first call
        noise = np.random.randint(784)
        print("SEED  VALUES : ")
        print(noise)
        s += 1
        noisy_images[k, noise] = (1 - noisy_images[k, noise])
    # print("Noisy image : ")
    # print(sum(noisy_images[k, :]))
    # print(784 - sum(noisy_images[k, :]))
    # reshaped_noisy_image = noisy_images[k, :].reshape(28, 28)
    # print(reshaped_noisy_image.shape)
    #im_noisy_reshaped = im_noisy[k, :].reshape(28, 28)
    # plt.gray()
    # plt.imshow(reshaped_noisy_image)
    # plt.show()

print(clean_images[1,:])
print(noisy_images[1,:])
print(clean_images[1,:] - noisy_images[1, :])

np.savetxt(my_path + "/noisy_images_5.csv", noisy_images, fmt='%i', delimiter=",")
# np.savetxt(my_path + "/labels_10.csv", labels, fmt='%i')
# np.savetxt(my_path + "/clean_images.csv", clean_images, fmt='%i', delimiter=",")


import tensorflow as tf
import click
import cv2
import numpy as np
import importlib
import time

from estimation.config import get_default_configuration
from estimation.coordinates import get_coordinates
from estimation.connections import get_connections
from estimation.estimators import estimate
from estimation.renderers import draw

from train_singlenet_mobilenetv3 import register_tf_netbuilder_extensions

def process_frame(cropped, heatmap_idx, model, paf_idx, output_resize_factor):
    input_img = cropped[np.newaxis, ...]
    inputs = tf.convert_to_tensor(input_img)
    outputs = model.predict(inputs)
    pafs = outputs[paf_idx][0, ...]
    heatmaps = outputs[heatmap_idx][0, ...]
    cfg = get_default_configuration()
    coordinates = get_coordinates(cfg, heatmaps)
    connections = get_connections(cfg, coordinates, pafs)
    skeletons = estimate(cfg, connections)
    canvas = draw(cfg, cropped, coordinates, skeletons, resize_fac=output_resize_factor)

    return canvas

@click.command()
@click.option('--video', required=True,
              help='Path to the input video file')
@click.option('--output-video', required=True,
              help='Path to the output video file')
@click.option('--create-model-fn', required=True,
              help='Name of a function to create model instance. Check available names here: .models._init__.py')
@click.option('--input-size', required=True, type=int,
              help='Model''s input size ')
@click.option('--output-resize-factor', required=True, type=int,
              help='Output resize factor')
@click.option('--paf-idx', default=2, type=int,
              help='Index of model''s output containing PAF')
@click.option('--heatmap-idx', default=3, type=int,
              help='Index of model''s output containing heatmap')
@click.option('--frames-to-analyze', default=None, type=int,
              help='Number of the frames to analyze')
@click.option('--frame-ratio', default=1,
              help='Analyze every [n] frames')
def main(video, output_video, create_model_fn, input_size, output_resize_factor, paf_idx, heatmap_idx, frames_to_analyze, frame_ratio):

    register_tf_netbuilder_extensions()

    module = importlib.import_module('models')
    create_model = getattr(module, create_model_fn)
    model = create_model(pretrained=True)

    # Video reader
    cam = cv2.VideoCapture(video)
    input_fps = cam.get(cv2.CAP_PROP_FPS)
    ret_val, orig_image = cam.read()
    video_length = int(cam.get(cv2.CAP_PROP_FRAME_COUNT))

    if frames_to_analyze is None:
        frames_to_analyze = video_length

    # Video writer
    output_fps = input_fps / frame_ratio
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    w = orig_image.shape[1]
    h = orig_image.shape[0]
    scale = input_size / w if w < h else input_size / h
    out = cv2.VideoWriter(output_video, fourcc, output_fps, (input_size, input_size))

    i = 0
    while (cam.isOpened()) and ret_val is True and i < frames_to_analyze:
        if i % frame_ratio == 0:

            tic = time.time()

            im = cv2.resize(orig_image, (0, 0), fx=scale, fy=scale)
            new_w = im.shape[1]
            new_h = im.shape[0]
            if new_w > new_h:
                offset = (new_w - input_size) // 2
                cropped = im[0: input_size, offset: offset + input_size]
            else:
                offset = (new_h - input_size) // 2
                cropped = im[offset: offset + input_size, 0: input_size]

            canvas = process_frame(cropped, heatmap_idx, model, paf_idx, output_resize_factor)

            print('Processing frame: ', i)
            toc = time.time()
            print('processing time is %.5f' % (toc - tic))

            out.write(canvas)

        ret_val, orig_image = cam.read()

        i += 1

if __name__ == '__main__':
    main()


import numpy as np
import torch
import math

color_dict = {0: torch.tensor([0, 0, 0]),
              1: torch.tensor([0, 125, 0]),
              2: torch.tensor([150, 80, 0]),
              3: torch.tensor([255, 255, 0]),
              4: torch.tensor([100, 100, 100]),
              5: torch.tensor([0, 255, 0]),
              6: torch.tensor([0, 0, 150]),
              7: torch.tensor([150, 150, 255]),
              8: torch.tensor([255, 255, 255])}

def pad_to_square(image, fill_color=0):
    height, width = image.shape[:2]
    max_dim = max(width, height)
    # Calculate padding size for both sides
    left_padding = (max_dim - width) // 2
    top_padding = (max_dim - height) // 2
    # Create a new square canvas with the desired value for padding
    padded_image = np.full((max_dim, max_dim) + image.shape[2:], fill_color, dtype=image.dtype)
    # Paste the original image onto the new canvas
    padded_image[top_padding:top_padding+height, left_padding:left_padding+width, ...] = image
    return padded_image

def rgb_to_onehot(rgb_arr, color_dict):
    num_classes = len(color_dict)
    shape = rgb_arr.shape[:2]+(num_classes,)
    arr = np.zeros(shape, dtype=np.int8 )
    for i, cls in enumerate(color_dict):
        arr[:, :, i] = torch.all(rgb_arr.reshape((-1, 3)) == color_dict[i], axis=1).reshape(shape[:2])
    return arr

def onehot_to_rgb(onehot):
    output = np.zeros(onehot.shape+(3,))
    for k in color_dict.keys():
        output[onehot == k] = color_dict[k].numpy()
    return np.uint8(output)

def to_class_no(y_hot_list):
    y_class_list = []
    n = len(y_hot_list)
    for i in range(n):
        out = np.argmax(y_hot_list[i])
        y_class_list.append(out)
    return y_class_list

def numericalSort(value):
    import re
    numbers = re.compile(r'(\d+)')
    parts = numbers.split(value)
    parts[1::2] = map(int, parts[1::2])
    return parts

def crop(img, crop_size=256, stride=None):
    if stride is None:
        stride = crop_size/2
    croped_images = []
    h, w, c = img.shape

    n_h = math.ceil((h-crop_size)/stride+1)
    n_w = math.ceil((w-crop_size)/stride+1)

    for i in range(n_h):
        h1 = min(int(i*stride), h-crop_size)
        h2 = min(int(i*stride+crop_size), h)
        for j in range(n_w):
            w1 = min(int(j*stride), w-crop_size)
            w2 = min(int(j*stride+crop_size), w)
            crop_x = img[h1:h2, w1:w2, :]
            croped_images.append(crop_x)
    return croped_images

def conf_matrix(val_dataset, predictions, plot=True):
    from sklearn.metrics import confusion_matrix
    num_classes = 9
    total_conf_matrix = np.zeros((num_classes, num_classes), dtype=np.int)

    i = 0
    for batch in predictions:
        for image in batch:
            pred = image.flatten()
            target = np.argmax(val_dataset[i][1], axis=0).flatten()

            conf_matrix_batch = confusion_matrix(pred, target, labels=range(num_classes))
            total_conf_matrix += conf_matrix_batch
            i += 1

    if plot:
        class_labels = list(range(num_classes))
        import seaborn as sns
        import matplotlib.pyplot as plt
        plt.figure(figsize=(8, 6))
        sns.heatmap(total_conf_matrix, annot=True, cmap='Blues', fmt='d', xticklabels=class_labels, yticklabels=class_labels)
        plt.xlabel('Predicted')
        plt.ylabel('True')
        plt.title('Confusion Matrix')
        plt.show()

    return total_conf_matrix


from cerberus import Validator
from cerberus import TypeDefinition

class ParserModelType:
    """Defines a type for parser classes."""

    name = None
    is_model = False
    func = None

    def __init__(self, name):
        self.name = name
        if name.endswith('ModelElement'):
            self.is_model = True
            self.func = getattr(__import__("aminer.parsing", fromlist=[name]), name)
        else:
            self.is_model = False
            # we need this import:
            # skipcq: PTC-W0034
            self.func = getattr(__import__(name), 'get_model')

    def __str__(self):
        return self.name

class AnalysisType:
    """Defines a type for analysis classes."""

    name = None
    func = None

    def __init__(self, name):
        self.name = name
        self.func = getattr(__import__("aminer.analysis", fromlist=[name]), name)

    def __str__(self):
        return self.name

class EventHandlerType:
    """Defines a type for event classes."""
    name = None
    func = None

    def __init__(self, name):
        self.name = name
        self.func = getattr(__import__("aminer.events", fromlist=[name]), name)

    def __str__(self):
        return self.name

parser_type = TypeDefinition('parsermodel', (ParserModelType, str), ())
analysis_type = TypeDefinition('analysistype', (AnalysisType, str), ())
event_handler_type = TypeDefinition('eventhandlertype', (EventHandlerType, str), ())

class ConfigValidator(Validator):
    """Validates values from the configs."""

    types_mapping = Validator.types_mapping.copy()
    types_mapping['parsermodel'] = parser_type
    types_mapping['analysistype'] = analysis_type
    types_mapping['eventhandlertype'] = event_handler_type

    # we skip the following issue, otherwise an
    # "must have self"-issue will pop up
    # skipcq: PYL-R0201
    def _normalize_coerce_toparsermodel(self, value):
        """Create a ParserModelType from the string representation."""
        if isinstance(value, str):
            return ParserModelType(value)
        return None

    # we skip the following issue, otherwise an
    # "must have self"-issue will pop up
    # skipcq: PYL-R0201
    def _normalize_coerce_toanalysistype(self, value):
        """Create a AnalysisType from the string representation."""
        if isinstance(value, str):
            return AnalysisType(value)
        return None

    # we skip the following issue, otherwise an
    # "must have self"-issue will pop up
    # skipcq: PYL-R0201
    def _normalize_coerce_toeventhandlertype(self, value):
        """Create a EventHandlerType from the string representation."""
        if isinstance(value, str):
            return EventHandlerType(value)
        return None

    def _validate_has_start(self, has_start, field, value):
        """
        Test if there is a key named 'has_start'.
        The rule's arguments are validated against this schema:
        {'type': 'boolean'}
        """
        seen_start = False
        for var in value:
            if "start" in var and var['start'] is True:
                if seen_start:
                    self._error(field, "Only one parser with 'start'-key is allowed")
                seen_start = True
        if has_start and not seen_start:
            self._error(field, "Parser must contain a 'start'-key")


import re
import my_Selenium
from pyecharts.globals import ThemeType
from pyecharts import options as opts
from pyecharts.charts import *
import pandas as pd
def City(city):
    #判断数据是否是需要统计的城市
    list = ['河北', '山西', '辽宁', '吉林', '黑龙江', '江苏', '浙江', '安徽', '福建', '江西', '山东', '河南', '湖北', '湖南', '广东', '海南',
                 '四川', '贵州', '云南', '陕西', '甘肃', '青海', '内蒙古', '广西', '西藏', '宁夏', '新疆', '北京', '天津', '上海', '重庆','兵团']

    return list.count(city)

def write2excel(data,cn1,cn2,name):
    #使用pandas导出excel
    write2exce = pd.DataFrame(data,index=list(range(1,len(data.keys())+1)),columns=[cn1,cn2])
    write2exce[cn1] = data.keys()
    write2exce[cn2] = data.values()
    write2exce.to_excel(name)

def my_Bar(data,name):
    #使用Bar导出柱状图
    bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
    bar.add_xaxis(list(data.keys()))
    bar.add_yaxis("新增人数", list(map(int, data.values())), category_gap= '80%')
    bar.set_global_opts(
        title_opts=opts.TitleOpts(title=name),
        # 设置数据缩放滑块
        datazoom_opts=opts.DataZoomOpts(),
    )
    bar.render(name)

def my_main():
    # 获取url
    for cnt in range(1,40):
        if cnt == 1 :
            url_dir = "http://www.nhc.gov.cn/xcs/yqtb/list_gzbd.shtml"
        else:
            url_dir = 'http://www.nhc.gov.cn/xcs/yqtb/list_gzbd_'+str(cnt)+'.shtml'
        #正则筛url
        contents_directory = my_Selenium.getURL_dir(url_dir)
        contents_directory = re.findall('
.*?
',contents_directory,re.DOTALL)
        content_directory = re.findall('href="(.*?)" target', contents_directory[0], re.DOTALL)
        i = 0
        for url_target_half in content_directory:

            url_target = "http://www.nhc.gov.cn" + url_target_half  # 生成目标URL
            #打开网页
            contents_target = my_Selenium.getURL_dir(url_target)
            # 获取时间
            date_Get = re.findall('
截至(.*?)24时', contents_target)
            date_Get_year = re.findall('发布时间.+?([0-9]{4})', contents_target, re.DOTALL)
            #获取全部段落
            content_target = re.findall('>(.*?)<', contents_target)
            text = ''
            for i in content_target:
                text += i
            ##正则筛选目标数据
            text_target = re.findall('新增确诊病例(.*?)例',text)[0]
            text_target_null = re.findall('新增无症状感染者(.*?)例',text)[0]
            data_nation = {}
            data_nation['新增确诊病例'] = text_target
            data_nation['新增无症状感染者'] = text_target_null

            #正则筛选目标数据
            city_newcases = re.findall('本土病例.*?(.*?)）',text)[0]
            city_newcases_key = re.findall('([\u4E00-\u9FA5]+?)[0-9]*?例',city_newcases)
            city_newcases_value = re.findall('[\u4E00-\u9FA5]+?([0-9]*?)例',city_newcases)

            data_newcases = {}
            # 判断是否在统计城市
            for i  in range(0,len(city_newcases_key)):
                if City(city_newcases_key[i]) == 1 :
                    data_newcases[city_newcases_key[i]] = city_newcases_value[i]

            # 正则筛选目标数据
            data_null = {}
            city_null = re.findall('本土[0-9]*?例（(.*?)）',text)[0]
            city_null_key = re.findall('([\u4E00-\u9FA5]+?)[0-9]*?例',city_null)
            city_null_value = re.findall('[\u4E00-\u9FA5]+?([0-9]*?)例',city_null)
            #判断是否在统计城市
            for i  in range(0,len(city_null_key)):
                if City(city_null_key[i]) == 1 :
                    data_null[city_null_key[i]] = city_null_value[i]

            #导出execel表格
            write2excel(data=data_nation, cn1='新增类型', cn2='新增数量', name='中国大陆'+date_Get_year[0]+'年' + date_Get[0] + '疫情通报.xlsx')
            write2excel(data_newcases,'省份','新增确诊','各省份'+date_Get_year[0]+'年' + date_Get[0] + '新增确诊疫情通报.xlsx')
            write2excel(data_null,'省份','无症状感染者','各省份'+date_Get_year[0]+'年' + date_Get[0] + '无症状感染者疫情通报.xlsx')
            #数据可视化
            my_Bar(data_nation,'中国大陆'+date_Get_year[0]+'年'+date_Get[0]+'疫情柱状图.html')
            my_Bar(data_newcases,'各省份'+date_Get_year[0]+'年'+date_Get[0]+'新增确诊柱状图.html')
            my_Bar(data_null,'各省份'+date_Get_year[0]+'年'+date_Get[0]+'新增无症状柱状图.html')
            #数据热点
            my_Selenium.hot_spot('疫情 '+date_Get_year[0]+'年'+date_Get[0])

if __name__ == '__main__':
    my_main()


from argparse import _VersionAction
from pstats import Stats
from django.shortcuts import render
from django.http import HttpResponse
from django.http.response import JsonResponse
from rest_framework.parsers import JSONParser
from rest_framework import status

from shinobiAPI.models import Nation
from shinobiAPI.serializers import NationSerializer
from rest_framework.decorators import api_view

def index(request):
    return HttpResponse("The Nation Table")

@api_view(['GET', 'POST', 'DELETE'])
def nation_list(request):

    if request.method =='GET':
        nations = Nation.objects.all()

        nation_serilizer = NationSerializer(nations, many=True)
        return JsonResponse(nation_serilizer.data, safe=False)
    elif request.method=='POST':
        nation_data =JSONParser().parse(request)
        nation_serializer = NationSerializer(data=nation_data)
        if nation_serializer.is_valid():
            nation_serializer.save()
            return JsonResponse(nation_serializer.data, status=status.HTTP_201_CREATED)
        return JsonResponse(nation_serializer.errors,status=status.HTTP_400_BAD_REQUEST)
    elif request.method =='DELETE':
        count = Nation.objects.all.delete()
        return JsonResponse({'message': '{} All nations are deleted successfully! '.format(count[0])}, status=status.HTTP_204_NO_CONTENT)

@api_view(['GET', 'PUT', 'DELETE'])
def nation_details(request,pk):
    try:
        nation = Nation.objects.get(pk=pk)
    except nation.DoesNotExist:
        return JsonResponse({'message': 'The nation does not exist in the table'}, status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        nation_serializer = NationSerializer(nation)
        return JsonResponse(nation_serializer.data)
    elif request.method == 'PUT':
        nation_data = JSONParser().parse(request)
        nation_serializer = NationSerializer(nation, data=nation_data)
        if nation_serializer.is_valid():
            nation_serializer.save()
            return JsonResponse(nation_serializer.data)
        return JsonResponse(nation_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == 'DELETE':
        nation.delete()
        return JsonResponse({'message': 'Nation was deleted successfully!'}, status=status.HTTP_204_NO_CONTENT)


# --------------------------------------------------------------------------------------------------
# Logging: add a logging file to code
#   - prints out to console or file
#   - helps to trace the code execution
#   - logging level: DEBUG / INFO / WARNING / ERROR / CRITICAL
#   - name: logging module gives it to the default logger, [default] 'root'
#
#   Basic Config:
#       filename:   file name and extension
#       mode:       file mode (w/a)
#       format:     format of the log message
#       level:      level of severity
#
#   getLogger returns a logger with the specified name
# --------------------------------------------------------------------------------------------------

import os
import logging          # logging module
os.system('cls')        # cls command

print(dir(logging))

logging.basicConfig(filename= 'my_log.log',
                    filemode= 'a',
                    format= '%(asctime)s:\t %(name)s | %(levelname)s | \'%(message)s\'',
                    datefmt= '%d/%m/%Y, %H:%M:%S')

my_logger = logging.getLogger('Amr')

my_logger.critical('This is a critical status')
my_logger.error('This is an error message')
my_logger.warning('This is warning')
my_logger.info('This is an info')
my_logger.debug('This is debug')

my_logger2 = logging.getLogger('Lina')

my_logger2.critical('This is a critical status')
my_logger2.error('This is an error message')
my_logger2.warning('This is warning')
my_logger2.info('This is an info')
my_logger2.debug('This is debug')


# coding; utf-8

import logging
log = logging.getLogger(__name__)

import sqlalchemy
from sqlalchemy.sql import and_, or_, desc
from sqlalchemy.sql.expression import func
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.orm.relationships import RelationshipProperty
from sqlalchemy.orm.properties import  ColumnProperty

from .config import config

class RestMixin(object):

    @classmethod
    def rest_get_by_id(cls, id):
        obj = config.sqlalchemy_session().query(cls).get(id)

        if obj is None:
            raise NoResultFound

        return obj

    @classmethod
    def rest_get_by_ids(cls, appstruct):
        ids = [el['id'] for el in appstruct]

        return (config.sqlalchemy_session().query(cls)
            .filter(cls.id.in_(ids))
            .all())

    @classmethod
    def _rest_get_inner_query(cls, session, query, query_params):
        return query

    @classmethod
    def _rest_get_joined_query(cls, session, query, query_params):
        return query

    @classmethod
    def rest_get_list(cls, query_params):
        """
        cls._rest_search_columns = [cls.name, cls.description] - list of columns for search filtering
        :param start: number (default 0)
        :param limit: number or None
        :param order: {col: '', dir: 'asc|desc'} or None
        :param search:
        :param filters:
        :param query: sqlalchemy query
        :return: result of an executed query
        """

        def apply_search(query):
            search_columns = getattr(cls, '_rest_search_columns', None)
            if not search_columns or not 'search' in query_params:
                return query

            search = query_params['search'].lower()

            if len(search_columns) == 1:
                col = search_columns[0]
                search_filter = func.lower(col).like('%' + search + '%')
            else:  # > 1
                clauses = [func.lower(col).like('%' + search + '%') for col in search_columns]
                search_filter = or_(*clauses)

            return query.filter(search_filter)

        def apply_filters(query):
            if 'filters' not in query_params:
                return query

            filters = query_params['filters']

            for key, val in filters.items():
                op, field_name = key.split('_', 1)

                try:
                    field = getattr(cls, field_name)
                except AttributeError:
                    log.warn('RestMixin.rest_get_list(): filter "%s=%s": unknown attribute %s',
                             key, val, field_name)
                    continue

                if op == 'e':
                    query = query.filter(field == val)
                elif op == 'n':
                    query = query.filter(or_(field == val, field == None))
                elif op == 'l':
                    query = query.filter(func.lower(field).like('%' + val.lower() + '%'))
                elif op == 's':
                    query = query.filter(func.lower(field).like(val.lower() + '%'))
                else:
                    log.error('get_for_rest_grid: filter "%s=%s": unknown op: %s' % (key, val, op))

            return query

        def apply_order(query):
            if 'order' not in query_params:
                return query

            order = query_params['order']
            order_split = order['col'].split('.')

            try:
                order_attr = getattr(cls, order_split[0])
            except AttributeError:
                log.error('get_for_rest_grid: sort key %s: unknown attribute %s.%s' % (order['col'], cls.__name__, order['col']))
                return query

            for el in order_split[1:]:
                if not isinstance(order_attr.property, RelationshipProperty):
                    log.error('get_for_rest_grid: sort key %s: not a RelationshipProperty: %s' % (order['col'], str(order_attr.property)))
                    return query

                entity = order_attr.property.mapper.entity

                try:
                    order_attr = getattr(entity, el)
                except AttributeError:
                    log.error('get_for_rest_grid: sort key %s: unknown attribute %s.%s' % (order['col'], entity.__name__, el))
                    return query

            if not isinstance(order_attr.property, ColumnProperty):
                log.error('get_for_rest_grid: sort key %s: not a ColumnProperty: %s' % (order['col'], str(order_attr.property)))
                return query

            return query.order_by(desc(order_attr) if order['dir'] == 'desc' else order_attr)

        def apply_limit(query):
            if 'limit' in query_params:
                query = query.limit(query_params['limit'])

            if 'start' in query_params:
                query = query.offset(query_params['start'])

            return query

        # select * from (select * from users limit 10 offset 10) as u left join files f on u.id = f.user_id
        # http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#using-subqueries

        session = config.sqlalchemy_session

        q_inner = session().query(cls)
        q_inner = cls._rest_get_inner_query(session, q_inner, query_params)
        q_inner = apply_search(q_inner)
        q_inner = apply_filters(q_inner)
        q_count = q_inner  # count() query should not have ORDER BY
        q_inner = apply_order(q_inner)
        q_inner = apply_limit(q_inner)

        q_joined = q_inner.from_self()
        q_joined = cls._rest_get_joined_query(session, q_joined, query_params)
        q_joined = apply_order(q_joined)

        return q_count.count(), q_joined.all()

    def rest_add(self, flush=False):
        config.sqlalchemy_session().add(self)
        if flush:
            config.sqlalchemy_session().flush()

    def rest_delete(self, flush=False):
        config.sqlalchemy_session().delete(self)
        if flush:
            config.sqlalchemy_session().flush()


"""
    Given an array A of N elements. Find the majority element in the array.
    A majority element in an array A of size N is an element that appears more
    than N/2 times in the array.

    Input:
    The first line of the input contains T denoting the number of testcases.
    The first line of the test case will be the size of array and second line
    will be the elements of the array.

    Output:
    For each test case the output will be the majority element of the array.
    Output "-1" if no majority element is there in the array.
"""

from collections import Counter
class Solution:
    def majority_elem(self, arr, n):
        if not arr:
            return -1

        count = Counter(arr)
        most_common = count.most_common(1)[0]

        if most_common[1] > int(n/2):
            return most_common[0]
        else:
            return -1

def main():
    t = int(input())
    sol = Solution()

    for _ in range(t):
        n = int(input())
        arr = [int(elem) for elem in input().split()]
        print(sol.majority_elem(arr, n))

if __name__ == '__main__':
    main()


#!/usr/bin/python3

# Autor: Mateusz Adamowski
# Email: mateusz.adamowski@nlo.edu.pl

import sqlite3
import urllib.request
import os

URL = "https://github.com/mateusza2/2020-nlo-inf/raw/master/2021-05-20-sprawdzian/kandydaci.db"
BAZA = "kandydaci.db"

if not os.path.exists(BAZA):
    print(f"Pobieram {URL}...")
    urllib.request.urlretrieve(URL, BAZA)

db = sqlite3.connect(BAZA)

print("Przykład 1 - jeden wiersz, jedna kolumna:")
sql = """
    Select count(*)
    From kandydat
    Where nazwisko Like 'E%'
"""
print(sql)
for wiersz in db.execute(sql):
    (n,) = wiersz
    print(f"Liczba kandydatów: {n}")
print("----------");

print("Przykład 2 - jeden wiersz, kilka kolumn:")
sql = """
    Select min(wiek), max(wiek)
    From kandydat
    Where imie = 'ALFRED'
"""
print(sql)
for wiersz in db.execute(sql):
    wiek_min, wiek_max = wiersz
    print(f"Przedział wieku: {wiek_min}-{wiek_max}")
print("----------");

print("Przykład 3 - wiele wierszy, wiele kolumn:")
sql = """
    Select imie, nazwisko, rok_ur
    From kandydat
    Where
        wiek > 40
        And wiek < 45
        And imie in ('BORYS', 'ANGELIKA')
    Order By nazwisko
"""
print(sql)
for wiersz in db.execute(sql):
    imie, nazwisko, rok = wiersz
    print(f"* {nazwisko} {imie} ({rok})")
print(f"----------");


# import required modules
from delivery_schedule import delivery_schedule
import math
from typing import List, Tuple
from tabulate import tabulate

# define function to extract stops from a schedule for a given day
def get_stops_from_schedule(schedule: dict, day: str) -> List[tuple]:
    stops = []
    # loop over each delivery on the given day
    for delivery in schedule[day]["deliveries"]:
        # extract the location coordinates of the delivery and append to stops list
        stop = (delivery["location"]["x"], delivery["location"]["y"])
        stops.append(stop)
    return stops

# define function to calculate distance between two points in 2D space
def distance(x1, y1, x2, y2):
    distance = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
    return distance

# define function to calculate time required to travel a given distance at a given speed
def calculate_delivery_time(distance, speed):
    time = distance / speed
    return time

# define function to calculate the optimal route to visit all stops in a given schedule for a day
def calculate_route(stops):
    # initialize current location of the van to (0, 0)
    current_location = (0, 0)
    # list to hold the route
    route = []
    # loop until all stops have been visited
    while stops:
        # find the closest stop to the current location
        closest_stop = min(stops, key=lambda s: distance(current_location[0], current_location[1], s[0], s[1]))
        # add the closest stop to the route
        route.append(closest_stop)
        # remove the closest stop from the list of stops
        stops.remove(closest_stop)
        # update the current location of the van
        current_location = closest_stop
    # add the starting point to the route
    route.append((0, 0))
    return route

# define function to sort deliveries in a schedule for a given day based on optimal route
def sort_deliveries_by_route(info):
    # Get the stops for the current day
    stops = [(d['location']['x'], d['location']['y']) for d in info['deliveries']]
    # Calculate the route for the day
    route = calculate_route(stops)
    # Sort the deliveries by their position in the route
    deliveries = info['deliveries']
    deliveries_sorted = []
    for r in route:
        for d in deliveries:
            if (d['location']['x'], d['location']['y']) == r:
                deliveries_sorted.append(d)
                break
    return deliveries_sorted

# define function to calculate time required to travel between two stops on a given route at a given speed
def calculate_time_to_next_stop(current_stop: Tuple[int, int], next_stop: Tuple[int, int], speed: int, route: List[Tuple[int, int]]) -> float:
    distance_per_stop = 0
    for i in range(len(route)):
        if route[i] == current_stop:
            for j in range(i+1, len(route)):
                if route[j] == next_stop:
                    distance_per_stop = sum([distance(route[k][0], route[k][1], route[k+1][0], route[k+1][1]) for k in range(i, j)])
                    break
            break
    time = distance_per_stop / speed
    return time * 60  # multiply time in hours by 60 to get time in minutes

def write_delivery_schedule(schedule: dict, filename: str):
    with open(filename, "w") as f:
        # Iterate over each day in the schedule
        for day, info in schedule.items():
            f.write(f"{day}:\n")
            start_time = info["start_time"]
            end_time = info["end_time"]

            # Sort the deliveries by their position in the route
            deliveries = sort_deliveries_by_route(info)

            # Print the stops for the current day
            stops = [(d['location']['x'], d['location']['y']) for d in deliveries] + [(0, 0)]
            f.write(f"Stops for {day}: {stops}\n\n")
            f.write("Good Morning Have a safe drive\n\n")

            # Calculate the route for the day
            route = calculate_route(stops)

            total_distance = 0
            total_time = 0
            for i in range(len(route)):
                current_stop = route[i]
                if i < len(route) - 1:
                    next_stop = route[i + 1]
                    stop_distance = distance(current_stop[0], current_stop[1], next_stop[0], next_stop[1])
                    time = calculate_time_to_next_stop(current_stop, next_stop, 30, route)
                else:
                    stop_distance = 0
                    time = 0
                total_distance += stop_distance
                total_time += time
                f.write(f"Location: ({current_stop[0]}, {current_stop[1]})\n")
                if i < len(route) - 1:
                    f.write(f"Next stop is {stop_distance:.2f} miles away and will take {time:.2f} minutes to get there.\n")
                else:
                    f.write("Welcome Back to HQ.\nThank you for completing all deliveries and returning safely to the headquarters!\n\n")

            # Print the total distance for the day
            f.write(f"Total distance for {day}: {total_distance:.1f} miles\n")
            f.write(f"Total time for {day}: {total_time:.2f} minutes\n\n")

            # Iterate over the sorted deliveries and print their information
            for i, delivery in enumerate(deliveries):
                f.write(f"Delivery {i + 1}:\n")
                f.write(f"Location: ({delivery['location']['x']}, {delivery['location']['y']})\n")
                f.write(f"Address: {delivery['address']}\n")
                f.write("Boxes to be delivered:\n")
                for boxes in delivery["boxes"]:
                    f.write(f"- {boxes}\n")
                f.write("\n")

def print_delivery_schedule_table(schedule: dict, filename: str):
    # Initialize a list to store the data for the table
    table_data = []

    # Iterate over each day in the schedule
    for day, info in schedule.items():
        start_time = info["start_time"]
        end_time = info["end_time"]

        # Sort the deliveries by their position in the route
        deliveries = sort_deliveries_by_route(info)

        # Calculate the stops for the current day
        stops = [(d['location']['x'], d['location']['y']) for d in deliveries] + [(0, 0)]

        # Calculate the route for the day
        route = calculate_route(stops)

        total_distance = 0
        total_time = 0
        for i in range(len(route)):
            current_stop = route[i]
            if i < len(route) - 1:
                next_stop = route[i + 1]
                stop_distance = distance(current_stop[0], current_stop[1], next_stop[0], next_stop[1])
                time = calculate_time_to_next_stop(current_stop, next_stop, 30, route)
            else:
                stop_distance = 0
                time = 0
            total_distance += stop_distance
            total_time += time

        # Add the information for the current day to the table data
        table_data.append([day, start_time, end_time, f"{total_distance:.1f}", f"{total_time:.2f}"])

    # Write the table to a txt file
    with open(filename, "w") as file:
        file.write(tabulate(table_data,
                            headers=["Day", "Start Time", "End Time", "Total Distance (miles)", "Total Time (minutes)"],
                            tablefmt="plain"))

    print(f"Delivery schedule table has been written to {filename}.\n")

# Print the updated delivery schedule
write_delivery_schedule(delivery_schedule, "delivery_schedule.txt")
print_delivery_schedule_table(delivery_schedule, "delivery_schedule_table.txt")


import copy
import sys
from pprint import pprint

from django.apps import apps as django_apps
from django.core.exceptions import ObjectDoesNotExist
from django.utils.module_loading import import_module, module_has_submodule

class RegistryNotLoaded(Exception):
    pass

class AlreadyRegisteredVisitSchedule(Exception):
    pass

class SiteVisitScheduleError(Exception):
    pass

class SiteVisitSchedules:
    """Main controller of :class:`VisitSchedule` objects.

    A visit_schedule contains schedules
    """

    def __init__(self):
        self._registry = {}
        self._all_post_consent_models = None
        self.loaded = False

    @property
    def registry(self):
        pass
        # if not self.loaded:
        #     raise RegistryNotLoaded(
        #         "Registry not loaded. Is AppConfig for 'edcs_visit_schedule' "
        #         "declared in settings?."
        #     )
        # return self._registry

    def register(self, visit_schedule):
        self.loaded = True
        if not visit_schedule.schedules:
            raise SiteVisitScheduleError(
                f"Visit schedule {visit_schedule} has no schedules. "
                f"Add one before registering."
            )
        if visit_schedule.name not in self.registry:
            self.registry.update({visit_schedule.name: visit_schedule})
        else:
            raise AlreadyRegisteredVisitSchedule(
                f"Visit Schedule {visit_schedule} is already registered."
            )
        self._all_post_consent_models = None

    @property
    def visit_schedules(self):
        return self.registry

    def get_visit_schedule(self, visit_schedule_name=None, **kwargs):
        """Returns a visit schedule instance or raises."""
        try:
            visit_schedule_name = visit_schedule_name.split(".")[0]
        except AttributeError:
            pass
        visit_schedule = self.registry.get(visit_schedule_name)
        if not visit_schedule:
            visit_schedule_names = "', '".join(self.registry.keys())
            pprint(self.registry.keys())
            raise SiteVisitScheduleError(
                f"Invalid visit schedule name. Got '{visit_schedule_name}'. "
                f"Expected one of '{visit_schedule_names}'. See {repr(self)}."
            )
        return visit_schedule

    def get_visit_schedules(self, *visit_schedule_names):
        """Returns a dictionary of visit schedules.

        If visit_schedule_name not specified, returns all visit schedules.
        """
        visit_schedules = {}
        for visit_schedule_name in visit_schedule_names:
            try:
                visit_schedule_name = visit_schedule_name.split(".")[0]
            except AttributeError:
                pass
            visit_schedules[visit_schedule_name] = self.get_visit_schedule(
                visit_schedule_name
            )
        return visit_schedules or self.registry

    def get_by_onschedule_model(self, onschedule_model=None):
        """Returns a tuple of (visit_schedule, schedule)
        for the given onschedule model.

        attr `onschedule_model` is in "label_lower" format.
        """
        return self._get_by_model(attr="onschedule_model", model=onschedule_model)

    def get_by_offschedule_model(self, offschedule_model=None):
        """Returns a tuple of visit_schedule, schedule
        for the given offschedule model.

        attr `offschedule_model` is in "label_lower" format.
        """
        return self._get_by_model(attr="offschedule_model", model=offschedule_model)

    def get_by_loss_to_followup_model(self, loss_to_followup_model=None):
        """Returns a tuple of visit_schedule, schedule
        for the given loss_to_followup model.

        attr `loss_to_followup_model` is in "label_lower" format.
        """
        return self._get_by_model(
            attr="loss_to_followup_model", model=loss_to_followup_model
        )

    def _get_by_model(self, attr=None, model=None):
        ret = []
        for visit_schedule in self.visit_schedules.values():
            for schedule in visit_schedule.schedules.values():
                if getattr(schedule, attr) == model:
                    ret.append([visit_schedule, schedule])
        if not ret:
            raise SiteVisitScheduleError(
                f"Schedule not found. No schedule exists for {attr}={model}."
            )
        elif len(ret) > 1:
            raise SiteVisitScheduleError(
                f"Schedule is ambiguous. More than one schedule exists for "
                f"{attr}={model}. Got {ret}"
            )
        return ret[0]

    def get_by_offstudy_model(self, offstudy_model=None):
        """Returns a list of visit_schedules for the given
        offstudy model.
        """
        visit_schedules = []
        for visit_schedule in self.visit_schedules.values():
            if visit_schedule.offstudy_model == offstudy_model:
                visit_schedules.append(visit_schedule)
        if not visit_schedules:
            raise SiteVisitScheduleError(
                f"No visit schedules have been defined using the "
                f"offstudy model '{offstudy_model}'"
            )
        return visit_schedules

    @property
    def all_post_consent_models(self):
        """Returns a dictionary of models that require consent before save.

        {model_name1: consent_model_name, model_name2: consent_model_name, ...}
        """
        if not self._all_post_consent_models:
            models = {}
            for visit_schedule in self.visit_schedules.values():
                models.update(**visit_schedule.all_post_consent_models)
            self._all_post_consent_models = models
        return self._all_post_consent_models

    def check(self):
        if not self.loaded:
            raise SiteVisitScheduleError("Registry is not loaded.")
        errors = {"visit_schedules": [], "schedules": [], "visits": []}
        for visit_schedule in site_visit_schedules.visit_schedules.values():
            errors["visit_schedules"].extend(visit_schedule.check())
            for schedule in visit_schedule.schedules.values():
                errors["schedules"].extend(schedule.check())
                for visit in schedule.visits.values():
                    errors["visits"].extend(visit.check())
        return errors

    def to_model(self, model_cls):
        model_cls.objects.update(active=False)
        for visit_schedule in site_visit_schedules.visit_schedules.values():
            for schedule in visit_schedule.schedules.values():
                for visit in schedule.visits.values():
                    opts = dict(
                        visit_schedule_name=visit_schedule.name,
                        schedule_name=schedule.name,
                        visit_code=visit.code,
                        visit_name=visit.name,
                        visit_title=visit.title,
                        timepoint=visit.timepoint,
                        active=True,
                    )
                    try:
                        obj = model_cls.objects.get(
                            visit_schedule_name=visit_schedule.name,
                            schedule_name=schedule.name,
                            timepoint=visit.timepoint,
                        )
                    except ObjectDoesNotExist:
                        model_cls.objects.create(**opts)
                    else:
                        for fld, value in opts.items():
                            setattr(obj, fld, value)
                        obj.save()

    def autodiscover(self, module_name=None, apps=None, verbose=None):
        """Autodiscovers classes in the visit_schedules.py file of
        any INSTALLED_APP.
        """
        self.loaded = True
        module_name = module_name or "visit_schedules"
        verbose = True if verbose is None else verbose
        if verbose:
            sys.stdout.write(f" * checking site for module '{module_name}' ...\n")
        for app in apps or django_apps.app_configs:
            try:
                mod = import_module(app)
                try:
                    before_import_registry = copy.copy(site_visit_schedules._registry)
                    import_module(f"{app}.{module_name}")
                    if verbose:
                        sys.stdout.write(
                            " * registered visit schedule from " f"'{app}'\n"
                        )
                except Exception as e:
                    if f"No module named '{app}.{module_name}'" not in str(e):
                        raise
                    site_visit_schedules._registry = before_import_registry
                    if module_has_submodule(mod, module_name):
                        raise
            except ModuleNotFoundError:
                pass

site_visit_schedules = SiteVisitSchedules()


import unittest
from unittest import mock
from parameterFileParser import parse_pairwise_alignments, parse_param_file
from dotalignerWrapper import DotAlignerWrapper, DotAlignerGrouped
from collections import OrderedDict

class TestPairListParameters(unittest.TestCase):

    def setUp(self):
        self.file_content = ['M35570.1_5-120\tX12624.1_61-178\tapsi-37\tsci-107\tno-1',
                             'M19950.1_1-120\tX52300.1_5-122\tapsi-37\tsci-89\tno-1']
        self.file_name = "test.txt"

    def test_parse_pairwise_alignments(self):
        m = unittest.mock.mock_open(read_data='\n'.join(self.file_content))
        m.return_value.__iter__ = lambda self: self
        m.return_value.__next__ = lambda self: self.readline()
        with mock.patch('builtins.open',m ):
            results = parse_pairwise_alignments(self.file_name)
        self.assertEqual(results, [['M35570.1_5-120' , 'X12624.1_61-178'], ['M19950.1_1-120', 'X52300.1_5-122']])

class TestParameters(unittest.TestCase):
    def setUp(self):
        self.file_content = ['Parameters\tValue', 'e\t1,2','k\t2']
        self.file_name = "text.txt"

    def test_parse_param_file(self):
        m = unittest.mock.mock_open(read_data='\n'.join(self.file_content))
        m.return_value.__iter__ = lambda self: self
        m.return_value.__next__ = lambda self: self.readline()
        with mock.patch('builtins.open',m ):
            results = parse_param_file(self.file_name)

        self.assertDictEqual(results, {"e" : ['1', '2'] , 'k' : ['2']})

class TestDotAlignerWrapper(unittest.TestCase):

    def side_effect(self, file_name):
        if file_name == '/found':
            return True
        else :
            return False

    def test_dotaligner_wrapper(self):
        mock_object = unittest.mock.Mock( side_effect=self.side_effect)
        with unittest.mock.patch('os.path.exists', mock_object ) as m :
            da = DotAlignerWrapper('/found')
        self.assertIsNotNone(da)
        with unittest.mock.patch('os.path.exists', mock_object ) as m :
            self.assertRaises(FileNotFoundError, DotAlignerWrapper, '/unfound')

    def test_dotaligner_wrapper_add_params(self):

        mock_object = unittest.mock.Mock( side_effect= self.side_effect)
        params  = {"e" : ['10','20']}
        with unittest.mock.patch('os.path.exists', mock_object ) as m :
            da = DotAlignerWrapper('/found')
            da.update_parameters(params)
            self.assertDictEqual(da.params_dict,    {
            'e' : ['10','20'],
            'o' : ['1'],
            't' : ['0.5'],
            'k' : ['0.5'],
            'T' : ['1'],
            'S' : ['10'],
        })

    def test_get_combinatios(self):
        mock_object = unittest.mock.Mock( side_effect= self.side_effect)
        params  = {"e" : ['10','20']}
        with unittest.mock.patch('os.path.exists', mock_object ) as m :
            da = DotAlignerWrapper('/found')
            da.update_parameters(params)
            comb_iter = da.get_combinations()
            comb_iter = list(comb_iter)
        self.assertListEqual(comb_iter,
                             [{'e' : '10', 'o': '1' ,'t' : '0.5' , 'k' : '0.5', 'T' : '1', 'S' : '10' },
                              {'e' : '20', 'o': '1' ,'t' : '0.5' , 'k' : '0.5', 'T' : '1', 'S' : '10' }])

    def test_add_pairs(self):
        mock_object = unittest.mock.Mock( side_effect= self.side_effect)
        params  = {"e" : ['10','20']}
        with unittest.mock.patch('os.path.exists', mock_object ) as m :
            da = DotAlignerWrapper('/found')
            da.add_pairs([['a', 'b']])
            self.assertListEqual(da.pairs,[ ['a','b']])

    def test_generate_and_run(self):
        mock_object = unittest.mock.Mock( side_effect= self.side_effect)
        with unittest.mock.patch('os.path.exists', mock_object ) as m :
            with unittest.mock.patch.object(DotAlignerWrapper, 'run_dotaligner') as dot_mock:
                da = DotAlignerWrapper('/found')
                da.add_pairs([['a', 'b']])
                da.generate_and_run()
                dot_mock.assert_called_with(
                    "(time -f '\\t%E\\t%M' /found -k 0.5 -t 0.5 -o 1 -e 0.2 -s 10 -T 1 -d a_dp.pp -d b_dp.pp; ) >> out/k_0.5-t_0.5-o_1-e_0.2-T_1.dotaligner.out 2>&1",
                    ['a','b'],
                    OrderedDict([('e', '0.2'), ('o', '1'), ('t', '0.5'), ('k', '0.5'), ('T', '1'), ('S', '10')])
                )

class TestDotAlignerGrouped(unittest.TestCase):
    def side_effect(self, file_name):
        if file_name == '/found':
            return True
        else :
            return False

    def test_initialization(self):
        mock_object = unittest.mock.Mock( side_effect= self.side_effect)
        with unittest.mock.patch('os.path.exists', mock_object ) as m :
            da = DotAlignerGrouped('/found')
            self.assertEqual(da.current_id, None)
            self.assertEqual(da.command_list, [])

    def test_run_dotaligner(self):
        fh = unittest.mock.mock_open()
        mock_object = unittest.mock.Mock( side_effect= self.side_effect)
        with unittest.mock.patch('os.path.exists', mock_object ) as m :
            da = DotAlignerGrouped('/found')
            da.add_pairs([['a','b'], ['b','c']])
            params  = {"e" : ['10','20']}
            da.update_parameters(params)
            with unittest.mock.patch('builtins.open', fh):
                da.generate_and_run()
                calls = unittest.mock.call
                calls_list = [calls('e_10_o_1_t_0.5_k_0.5_T_1_S_10' ,'w'), calls('e_20_o_1_t_0.5_k_0.5_T_1_S_10' ,'w')]
                fh.assert_has_calls(calls_list, any_order=True)
                handle = fh()
                calls_list =  [
                    calls("(time -f '\\t%E\\t%M' /found -k 0.5 -t 0.5 -o 1 -e 10 -s 10 -T 1 -d a_dp.pp -d b_dp.pp; ) >> out/k_0.5-t_0.5-o_1-e_10-T_1.dotaligner.out 2>&1\n" +\
                          "(time -f '\\t%E\\t%M' /found -k 0.5 -t 0.5 -o 1 -e 10 -s 10 -T 1 -d b_dp.pp -d c_dp.pp; ) >> out/k_0.5-t_0.5-o_1-e_10-T_1.dotaligner.out 2>&1"),
                    calls("(time -f '\\t%E\\t%M' /found -k 0.5 -t 0.5 -o 1 -e 20 -s 10 -T 1 -d a_dp.pp -d b_dp.pp; ) >> out/k_0.5-t_0.5-o_1-e_20-T_1.dotaligner.out 2>&1\n" +\
                          "(time -f '\\t%E\\t%M' /found -k 0.5 -t 0.5 -o 1 -e 20 -s 10 -T 1 -d b_dp.pp -d c_dp.pp; ) >> out/k_0.5-t_0.5-o_1-e_20-T_1.dotaligner.out 2>&1")
                ]
                handle.write.assert_has_calls(calls_list)

if __name__ == '__main__':
    unittest.main()


import pandas as pd
import requests
from selenium import webdriver
import time
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
from selenium.webdriver.firefox.options import Options

path = '파일 위치'

df = pd.read_csv(f'{path}/youtube_name.csv')

options = Options()
options.set_preference('intl.accept_languages', 'ko')
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.35")

driver = webdriver.Firefox(options=options)

data = {
    "channel_name" : [],
    "video_id" : []
}

for name in df['channel_name']:
    try:
        url=f"https://www.youtube.com/{name}/videos"

        driver.get(url)

        time.sleep(2)
        html = driver.page_source
        time.sleep(2)
        soup = BeautifulSoup(html,'html.parser')

        contents = driver.find_element(By.ID,'video-title-link')
        video_id = contents.get_attribute('href')[32:]
        print(video_id)
        time.sleep(2)
        data['channel_name'].append(name)
        data['video_id'].append(video_id)
        time.sleep(2)

    except:
        time.sleep(2)
        data['channel_name'].append(name)
        data['video_id'].append(None)

    finally:
        df1 = pd.DataFrame(data)
        df1.to_csv(f'{path}/youtube_video_id.csv',encoding='utf-8')

driver.quit()


"""Timeplus target sink class, which handles writing streams."""

from __future__ import annotations

from singer_sdk import PluginBase
from singer_sdk.sinks import BatchSink

from timeplus import Stream, Environment
import json
import datetime

class TimeplusSink(BatchSink):
    """Timeplus target sink class."""

    def __init__(  # noqa: D107
        self,
        target: PluginBase,
        stream_name: str,
        schema: Dict,
        key_properties: Optional[List[str]],
    ) -> None:

        super().__init__(target, stream_name, schema, key_properties)

        # self.logger.info(f"__init__ stream:{stream_name}, schema {schema}")

        endpoint = self.config["endpoint"]
        apikey = self.config["apikey"]
        if endpoint[-1] == '/':
            endpoint = endpoint[0:len(endpoint) - 1]
        env = Environment().address(endpoint).apikey(apikey)
        self.env = env

        stream_list = Stream(env=env).list()
        all_streams = {s.name for s in stream_list}
        stream_exists = stream_name in all_streams
        self.logger.info(f"__init__ stream_exists:{stream_exists}")
        if not stream_exists:
            TimeplusSink.create_stream(env, stream_name, schema)

    @staticmethod
    def create_stream(env, stream_name: str, schema: Dict):
        # singlel-column stream
        # Stream(env=env).name(stream.name).column('raw','string').create()

        tp_stream = Stream(env=env).name(stream_name.strip())
        for name, v in schema['properties'].items():
            tp_stream.column(name.strip(), TimeplusSink.type_mapping(v))

        tp_stream.create()

    @staticmethod
    def type_mapping(v) -> str:
        data_type = v['type']
        if type(data_type) is list:
            for t in list(data_type):
                if t != 'null':
                    type_def = {'type': t}
                    if t == 'array':
                        type_def['items'] = v['items']
                    return TimeplusSink.type_mapping(type_def)
        if data_type == 'number':
            return 'float'
        elif data_type == 'integer':
            return 'integer'
        elif data_type == 'boolean':
            return 'bool'
        elif data_type == 'object':
            return 'string'
        elif data_type == 'array':
            return f"array({TimeplusSink.type_mapping(v['items'])})"
        else:
            return 'string'

    def start_batch(self, context: dict) -> None:
        """Start a batch.

        Developers may optionally add additional markers to the `context` dict,
        which is unique to this batch.

        Args:
            context: Stream partition or context dictionary.
        """
        # self.logger.info(f"stream:{self.stream_name}, start_batch {context}")
        self.rows = []

    def process_record(self, record: dict, context: dict) -> None:
        # self.logger.info(f"process_record stream:{self.stream_name}, record: {record}, and context: {context}")
        """Process the record.

        Developers may optionally read or write additional markers within the
        passed `context` dict from the current batch.

        Args:
            record: Individual record in the stream.
            context: Stream partition or context dictionary.
        """
        # Define a custom function to serialize datetime objects
        def serialize_datetime(obj):
            if isinstance(obj, datetime.datetime):
                return obj.isoformat()
            raise TypeError("Type not serializable")

        self.rows.append(json.dumps(record, default=serialize_datetime))

        #force flush the batch to avoid sending too much data (over 10MB) to Timeplus
        if len(self.rows) > 100:
            self.process_batch(context=dict())
            self.start_batch(context=dict())

    def process_batch(self, context: dict) -> None:
        """Write out any prepped records and return once fully written.

        Args:
            context: Stream partition or context dictionary.
        """
        # self.logger.info(f"process_batch stream:{self.stream_name},  {context}")

        Stream(env=self.env).name(self.stream_name.strip()).ingest(payload='\n'.join(self.rows),format="streaming")


from shesha.supervisor.genericSupervisor import GenericSupervisor
from shesha.supervisor.components import AtmosCompass, DmCompass, RtcCompass, TargetCompass, TelescopeCompass, WfsCompass, CoronagraphCompass
from shesha.supervisor.optimizers import ModalBasis, Calibration, ModalGains
import numpy as np
import time

import shesha.constants as scons

from typing import Iterable

class CompassSupervisor(GenericSupervisor):
    """ This class implements generic supervisor to handle compass simulation

    Attributes inherited from GenericSupervisor:
        context : (CarmaContext) : a CarmaContext instance

        config : (config) : Parameters structure

        is_init : (bool) : Flag equals to True if the supervisor has already been initialized

        iter : (int) : Frame counter

    Attributes:
        telescope : (TelescopeComponent) : a TelescopeComponent instance

        atmos : (AtmosComponent) : An AtmosComponent instance

        target : (targetComponent) : A TargetComponent instance

        wfs : (WfsComponent) : A WfsComponent instance

        dms : (DmComponent) : A DmComponent instance

        rtc : (RtcComponent) : A Rtc component instance

        cacao : (bool) : CACAO features enabled in the RTC

        basis : (ModalBasis) : a ModalBasis instance (optimizer)

        calibration : (Calibration) : a Calibration instance (optimizer)

        modalgains : (ModalGains) : a ModalGain instance (optimizer) using CLOSE algorithm

        close_modal_gains : (list of floats) : list of the previous values of the modal gains
    """

    def __init__(self, config, *, cacao: bool = False):
        """ Instantiates a CompassSupervisor object

        Args:
            config: (config module) : Configuration module

        Kwargs:
            cacao : (bool) : If True, enables CACAO features in RTC (Default is False)
                                      Requires OCTOPUS to be installed
        """
        self.cacao = cacao
        self.tel = None
        self.atmos = None
        self.target = None
        self.wfs = None
        self.dms = None
        self.rtc = None
        self.corono = None

        GenericSupervisor.__init__(self, config)
        self.basis = ModalBasis(self.config, self.dms, self.target)
        self.calibration = Calibration(self.config, self.tel, self.atmos, self.dms,
                                       self.target, self.rtc, self.wfs)
        if config.p_controllers is not None:
            self.modalgains = ModalGains(self.config, self.rtc)
        self.close_modal_gains = []

#     ___                  _      __  __     _   _            _
#    / __|___ _ _  ___ _ _(_)__  |  \/  |___| |_| |_  ___  __| |___
#   | (_ / -_) ' \/ -_) '_| / _| | |\/| / -_)  _| ' \/ _ \/ _` (_-<
#    \___\___|_||_\___|_| |_\__| |_|  |_\___|\__|_||_\___/\__,_/__/

    def _init_tel(self):
        """Initialize the telescope component of the supervisor as a TelescopeCompass
        """
        self.tel = TelescopeCompass(self.context, self.config)

    def _init_atmos(self):
        """Initialize the atmosphere component of the supervisor as a AtmosCompass
        """
        self.atmos = AtmosCompass(self.context, self.config)

    def _init_dms(self):
        """Initialize the DM component of the supervisor as a DmCompass
        """
        self.dms = DmCompass(self.context, self.config)

    def _init_target(self):
        """Initialize the target component of the supervisor as a TargetCompass
        """
        if self.tel is not None:
            self.target = TargetCompass(self.context, self.config, self.tel)
        else:
            raise ValueError("Configuration not loaded or Telescope not initilaized")

    def _init_wfs(self):
        """Initialize the wfs component of the supervisor as a WfsCompass
        """
        if self.tel is not None:
            self.wfs = WfsCompass(self.context, self.config, self.tel)
        else:
            raise ValueError("Configuration not loaded or Telescope not initilaized")

    def _init_rtc(self):
        """Initialize the rtc component of the supervisor as a RtcCompass
        """
        if self.wfs is not None:
            self.rtc = RtcCompass(self.context, self.config, self.tel, self.wfs,
                                  self.dms, self.atmos, cacao=self.cacao)
        else:
            raise ValueError("Configuration not loaded or Telescope not initilaized")

    def _init_components(self) -> None:
        """ Initialize all the components
        """

        if self.config.p_tel is None or self.config.p_geom is None:
            raise ValueError("Telescope geometry must be defined (p_geom and p_tel)")
        self._init_tel()

        if self.config.p_atmos is not None:
            self._init_atmos()
        if self.config.p_dms is not None:
            self._init_dms()
        if self.config.p_targets is not None:
            self._init_target()
        if self.config.p_wfss is not None:
            self._init_wfs()
        if self.config.p_controllers is not None or self.config.p_centroiders is not None:
            self._init_rtc()
        if self.config.p_coronos is not None:
            self._init_coronagraph()

        GenericSupervisor._init_components(self)

    def _init_coronagraph(self):
        """ Initialize the coronagraph
        """
        self.corono = CoronagraphCompass()
        for p_corono in self.config.p_coronos:
            self.corono.add_corono(self.context, p_corono, self.config.p_geom, self.target)

    def next(self, *, move_atmos: bool = True, nControl: int = 0,
             tar_trace: Iterable[int] = None, wfs_trace: Iterable[int] = None,
             do_control: bool = True, apply_control: bool = True,
             compute_tar_psf: bool = True, compute_corono: bool=True) -> None:
        """Iterates the AO loop, with optional parameters.

        Overload the GenericSupervisor next() method to handle the GEO controller
        specific raytrace order operations

        Kwargs:
            move_atmos: (bool): move the atmosphere for this iteration. Default is True

            nControl: (int): Controller number to use. Default is 0 (single control configuration)

            tar_trace: (List): list of targets to trace. None is equivalent to all (default)

            wfs_trace: (List): list of WFS to trace. None is equivalent to all (default)

            do_control : (bool) : Performs RTC operations if True (Default)

            apply_control: (bool): if True (default), apply control on DMs

            compute_tar_psf : (bool) : If True (default), computes the PSF at the end of the iteration

            compute_corono: (bool): If True (default), computes the coronagraphic image
        """
        try:
            iter(nControl)
        except TypeError:
            # nControl is not an iterable creating a list
            nControl = [nControl]

        #get the index of the first GEO controller (-1 if there is no GEO controller)
        geo_index = next(( i for i,c in enumerate(self.config.p_controllers)
            if c.type== scons.ControllerType.GEO ), -1)

        if tar_trace is None and self.target is not None:
            tar_trace = range(len(self.config.p_targets))
        if wfs_trace is None and self.wfs is not None:
            wfs_trace = range(len(self.config.p_wfss))

        if move_atmos and self.atmos is not None:
            self.atmos.move_atmos()
        # in case there is at least 1 controller GEO in the controller list : use this one only
        self.tel.update_input_phase()
        if ( geo_index > -1):
            nControl = geo_index
            if tar_trace is not None:
                for t in tar_trace:
                    if self.atmos.is_enable:
                        self.target.raytrace(t, tel=self.tel, atm=self.atmos, ncpa=False)
                    else:
                        self.target.raytrace(t, tel=self.tel, ncpa=False)

                    if do_control and self.rtc is not None:
                        self.rtc.do_control(nControl, sources=self.target.sources)
                        self.target.raytrace(t, dms=self.dms, ncpa=True, reset=False)
                        if apply_control:
                            self.rtc.apply_control(nControl)
                        if self.cacao:
                            self.rtc.publish()
        else:
            if tar_trace is not None: # already checked at line 213?
                for t in tar_trace:
                    if self.atmos.is_enable:
                        self.target.raytrace(t, tel=self.tel, atm=self.atmos,
                                             dms=self.dms)
                    else:
                        self.target.raytrace(t, tel=self.tel, dms=self.dms)

            if wfs_trace is not None: # already checked at line 215?
                for w in wfs_trace:
                    if self.atmos.is_enable:
                        self.wfs.raytrace(w, tel=self.tel, atm=self.atmos)
                    else:
                        self.wfs.raytrace(w, tel=self.tel)

                    if not self.config.p_wfss[w].open_loop and self.dms is not None:
                        self.wfs.raytrace(w, dms=self.dms, ncpa=False, reset=False)
                    self.wfs.compute_wfs_image(w)
            if do_control and self.rtc is not None:
                for ncontrol in nControl : # range(len(self.config.p_controllers)):
                    self.rtc.do_centroids(ncontrol)
                    self.rtc.do_control(ncontrol)
                    self.rtc.do_clipping(ncontrol)

            if apply_control:
                for ncontrol in nControl :
                    self.rtc.apply_control(ncontrol)

            if self.cacao:
                self.rtc.publish()

        if compute_tar_psf:
            for tar_index in tar_trace:
                self.target.comp_tar_image(tar_index)
                self.target.comp_strehl(tar_index)

        if self.corono is not None and compute_corono:
            for coro_index in range(len(self.config.p_coronos)):
                self.corono.compute_image(coro_index)

        if self.config.p_controllers[0].close_opti and (not self.rtc._rtc.d_control[0].open_loop):
            self.modalgains.update_mgains()
            self.close_modal_gains.append(self.modalgains.get_modal_gains())

        self.iter += 1

    def _print_strehl(self, monitoring_freq: int, iters_time: float, total_iters: int, *,
                      tar_index: int = 0):
        """ Print the Strehl ratio SE and LE from a target on the terminal, the estimated remaining time and framerate

        Args:
            monitoring_freq : (int) : Number of frames between two prints

            iters_time : (float) : time elapsed between two prints

            total_iters : (int) : Total number of iterations

        Kwargs:
            tar_index : (int) : Index of the target. Default is 0
        """
        framerate = monitoring_freq / iters_time
        strehl = self.target.get_strehl(tar_index)
        etr = (total_iters - self.iter) / framerate
        print("%d \t %.3f \t  %.3f\t     %.1f \t %.1f" % (self.iter + 1, strehl[0],
                                                          strehl[1], etr, framerate))

    def loop(self, number_of_iter: int, *, monitoring_freq: int = 100,
             compute_tar_psf: bool = True, **kwargs):
        """ Perform the AO loop for <number_of_iter> iterations

        Args:
            number_of_iter: (int) : Number of iteration that will be done

        Kwargs:
            monitoring_freq: (int) : Monitoring frequency [frames]. Default is 100

            compute_tar_psf : (bool) : If True (default), computes the PSF at each iteration
                                                 Else, only computes it each <monitoring_freq> frames
        """
        if not compute_tar_psf:
            print("WARNING: Target PSF will be computed (& accumulated) only during monitoring"
                  )

        print("----------------------------------------------------")
        print("iter# | S.E. SR | L.E. SR | ETR (s) | Framerate (Hz)")
        print("----------------------------------------------------")
        # self.next(**kwargs)
        t0 = time.time()
        t1 = time.time()
        if number_of_iter == -1:  # Infinite loop
            while (True):
                self.next(compute_tar_psf=compute_tar_psf, **kwargs)
                if ((self.iter + 1) % monitoring_freq == 0):
                    if not compute_tar_psf:
                        self.target.comp_tar_image(0)
                        self.target.comp_strehl(0)
                    self._print_strehl(monitoring_freq, time.time() - t1, number_of_iter)
                    t1 = time.time()

        for _ in range(number_of_iter):
            self.next(compute_tar_psf=compute_tar_psf, **kwargs)
            if ((self.iter + 1) % monitoring_freq == 0):
                if not compute_tar_psf:
                    self.target.comp_tar_image(0)
                    self.target.comp_strehl(0)
                self._print_strehl(monitoring_freq, time.time() - t1, number_of_iter)
                t1 = time.time()
        t1 = time.time()
        print(" loop execution time:", t1 - t0, "  (", number_of_iter, "iterations), ",
              (t1 - t0) / number_of_iter, "(mean)  ", number_of_iter / (t1 - t0), "Hz")

    def reset(self):
        """ Reset the simulation to return to its original state
        """
        self.atmos.reset_turbu()
        self.wfs.reset_noise()
        for tar_index in range(len(self.config.p_targets)):
            self.target.reset_strehl(tar_index)
        self.dms.reset_dm()
        self.rtc.open_loop()
        self.rtc.close_loop()

#    ___              _  __ _      __  __     _   _            _
#   / __|_ __  ___ __(_)/ _(_)__  |  \/  |___| |_| |_  ___  __| |___
#   \__ \ '_ \/ -_) _| |  _| / _| | |\/| / -_)  _| ' \/ _ \/ _` (_-<
#   |___/ .__/\___\__|_|_| |_\__| |_|  |_\___|\__|_||_\___/\__,_/__/
#       |_|

    def record_ao_circular_buffer(
            self, cb_count: int, sub_sample: int = 1, controller_index: int = 0,
            tar_index: int = 0, see_atmos: bool = True, cube_data_type: str = None,
            cube_data_file_path: str = "", ncpa: int = 0, ncpa_wfs: np.ndarray = None,
            ref_slopes: np.ndarray = None, ditch_strehl: bool = True,
            projection_matrix: np.ndarray = None):
        """ Used to record a synchronized circular buffer AO loop data.

        Args:
            cb_count: (int) : the number of iterations to record.

            sub_sample:  (int) : sub sampling of the data (default=1, I.e no subsampling)

            controller_index:  (int) :

            tar_index:  (int) : target number

            see_atmos:  (int) : used for the next function to enable or not the Atmos

            cube_data_type:   (int) : if  specified ("tarPhase" or "psfse") returns the target phase or short exposure PSF data cube in the output variable

            cube_data_file_path:  (int) : if specified it will also save the target phase cube data (full path on the server)

            ncpa:  (int) : !!experimental!!!: Used only in the context of PYRWFS + NCPA compensation on the fly (with optical gain)
            defines how many iters the NCPA refslopes are updates with the proper optical gain. Ex: if NCPA=10 refslopes will be updates every 10 iters.

            ncpa_wfs:  (int) : the ncpa phase as seen from the wfs array with dims = size of Mpupil

            ref_slopes:  (int) : the reference slopes to use.

            ditch_strehl:  (int) : resets the long exposure SR computation at the beginning of the Circular buffer (default= True)

            projection_matrix : (np.ndarray) : projection matrix on modal basis to compute residual coefficients

        Returns:
            slopes:  (int) : the slopes CB

            volts:  (int) : the volts applied to the DM(s) CB

            ai:  (int) : the modal coefficient of the residual phase projected on the currently used modal Basis

            psf_le:  (int) : Long exposure PSF over the <cb_count> iterations (I.e SR is reset at the begining of the CB if ditch_strehl=True)

            strehl_se_list:  (int) : The SR short exposure evolution during CB recording

            strehl_le_list:  (int) : The SR long exposure evolution during CB recording

            g_ncpa_list:  (int) : the gain applied to the NCPA (PYRWFS CASE) if NCPA is set to True

            cube_data:  (int) : the tarPhase or psfse cube data (see cube_data_type)
        """
        slopes_data = None
        volts_data = None
        cube_data = None
        ai_data = None
        k = 0
        sthrel_se_list = []
        sthrel_le_list = []
        g_ncpa_list = []

        # Resets the target so that the PSF LE is synchro with the data
        # Doesn't reset it if Ditch_strehl == False (used for real time gain computation)
        if ditch_strehl:
            for i in range(len(self.config.p_targets)):
                self.target.reset_strehl(i)

        # Starting CB loop...
        for j in range(cb_count):
            print(j, end="\r")
            if (ncpa):
                if (j % ncpa == 0):
                    ncpa_diff = ref_slopes[None, :]
                    ncpa_turbu = self.calibration.do_imat_phase(
                            controller_index, -ncpa_wfs[None, :, :], noise=False,
                            with_turbu=True)
                    g_ncpa = float(
                            np.sqrt(
                                    np.dot(ncpa_diff, ncpa_diff.T) / np.dot(
                                            ncpa_turbu, ncpa_turbu.T)))
                    if (g_ncpa > 1e18):
                        g_ncpa = 0
                        print('Warning NCPA ref slopes gain too high!')
                        g_ncpa_list.append(g_ncpa)
                        self.rtc.set_ref_slopes(-ref_slopes * g_ncpa)
                    else:
                        g_ncpa_list.append(g_ncpa)
                        print('NCPA ref slopes gain: %4.3f' % g_ncpa)
                        self.rtc.set_ref_slopes(-ref_slopes / g_ncpa)

            self.atmos.enable_atmos(see_atmos)
            self.next()
            for t in range(len(self.config.p_targets)):
                self.target.comp_tar_image(t)

            srse, srle, _, _ = self.target.get_strehl(tar_index)
            sthrel_se_list.append(srse)
            sthrel_le_list.append(srle)
            if (j % sub_sample == 0):
                if (projection_matrix is not None):
                    ai_vector = self.calibration.compute_modal_residuals(
                            projection_matrix, selected_actus=self.basis.selected_actus)
                    if (ai_data is None):
                        ai_data = np.zeros((len(ai_vector), int(cb_count / sub_sample)))
                    ai_data[:, k] = ai_vector

                slopes_vector = self.rtc.get_slopes(controller_index)
                if (slopes_data is None):
                    slopes_data = np.zeros((len(slopes_vector),
                                            int(cb_count / sub_sample)))
                slopes_data[:, k] = slopes_vector

                volts_vector = self.rtc.get_command(
                        controller_index)  # get_command or get_voltages ?
                if (volts_data is None):
                    volts_data = np.zeros((len(volts_vector),
                                           int(cb_count / sub_sample)))
                volts_data[:, k] = volts_vector

                if (cube_data_type):
                    if (cube_data_type == "tarPhase"):
                        dataArray = self.target.get_tar_phase(tar_index, pupil=True)
                    elif (cube_data_type == "psfse"):
                        dataArray = self.target.get_tar_image(tar_index, expo_type="se")
                    else:
                        raise ValueError("unknown dataData" % cube_data_type)
                    if (cube_data is None):
                        cube_data = np.zeros((*dataArray.shape,
                                              int(cb_count / sub_sample)))
                    cube_data[:, :, k] = dataArray
                k += 1
        if (cube_data_file_path != ""):
            print("Saving tarPhase cube at: ", cube_data_file_path)
            from astropy.io import fits as pf
            pf.writeto(cube_data_file_path, cube_data, overwrite=True)

        psf_le = self.target.get_tar_image(tar_index, expo_type="le")
        return slopes_data, volts_data, ai_data, psf_le, sthrel_se_list, sthrel_le_list, g_ncpa_list, cube_data

    def export_config(self):
        """
        Extract and convert compass supervisor configuration parameters
        into 2 dictionnaries containing relevant AO parameters

        Args:
            root: (object), COMPASS supervisor object to be parsed

        Returns :
            2 dictionaries... See F. Vidal :)
        """
        return self.config.export_config()

    def get_s_pupil(self):
        """
        Returns the so called S Pupil of COMPASS

        Return:
            s_pupil: (np.array) : S Pupil of COMPASS
        """
        return self.config.p_geom.get_spupil()

    def get_i_pupil(self):
        """
        Returns the so called I Pupil of COMPASS

        Return:
            i_pupil: (np.array) : I Pupil of COMPASS
        """
        return self.config.p_geom.get_ipupil()

    def get_m_pupil(self):
        """
        Returns the so called M Pupil of COMPASS

        Return:
            m_pupil: (np.array) : M Pupil of COMPASS
        """
        return self.config.p_geom.get_mpupil()


import sqlite3
from SQLdatabase import SQLdatabase
import re

class Database:
    def __init__(self):
        self.years = list()  # list for years
        self.median = list()  # list for median
        self.upper = list()
        self.lower = list()
        self.SQ = SQLdatabase()
        self.SQ.Table()
        self.SQ.insertBLOB(1, "Temperature", "Temperature.png", "Temperature.html")
        try:
            self.SQ.sqliteConnection = sqlite3.connect('SQLite_Python.db')
            cursor = self.SQ.sqliteConnection.cursor()
            print("Connected to SQLite")

            sqlite_select_query = """SELECT html from Database"""
            cursor.execute(sqlite_select_query)
            records = cursor.fetchall()
            for row in records:
                for i in row:
                    fields = re.findall( #Using findall because i is actually one line
                        r"(\d{4}).*?([-][0]+[.]\d+|[0]+[.]\d+).*?([-][0]+[.]\d+|[0]+[.]\d+|[0]).*?([-][0]+[.]\d+|[0]+["
                        r".]\d+)",
                        i.decode(
                            "utf-8"))  # Needed because i is in bytes. Using the decode function to turn i into string
                    for x in fields:
                        self.years.append(float(x[0]))
                        self.median.append(float(x[1]))
                        self.upper.append(float(x[2]))
                        self.lower.append(float(x[3]))

            cursor.close()

        except sqlite3.Error as error:
            print("Failed to read data from sqlite table", error)

def main():
   BE = Database()

if __name__ == "__main__":
    main()


from django.conf import settings
from rest_framework import serializers

from groups.models import Group
from userProfile.models import UserProfile
from users.serializers import ProfileSearchSerializer

class GroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = Group
        fields = '__all__'
        read_only_fields = ('leader', )

    def create(self, validated_data):
        group_members = validated_data.pop('group_members')
        validated_data['leader'] = self.context['leader']
        group = Group.objects.create(**validated_data)
        group.group_members.set(group_members)

        return group

class GroupDetailSerializer(serializers.ModelSerializer):
    group_members = serializers.SerializerMethodField()

    class Meta:
        model = Group
        fields = ['id', 'group_name', 'group_members']

    def get_group_members(self, obj):
        user_profiles = UserProfile.objects.filter(user__in=obj.group_members.all())
        users = []

        for profile in user_profiles:
            full_name = profile.get_full_name

            if full_name is None:
                full_name = ''

            profile_pic = ''
            if profile.profile_pics != '':
                profile_pic = settings.MEDIA_URL+str(profile.profile_pics)

            user = {
                'user_id': profile.user.id,
                'user_name': full_name,
                'profile_pics': profile_pic
            }
            users.append(user)
        return users