"""
Memory - 59,724 KB
Time - 222 ms
"""

import sys
sys.stdin = open('input.txt')

T = int(input())

for tc in range(1, T+1):
    N = int(input())
    num_li = list(map(int, input().split()))
    answer_li = [1] + ([0] * sum(num_li))

    start_idx = 0                           # 현재 가능한 가장 큰 수 (반복횟수 줄이기 위함)
    for e in num_li:
        idx = start_idx
        while idx >= 0:                     # 인덱스가 0번 까지
            if answer_li[idx]:              # 가능한 점수이면
                answer_li[idx+e] = 1        # 그 점수에 현재 점수를 더한것을 가능하게 표시
                if idx + e > start_idx:     # 가장 큰수가 변경되면
                    start_idx = idx + e
            idx -= 1

    answer = sum(answer_li)

    print('#{} {}'.format(tc, answer))

print('-----')

"""
비트마스킹
"""

import sys
sys.stdin = open('input.txt')

T = int(input())

for tc in range(1, T+1):
    N = int(input())
    n_li = list(map(int, input().split()))
    a = 1

    for i in n_li:
        a |= a << i

    print('#{} {}'.format(tc, bin(a).count('1')))

    # for k in range(N+1):
    #     collect = set(combinations(n_li, k))
    #     # print('LOG --- TC : {} ___ COLLECT : {}'.format(tc, collect))

    #     for element in collect:
    #         answer.add(sum(element))


import os

import pytest

from tests.setup_test_sql_db import SqlServerWrapper

@pytest.fixture(scope="session")
def sql_test_db(tmpdir_factory):
    data_dir = tmpdir_factory.mktemp("db_dir")
    sql_db = SqlServerWrapper(data_dir)
    sql_db.start()
    # export db params
    os.environ["MYSQL_USER"] = "root"
    os.environ["MYSQL_HOST"] = "127.0.0.1"
    os.environ["MYSQL_PW"] = ""
    print("fixture")
    print(sql_db)
    yield sql_db
    sql_db.stop()


import csv
import datetime
import time
from gui.uis.custom.api import WebAPI
from gui.uis.custom.node_sort_filter_proxy_model import NodeSortFilterProxyModel
from gui.uis.custom.result_tree_view import ResultTreeView
from gui.uis.custom.styled_button import StyledButton
from gui.uis.custom.time_series_table_model import TimeSeriesTableModel
from gui.uis.custom.time_series_table_view import TimeSeriesTableView
from gui.uis.custom.time_series_tree_view import TimeSeriesTreeView
from gui.uis.custom.constants import plot_colors
from gui.widgets.comboBoxSearchable.comboBoxSearchable import style as comboBox_style
from gui.widgets.py_date_edit import PyDateEdit
from gui.widgets.py_line_edit.py_line_edit import PyLineEdit
from pyqtgraph import DateAxisItem, PlotWidget, mkPen
from qt_core import *

class ResultsController:
    def __init__(self, api: WebAPI, layout: QBoxLayout, themes: dict) -> None:
        self.api = api
        self.current_sample_from = ""
        self.current_sample_to = ""
        self.averages_only = False
        self.from_date = QDate(1900, 1, 1)
        self.to_date = QDate(3000, 1, 1)

        self.setup_layout(layout, themes)

    def load_results(self):
        self.results_tree.rootModel.clear()
        self.results = self.api.list_results()
        for result in self.results:
            self.results_tree.rootModel.invisibleRootItem().appendRow(QStandardItem(result))

    def results_selection_changed(self):
        selected_index = self.results_tree.currentIndex()
        if selected_index is None:
            return

        self.time_series_tree.rootModel = QStandardItemModel()

        self.tsns = self.api.list_tsn_for_result(selected_index.data(Qt.DisplayRole))
        for tsn in self.tsns:
            item = QStandardItem(tsn["tsn_name"])
            item.setData(tsn["tsn_id"], Qt.UserRole)
            self.time_series_tree.rootModel.invisibleRootItem().appendRow(item)

        self.time_series_tree.proxyModel = NodeSortFilterProxyModel(self.time_series_tree, self.time_series_tree.rootModel)
        self.time_series_tree.setModel(self.time_series_tree.proxyModel)
        self.set_time_series_filter(self.time_series_filter_edit.text())

    def set_results_filter(self, text: str):
        self.results_tree.proxyModel.setFilterRegularExpression(text)

    def set_time_series_filter(self, text: str):
        self.time_series_tree.proxyModel.setFilterRegularExpression(text)

    def set_sample_from(self, text: str):
        self.current_sample_from = text

    def set_sample_to(self, text: str):
        self.current_sample_to = text

    def set_granularity(self):
        self.draw_chart()

    def set_averages_only_checked(self, state: int):
        self.averages_only = state == 2
        self.draw_chart()

    def set_date_from(self, date_from: QDate):
        self.from_date = date_from
        self.draw_chart()

    def set_date_to(self, date_to: QDate):
        self.to_date = date_to
        self.draw_chart()

    def add_time_series(self):
        selected_results_index = self.results_tree.currentIndex()
        selected_time_series_index = self.time_series_tree.currentIndex()
        if selected_results_index is None or selected_time_series_index is None or \
                selected_results_index.data(Qt.DisplayRole) is None or selected_time_series_index.data(Qt.DisplayRole) is None or \
                self.current_sample_from == "" or self.current_sample_to == "":
            return

        self.time_series_table_model.appendRow([
            selected_results_index.data(Qt.DisplayRole),
            selected_time_series_index.data(Qt.DisplayRole),
            self.current_sample_from,
            self.current_sample_to,
            selected_time_series_index.data(Qt.UserRole)
        ])

    def delete_rows(self):
        selected_rows = self.time_series_table_view.selectionModel().selectedRows()
        self.time_series_table_model.removeRows(selected_rows)

    def get_time_series_data(self):
        queries = []
        rows = self.time_series_table_model.getData()
        for row in rows:
            queries.append({
                "result": row[0],
                "time_series_id": int(row[4]),
                "time_series_name": row[1],
                "sample_from": int(row[2]),
                "sample_to": int(row[3]),
                "granularity": self.granularity_comboBox.currentText()
            })
        data = self.api.get_time_series_data(queries)
        # 3-dimensional array
        # 1st dimension is series
        # 2nd dimension is sample (starting at sampleFrom, ending at sampleTo)
        # 3rd dimension is data point
        data_points = []
        for series_idx, series in enumerate(data):
            series_points = []
            for point in series:
                sample_idx: int = point["tss_sample_number"] - queries[series_idx]["sample_from"]
                while sample_idx >= len(series_points):
                    series_points.append([])

                start = datetime.datetime(2000, 1, 1) + datetime.timedelta(days=int(point["tsd_tim_id_start"])-1)
                if self.granularity_comboBox.currentText() == "5 min":
                    offset = point["tsd_time_number"]
                    start = start + datetime.timedelta(minutes=offset*5)
                elif self.granularity_comboBox.currentText() == "Quarter hourly":
                    offset = point["tsd_time_number"]
                    start = start + datetime.timedelta(minutes=offset*15)
                elif self.granularity_comboBox.currentText() == "Hourly":
                    offset = point["tsd_time_number"]
                    start = start + datetime.timedelta(minutes=offset*60)

                series_points[sample_idx].append({
                    "id": int(point["tsd_id"]),
                    "sample": point["tss_sample_number"],
                    "start": start,
                    "value": point["tsd_value"],
                })
            data_points.append(series_points)
        return queries, data_points

    def draw_chart(self):
        def date_to_unix_time(date):
            return time.mktime(date.timetuple())

        # self.granularity_comboBox.currentText()
        queries, data = self.get_time_series_data()
        self.plot_widget.clear()
        counter = 0
        for i in range(len(data)):
            if self.averages_only:
                xs = []
                ys = []
                for j in range(len(data[i])):
                    for k in range(len(data[i][j])):
                        item = data[i][j][k]
                        if item["start"] < self.from_date or item["start"] > self.to_date:
                            continue

                        while len(xs) <= k:
                            xs.append(0)
                            ys.append(0)

                        xs[k] = date_to_unix_time(item["start"])
                        ys[k] += item["value"]

                for j in range(len(ys)):
                    ys[j] /= len(data[i])

                color = plot_colors[counter % len(plot_colors)]
                counter += 1
                self.plot_widget.plot(xs, ys, pen=mkPen(color=color), name=f"{queries[i]['time_series_name']} Sample Averages {queries[i]['sample_from']}-{queries[i]['sample_to']}")
            else:
                for j in range(len(data[i])):
                    xs = []
                    ys = []
                    for item in data[i][j]:
                        if item["start"] < self.from_date or item["start"] > self.to_date:
                            continue

                        xs.append(date_to_unix_time(item["start"]))
                        ys.append(item["value"])

                    color = plot_colors[counter % len(plot_colors)]
                    counter += 1
                    self.plot_widget.plot(xs, ys, pen=mkPen(color=color), name=f"{queries[i]['time_series_name']} Sample {queries[i]['sample_from'] + j}")

    def export_csv(self):
        queries, data = self.get_time_series_data()
        (name, _) = QFileDialog.getSaveFileName(None, "Select CSV File", dir=f"results.csv")
        if name != '':
            with open(name, "w", encoding="utf8", newline='') as file:
                writer = csv.writer(file)
                writer.writerow(["result", "tss_id", "tss_sample_number", "tsd_id", "tsd_start_date", "tsd_value"])
                for i in range(len(data)):
                    query = queries[i]
                    for j in range(len(data[i])):
                        for k in range(len(data[i][j])):
                            point = data[i][j][k]
                            writer.writerow([
                                query["result"],
                                query["time_series_name"],
                                int(point["sample"]),
                                int(point["id"]),
                                point["start"].strftime("yyyy-MM-dd"),
                                point["value"],
                            ])

    def setup_layout(self, layout: QBoxLayout, themes: dict):
        self.results_filter_edit = PyLineEdit(
            text = "",
            place_holder_text = "Filter results",
            radius = 8,
            border_size = 2,
            color = themes["app_color"]["text_foreground"],
            selection_color = themes["app_color"]["white"],
            bg_color = themes["app_color"]["dark_one"],
            bg_color_active = themes["app_color"]["dark_three"],
            context_color = themes["app_color"]["context_color"]
        )
        self.results_filter_edit.textChanged.connect(self.set_results_filter)

        self.results_tree = ResultTreeView(
            radius = 8,
            color = themes["app_color"]["text_foreground"],
            selection_color = themes["app_color"]["bg_one"],
            bg_color = themes["app_color"]["bg_two"],
            scroll_bar_bg_color = themes["app_color"]["bg_one"],
            scroll_bar_btn_color = themes["app_color"]["dark_four"],
            context_color = themes["app_color"]["context_color"]
        )
        self.results_tree.clicked.connect(self.results_selection_changed)

        self.time_series_filter_edit = PyLineEdit(
            text = "",
            place_holder_text = "Filter time series",
            radius = 8,
            border_size = 2,
            color = themes["app_color"]["text_foreground"],
            selection_color = themes["app_color"]["white"],
            bg_color = themes["app_color"]["dark_one"],
            bg_color_active = themes["app_color"]["dark_three"],
            context_color = themes["app_color"]["context_color"]
        )
        self.time_series_filter_edit.textChanged.connect(self.set_time_series_filter)

        self.time_series_tree = TimeSeriesTreeView(
            radius = 8,
            color = themes["app_color"]["text_foreground"],
            selection_color = themes["app_color"]["bg_one"],
            bg_color = themes["app_color"]["bg_two"],
            scroll_bar_bg_color = themes["app_color"]["bg_one"],
            scroll_bar_btn_color = themes["app_color"]["dark_four"],
            context_color = themes["app_color"]["context_color"]
        )

        self.sample_from_edit = PyLineEdit(
            text = "",
            place_holder_text = "Sample from",
            radius = 8,
            border_size = 2,
            color = themes["app_color"]["text_foreground"],
            selection_color = themes["app_color"]["white"],
            bg_color = themes["app_color"]["dark_one"],
            bg_color_active = themes["app_color"]["dark_three"],
            context_color = themes["app_color"]["context_color"]
        )
        self.sample_from_edit.textChanged.connect(self.set_sample_from)

        self.sample_to_edit = PyLineEdit(
            text = "",
            place_holder_text = "Sample to",
            radius = 8,
            border_size = 2,
            color = themes["app_color"]["text_foreground"],
            selection_color = themes["app_color"]["white"],
            bg_color = themes["app_color"]["dark_one"],
            bg_color_active = themes["app_color"]["dark_three"],
            context_color = themes["app_color"]["context_color"]
        )
        self.sample_to_edit.textChanged.connect(self.set_sample_to)

        self.add_time_series_button = StyledButton(text="Add Time Series", themes=themes)
        self.add_time_series_button.clicked.connect(self.add_time_series)

        self.time_series_table_view = TimeSeriesTableView(themes["app_color"])
        self.time_series_table_model = TimeSeriesTableModel([])
        self.time_series_table_view.setModel(self.time_series_table_model)

        self.delete_rows_button = StyledButton(text="Delete Selected Rows", themes=themes)
        self.delete_rows_button.clicked.connect(self.delete_rows)

        self.draw_chart_button = StyledButton(text="Draw Chart", themes=themes)
        self.draw_chart_button.clicked.connect(self.draw_chart)

        self.export_csv_button = StyledButton(text="Export CSV", themes=themes)
        self.export_csv_button.clicked.connect(self.export_csv)

        self.granularity_label = QLabel("Granularity")
        self.granularity_comboBox = QComboBox()
        self.granularity_comboBox.setObjectName("granularity_comboBox")
        self.granularity_comboBox.setStyleSheet(comboBox_style)
        self.granularity_comboBox.addItem("Normal")
        self.granularity_comboBox.addItem("5 min")
        self.granularity_comboBox.addItem("Quarter hourly")
        self.granularity_comboBox.addItem("Hourly")
        self.granularity_comboBox.setCurrentText("Normal")
        self.granularity_comboBox.currentIndexChanged.connect(self.set_granularity)

        self.averages_only_checkbox = QCheckBox("Show series averages only")
        self.averages_only_checkbox.stateChanged.connect(self.set_averages_only_checked)

        self.date_from_label = QLabel("Date from")
        self.date_from_edit = PyDateEdit(
            radius = 8,
            border_size = 2,
            color = themes["app_color"]["text_foreground"],
            selection_color = themes["app_color"]["white"],
            bg_color = themes["app_color"]["dark_one"],
            bg_color_active = themes["app_color"]["dark_three"],
            context_color = themes["app_color"]["context_color"]
        )
        self.date_from_edit.setDate(self.from_date)
        self.date_from_edit.dateChanged.connect(self.set_date_from)

        self.date_to_label = QLabel("Date to")
        self.date_to_edit = PyDateEdit(
            radius = 8,
            border_size = 2,
            color = themes["app_color"]["text_foreground"],
            selection_color = themes["app_color"]["white"],
            bg_color = themes["app_color"]["dark_one"],
            bg_color_active = themes["app_color"]["dark_three"],
            context_color = themes["app_color"]["context_color"]
        )
        self.date_to_edit.setDate(self.to_date)
        self.date_to_edit.dateChanged.connect(self.set_date_to)

        self.axis = DateAxisItem()
        self.plot_widget = PlotWidget(axisItems={'bottom': self.axis})
        self.plot_widget.addLegend()

        self.results_left_layout = QVBoxLayout()
        self.results_left_layout.setObjectName(u"results_left_layout")
        layout.addLayout(self.results_left_layout, 1)

        self.results_right_layout = QVBoxLayout()
        self.results_right_layout.setObjectName(u"results_right_layout")
        layout.addLayout(self.results_right_layout, 2)

        self.results_left_layout.addWidget(self.results_filter_edit)
        self.results_left_layout.addWidget(self.results_tree)

        self.results_left_layout.addWidget(self.time_series_filter_edit)
        self.results_left_layout.addWidget(self.time_series_tree)

        self.sample_range_layout = QHBoxLayout()
        self.sample_range_layout.addWidget(self.sample_from_edit)
        self.sample_range_layout.addWidget(self.sample_to_edit)
        self.results_left_layout.addLayout(self.sample_range_layout)

        self.results_left_layout.addWidget(self.add_time_series_button)

        self.results_right_layout.addWidget(self.time_series_table_view)

        self.time_series_controls_layout = QHBoxLayout()
        self.time_series_controls_layout.addWidget(self.delete_rows_button)
        self.time_series_controls_layout.addWidget(self.draw_chart_button)
        self.time_series_controls_layout.addWidget(self.export_csv_button)
        self.results_right_layout.addLayout(self.time_series_controls_layout)

        self.chart_controls_layout = QHBoxLayout()
        self.chart_controls_layout.addWidget(self.granularity_label)
        self.chart_controls_layout.addWidget(self.granularity_comboBox, 1)
        self.chart_controls_layout.addWidget(self.averages_only_checkbox)
        self.chart_controls_layout.addWidget(self.date_from_label)
        self.chart_controls_layout.addWidget(self.date_from_edit, 1)
        self.chart_controls_layout.addWidget(self.date_to_label)
        self.chart_controls_layout.addWidget(self.date_to_edit, 1)
        self.results_right_layout.addLayout(self.chart_controls_layout)

        self.results_right_layout.addWidget(self.plot_widget)


from casadi import mtimes

from yaocptool.methods import DirectMethod
from yaocptool.modelling import OptimalControlProblem, SystemModel

# create model
model = SystemModel(name="dae_system")

x = model.create_state("x", 2)
y = model.create_algebraic_variable("y", 2)
u = model.create_control("u")
a = model.create_parameter("a")
b = model.create_theta("b")

model.include_equations(
    ode=[-a * x[0] + b * y[0], -x[1] + y[1] + u[0]],
    alg=[-y[0] - x[1] ** 2, -y[1] - x[0] ** 1],
)

# create ocp
problem = OptimalControlProblem(model)
problem.t_f = 10
# problem.L = mtimes(x.T, x) + u ** 2
problem.S = mtimes(x.T, x) + u ** 2 + b ** 2
problem.x_0 = [0, 1]
problem.set_theta_as_optimization_theta(b, -0.5, 0.5)
# problem.include_equality(problem.p_opt + 0.25)
problem.include_time_inequality(+u + x[0], when="end")

# instantiate a solution method
solution_method = DirectMethod(
    problem,
    discretization_scheme="collocation",
    degree_control=1,
)
# theta = create_constant_theta(1, 1, 10)

# initial_guess = solution_method.discretizer.create_initial_guess_with_simulation(p=[1])
# solution = solution_method.solve(p=[1], theta=theta, initial_guess=initial_guess)
solution = solution_method.solve(p=[1], x_0=[2, 3, 0])

solution.plot(
    [
        {"x": ["x_0", "x_1"]},
        {"y": ["y_0", "y_1"]},
        {"x": [0, 1], "u": ["u"]},
        {"theta_opt": ["b"]},
    ]
)

solution.to_dataset()


#!/usr/bin/python3
from sys import argv
if __name__ == "__main__":
    sum = 0
    if len(argv) == 1:
        print("0")
    if len(argv) > 1:
        for i in range(1, len(argv)):
            argvi = int(argv[i], 10)
            sum = sum + argvi
        print("{:d}".format(sum))


import torch
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
from utils.pt.building_block import BB

class CC(BB):
    def start(self):
        self.C = self.kwargs.get('C', dict())
        self.C0 = self.kwargs.get('C0', {**self.C})
        self.C1 = self.kwargs.get('C1', {**self.C})
        self.C1['in_channels'] = self.C0['out_channels']

        self.double_conv = nn.Sequential(
            nn.Conv2d(**self.C0),
            nn.BatchNorm2d(self.C0['out_channels']),
            nn.ReLU(inplace=True),
            nn.Conv2d(**self.C1),
            nn.BatchNorm2d(self.C1['out_channels']),
            nn.ReLU(inplace=True)
        )

    def forward(self, x):
        return self.double_conv(x)


from flask import Flask
from flask_sse import sse
from flask import Response
from flask_cors import CORS

import cv2
import numpy as np
import dlib
from picamera import PiCamera
from picamera.array import PiRGBArray
import time
from math import hypot

app = Flask(__name__)
CORS(app)

@app.route("/")
def hello():
    return "Eye tracking"

# def get_message():
# #'''this could be any function that blocks until data is ready'''
#     time.sleep(1.0)
#     s = time.ctime(time.time())
#     print(s)
#     return s

#init camera
dimpx = 624
dimpy = 480
camera = PiCamera()
# camera.rotation = 180
camera.resolution = (dimpx, dimpy)
camera.framerate = 32
rawCapture = PiRGBArray(camera, size=(dimpx, dimpy))
time.sleep(0.1)

font = cv2.FONT_HERSHEY_SIMPLEX

detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("/home/pi/Desktop/repo/talia-rasp-pi/landmarks/shape_predictor_68_face_landmarks.dat")

def nothing(x):
    pass

#init trackbar
windowName = "eye-tracker"
ratioName = "ratio"
thresholdName = "threshold"
gazeMinName = "gazeMin (right)"
gazeMaxName = "gazeMax (left)"
cv2.namedWindow(windowName)
cv2.createTrackbar(ratioName, windowName, 4, 10, nothing)
cv2.createTrackbar(thresholdName, windowName, 43, 255, nothing)
cv2.createTrackbar(gazeMinName, windowName, 604, 5000, nothing)
cv2.createTrackbar(gazeMaxName, windowName, 1024, 5000, nothing)

#init dimensionamento punti
def midpoint(p1,p2):
    return int((p1.x + p2.x)/2), int((p1.y + p2.y)/2)

def get_blinking_ratio(eyeType, landmarks):
    nordEst ,nordOvest, sudEst, sudOvest, est, ovest = (0,)*6
    if eyeType == "L":
        ovest = 36
        est = 39
        nordOvest = 37
        nordEst = 38
        sudEst = 40
        sudOvest = 41
    elif eyeType == "R":
        ovest = 42
        est = 45
        nordOvest = 43
        nordEst = 44
        sudEst = 46
        sudOvest = 47

    #riga orizzontale occhio
    left_point = (landmarks.part(ovest).x, landmarks.part(ovest).y)
    right_point = (landmarks.part(est).x, landmarks.part(est).y)
    #riga verticale occhio
    center_top = midpoint(landmarks.part(nordOvest), landmarks.part(nordEst))
    center_bottom = midpoint(landmarks.part(sudOvest), landmarks.part(sudEst))

    #linea orizzontale e verticale:
#     hor_line = cv2.line(frame, left_point, right_point, (0, 255, 0),2)
#     ver_line = cv2.line(frame, center_top, center_bottom, (0, 255, 0),2)

    hor_line_lenght = hypot((left_point[0] - right_point[0]), (left_point[1] - right_point[1]))
    ver_line_lenght = hypot((center_top[0] - center_bottom[0]), (center_top[1] - center_bottom[1]))
#     print("lunghezza linea orizzontale: {}, lunghezza linea verticale: {}" .format(hor_line_lenght, ver_line_lenght))

    ratioS = hor_line_lenght/ver_line_lenght
    return ratioS

def get_threshold(eye, threshold_value):
    eye = cv2.medianBlur(eye, 3)
    _, the_threshold = cv2.threshold(eye, threshold_value, 255, cv2.THRESH_BINARY) #######pupilla nera, occhio bianco
    if the_threshold is not None:
        cv2.imshow("THRESHOLD", cv2.resize(the_threshold, (dimpx, dimpy), fx=5, fy=5))
    return the_threshold

def get_gaze_ratio(eyeType, landmarks, frame, gray, threshold_value):
    nordEst ,nordOvest, sudEst, sudOvest, est, ovest, occhio = (0,)*7
    if eyeType == "L":
        ovest = 36
        est = 39
        nordOvest = 37
        nordEst = 38
        sudEst = 40
        sudOvest = 41
        occhio = "sinistro"
    elif eyeType == "R":
        ovest = 42
        est = 45
        nordOvest = 43
        nordEst = 44
        sudEst = 46
        sudOvest = 47
        occhio = "destro"

    eye_region = np.array([(landmarks.part(ovest).x, landmarks.part(ovest).y),
                                    (landmarks.part(nordOvest).x, landmarks.part(nordOvest).y),
                                    (landmarks.part(nordEst).x, landmarks.part(nordEst).y),
                                    (landmarks.part(est).x, landmarks.part(est).y),
                                    (landmarks.part(sudEst).x, landmarks.part(sudEst).y),
                                    (landmarks.part(sudOvest).x, landmarks.part(sudOvest).y)], np.int32)
#         cv2.polylines(frame, [eye_region], True, (0, 0, 255), 2) ################################## contorno occhio colore rosso

    #maschera immagine --> mostra solo occhio
    height, width,_ = frame.shape
    mask = np.zeros((height, width), np.uint8)
    cv2.polylines(mask, [eye_region], True, 255, 2)
    cv2.fillPoly(mask, [eye_region], 255)
    the_eye = cv2.bitwise_and(gray, gray, mask = mask)

    #ritaglio eye
    min_x = np.min(eye_region[:,0])
    max_x = np.max(eye_region[:,0])
    min_y = np.min(eye_region[:,1])
    max_y = np.max(eye_region[:,1])

    eye = the_eye[min_y: max_y, min_x: max_x]

    #estrazione threshold
    threshold_eye = get_threshold(eye, threshold_value)
    gaze_ratio = -1
    if threshold_eye is not None:
        h_t, w_t = threshold_eye.shape
        left_side_threshold = threshold_eye[0: h_t, 0: int(w_t/2)]
        right_side_threshold = threshold_eye[0: h_t, int(w_t/2): w_t]
        left_side_white = cv2.countNonZero(left_side_threshold)
        right_side_white = cv2.countNonZero(right_side_threshold)
        if left_side_white == 0:
            gaze_ratio = 0
        elif right_side_white == 0:
            gaze_ratio = h_t*w_t
        else:
            gaze_ratio = left_side_white/right_side_white
    return gaze_ratio

@app.route('/stream', methods=['GET', 'OPTIONS'])
def stream():
    def eventStream():
        for f in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
            print("--------------------------------------------------------------------------------------------------------")
            frame = f.array
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

            faces = detector(gray)

            for face in faces:
                messageResponse = ""
                x1 = face.left()
                y1 = face.top()
                x2 = face.right()
                y2 = face.bottom()

                landmarks = predictor(gray, face)

                #Detect blinking
                ratioS = get_blinking_ratio("L", landmarks)
                ratioD = get_blinking_ratio("R", landmarks)

                maxRatio = r = cv2.getTrackbarPos(ratioName, windowName)
                threshold_value = t = cv2.getTrackbarPos(thresholdName, windowName)
                gaze_ratio_min = gmin = cv2.getTrackbarPos(gazeMinName, windowName)
                gaze_ratio_max = gmax = cv2.getTrackbarPos(gazeMaxName, windowName)

                if ratioS > maxRatio and ratioD > maxRatio:
                    cv2.putText(frame, "BLINK", (50, 150), font, 5, (0, 255 ,0))
                    messageResponse = "BLINK"
                else:
                    messageResponses = ""

                #Gaze detection
                if messageResponse is "":
                    #left_eye_gaze = get_gaze_ratio("L", landmarks, frame, gray, threshold_value)
                    right_eye_gaze = get_gaze_ratio("R", landmarks, frame, gray, threshold_value)
                    #print("valore gaze sinistro:{}, valore gaze destro:{}".format(left_eye_gaze, right_eye_gaze))

                    #gaze_ratio_tot = int(((left_eye_gaze + right_eye_gaze)/2)*1000)

                    gaze_ratio_tot = int(((right_eye_gaze)/2)*1000)
                    if gaze_ratio_tot <= gaze_ratio_min:
                        cv2.putText(frame, "RIGHT", (50, 100), font, 2, (0, 0, 255),3)
                        messageResponse = "RIGHT"
                    elif gaze_ratio_min < gaze_ratio_tot < gaze_ratio_max:
                        cv2.putText(frame, "CENTER", (50, 100), font, 2, (0, 0, 255),3)
                        messageResponse = "CENTER"
                    else:
                        cv2.putText(frame, "LEFT", (50, 100), font, 2, (0, 0, 255),3)
                        messageResponse = "LEFT"

                    cv2.putText(frame, str(gaze_ratio_tot), (50,300), font, 2, (0,0,255),3)

                yield 'data: {}\n\n'.format(messageResponse)

            rawCapture.truncate(0)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

            cv2.imshow(windowName, frame)

        cv2.destroyAllWindows()
    # response = Response(eventStream(), mimetype="text/event-stream")
    # response.headers['Access-Control-Allow-Origin'] = '*'
    return Response(eventStream(), mimetype="text/event-stream")

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


import requests

from prometheus_client.core import Gauge, GaugeMetricFamily
from datetime import date, timedelta
from datetime import datetime

from src.config import EXPORTER_API_REQUESTS_FAILED_TOTAL, EXPORTER_API_REQUESTS_TOTAL, EXPORTER_TIME_FOR_REQUEST
from src.config import settings

class UsersWithoutTurnedOnNotificationsCollector:
    """
        Класс, собирает метрику - кол-во юзеров, у которых не стоят никакие нотификации, когда они primary роль имеют.
    """

    def _count_users_without_turned_on(self) -> int:
        time_beg = datetime.now()
        users_response = requests.get(settings.ONCALL_EXPORTER_API_URL + "/api/v0/users")
        time_end = datetime.now()
        seconds = (time_end - time_beg).seconds
        EXPORTER_TIME_FOR_REQUEST.set(seconds)
        EXPORTER_API_REQUESTS_TOTAL.inc()
        if users_response.status_code != 200:
            EXPORTER_API_REQUESTS_FAILED_TOTAL.inc()
            return 0
        all_usernames = [user.get('name') for user in users_response.json()]
        all_usernames_set = set(all_usernames)
        for user_name in all_usernames:
            EXPORTER_API_REQUESTS_TOTAL.inc()
            notifications_and_reminders_request = requests.get(
                settings.ONCALL_EXPORTER_API_URL + f"/api/v0/users/{user_name}/notifications")
            if notifications_and_reminders_request.status_code != 200:
                EXPORTER_API_REQUESTS_FAILED_TOTAL.inc()
            notifications_and_reminders = notifications_and_reminders_request.json()

            flag = False

            for notification in notifications_and_reminders:
                flag |= 'primary' in notification.get('roles')

            if flag:
                try:
                    all_usernames_set.remove(user_name)
                except KeyError:
                    pass

        return len(all_usernames_set)

    def collect(self):
        exporter_users_without_turned_on_gauge = GaugeMetricFamily(
            "exporter_users_without_turned_on_notification",
            "Check if we have users without turned on",
            labels=['exporter_users_without_turned_on']
        )
        exporter_users_without_turned_on_gauge.add_metric(['exporter_users_without_turned_on'],
                                                          self._count_users_without_turned_on())
        yield exporter_users_without_turned_on_gauge

class DaysWithoutUserOnCall:
    """
        Рассчитать кол-во дней, Когда ни у одной команды нет челвека на смене с ролью "primary" в течении сл 30 дней.
    """

    def _count_days_without_users_oncall(self):
        url_to_events = settings.ONCALL_EXPORTER_API_URL + "/api/v0/events"
        today = datetime.combine(date.today(), datetime.min.time())
        past_30_days = today + timedelta(days=30)
        all_dates_timestamps = set()
        for i in range(31):
            all_dates_timestamps.add((today + timedelta(days=i)).timestamp())
        url_all_teams = settings.ONCALL_EXPORTER_API_URL + "/api/v0/teams"

        EXPORTER_API_REQUESTS_TOTAL.inc()
        time_beg = datetime.now()
        team_names_response = requests.get(url_all_teams)
        time_end = datetime.now()
        seconds = (time_end - time_beg).seconds
        EXPORTER_TIME_FOR_REQUEST.set(seconds)
        if team_names_response.status_code != 200:
            EXPORTER_API_REQUESTS_FAILED_TOTAL.inc()

        for team_name in team_names_response.json():
            EXPORTER_API_REQUESTS_TOTAL.inc()
            response = requests.get(
                url_to_events,
                params={
                    "start__lt": int(past_30_days.timestamp()),
                    "end__ge": int(today.timestamp()),
                    "team__eq": team_name
                }
            )
            if response.status_code != 200:
                EXPORTER_API_REQUESTS_FAILED_TOTAL.inc()
            for record in response.json():
                if record.get('role') == "primary":
                    record_start_datetime = datetime.fromtimestamp(record.get('start'))
                    record_end_datetime = datetime.fromtimestamp(record.get('end'))
                    while record_start_datetime < record_end_datetime:
                        record_start_datetime = datetime.combine((record_start_datetime + timedelta(days=1)),
                                                                 datetime.min.time())
                        try:
                            all_dates_timestamps.remove(record_start_datetime.timestamp())
                        except KeyError:
                            pass

            return len(all_dates_timestamps)

    def collect(self):
        exporter_days_without_users_on_call_gauge = GaugeMetricFamily(
            "exporter_days_without_users_on_call",
            "Check if there are days in next 30 days without primary user on duty",
            labels=['exporter_days_without_users_on_call']
        )
        exporter_days_without_users_on_call_gauge.add_metric(['exporter_days_without_users_on_call'],
                                                             self._count_days_without_users_oncall())
        yield exporter_days_without_users_on_call_gauge


k = int(input())
a = list(map(int, input().split()))
S = 0
D = 0

i=0
start = 0
end = len(a)-1
while(start<=end):
    if i%2==0:
        if a[start]>a[end]:
            S+=a[start]
            start+=1
        else:
            S+=a[end]
            end-=1
    else:
        if a[start]>a[end]:
            D+=a[start]
            start+=1
        else:
            D+=a[end]
            end-=1
    i+=1
print(S,D)


from ctypes import c_uint16

from pynes.core.devices import AbstractMemoryDevice
from pynes.core.exceptions import NoSuchDeviceException

class Bus:

    def __init__(self):
        self.devices = {}

    def register_device(self, device) -> None:
        self.devices.update({type(device).__name__: device})

    def get_ram(self):
        device_name = 'Ram'
        ram = self.devices.get(device_name)
        if not ram:
            raise NoSuchDeviceException(device_name)
        return ram

    def get_cartridge(self):
        device_name = 'Cartridge'
        cartridge = self.devices.get(device_name)
        if not cartridge:
            raise NoSuchDeviceException(device_name)
        return cartridge

    def get_cpu6502(self):
        device_name = 'Cpu6502'
        cpu = self.devices.get(device_name)
        if not cpu:
            raise NoSuchDeviceException(device_name)
        return cpu

    def get_ppu2C02(self):
        device_name = 'Ppu2C02'
        ppu = self.devices.get(device_name)
        if not ppu:
            raise NoSuchDeviceException(device_name)
        return ppu

    def address_owner(self, address: c_uint16) -> AbstractMemoryDevice:
        memory_devices = filter(lambda d: d.__class__ in AbstractMemoryDevice.__subclasses__(), self.devices.values())
        for device_instance in memory_devices:
            if device_instance.is_address_valid(address):
                return device_instance
        else:
            raise NoSuchDeviceException(f'with address {hex(address.value)}')

    def __repr__(self) -> str:
        return "Bus({i}) {d}".format(i=id(self),
                                     d=self.devices)


from rlpy.agents import (
    CountBasedBonus,
    GaussianPSRL,
    GreedyGQ,
    LSPI,
    MBIE_EB,
    NaturalActorCritic,
    OptimisticPSRL,
    PSRL,
    Q_Learning,
    SARSA,
    UCBVI,
)
from rlpy.policies import eGreedy, GibbsPolicy
from rlpy import representations
from rlpy.representations import (
    Fourier,
    iFDD,
    iFDDK,
    IncrementalTabular,
    IndependentDiscretization,
    KernelizediFDD,
    RBF,
    Tabular,
    TileCoding,
)

def tabular_lspi(domain, max_steps, discretization=20):
    tabular = Tabular(domain, discretization=discretization)
    policy = eGreedy(tabular, epsilon=0.1)
    return LSPI(policy, tabular, domain.discount_factor, max_steps, 1000)

def tabular_nac(
    domain,
    gamma=0.9,
    discretization=20,
    forgetting_rate=0.3,
    lambda_=0.7,
    learn_rate=0.1,
):
    tabular = Tabular(domain, discretization=discretization)
    return NaturalActorCritic(
        GibbsPolicy(tabular),
        tabular,
        discount_factor=gamma,
        forgetting_rate=forgetting_rate,
        min_steps_between_updates=100,
        max_steps_between_updates=1000,
        lambda_=lambda_,
        learn_rate=learn_rate,
    )

def tabular_q(
    domain,
    epsilon=0.1,
    epsilon_decay=0.0,
    epsilon_min=0.0,
    discretization=20,
    lambda_=0.3,
    initial_learn_rate=0.1,
    boyan_N0=100,
    incremental=False,
):
    if incremental:
        tabular = IncrementalTabular(domain, discretization=discretization)
    else:
        tabular = Tabular(domain, discretization=discretization)
    return Q_Learning(
        eGreedy(
            tabular,
            epsilon=epsilon,
            epsilon_decay=epsilon_decay,
            epsilon_min=epsilon_min,
        ),
        tabular,
        discount_factor=domain.discount_factor,
        lambda_=lambda_,
        initial_learn_rate=initial_learn_rate,
        learn_rate_decay_mode="boyan",
        boyan_N0=boyan_N0,
    )

def count_based_tabular_q(
    domain, beta=0.05, count_mode="s-a", show_reward=False, **kwargs
):
    agent = tabular_q(domain, **kwargs)
    return CountBasedBonus(
        agent, count_mode=count_mode, beta=beta, show_reward=show_reward
    )

def tabular_sarsa(domain, discretization=20, lambda_=0.3):
    tabular = Tabular(domain, discretization=discretization)
    policy = eGreedy(tabular, epsilon=0.1)
    return SARSA(policy, tabular, domain.discount_factor, lambda_=lambda_)

def tabular_psrl(
    domain,
    seed,
    show_reward=False,
    epsilon=0.1,
    epsilon_decay=0.0,
    epsilon_min=0.0,
    vi_threshold=1e-6,
):
    tabular = Tabular(domain, discretization=20)
    policy = eGreedy(
        tabular, epsilon=epsilon, epsilon_decay=epsilon_decay, epsilon_min=epsilon_min
    )
    return PSRL(
        policy, tabular, domain.discount_factor, seed=seed, show_reward=show_reward
    )

def tabular_mbie_eb(
    domain,
    seed,
    show_reward=False,
    beta=0.1,
    epsilon=0.1,
    epsilon_decay=0.0,
    epsilon_min=0.0,
    vi_threshold=1e-6,
):
    tabular = Tabular(domain, discretization=20)
    policy = eGreedy(
        tabular, epsilon=epsilon, epsilon_decay=epsilon_decay, epsilon_min=epsilon_min
    )
    return MBIE_EB(
        policy,
        tabular,
        domain.discount_factor,
        beta=beta,
        seed=seed,
        show_reward=show_reward,
    )

def tabular_opt_psrl(
    domain,
    seed,
    show_reward=False,
    epsilon=0.1,
    epsilon_decay=0.0,
    epsilon_min=0.0,
    n_samples=10,
    vi_threshold=1e-6,
):
    tabular = Tabular(domain, discretization=20)
    policy = eGreedy(
        tabular, epsilon=epsilon, epsilon_decay=epsilon_decay, epsilon_min=epsilon_min
    )
    return OptimisticPSRL(
        policy,
        tabular,
        domain.discount_factor,
        seed=seed,
        show_reward=show_reward,
        n_samples=n_samples,
    )

def tabular_gaussian_psrl(
    domain,
    seed,
    show_reward=False,
    epsilon=0.1,
    epsilon_decay=0.0,
    epsilon_min=0.0,
    vi_threshold=1e-6,
):
    tabular = Tabular(domain, discretization=20)
    policy = eGreedy(
        tabular, epsilon=epsilon, epsilon_decay=epsilon_decay, epsilon_min=epsilon_min
    )
    return GaussianPSRL(
        policy, tabular, domain.discount_factor, seed=seed, show_reward=show_reward
    )

def tabular_ucbvi(
    domain,
    seed,
    show_reward=False,
    epsilon=0.1,
    epsilon_decay=0.0,
    epsilon_min=0.0,
    vi_threshold=1e-6,
):
    tabular = Tabular(domain, discretization=20)
    policy = eGreedy(
        tabular, epsilon=epsilon, epsilon_decay=epsilon_decay, epsilon_min=epsilon_min
    )
    return UCBVI(
        policy, tabular, domain.discount_factor, seed=seed, show_reward=show_reward
    )

def tile_ggq(domain, res_mat, lambda_=0.3, initial_learn_rate=0.1, boyan_N0=100):
    tile = TileCoding(
        domain,
        memory=2000,
        num_tilings=[1] * res_mat.shape[0],
        resolution_matrix=res_mat,
        safety="none",
    )
    return GreedyGQ(
        eGreedy(tile, epsilon=0.1),
        tile,
        discount_factor=domain.discount_factor,
        lambda_=lambda_,
        initial_learn_rate=initial_learn_rate,
        boyan_N0=boyan_N0,
    )

def _ifdd_q_common(
    agent_class,
    domain,
    epsilon=0.1,
    discretization=20,
    threshold=1.0,
    lambda_=0.3,
    initial_learn_rate=0.1,
    boyan_N0=100,
    ifddplus=True,
):
    ifdd = iFDD(
        domain,
        discovery_threshold=threshold,
        initial_representation=IndependentDiscretization(
            domain, discretization=discretization
        ),
        useCache=True,
        iFDDPlus=ifddplus,
    )
    return agent_class(
        eGreedy(ifdd, epsilon=epsilon),
        ifdd,
        discount_factor=domain.discount_factor,
        lambda_=lambda_,
        initial_learn_rate=initial_learn_rate,
        learn_rate_decay_mode="boyan",
        boyan_N0=boyan_N0,
    )

def ifdd_ggq(*args, **kwargs):
    return _ifdd_q_common(GreedyGQ, *args, **kwargs)

def ifdd_q(*args, **kwargs):
    return _ifdd_q_common(Q_Learning, *args, **kwargs)

def ifdd_sarsa(*args, **kwargs):
    return _ifdd_q_common(SARSA, *args, **kwargs)

def _ifddk_common(
    agent_class,
    domain,
    epsilon=0.1,
    discretization=20,
    threshold=1.0,
    lambda_=0.3,
    initial_learn_rate=0.1,
    boyan_N0=100,
):
    ifddk = iFDDK(
        domain,
        discovery_threshold=threshold,
        initial_representation=IndependentDiscretization(
            domain, discretization=discretization
        ),
        sparsify=True,
        useCache=True,
        lazy=True,
        lambda_=lambda_,
    )
    return agent_class(
        eGreedy(ifddk, epsilon=epsilon),
        ifddk,
        discount_factor=domain.discount_factor,
        lambda_=lambda_,
        initial_learn_rate=initial_learn_rate,
        learn_rate_decay_mode="boyan",
        boyan_N0=boyan_N0,
    )

def ifddk_q(domain, **kwargs):
    return _ifddk_common(Q_Learning, **kwargs)

def ifddk_sarsa(domain, **kwargs):
    return _ifddk_common(SARSA, **kwargs)

def _kifdd_common(
    agent_class,
    domain,
    kernel_resolution,
    threshold=1.0,
    lambda_=0.3,
    initial_learn_rate=0.1,
    boyan_N0=100,
    kernel="gaussian",
):
    kernel_width = (
        domain.statespace_limits[:, 1] - domain.statespace_limits[:, 0]
    ) / kernel_resolution
    kifdd = KernelizediFDD(
        domain,
        sparsify=True,
        kernel=getattr(representations, kernel),
        kernel_args=[kernel_width],
        active_threshold=0.01,
        discover_threshold=threshold,
        normalization=True,
        max_active_base_feat=10,
        max_base_feat_sim=0.5,
    )
    return agent_class(
        eGreedy(kifdd, epsilon=0.1),
        kifdd,
        discount_factor=domain.discount_factor,
        lambda_=lambda_,
        initial_learn_rate=initial_learn_rate,
        learn_rate_decay_mode="boyan",
        boyan_N0=boyan_N0,
    )

def kifdd_q(domain, **kwargs):
    return _kifdd_common(Q_Learning, **kwargs)

def kifdd_sarsa(domain, **kwargs):
    return _kifdd_common(SARSA, **kwargs)

def _rbf_common(
    agent_class,
    domain,
    seed=1,
    num_rbfs=96,
    resolution=21,
    initial_learn_rate=0.1,
    lambda_=0.3,
    boyan_N0=100,
):
    rbf = RBF(
        domain,
        num_rbfs=num_rbfs,
        resolution_max=resolution,
        resolution_min=resolution,
        const_feature=False,
        normalize=True,
        seed=seed,
    )
    return agent_class(
        eGreedy(rbf, epsilon=0.1),
        rbf,
        discount_factor=domain.discount_factor,
        lambda_=lambda_,
        initial_learn_rate=initial_learn_rate,
        learn_rate_decay_mode="boyan",
        boyan_N0=boyan_N0,
    )

def rbf_q(domain, **kwargs):
    return _rbf_common(Q_Learning, **kwargs)

def rbf_sarsa(domain, **kwargs):
    return _rbf_common(SARSA, **kwargs)

def _fourier_common(
    agent_class,
    domain,
    order=3,
    scaling=False,
    initial_learn_rate=0.1,
    lambda_=0.3,
    boyan_N0=100,
):
    fourier = Fourier(domain, order=order, scaling=scaling)
    return agent_class(
        eGreedy(fourier, epsilon=0.1),
        fourier,
        discount_factor=domain.discount_factor,
        lambda_=lambda_,
        initial_learn_rate=initial_learn_rate,
        learn_rate_decay_mode="boyan",
        boyan_N0=boyan_N0,
    )

def fourier_q(domain, **kwargs):
    return _fourier_common(Q_Learning, domain, **kwargs)

def fourier_sarsa(domain, **kwargs):
    return _fourier_common(SARSA, domain, **kwargs)


def main():
    # Load the dataset from CSV file
    file_path = "data.csv"
    try:
        df = pd.read_csv(file_path)
        feedback_data = df["feedback"].tolist()

        # Get user input for the top N most frequent words to display
        n = int(input("Enter the number of top frequent words to display: "))

        word_frequency = calculate_word_frequency(feedback_data)

        # Sort the word_frequency dictionary by values (word counts) in descending order
        sorted_word_freq = dict(sorted(word_frequency.items(), key=lambda x: x[1], reverse=True))

        # Display the top N most frequent words and their corresponding frequencies
        print(f"\nTop {n} most frequent words:")
        for i, (word, frequency) in enumerate(sorted_word_freq.items()):
            if i >= n:
                break
            print(f"{word}: {frequency}")

        # Plot a bar graph to visualize the top N most frequent words and their frequencies
        top_n_words = list(sorted_word_freq.keys())[:n]
        top_n_frequencies = list(sorted_word_freq.values())[:n]

        plt.bar(top_n_words, top_n_frequencies)
        plt.xlabel("Words")
        plt.ylabel("Frequencies")
        plt.title(f"Top {n} Most Frequent Words")
        plt.xticks(rotation=45)
        plt.tight_layout()
        plt.show()

    except FileNotFoundError:
        print(f"Error: File '{file_path}' not found.")

if __name__ == "__main__":
    main()


from elasticsearch_dsl import analyzer, token_filter

__all__ = ('standard_analyzer', 'polish_analyzer')

polish_hunspell = token_filter(
    'pl',
    type="hunspell",
    locale="pl_PL",
    dedup=True
)

polish_stopwords = token_filter(
    'polish_stopwords',
    type="stop",
    ignore_case=True,
    stopwords_path='stopwords.txt'
)

standard_analyzer = analyzer(
    'standard_analyzer',
    tokenizer="standard",
    filter=["standard", polish_stopwords, "lowercase"],
    char_filter=["html_strip"]
)

standard_asciied = analyzer(
    'standard_analyzer',
    tokenizer="standard",
    filter=["lowercase", "asciifolding", "trim"],
    char_filter=["html_strip"]
)

polish_analyzer = analyzer(
    'polish_analyzer',
    tokenizer="standard",
    filter=["standard", polish_stopwords, "lowercase", polish_hunspell],
    char_filter=["html_strip"]
)

pl_ascii_folding = token_filter(
    'pl_ascii_folding',
    type='asciifolding',
    preserve_original=True
)

polish_asciied = analyzer(
    'polish_asciied',
    type='custom',
    tokenizer="standard",
    filter=["lowercase", pl_ascii_folding, "trim"],
    char_filter=["html_strip"]
)


from PIL import Image, ImageOps, ImageDraw, ImageFont
import numpy as np
import math
import matplotlib.pyplot as plt
import cv2
import os

# Function to Convert Images to grayscale
def ICV_grayscale(img):

    height, width = img.shape[:2]

    imgOutput= np.zeros(shape=(height,width))
    for i in range(height):
        for j in range(width):
           imgOutput[i, j] = (int(img[i, j, 0]*0.299)+int(img[i, j, 1]*0.587)+int(img[i, j, 2]*0.114))

    #plt.imshow(imgOutput)
    #plt.show()
    return imgOutput
#ICV_grayscale("Dataset/DatasetA/car-1.JPG")

############################################################
# START Question - 1 - Transformations
############################################################

def ICV_transform_Image(fileName, conv, rotAngle, skewAngle):

    thetaShear = np.radians(skewAngle) # angle to shear
    thetaRot = np.radians(rotAngle)# angle to rotate

    cos1 = (np.cos(thetaRot))# calculating cosine for rotation
    sin1 = (np.sin(thetaRot))# calculating sine for rotation
    shearX = ((np.tan(thetaShear)))# calculating shear angle
    #shearY = (1/(np.tan(thetaShear)))

    # Rotation Matrix
    Tr = np.array([
        [cos1,sin1],
        [-sin1,cos1]])

    # Skew Matrix
    Tsk = np.array([
        [1,-shearX],
        [0,1]]).T
    Ts = np.array([
        [2,0],
        [0,2]])

    # Combined Matrix i
    Tcomb1 = Tsk@Tr

    # Combined Matrix ii
    Tcomb2 = Tr@Tsk

    if(conv == 0):
        Tf = Tsk
    if(conv == 1):
        Tf = Tr
    if(conv == 2):
        Tf = Tcomb1
    if(conv == 3):
        Tf = Tcomb2

    img = plt.imread(fileName)

    height, width = img.shape[:2]

    main_dimension = height
    if(height>=width):
        main_dimension = height
    else:
        main_dimension = width

    center_x = main_dimension
    center_y = main_dimension
    imgOutput = np.ndarray((main_dimension*2,main_dimension*2,3))

    #loop over the entire image
    for i in range(height):
        for j in range(width):
            pixelValue = img[i, j, :]

            # positioning relative to the center of the input image
            i_transfO = i-(height/2)
            j_transfO = j-(width/2)

            #transforming image coordinates
            i_transf = i_transfO*Tf[0,0] + Tf[0,1]*j_transfO
            j_transf = i_transfO*Tf[1,0] + Tf[1,1]*j_transfO

            #centering image coordinates back relative to the output image
            i_transf+= center_x
            j_transf+=center_y
            # the transformed coordinates are used for the new image
            if(0<i_transf < main_dimension*2 and 0<j_transf < main_dimension*2):
                imgOutput[int(i_transf), int(j_transf), :] = pixelValue

    plt.imshow(imgOutput.astype('uint8'))
    plt.show()

    if(conv>0):
        imgOutputInv = np.ndarray((main_dimension*2,main_dimension*2,3))
        center_x = height/2
        center_y = width/2
        TInv = np.linalg.inv(Tf)#computing the inverse matrix

        for i in range(height):
            for j in range(width):

                i_transfI = i-center_x
                j_transfI = j-center_y

                inputCoords= np.array([i_transfI, j_transfI])
                i_transfI, j_transfI = np.dot(TInv,inputCoords)

                i_transfI+= center_x
                j_transfI+=center_y
                # the inverse transformed coordinates are used for the original image this time
                if(0<i_transfI < height and 0<j_transfI < width):
                    imgOutputInv[int(i+main_dimension/2), int(j+main_dimension/2), :] = img[int(i_transfI), int(j_transfI), :]

        plt.imshow(imgOutputInv.astype('uint8'))
        plt.show()

#ICV_transform_Image("name_image.JPG", 1, -50, 60)
ICV_transform_Image("Dataset/DatasetA/car-1.JPG", 1, 20, 50)

def ICV_createTextImage():

    imgOutput = Image.new('RGB', (400, 100), color = 'blue')
    #rect = patches.Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none')
    fnt = ImageFont.truetype('arial.ttf', 72)
    draw = ImageDraw.Draw(imgOutput)
    draw.text((0,0), "SHEHRYAR", font=fnt,fill=(255,255,255))

    imgOutput.save('name_image.jpg')
    plt.imshow(imgOutput)
    plt.show()
#ICV_createTextImage()

############################################################
# END Question - 1 - Transformations
############################################################

############################################################
# START Question - 2 - Convolutions
############################################################

# gray = 1 or 0, filter = 0,1,2 for average, A and B respectively
def ICV_filter_Image(fileName, gray, filter):

    #Mean filter
    filterAvg = np.array([
        [1/9,1/9,1/9],
        [1/9,1/9,1/9],
        [1/9,1/9,1/9]])

    #Laplacian filter
    filterB = np.array([
        [0,1,0],
        [1,-4,1],
        [0,1,0]])

    # Gaussian blur
    filterA = np.array([
        [1/16,2/16,1/16],
        [2/16,4/16,2/16],
        [1/16,2/16,1/16]])

    if(filter == 0):
       Tfilter = filterAvg
    elif(filter == 1):
       Tfilter = filterA
    elif(filter == 2):
       Tfilter = filterB

    img = plt.imread(fileName)
    if(gray == 1):
        img = ICV_grayscale(img)

    height, width = img.shape[:2]

    imgOutput = np.ndarray((height,width,3))

    upper = 0
    lower = 0
    right = 0
    left = 0

    # if image is grayscale
    if(gray == 1):
        # iterating over the whole image
        for i in range(height):
            for j in range(width):

                # conditional statements to ignore the borders
                if(i-1>height):
                    upper = img[i-1, j]*(Tfilter[0,1])

                if(i+1<height):
                    lower = img[i+1, j]*(Tfilter[2,1])
                    lower_left = img[i+1, j-1]*(Tfilter[2,0])

                if(j+1<width):
                    right = img[i, j+1]*(Tfilter[1,2])
                    upper_right= img[i-1, j+1]*(Tfilter[0,2])

                if(j+1<width) and (i+1<height):
                    lower_right = img[i+1, j+1]*(Tfilter[2,2])

                left = img[i, j-1]*(Tfilter[1,0])
                upper_left = img[i-1, j-1]*(Tfilter[0,0])

                # the center value is computed by also adding the filtered values of the neighbouring pixels
                imgOutput[i, j] = (img[i, j]*(Tfilter[1,1]) + upper+lower+left+right+lower_left+lower_right+upper_left+upper_right)

                # each newly assigned pixel value is checked for an overflow of value
                for channel in range(3):
                    if(imgOutput[i, j, channel] > 255):
                        imgOutput[i, j, channel] = 255
                    if(imgOutput[i, j, channel] < 0):
                        imgOutput[i, j, channel] = 0

    # if image is not grayscale
    else:

        for i in range(height):
            for j in range(width):

                if(i-1>height):
                    upper = img[i-1, j, :]*(Tfilter[0,1])

                if(i+1<height):
                    lower = img[i+1, j, :]*(Tfilter[2,1])
                    lower_left = img[i+1, j-1, :]*(Tfilter[2,0])

                if(j+1<width):
                    right = img[i, j+1, :]*(Tfilter[1,2])
                    upper_right= img[i-1, j+1, :]*(Tfilter[0,2])

                if(j+1<width) and (i+1<height):
                    lower_right = img[i+1, j+1, :]*(Tfilter[2,2])

                left = img[i, j-1, :]*(Tfilter[1,0])
                upper_left = img[i-1, j-1, :]*(Tfilter[0,0])

                imgOutput[i, j, :] = (img[i, j, :]*(Tfilter[1,1]) + upper+lower+left+right+lower_left+lower_right+upper_left+upper_right)

                for channel in range(3):
                    if(imgOutput[i, j, channel] > 255):
                        imgOutput[i, j, channel] = 255
                    if(imgOutput[i, j, channel] < 0):
                        imgOutput[i, j, channel] = 0

    plt.axis('off')

    plt.imshow(imgOutput.astype('uint8'))
    plt.savefig("test.jpg", bbox_inches='tight')
    plt.show()

#ICV_filter_Image("test.JPG",1,2)
#ICV_filter_Image("Dataset/DatasetA/car-1.JPG",1,2)

############################################################
# END Question - 2 - Convolutions
############################################################

############################################################
# START Question - 3 - Histograms and Video Segmentation
############################################################

# intersection = 1 or 0
def ICV_histogram_Image(imagehist, intersection):

    img = plt.imread(imagehist)
    imgGray = ICV_grayscale(img)

    height, width = img.shape[:2]

    #no_pixels_channel = width*height

    #create integer arrays for 256 values
    red_hist = [0]*256
    green_hist = [0]*256
    blue_hist = [0]*256
    final_hist = [0]*256

    #iterate over the whole image for image values
    for i in range(height):
        for j in range(width):
            # use the image pixel value as the index value of each channel's histogram and increment the indexed value of that channel histogram
            final_hist[int(imgGray[i, j])] += 1

    # if intersection is not required also compute the histograms of the channels separately
    if(intersection == 0):
        #iterate over the whole image for image values
        for i in range(height):
            for j in range(width):
                # use the image pixel value as the index value of each channel's histogram and increment the indexed value of that channel histogram
                red_hist[int(img[i, j,0])] += 1
                green_hist[int(img[i, j, 1])] += 1
                blue_hist[int(img[i, j, 2])] += 1

        #graph for color channels histogram
        for i in range(0, 256):

            #normalize the histogram values
            red_hist[i]/=1
            green_hist[i]/=1
            blue_hist[i]/=1

            plt.bar(i, red_hist[i], color='red', alpha=0.6)
            plt.bar(i, green_hist[i], color='green', alpha=0.6)
            plt.bar(i, blue_hist[i], color='blue', alpha=0.8)

        plt.xlabel('Pixel Range (0-255)')
        plt.ylabel('Pixel Frequencies')
        plt.title('RGB Histogram')
        plt.show()

        # graph the grayscale histogram
        for i in range(0, 256):
            plt.bar(i, final_hist[i], color='black', alpha=0.8)

        plt.xlabel('Pixel Range (0-255)')
        plt.ylabel('Pixel Frequencies')
        plt.title('Grayscale Histogram')
        plt.show()

    return final_hist, np.sum(final_hist)

#ICV_histogram_Image("cap1.JPG",0)

# seq_intersection = 0 or 1, normalize = 0 or 1
# function takes the intersection between the histograms of two images, and returns the overlap value
def ICV_histogram_intersection(img_1, img_2, seq_intersection, normalize):

    sum_hist = 0.0

    # getting the histograms of the two frames
    hist_1, no = ICV_histogram_Image(img_1,1)
    hist_2, no_pixels = ICV_histogram_Image(img_2,1)
    inter_hist = [0]*256

    # to calculate the intersection value, take the minimum of value amongst the two histograms.
    # Also calculate the sum of the intersection values
    # If required to normalize divide by the number of pixels
    for i in range(0,256):
        inter_hist[i] = min(hist_1[i], hist_2[i])
        if(normalize == 1):
            inter_hist[i] /= no_pixels
        sum_hist += inter_hist[i]

    # check whether if it is a video sequence, plotting individual intersections would not be efficient
    if(seq_intersection == 0):
        #plotting the values of the two histograms together
        for i in range(0,256):

            plt.bar(i, hist_1[i], color='gray', alpha=0.8)
            plt.bar(i, hist_2[i], color='yellow', alpha=0.5)

        plt.xlabel('Pixel Range (0-255)')
        plt.ylabel('Pixel Frequencies')
        plt.title('Overlap of the two histograms')
        plt.show()

        #plotting the intersection values of the histograms
        for i in range(0,256):
            plt.bar(i, inter_hist[i], color='black', alpha=0.8)

        plt.xlabel('Pixel Range (0-255)')
        plt.ylabel('Pixel Frequencies')
        plt.title('Plot for intersection values')
        plt.show()

    print("Intersection Value: ", (sum_hist))
    if(normalize == 1):
        print("Normalized Intersection Value: ", (sum_hist)*100)

    return (sum_hist)
#ICV_histogram_intersection("cap0.JPG","cap1.JPG",0, 0)

# normalize = 1 and 0
def ICV_capVid(filename, normalize):
    cam = cv2.VideoCapture(filename)
    inter_vals = [0]*int(cam.get(cv2.CAP_PROP_FRAME_COUNT))
    i=0

    if(normalize ==1):
        max_val = 1.0 # for normailzed value between 0 and 1
    else:
        max_val = 80000

    while(cam.isOpened()):
        ret, frame = cam.read()
        if ret == False:
            break
        cv2.imwrite('cap'+str(i)+'.jpg',frame)

        # only if one frame has been captured, then start with taking intersections
        if(i>0):
            img_1 = 'cap'+str(i-1)+'.jpg'
            img_2 = 'cap'+str(i)+'.jpg'
            inter_vals[i] = ICV_histogram_intersection(img_1, img_2,1,normalize)
            sec = ((int(cam.get(cv2.CAP_PROP_POS_MSEC)))/1000)# convert milliseconds to seconds
            print(i, sec, img_1, img_2, inter_vals[i])
            plt.bar(sec, (max_val-inter_vals[i]), color='black', alpha=0.8)
        i+=1

    plt.xlabel('Time (seconds)')
    plt.ylabel('Intersection Values (max intersection value-intersection value)')
    plt.show()
    cam.release()
    cv2.destroyAllWindows()

#ICV_capVid("Dataset/DatasetB.AVI",1)

############################################################
# END Question - 3 - Histograms and Video Segmentation
############################################################

############### References
#https://stackabuse.com/affine-image-transformations-in-python-with-numpy-pillow-and-opencv/

############### README

############### TRANSFORMATIONS
############################################################
#ICV_transform_Image(filename, transformation, rotation angle, skew angle)
#transformations: 0=skew matrix, 1=rotation matrix, 2=rotation+skew, 3=skew+rotation

#ICV_transform_Image("Dataset/DatasetA/car-1.JPG", 3, 20, 50)

############### CONVOLUTIONS
############################################################
#ICV_filter_Image(filname,convert it to grayscale?,filter)
#filter: 0=average filter, 1=filter A, 2=filter=B
#convert it to grayscale?: 0=No, 1=Yes

#ICV_filter_Image("Dataset/DatasetA/car-1.JPG",1,2)

############### HISTORGRAMS AND VIDEO SEGMENTATION
############################################################
#ICV_histogram_Image(filename,is for intersection?)
#is for intersection?: 0=No, 1=Yes

#ICV_histogram_Image("cap1.JPG",0)

#ICV_histogram_intersection(filename1,filename2, is video sequence?, to normalize?)
#is video sequence?: 0=No, 1=Yes
#to normalize?: 0=No, 1=Yes

#ICV_histogram_intersection("cap0.JPG","cap1.JPG",0, 0)

#ICV_capVid(filename, to normalize?)
#to normalize?: 0=No, 1=Yes

#ICV_capVid(filename,1)


"""Sphinx configuration."""
from datetime import datetime
from typing import List

project = "chenv"
author = "Jonathan Shemer"
copyright = f"{datetime.now().year}, {author}"
extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon", "sphinx_autodoc_typehints"]
html_static_path: List[str] = []


#!/usr/bin/env python
# coding: utf-8

# ## Mutable vs Immutable

# - mutable= can mutate/change
# - Note: reassigning variable is different thing

# ### Strings are immutable,can't be changed

# In[1]:

s='sahil'

# In[2]:

#s[0]='H'  #can't be done because strings are immutable

# ### Lists are mutable

# In[3]:

s=[1,2,3]
s[0]=3
s

# ### Immmutable datatypes:
# - tupple
# - string
# - float
# - int

_build/jupyter_execute/Chapter files/Mutable vs Immutable.py


from requests import request, RequestException
from requests.auth import HTTPBasicAuth
from local_server import *
from threading import Thread
from sys import stderr
import traceback
try:
    import simplejson as json
except ImportError:
    import json

from .i18n import translations

_, _N = translations('utils')

# Default address for the server providing the REST API
_REST_ADDR = 'http://localhost/'

def _execute_request(verb, path, **kwargs):
    """Send an HTTP request to the REST API.

    Parameters:
        verb: HTTP verb to use for the request (mainly 'GET' and 'POST').
        path: URL of the target page.
        kwargs: extra arguments for the request such as POST data or timeout.
    """
    kwargs.update({'auth': HTTPBasicAuth(basic_user, basic_password)})
    try:
        request(verb, _REST_ADDR + path, **kwargs)
    except RequestException as e:
        print(_('REST request {} failed:').format(path[:-1]), file=stderr)
        for pretty_print in traceback.format_exception_only(type(e), e):
            print(pretty_print, file=stderr)

def _do_request(path, args=None):
    """Execute a request on a separate thread to avoid waiting on I/O.

    Parameters:
        path: URL of the target page.
        args: POST data for the page that will be json encoded.
    """
    if args:
        thread = Thread(target=_execute_request,
                name='rest-post',
                args=('POST', path),
                kwargs={'timeout':15, 'data':{'data':json.dumps(args)}})
    else:
        thread = Thread(target=_execute_request,
                name='rest-get',
                args=('GET', path),
                kwargs={'timeout':15})
    thread.start()

def setup(game_name, rules, *people):
    """Tell the REST API about a new race that is likely to be started soon.

    Parameters:
        game_name: name for the route and custom rules used for this race.
        rules: route and custom rules data for this race.
        people: informations on the drivers of this race.
    """
    """JSON
    Setup object:
    -------------
     - pilotes: Array of driver objects
            -> drivers for this race
     - course: Race object
            -> rules for this race

    Race object:
    ------------
     - nom: string
            -> name for the set of rules
     - temps: number or null
            -> time available before the race ends, if relevant
     - tours: number or null
            -> number or laps needed to clear the race, if relevant
     - portes: Array of strings
            -> active gates identificators for this race

    Driver object:
    --------------
     - id: number
            -> identification of the beacon given to the driver for the race
     - nom: string
            -> name of the driver
     - drone: string
            -> kind of its drone
    """
    setup = rules.get_setup()
    setup.update({'nom': game_name})
    data = {'pilotes': people, 'course': setup}
    _do_request('setup/', data)

def warmup(text, start):
    """Tell the REST API that a race is being started and provide a
    text to display.
    """
    """JSON
    Warm-up object:
    --------------
     - texte: string
            -> text to display
     - start: bool
            -> whether the race should be started (timer, leader-board, etc.)
    """
    _do_request('warmup/', {'texte': text, 'start': start})

def update(drone):
    """Tell the REST API that a drone had its status changed."""
    """JSON
    Drone object:
    -------------
     - id: number
            -> identification number of the beacon attached on the drone
     - position: number
            -> ranking of the drone at this moment of the race
     - points: number
            -> number of points for the drone at this moment of the race
     - temps: number
            -> elapsed time from the beginning of the race
     - retard: number or null
            -> delay accumulated over the first overall drone, if relevant
     - tour: number or null
            -> timing of the last lap for this drone, if relevant
     - finish: bool or null
            -> whether the drone finished the race or was declared dead,
                if it is not still flying
     - tours: number
            -> number of laps performed by the drone
     - porte: string or null
            -> identification of the last gate the drone passed by, if relevant
    """
    _do_request('update/', drone)

def cancel():
    """Tell the REST API that a race has been canceled."""
    """JSON
    No data
    """
    _do_request('cancel/')

def finish():
    """Tell the REST API that a race just finished.
    Leader-board may still change.
    """
    """JSON
    No data
    """
    _do_request('finish/')

def leaderboard(*drones):
    """Send the final leader-board to the REST API."""
    """JSON
    Array of drone objects.

    Drone object:
    -------------
     - id: number
            -> identification number of the beacon attached on the drone
     - position: number
            -> ranking of the drone at this moment of the race
     - points: number
            -> number of points for the drone at this moment of the race
     - temps: number
            -> time required by the drone to clear the race
     - retard: number or null
            -> delay accumulated over the first overall drone, if relevant
     - tour: number or null
            -> timing of the best lap for this drone, if relevant
     - finish: bool or null
            -> whether the drone finished the race or was declared dead,
                if it is not still flying
     - tours: number
            -> number of laps performed by the drone
     - porte: string or null
            -> identification of the last gate the drone passed by, if relevant
    """
    _do_request('leaderboard/', {'drones': drones})


from math import log10

POW10 = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]

def count_from_1(n):
    count = [0] * 10
    if n == 0:
        return count

    power_max = int(log10(n))
    for p, d in enumerate([int(i) for i in str(n)]):
        left_side, right_side = divmod(n, POW10[power_max - p])
        count[d] += right_side + 1
        left_side //= 10

        for i in range(d):
            count[i] += (left_side + 1) * POW10[power_max - p]
        for i in range(d, 10):
            count[i] += left_side * POW10[power_max - p]

        count[0] -= POW10[power_max - p]
    return count

if __name__ == '__main__':
    while True:
        a, b = map(int, input().split())
        if a == b == 0:
            break
        digits_count_a = count_from_1(a - 1)
        digits_count_b = count_from_1(b)
        digit_count_from_a_to_b = [digits_count_b[i] - digits_count_a[i] for i in range(10)]
        print(' '.join([str(d) for d in digit_count_from_a_to_b]))


# ABOUT: Script to calculate mean execution time
#
# Input 1: query output file consisting of two columns: (query name with ID) and (query exec time)
# Output: Mean query execution time for every query pattern

import sys

if __name__ == '__main__':

    result_file = open(sys.argv[1])
    output_file = open(sys.argv[2])

    id_dict = dict()
    mean_time_dict = dict()
    for line in result_file:
        line = line.strip()
        parts = line.split("\t")
        id = int(parts[0].split("--SO-OS-SS-VP")[0])
        pattern_id = id - 1 / 100 + 1
        time = parts[1]
        if pattern_id in id_dict:
            lst = id_dict[pattern_id]
            lst.add(time)
            id_dict[pattern_id] = lst
        else:
            lst = list()
            lst.add(time)
            id_dict[pattern_id] = lst

    for key in id_dict.keys():
        lst = id_dict[key]
        meantime = 0
        size = len(lst)
        for elem in lst:
            meantime += elem
        mean_time_dict[key] = meantime / size

    for key in mean_time_dict.keys():
        output_file.write(key + "\t" + mean_time_dict[key])

    output_file.close()


from requests import get
from os import system
from twilio.rest import Client

VERSION = "0.0.1"
ACCOUNT_SID = ""
AUTH_TOKEN = ""
PHONE_NUMBER = ""

system("cls")
system("clear")

print(f"Text Program v{VERSION}\nFetching Database...")

# FETCH DATABASE
try:
    text_database = get("FETCH_API_HERE").json()
except:
    print("Error - Stopping")
    SystemExit()

# GET USER COUNT
count = 0
for user in text_database["data"]:
    count += 1

print(f"Fetched {count} users")

# CONNECT TO TWILIO
try:
    client = Client(ACCOUNT_SID, AUTH_TOKEN)
except:
    print("Error - Stopping")
    SystemExit()

# READ MESSAGE
def get_message():
    message = open("message.txt", "w")
    message.write("TEXT MESSAGE HERE, USE {@user} TO REPLACE WITH THEIR NAME\nDELETE ALL CONTENTS OF FILE FIRST!")
    message.close()

    system("cls")
    system("clear")

    print("Open the file 'message.txt' and put the text in this file. Be sure to delete all contents of file.")
    input("Press enter when ready...")

    message = open("message.txt", "r")
    print("Your message:\n---\n")
    output = message.read()
    message.close()

    print(output)
    print("\n--\n")

    check = input("Enter the number '1' if this is the message you want to use, otherwise, enter anything to update it.")
    if check == "1":
        return output
    else:
        return get_message()

# SECONDARY MENU
def message_menu():
    check = input("[3] Send as test (to steve and Erik)\n[4] Send officially (to everyone)\n")
    if check == "3":
        return "test"
    elif check == "4":
        return "everyone"
    else:
        print("Huh, I am not sure what you meant. Maybe try again?")
        return message_menu()

# SEND TEXT
def text(message, to, name="Test"):
    try:
        msg = client.messages.create(
            body = message,
            from_ = PHONE_NUMBER,
            to = "+1" + to
        )
        print (f"Sent text to {name} at {to}")
        return msg
    except:
        print("Error - Stopping")

# SHOW MENU
request = input("Enter the number of the command:\n[1] Send Text\n[2] Quit\n")
while not request == "2":
    if request == "1":
        print("Send Text")

        message = get_message()
        option = message_menu()

        if option == "test":
            msg = text(message.replace("{@user}", "Erik"), "", "Erik") # Send to Erik
            msg = text(message.replace("{@user}", "Steve"), "", "Steve") # Send to Steve
            print("Done!")
        elif option == "everyone":
            sent = 0
            for user in text_database["data"]:
                msg = text(message.replace("{@user}", user['name']), user['phone'], user['name'])

                system("cls")
                system("clear")

                to_percent = round((sent / count), 2) * 100
                print(f"Sending...\n{to_percent}% Complete")

                sent += 1
            print("Done!")

    else:
        print(f"Command '{request}' not recognized")
    request = input("Enter the number of the command:\n[1] Send Text\n[2] Quit\n")

print("Goodbye!")


import requests
import re

class WaybackAnalysis:

    def __init__(self, domain:str) -> None:
        self.domain = domain

        self.wayback_url = "https://web.archive.org/web/*/http://" + domain

        url = "http://" + domain
        wburl = "http://web.archive.org/web/timemap/link/http://" + url

        response = requests.get(wburl,verify=False)

        self.response = response.content.decode().split('\n')

        length = len(self.response)

        self.number_archives = 0
        self.first_date = ""
        self.last_date = ""

        if length >= 4:
            self.number_archives = length - 4
            reg_expr = "datetime=\"(.*)\""

            first = re.search(reg_expr, self.response[3])
            if first:
                self.first_date = first.group(1)

            last = re.search(reg_expr, self.response[-2])
            if last:
                self.last_date = last.group(1)


from socket import *
from base64 import b64encode
import ssl
import sys
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage

# Construct multipart message
attachment = 'shibainu.jpg'

msg = MIMEMultipart()
msg["To"] = 'alice@gmail.com'
msg["From"] = 'bob@gmail.com'
msg["Subject"] = 'Mail Client Test'

msgText = MIMEText(
    f'
I love computer networks!
', 'html')
msg.attach(msgText)

with open(attachment, 'rb') as fp:
    img = MIMEImage(fp.read())
    img.add_header('Content-Disposition', 'inline', filename=attachment)
    img.add_header('Content-ID', f'<{attachment}>')
    msg.attach(img)

msg = msg.as_string()
endmsg = "\r\n.\r\n"

# Choose a mail server
mailserver = 'smtp.gmail.com'

# Create a socket and establish TCP connection with mailserver
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((mailserver, 587))

recv = clientSocket.recv(1024).decode()
print(recv)

if recv[:3] != '220':
    print('220 reply not received from server.')
    sys.exit()

# Send HELO command and print server response
heloCommand = 'HELO alice\r\n'
clientSocket.send(heloCommand.encode())
recv1 = clientSocket.recv(1024).decode()
print(recv1)
if recv1[:3] != '250':
    print('250 reply not received from server.')
    sys.exit()

# Start TLS connection
command = 'STARTTLS\r\n'
clientSocket.send(command.encode())
recv2 = clientSocket.recv(1024).decode()
print(recv2)
if recv2[:3] != '220':
    print('220 reply not received from server.')
    sys.exit()

# Wrap clientSocket
clientSocket = ssl.wrap_socket(clientSocket)

# Send EHLO command
heloCommand = 'EHLO alice\r\n'
clientSocket.send(heloCommand.encode())
recv3 = clientSocket.recv(1024).decode()
print(recv3)
if recv3[:3] != '250':
    print('250 reply not received from server.')
    sys.exit()

# Send AUTH command and print server response
info = 'alice@gmail.com\x00alice@gmail.com\x00password'
b64info = b64encode(info.encode()).decode('ascii')
authCommand = f'AUTH PLAIN {b64info}\r\n'
clientSocket.send(authCommand.encode())
recv4 = clientSocket.recv(1024).decode()
print(recv4)
if recv4[:3] != '235':
    print('235 reply not received from server.')
    sys.exit()

# Send MAIL FROM command and print server response
mailFromCommand = 'MAIL FROM: <alice@gmail.com>\r\n'
clientSocket.send(mailFromCommand.encode())
recv5 = clientSocket.recv(1024).decode()
print(recv5)
if recv5[:3] != '250':
    print('250 reply not received from server.')
    sys.exit()

# Send RCPT TO command and print server response
rcptCommand = 'RCPT TO: <bob@gmail.com>\r\n'
clientSocket.send(rcptCommand.encode())
recv6 = clientSocket.recv(1024).decode()
print(recv6)
if recv6[:3] != '250':
    print('250 reply not received from server.')
    sys.exit()

# Send DATA command and print server response
dataCommand = 'DATA\r\n'
clientSocket.send(dataCommand.encode())
recv7 = clientSocket.recv(1024).decode()
print(recv7)
if recv7[:3] != '354':
    print('354 reply not received from server')
    sys.exit()

# Send message data
for i in range(len(msg)):
    clientSocket.send(msg[i].encode())

# Message ends with a single period
clientSocket.send(endmsg.encode())

recv8 = clientSocket.recv(1024).decode()
print(recv8)
if recv8[:3] != '250':
    print('250 reply not received from server.')
    sys.exit()

# Send QUIT command and get server response
quitCommand = 'QUIT\r\n'
clientSocket.send(quitCommand.encode())
recv9 = clientSocket.recv(1024).decode()
print(recv9)
if recv9[:3] != '221':
    print('221 reply not received from server.')

clientSocket.close()