"""Route declaration."""
from flask import current_app as app
from flask import render_template
import yaml
import os

current_directory = os.path.abspath(os.path.dirname(__file__))

# nav = [
#     {"name": "Home", 'page' : 'home'},
#     {"name": "Short CV", 'page':'cv'},
#     {"name": "Publications", 'page':'pubs'},
#     {"name": "Recipes", 'page':'recipes'},
#     ]
nav = {
    'index': {"name":"About",
             'desc':""},
    # 'laurel': {"name": "Laurels",
    #          'desc':'Laurels'},
    'team': {"name":"Team",
             'desc':""},
    'press': {"name": "Press",
             'desc':''},
    'blurb': {"name": "What People are Saying",
              'desc':''},
    'impact': {"name": "Resources & Impact",
             'desc':''},
    # 'presskit': {"name": "Press Kit",
    #          'desc':''},
    'contact': {"name": "Contact",
                'desc':''},
     'watch': {"name": "Watch",
             'desc':''}
}

# press = [
# ("At The Movies: Some Women is a moving, painfully honest look at a trans woman's life in S'pore",
#  "https://str.sg/wnme",
#   "John Lui",
#      "Straits Times",
#      "2022-03-23",
#  "", ""),

#     ("Some Women film hopes to show that being transgender is not 'sexual deviancy'",
#      "https://str.sg/wnmP",
#      "John Lui",
#      "Straits Times",
#      "2022-03-23",
#      """SINGAPORE - In the documentary Some Women, film-maker Quen Wong shows herself being physically close to husband Francis Bond. They hold hands, cuddle and kiss - just like any ordinary couple.

# In a film filled with conversation and visuals that deal with the turbulent journey Wong and others have taken as transgender women in Singapore, the quiet moments of intimacy are akin to hitting the pause button.""",
#      ""),
#     ("《一些女人》一刀不剪公映 跨性别者从他变她",
#      "https://www.zaobao.com.sg/entertainment/story20220322-1254754",
#      "李亦筠",
#      "Zaobao",
#      "2022-03-23",
#      "", ""),
#     ("This Singaporean Filmmaker’s Debut Feature Is a Love Letter to the Trans Community",
#      "https://www.tatlerasia.com/culture/arts/sgiff-2021-singaporean-filmmaker-quen-wong-some-women-trans-community",
#      "HASHIRIN NURIN HASHIMI",
#      "Tatler",
#      "2021-12-03",
#      "", ""),
# ]

@app.route("/<page>.html")
def show(page):
    """Show a page"""
    if page == 'press':
        yaml_file= os.path.join(current_directory, 'press.yaml')
        with open(yaml_file, "r") as stream:
            details = yaml.safe_load(stream)
    elif page == 'blurb':
        yaml_file= os.path.join(current_directory, 'blurb.yaml')
        with open(yaml_file, "r") as stream:
            details = yaml.safe_load(stream)
    else:
         details = []

    return render_template(
        f"{page}.html",
        page=page,
        nav=nav,
        title=nav[page]['name'],
        description=nav[page]['desc'],
        details=details
    )

@app.route("/")
def home():
    """show the home page"""
    return show('index')


import tornado.web
import json
import config
from mongoengine import *
from models.activity_model import Activity

class MissingArgumentError(Exception):
    '''自定义异常类'''

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

class BaseHandler(tornado.web.RequestHandler):
    def set_default_headers(self):
        self.add_header('Access-Control-Allow-Origin', '*')
        self.set_header("Access-Control-Allow-Headers",
                        "Content-Type,Access-Token,X-Token,x-requested-with")
        self.set_header('Access-Control-Allow-Methods',
                        "GET, POST, OPTIONS, PUT")
        self.set_header('Access-Control-Allow-Credentials', '*')
        self.set_header('Access-Control-Expose-Headers', '*')

    def get_json_argument(self, name, default=None):
        args = json.loads(self.request.body)
        # name = to_unicode(name)
        if name in args:
            return args[name]
        elif default is not None:
            return default
        else:
            raise MissingArgumentError(name)

class get_activities(BaseHandler):

    def post(self, *args, **kwargs):
        data_list = Activity.get_activities()
        print(data_list)

        motion_list = []
        for activity in data_list:
            motion_list.append({'motion_id': activity.motion_id, 'motion_name': activity.motion_name,
                                'motion_type': activity.motion_type,'motion_content': activity.motion_content,
                                'motion_picture': activity.motion_picture, 'consume_calorie': activity.consume_calorie})

        data = {'code': '200', 'motion_list': motion_list}
        self.write(json.dumps(data))


import json
import logging

import requests

from azbankgateways.banks import BaseBank
from azbankgateways.exceptions import BankGatewayConnectionError, SettingDoesNotExist
from azbankgateways.exceptions.exceptions import BankGatewayRejectPayment
from azbankgateways.models import BankType, CurrencyEnum, PaymentStatus
from azbankgateways.utils import get_json, split_to_dict_querystring

class IDPay(BaseBank):
    _merchant_code = None
    _method = None
    _x_sandbox = None
    _payment_url = None
    _params = {}

    def __init__(self, **kwargs):
        super(IDPay, self).__init__(**kwargs)
        self.set_gateway_currency(CurrencyEnum.IRR)
        self._token_api_url = "https://api.idpay.ir/v1.1/payment"
        self._verify_api_url = "https://api.idpay.ir/v1.1/payment/verify"

    def get_bank_type(self):
        return BankType.IDPAY

    def set_default_settings(self):
        for item in ["MERCHANT_CODE", "METHOD", "X_SANDBOX"]:
            if item not in self.default_setting_kwargs:
                raise SettingDoesNotExist()
            setattr(self, f"_{item.lower()}", self.default_setting_kwargs[item])

        self._x_sandbox = str(self._x_sandbox)

    """
    gateway
    """

    def _get_gateway_payment_url_parameter(self):
        return self._payment_url

    def _get_gateway_payment_parameter(self):
        params = {}
        params.update(self._params)
        return params

    def _get_gateway_payment_method_parameter(self):
        return "GET"

    """
    pay
    """

    def get_pay_data(self):
        data = {
            "order_id": self.get_tracking_code(),
            "amount": self.get_gateway_amount(),
            "phone": self.get_mobile_number(),
            "callback": self._get_gateway_callback_url(),
        }
        return data

    def prepare_pay(self):
        super(IDPay, self).prepare_pay()

    def pay(self):
        super(IDPay, self).pay()
        data = self.get_pay_data()
        response_json = self._send_data(self._token_api_url, data)
        if "id" in response_json and "link" in response_json and response_json["link"] and response_json["id"]:
            token = response_json["id"]
            self._payment_url, self._params = split_to_dict_querystring(response_json["link"])
            self._set_reference_number(token)
        else:
            logging.critical("IDPay gateway reject payment")
            raise BankGatewayRejectPayment(self.get_transaction_status_text())

    """
    verify gateway
    """

    def prepare_verify_from_gateway(self):
        super(IDPay, self).prepare_verify_from_gateway()
        for method in ["GET", "POST", "data"]:
            token = getattr(self.get_request(), method).get("id", None)
            if token:
                self._set_reference_number(token)
                self._set_bank_record()
                break

    def verify_from_gateway(self, request):
        super(IDPay, self).verify_from_gateway(request)

    """
    verify
    """

    def get_verify_data(self):
        super(IDPay, self).get_verify_data()
        data = {
            "id": self.get_reference_number(),
            "order_id": self.get_tracking_code(),
        }
        return data

    def prepare_verify(self, tracking_code):
        super(IDPay, self).prepare_verify(tracking_code)

    def verify(self, transaction_code):
        super(IDPay, self).verify(transaction_code)
        data = self.get_verify_data()
        response_json = self._send_data(self._verify_api_url, data, timeout=10)
        if response_json.get("verify", {}).get("date", None):
            self._set_payment_status(PaymentStatus.COMPLETE)
            extra_information = json.dumps(response_json)
            self._bank.extra_information = extra_information
            self._bank.save()
        else:
            self._set_payment_status(PaymentStatus.CANCEL_BY_USER)
            logging.debug("IDPay gateway unapprove payment")

    def _send_data(self, api, data, timeout=5):
        headers = {
            "X-API-KEY": self._merchant_code,
            "X-SANDBOX": self._x_sandbox,
        }
        try:
            response = requests.post(api, headers=headers, json=data, timeout=timeout)
        except requests.Timeout:
            logging.exception("IDPay time out gateway {}".format(data))
            raise BankGatewayConnectionError()
        except requests.ConnectionError:
            logging.exception("IDPay time out gateway {}".format(data))
            raise BankGatewayConnectionError()

        response_json = get_json(response)
        if "error_message" in response_json:
            self._set_transaction_status_text(response_json["error_message"])
        return response_json


# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.3'
#       jupytext_version: 0.8.6
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

import numpy as np
import matplotlib.pyplot as plt
x = np.random.randn(1000)
y = np.random.randn(1000)
plt.scatter(x, y)
plt.show()

plt.hist(x)

plt.hist(y)


from dataclasses import dataclass
import dataclasses
from typing import Iterable
import numpy as np
import random
import math

@dataclass
class AdkGameOptions:
    width: int = 300
    height: int = 300

    player_speed: float = 30
    turn_speed: float = 90
    snake_radius: float = 2.5

    tps: float = 30

class AdkPlayer:
    def init(self, player_id: int, opts: AdkGameOptions):
        pass

    send_turn = None

    def get_turn(self, game_state: np.ndarray, x: float, y: float, dir: float) -> int:
        raise NotImplementedError

class AdkGame:
    def __init__(self, players: Iterable[AdkPlayer], opts: AdkGameOptions):
        self.players = tuple(players)
        self.num_players = len(players)
        self.opts = opts
        self._state = np.zeros(
            (self.opts.width, self.opts.height), dtype=np.int8)
        self._player_pos = [
            (random.uniform(self.opts.width / 4, self.opts.width * 3 / 4),
             random.uniform(self.opts.height / 4, self.opts.height * 3 / 4))
            for _ in self.players]
        self._player_alive = [True for _ in self.players]
        # self._player_dir = [90 for _ in self.players]
        self._player_dir = [random.uniform(0, 360) for _ in self.players]

        for i, p in enumerate(self.players):
            p.init(i+1, AdkGameOptions(**dataclasses.asdict(opts)))

    def _draw_snakes(self):
        R = self.opts.snake_radius
        R2 = R*R

        for i, ((px, py), pr) in enumerate(zip(self._player_pos, self._player_dir)):
            # rx, ry = math.sin(math.radians(pr)), math.cos(math.radians(pr))
            for cx in range(math.floor(px - 2*R), math.ceil(px + 2*R)):
                for cy in range(math.floor(py - 2*R), math.ceil(py + 2*R)):
                    if cx < 0 or cx >= self.opts.width or cy < 0 or cy >= self.opts.height:
                        continue
                    dx, dy = cx - px, cy - py
                    if dx*dx + dy*dy <= R2:
                        if self._state[cx, cy] == 0:
                            self._state[cx, cy] = -(i+1)
                    elif self._state[cx, cy] == -(i+1):
                        self._state[cx, cy] = i+1

    def _move_snakes(self):
        for pi, (player, (px, py), pr, p_alive) in enumerate(zip(self.players, self._player_pos, self._player_dir, self._player_alive)):
            if player.send_turn:
                player.send_turn(self._state.copy(), px, py, pr)
            if not p_alive:
                continue
            answer = player.get_turn(self._state.copy(), px, py, pr)
            if answer == -1:
                pr -= self.opts.turn_speed / self.opts.tps
            elif answer == 1:
                pr += self.opts.turn_speed / self.opts.tps

            pr %= 360
            if pr < 0:
                pr += 360

            px += math.cos(math.radians(pr)) * \
                self.opts.player_speed / self.opts.tps
            py += math.sin(math.radians(pr)) * \
                self.opts.player_speed / self.opts.tps

            self._player_pos[pi] = (px, py)
            self._player_dir[pi] = pr

    def _check_colision(self):
        for pi, ((px, py), p_alive) in enumerate(zip(self._player_pos, self._player_alive)):
            if not p_alive:
                continue

            cx, cy = math.floor(px), math.floor(py)

            # print(px, py, cx, cy)

            if (px > self.opts.width or px < 0
                or py > self.opts.height or py < 0
                    or self._state[cx, cy] not in (0, -(pi+1))):
                self._player_alive[pi] = False

    def turn(self):
        self._draw_snakes()
        self._move_snakes()
        self._check_colision()

        # print(self._state)

        return sum(self._player_alive) > 1

    def get_winner(self):
        if sum(self._player_alive) != 1:
            return None

        return self._player_alive.index(True) + 1


import time

from selenium.webdriver.common.action_chains import ActionChains

from Selenium.findElementByXpathToSelenium import search

def click(driver, xpathOrElement, debug=True, timer=2):
    try:
        if type(xpathOrElement).__name__ == "str":
            element = search(driver, xpathOrElement, debug=debug)
        else:
            element = xpathOrElement
        ActionChains(driver).move_to_element(element).click(element).perform()
        time.sleep(timer)
        return element
    except:
        return None


#!/usr/bin/env python
"""
Do the charge linearity anaylsis

Usage:
  digicam-charge-linearity [options] [--] <INPUT>...

Options:
  -h --help                   Show this screen.
  --max_events=N              Maximum number of events to analyse.
  --output_file=OUTPUT        File where to store the fit results.
                              [default: ./fit_results.npz]
  -c --compute                Compute the data.
  -d --display                Display.
  -v --debug                  Enter the debug mode.
  -p --pixel=<PIXEL>          Give a list of pixel IDs.
  --ac_levels=<DAC>           LED AC DAC level.
  --dc_levels=<DAC>           LED DC DAC level.
  --shift=N                   number of bins to shift before integrating
                              [default: 0].
  --integral_width=N          number of bins to integrate over
                              [default: 7].
  --save_figures              Save the plots to the OUTPUT folder
  --timing=FILE               Timing npz.
  --saturation_threshold=N    Saturation threshold in LSB
                              [default: 3000]
  --pulse_tail                Use pulse tail for charge integration
"""

import numpy as np
from tqdm import tqdm
import os
from docopt import docopt

from digicampipe.calib.baseline import subtract_baseline, fill_digicam_baseline
from digicampipe.calib.charge import \
    compute_charge_with_saturation_and_threshold
from digicampipe.io.event_stream import calibration_event_stream
from digicampipe.utils.docopt import convert_dac_level, convert_pixel_args, convert_max_events_args

def compute(files, ac_levels, dc_levels, output_filename, max_events, pixels,
         integral_width, timing, saturation_threshold, pulse_tail, debug):

    n_pixels = len(pixels)
    n_files = len(files)
    n_ac_level = len(ac_levels)
    n_dc_level = len(dc_levels)

    assert n_files == (n_ac_level * n_dc_level)

    for file in files:
        assert os.path.exists(file)

    assert not os.path.exists(output_filename)

    shape = (len(dc_levels), len(ac_levels), n_pixels)
    amplitude_mean = np.zeros(shape)
    amplitude_std = np.zeros(shape)
    baseline_mean = np.zeros(shape)
    baseline_std = np.zeros(shape)
    charge_mean = np.zeros(shape)
    charge_std = np.zeros(shape)

    for i, dc_level, in tqdm(enumerate(dc_levels), total=n_dc_level):

        for j, ac_level in tqdm(enumerate(ac_levels), total=n_ac_level):

            index_file = i * n_ac_level + j
            file = files[index_file]

            events = calibration_event_stream(file, max_events=max_events)
            events = fill_digicam_baseline(events)
            events = subtract_baseline(events)
            # events = compute_charge_with_saturation(events, integral_width=7)

            events = compute_charge_with_saturation_and_threshold(
                events, integral_width=integral_width, debug=debug,
                trigger_bin=timing, saturation_threshold=saturation_threshold,
                pulse_tail=pulse_tail)
            # events = compute_maximal_charge(events)

            for n, event in enumerate(events):

                charge_mean[i, j] += event.data.reconstructed_charge
                amplitude_mean[i, j] += event.data.reconstructed_amplitude

                charge_std[i, j] += event.data.reconstructed_charge**2
                amplitude_std[i, j] += event.data.reconstructed_amplitude**2

                baseline_mean[i, j] += event.data.baseline
                baseline_std[i, j] += event.data.baseline**2

            charge_mean[i, j] = charge_mean[i, j] / (n + 1)
            charge_std[i, j] = charge_std[i, j] / (n + 1)
            charge_std[i, j] = np.sqrt(charge_std[i, j] - charge_mean[i, j]**2)
            amplitude_mean[i, j] = amplitude_mean[i, j] / (n + 1)
            amplitude_std[i, j] = amplitude_std[i, j] / (n + 1)
            amplitude_std[i, j] = np.sqrt(amplitude_std[i, j] - amplitude_mean[i, j]**2)
            baseline_mean[i, j] = baseline_mean[i, j] / (n + 1)
            baseline_std[i, j] = baseline_std[i, j] / (n + 1)
            baseline_std[i, j] = np.sqrt(baseline_std[i, j] - baseline_mean[i, j]**2)

    np.savez(output_filename, charge_mean=charge_mean, charge_std=charge_std,
             amplitude_mean=amplitude_mean, amplitude_std=amplitude_std,
             ac_levels=ac_levels, dc_levels=dc_levels, baseline_mean=baseline_mean,
             baseline_std=baseline_std)

def entry():
    args = docopt(__doc__)

    files = args['<INPUT>']
    ac_levels = convert_dac_level(args['--ac_levels'])
    dc_levels = convert_dac_level(args['--dc_levels'])
    output_filename = args['--output_file']
    max_events = convert_max_events_args(args['--max_events'])
    pixels = convert_pixel_args(args['--pixel'])
    integral_width = float(args['--integral_width'])
    timing = args['--timing']
    timing = np.load(timing)['time'] // 4
    saturation_threshold = float(args['--saturation_threshold'])
    pulse_tail = args['--pulse_tail']
    debug = args['--debug']

    if args['--compute']:

        compute(files=files, ac_levels=ac_levels, dc_levels=dc_levels,
             output_filename=output_filename, max_events=max_events,
             pixels=pixels, integral_width=integral_width, timing=timing,
             saturation_threshold=saturation_threshold, pulse_tail=pulse_tail,
             debug=debug)

if __name__ == '__main__':
    integral_width = 7
    # saturation_threshold = dict(np.load('/home/alispach/Documents/PhD/ctasoft/digicampipe/thresholds.npz'))
    # saturation_threshold = saturation_threshold['threshold_charge']

    # mean = np.nanmean(saturation_threshold)
    # saturation_threshold[np.isnan(saturation_threshold)] = mean

    saturation_threshold = 3000

    max_events = 50
    pixels = np.arange(1296)
    debug = False
    pulse_tail = False
    output_filename = 'charge_linearity_29102018_all.npz'
    timing = np.load('/sst1m/analyzed/calib/timing/timing.npz')
    timing = timing['time'] // 4
    # files = ['/home/alispach/Downloads/ac_scan/SST1M_01_20180628_{}.fits.fz'.format(i) for i in range(1350, 1454 + 1, 1)] # 0 MHz no window
    # files = ['/sst1m/raw/2018/06/28/SST1M_01/SST1M_01_20180628_{}.fits.fz'.format(i) for i in range(1505, 1557 + 1, 1)] # 0 MHz window
    # files = ['/sst1m/raw/2018/06/28/SST1M_01/SST1M_01_20180628_{}.fits.fz'.format(i) for i in range(1982, 2034 + 1, 1)] # 125 MHz
    # files = ['/sst1m/raw/2018/06/28/SST1M_01/SST1M_01_20180628_{}.fits.fz'.format(i) for i in range(2088, 2140, 1)]  # < 660 MHz
    ac_levels = np.hstack([np.arange(0, 20, 2), np.arange(20, 450, 10)])
    dc_levels = np.arange(200, 320, 10)
    files = [
        '/sst1m/raw/2018/06/28/SST1M_01/SST1M_01_20180628_{}.fits.fz'.format(i)
        for i in range(1505, 2141)]

    compute(files=files, ac_levels=ac_levels, dc_levels=dc_levels,
         output_filename=output_filename, max_events=max_events,
         pixels=pixels, integral_width=integral_width, timing=timing,
         saturation_threshold=saturation_threshold, pulse_tail=pulse_tail,
         debug=debug)


from enum import Enum
from functools import lru_cache

from pydantic import BaseSettings

from morpheus_data.registry.model_manager import (
    download_controlnet_model_from_huggingface,
    download_magicprompt_model_from_huggingface,
    download_model_from_huggingface,
)

MODEL_FILE_PATH = "./scripts/models/models-info.yaml"
CONTROLNET_FILE_PATH = "./scripts/models/controlnet-models-info.yaml"
MAGICPROMPT_FILE_PATH = "./scripts/models/magicprompt-models-info.yaml"

class APIServer(str, Enum):
    local = "local"
    staging = "staging"
    production = "production"

class Target(str, Enum):
    sdiffusion = "sdiffusion"
    controlnet = "controlnet"
    magicprompt = "magicprompt"

class DBTarget(str, Enum):
    sdiffusion = "sdiffusion"
    controlnet = "controlnet"
    magicprompt = "magicprompt"

class Settings(BaseSettings):
    hf_auth_token: str = ""

@lru_cache()
def get_settings() -> Settings:
    settings = Settings()
    return settings

api_server_urls = {
    "local": "http://api:8001",
    "staging": "http://198.176.97.61:8001",
    "production": "https://api-morpheus.monadical.io",
}

# API service endpoints
models_url = {
    "sdiffusion": "models",
    "controlnet": "cnmodels",
}

# Map targets to their corresponding functions to download models
download_model = {
    "sdiffusion": download_model_from_huggingface,
    "controlnet": download_controlnet_model_from_huggingface,
    "magicprompt": download_magicprompt_model_from_huggingface,
}

# Map targets to their corresponding config file
config_file = {
    "sdiffusion": MODEL_FILE_PATH,
    "controlnet": CONTROLNET_FILE_PATH,
    "magicprompt": MAGICPROMPT_FILE_PATH,
}


import datetime as dt
from pathlib import Path

import luigi

from sipn_reanalysis_ingest._types import CfsrGranuleProductType
from sipn_reanalysis_ingest.constants.cfsr import CFSR_VERSION_BY_DATE
from sipn_reanalysis_ingest.constants.paths import (
    DATA_DAILY_FILENAME_TEMPLATE,
    DATA_FINISHED_DIR,
    DATA_MONTHLY_FILENAME_TEMPLATE,
)
from sipn_reanalysis_ingest.luigitasks.untar import (
    UntarCfsr1DayFile,
    UntarCfsr5DayFile,
    UntarCfsrV1MonthlyFile,
    UntarCfsrV2MonthlyFile,
)
from sipn_reanalysis_ingest.util.cfsr import (
    select_5daily_6hourly_analysis_grib2s,
    select_5daily_6hourly_forecast_grib2s,
    select_daily_6hourly_analysis_grib2s,
    select_daily_6hourly_forecast_grib2s,
    select_edgecase_6hourly_forecast_grib2s,
    select_monthly_grib2,
)
from sipn_reanalysis_ingest.util.convert import (
    convert_6hourly_grib2s_to_nc,
    convert_monthly_grib2s_to_nc,
)
from sipn_reanalysis_ingest.util.date import Cfsr5ishDayWindow, YearMonth
from sipn_reanalysis_ingest.util.log import logger
from sipn_reanalysis_ingest.util.misc import range_lookup

class Grib2ToDailyNc(luigi.Task):
    """Shared logic and configuration for daily NetCDF processing."""

    date = luigi.DateParameter()

    def output(self):
        fn = DATA_DAILY_FILENAME_TEMPLATE.format(date=self.date)
        return luigi.LocalTarget(DATA_FINISHED_DIR / fn)

    def convert(
        self,
        *,
        analysis_inputs: list[Path],
        forecast_inputs: list[Path],
    ) -> None:
        logger.info(f'Producing daily NetCDF for date {self.date}...')
        logger.debug(f'>> Analysis inputs: {analysis_inputs}')
        logger.debug(f'>> Forecast inputs: {forecast_inputs}')
        with self.output().temporary_path() as tempf:
            convert_6hourly_grib2s_to_nc(
                analysis_inputs=analysis_inputs,
                forecast_inputs=forecast_inputs,
                output_path=Path(tempf),
            )

            for ifile in [*analysis_inputs, *forecast_inputs]:
                ifile.unlink()

class Grib2InDailyTarToDailyNc(Grib2ToDailyNc):
    """Converts GRIB2 6-hourly input data in 1-daily tars to a daily NetCDF.

    The source data will be filtered for only the variables of interest, subset and
    reprojected for our area of interest.
    """

    def requires(self):
        req = [
            UntarCfsr1DayFile(date=self.date - dt.timedelta(days=1)),
            UntarCfsr1DayFile(date=self.date),
        ]
        return req

    def run(self):
        current_date_dir = Path(self.input()[1].path)
        analysis_inputs = select_daily_6hourly_analysis_grib2s(current_date_dir)

        previous_date_dir = Path(self.input()[0].path)
        forecast_inputs = select_daily_6hourly_forecast_grib2s(
            current_date_grib2_dir=current_date_dir,
            previous_date_grib2_dir=previous_date_dir,
        )

        self.convert(analysis_inputs=analysis_inputs, forecast_inputs=forecast_inputs)

class Grib2InDailyAnd5DailyTarsToDailyNc(Grib2ToDailyNc):
    """Converts GRIB2 6-hourly input data across 1&5-daily tars to a daily NetCDF.

    The source data will be filtered for only the variables of interest, subset and
    reprojected for our area of interest.
    """

    def requires(self):
        forecast_5day_window = Cfsr5ishDayWindow.from_date_in_window(
            self.date - dt.timedelta(days=1)
        )
        req = [
            UntarCfsr5DayFile(
                window_start=forecast_5day_window.start,
                window_end=forecast_5day_window.end,
                product_type=CfsrGranuleProductType.FORECAST,
            ),
            UntarCfsr1DayFile(date=self.date),
        ]
        return req

    def run(self):
        current_date_dir = Path(self.input()[1].path)
        analysis_inputs = select_daily_6hourly_analysis_grib2s(current_date_dir)

        previous_5day_window_forecast_dir = Path(self.input()[0].path)
        forecast_inputs = select_edgecase_6hourly_forecast_grib2s(
            previous_5day_window_forecast_grib2_dir=previous_5day_window_forecast_dir,
            current_date_grib2_dir=current_date_dir,
            previous_date=self.date - dt.timedelta(days=1),
        )

        self.convert(analysis_inputs=analysis_inputs, forecast_inputs=forecast_inputs)

class Grib2In5DailyTarToDailyNc(Grib2ToDailyNc):
    """Converts GRIB2 6-hourly input data in 5-daily tars to a daily NetCDF.

    The source data will be filtered for only the variables of interest, subset and
    reprojected for our area of interest.
    """

    def requires(self):
        five_day_window = Cfsr5ishDayWindow.from_date_in_window(self.date)

        req = {
            CfsrGranuleProductType.ANALYSIS: UntarCfsr5DayFile(
                window_start=five_day_window.start,
                window_end=five_day_window.end,
                product_type=CfsrGranuleProductType.ANALYSIS,
            ),
            CfsrGranuleProductType.FORECAST: UntarCfsr5DayFile(
                window_start=five_day_window.start,
                window_end=five_day_window.end,
                product_type=CfsrGranuleProductType.FORECAST,
            ),
        }

        # If the first day of analysis window, we also need the forecast files for the
        # previous window!
        if self.date == five_day_window.start:
            forecast_5day_window = Cfsr5ishDayWindow.from_date_in_window(
                self.date - dt.timedelta(days=1)
            )
            req[CfsrGranuleProductType.FORECAST] = [
                req[CfsrGranuleProductType.FORECAST],
                UntarCfsr5DayFile(
                    window_start=forecast_5day_window.start,
                    window_end=forecast_5day_window.end,
                    product_type=CfsrGranuleProductType.FORECAST,
                ),
            ]
        return req

    def run(self):
        analysis_dir = Path(self.input()[CfsrGranuleProductType.ANALYSIS].path)
        analysis_inputs = select_5daily_6hourly_analysis_grib2s(
            analysis_dir, date=self.date
        )

        forecast_dirs = [
            Path(d.path)
            for d in luigi.task.flatten(self.input()[CfsrGranuleProductType.FORECAST])
        ]
        forecast_inputs = select_5daily_6hourly_forecast_grib2s(
            forecast_dirs,
            date=self.date,
        )

        self.convert(analysis_inputs=analysis_inputs, forecast_inputs=forecast_inputs)

class Grib2ToMonthlyNc(luigi.Task):
    """Converts GRIB2 monthly input data to NetCDF.

    The source data will be filtered for only the variables of interest, subset and
    reprojected for our area of interest.
    """

    month = luigi.MonthParameter()

    @property
    def yearmonth(self):
        return YearMonth(year=self.month.year, month=self.month.month)

    @property
    def cfsr_version(self):
        return range_lookup(CFSR_VERSION_BY_DATE, self.month)

    def requires(self):
        # TODO: Make return values more consistent
        if self.cfsr_version == 1:
            # v1 data is in yearly tar files that contain _either_ forecast _or_
            # analysis data.
            return {
                CfsrGranuleProductType.ANALYSIS: UntarCfsrV1MonthlyFile(
                    year=self.month.year,
                    product_type=CfsrGranuleProductType.ANALYSIS,
                ),
                CfsrGranuleProductType.FORECAST: UntarCfsrV1MonthlyFile(
                    year=self.month.year,
                    product_type=CfsrGranuleProductType.FORECAST,
                ),
            }
        elif self.cfsr_version == 2:
            # v2 files are monthly and contain both analysis and forecast data in one.
            return UntarCfsrV2MonthlyFile(month=self.month)

    def output(self):
        fn = DATA_MONTHLY_FILENAME_TEMPLATE.format(yearmonth=self.yearmonth)
        return luigi.LocalTarget(DATA_FINISHED_DIR / fn)

    def run(self):
        if self.cfsr_version == 1:
            # v1 data is in yearly tar files that contain _either_ forecast _or_
            # analysis data.
            analysis_files_dir = Path(
                self.input()[CfsrGranuleProductType.ANALYSIS].path,
            )
            forecast_files_dir = Path(
                self.input()[CfsrGranuleProductType.FORECAST].path,
            )
        elif self.cfsr_version == 2:
            # v2 files are monthly and contain both analysis and forecast data in one.
            analysis_files_dir = Path(self.input().path)
            forecast_files_dir = Path(self.input().path)

        analysis_input = select_monthly_grib2(
            analysis_files_dir,
            month=self.yearmonth,
            product_type=CfsrGranuleProductType.ANALYSIS,
        )
        forecast_input = select_monthly_grib2(
            forecast_files_dir,
            month=self.yearmonth,
            product_type=CfsrGranuleProductType.FORECAST,
        )

        logger.info(f'Producing monthly NetCDF for month {self.yearmonth}...')
        logger.debug(f'>> Analysis input: {analysis_input}')
        logger.debug(f'>> Forecast input: {forecast_input}')

        with self.output().temporary_path() as tempf:
            convert_monthly_grib2s_to_nc(
                analysis_input=analysis_input,
                forecast_input=forecast_input,
                output_path=Path(tempf),
            )

            for ifile in [analysis_input, forecast_input]:
                ifile.unlink()


import json
import logging
import os
from enum import Enum
from typing import Any
from typing import AnyStr
from typing import Dict
from typing import IO
from typing import Optional
from typing import Tuple
from typing import Union

from gcloud.aio.auth import AioSession  # pylint: disable=no-name-in-module
from gcloud.aio.auth import BUILD_GCLOUD_REST  # pylint: disable=no-name-in-module
from gcloud.aio.auth import Token  # pylint: disable=no-name-in-module

# Selectively load libraries based on the package
if BUILD_GCLOUD_REST:
    from requests import Session
else:
    from aiohttp import ClientSession as Session  # type: ignore[assignment]

SCOPES = [
    'https://www.googleapis.com/auth/bigquery.insertdata',
    'https://www.googleapis.com/auth/bigquery',
]

log = logging.getLogger(__name__)

def init_api_root(api_root: Optional[str]) -> Tuple[bool, str]:
    if api_root:
        return True, api_root

    host = os.environ.get('BIGQUERY_EMULATOR_HOST')
    if host:
        return True, f'http://{host}/bigquery/v2'

    return False, 'https://www.googleapis.com/bigquery/v2'

class SourceFormat(Enum):
    AVRO = 'AVRO'
    CSV = 'CSV'
    DATASTORE_BACKUP = 'DATASTORE_BACKUP'
    NEWLINE_DELIMITED_JSON = 'NEWLINE_DELIMITED_JSON'
    ORC = 'ORC'
    PARQUET = 'PARQUET'

class Disposition(Enum):
    WRITE_APPEND = 'WRITE_APPEND'
    WRITE_EMPTY = 'WRITE_EMPTY'
    WRITE_TRUNCATE = 'WRITE_TRUNCATE'

class SchemaUpdateOption(Enum):
    ALLOW_FIELD_ADDITION = 'ALLOW_FIELD_ADDITION'
    ALLOW_FIELD_RELAXATION = 'ALLOW_FIELD_RELAXATION'

class BigqueryBase:
    _project: Optional[str]
    _api_root: str
    _api_is_dev: bool

    def __init__(
            self, project: Optional[str] = None,
            service_file: Optional[Union[str, IO[AnyStr]]] = None,
            session: Optional[Session] = None, token: Optional[Token] = None,
            api_root: Optional[str] = None,
    ) -> None:
        self._api_is_dev, self._api_root = init_api_root(api_root)
        self.session = AioSession(session)
        self.token = token or Token(
            service_file=service_file, scopes=SCOPES,
            session=self.session.session,  # type: ignore[arg-type]
        )

        self._project = project
        if self._api_is_dev and not project:
            self._project = (
                os.environ.get('BIGQUERY_PROJECT_ID')
                or os.environ.get('GOOGLE_CLOUD_PROJECT')
                or 'dev'
            )

    async def project(self) -> str:
        if self._project:
            return self._project

        self._project = await self.token.get_project()
        if self._project:
            return self._project

        raise Exception('could not determine project, please set it manually')

    async def headers(self) -> Dict[str, str]:
        if self._api_is_dev:
            return {}

        token = await self.token.get()
        return {
            'Authorization': f'Bearer {token}',
        }

    async def _post_json(
            self, url: str, body: Dict[str, Any], session: Optional[Session],
            timeout: int,
    ) -> Dict[str, Any]:
        payload = json.dumps(body).encode('utf-8')

        headers = await self.headers()
        headers.update({
            'Content-Length': str(len(payload)),
            'Content-Type': 'application/json',
        })

        s = AioSession(session) if session else self.session
        resp = await s.post(url, data=payload, headers=headers,
                            timeout=timeout)
        data: Dict[str, Any] = await resp.json()
        return data

    async def _get_url(
            self, url: str, session: Optional[Session], timeout: int,
            params: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        headers = await self.headers()

        s = AioSession(session) if session else self.session
        resp = await s.get(url, headers=headers, timeout=timeout,
                           params=params or {})
        data: Dict[str, Any] = await resp.json()
        return data

    async def _delete(
        self, url: str, session: Optional[Session], timeout: int,
    ) -> Dict[str, Any]:
        headers = await self.headers()

        s = AioSession(session) if session else self.session
        resp = await s.delete(url, headers=headers, timeout=timeout)
        data: Dict[str, Any] = await resp.json()
        return data

    async def close(self) -> None:
        await self.session.close()

    async def __aenter__(self) -> 'BigqueryBase':
        return self

    async def __aexit__(self, *args: Any) -> None:
        await self.close()


import eigenfaces
import image
import math
import vec
import svd
from matrix import matutil
from vector import vecutil

def image2vector(image):
  D = set()
  F = {}
  for i in range(len(image)):
    row = image[i]
    for j in range(len(row)):
      pixel = row[j]
      coord = (i, j)
      D.add(coord)
      F[coord] = pixel
  return vec.Vec(D, F)

def vector2image(vector):
  rows = 0
  columns = 0
  for coord in vector.D:
    rows = max(coord[0], rows)
    columns = max(coord[1], columns)
  image = [[0 for j in range(columns + 1)] for i in range(rows + 1)]
  for p in vector.f:
    pixel = vector.f[p]
    image[p[0]][p[1]] = pixel

  return image

def import_faces(source, n=20):
  imported = eigenfaces.load_images(source, n)
  return {
    i: image2vector(imported[i]) for i in imported
  }

def compute_image_centroid(images):
  """image is a listlist"""
  final = None
  for i in images:
    if final is None:
      final = images[i]
    else:
      final = final + images[i]

  return (1/len(images)) * final

faces = import_faces('singular_value_decomposition/faces')
centroid = compute_image_centroid(faces)
# image.image2display(vector2image(centroid))

centered_image_vectors = {
  k: faces[k] - centroid for k in faces
}

def norm(v):
  return math.sqrt(v * v)

A = matutil.rowdict2mat(centered_image_vectors)

U, Sigma, V = svd.factor(A)
Vt = V.transpose()
tenset = {i for i in range(10)}
Uten = matutil.submatrix(U, tenset, tenset)
Sigmaten = matutil.submatrix(Sigma, tenset, tenset)
Vten = matutil.submatrix(Vt, {i for i in range(10)}, Vt.D[1])

eigenfaces_basis = Uten*Sigmaten*Vten

def projected_representation(M, x):
  """
  input: a matrix M with orthonormal rows and a vector x with D from Col M
  output: the coordinate representation of the parallel of projection of x onto Row M
  """
  Mt = M.transpose()
  return Mt * x

def projection_length_squared(M, x):
  term = M * projected_representation(M, x)
  return term * term

def distance_squared(M, x):
  plen = projection_length_squared(M, x)
  x2 = x * x
  perpendicular = plen - x2
  return math.sqrt(perpendicular * perpendicular)

e_t = eigenfaces_basis.transpose()
classified_distances = [distance_squared(e_t, centered_image_vectors[x]) for x in centered_image_vectors]
print(classified_distances)

unclassified = import_faces('singular_value_decomposition/unclassified', 10)
# for k in unclassified:
#   vector = unclassified[k]
#   centered = vector - centroid
#   distance = distance_squared(e_t, centered)
#   print(distance)
#   image.image2display(vector2image(vector))

def project(M, x):
  return M * projected_representation(M, x)

image.image2display(vector2image(project(e_t, unclassified[1])))
image.image2display(vector2image(project(e_t, unclassified[2])))
image.image2display(vector2image(project(e_t, unclassified[3])))

# non-face
image.image2display(vector2image(project(e_t, unclassified[0])))


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- test-case-name: logsnarf.test.test_config -*-
# pylint: disable=invalid-name
"""Logsnarf configuration.

See :doc:`configuration <configuration>` for details on how to configure
logsnarf.
"""

from collections import abc
import logging.config
import configparser
import os
import os.path

from xdg import BaseDirectory
from twisted.python import log

DEFAULTS = {
    'batchsize': '250',
    'default_tz': 'UTC',
    'flush_interval': '30',
    'max_buffer': '1000',
    'pattern': r'.*\.log',
    'schema_file': '%(__name__)s_schema.json',
    'state_file': '%(__name__)s_state.json',
    'table_name_fmt': 'logs_{YEAR}{MONTH}{DAY}',
    'recursive': 'true'
}

class ConfigSection(abc.Mapping):
    """Class representing a configparser section.

    Provides a mapping interface that attempts to do some vaguely sane
    type casting. No attempt to be smart, cache results etc is done.
    """

    def __init__(self, name, cfg):
        """

        :param name: section name
        :type name: str
        :param cfg: configparser object
        :type cfg: configparser.ConfigParser
        """
        super(ConfigSection, self).__init__()
        self.name = name
        self.cfg = cfg

    def __getitem__(self, item):
        cfg, name = self.cfg, self.name

        for get in cfg.getboolean, cfg.getint, cfg.getfloat:
            try:
                value = get(name, item)
                return value
            except (ValueError, AttributeError):
                pass
            except configparser.NoOptionError as e:
                raise ValueError(*e.args)
        return cfg.get(name, item)

    def __len__(self):
        return len(self.cfg.items(self.name))

    def __iter__(self):
        return iter(dict(self.cfg.items(self.name)))

# noinspection PyPep8Naming
class Config(abc.Mapping):
    """Class to contain configuration information for Logsnarf.

    This class wraps loading of the configparser config file(s), initializing
    logging (from a logging.ini), and proxies some methods from
    xdg.BaseDirectory module for creating/opening config or data files in
    appropriate places.

    It also provides a dict-like read-only interface to the config file, with
    a vague attempt at type casting through ConfigSection objects.
    """
    # pylint: disable=too-many-public-methods

    def __init__(self, resource_name=None, config_file=None):
        """

        :param resource_name:
            The xdg resource name to use. Defaults to logsnarf
        :type resource_name: str
        :param config_file: absolute path to a configuration file
        :type config_file: str

        """
        super(Config, self).__init__()
        self.resource_name = resource_name or 'logsnarf'
        self.config_file = config_file
        self._cp = configparser.SafeConfigParser(DEFAULTS)
        self._sections = {}

    def __getitem__(self, item):
        if self._cp.has_section(item):
            return self._sections.setdefault(
                item,
                ConfigSection(item, self._cp))

    def __len__(self):
        return len(self._cp.sections())

    def __iter__(self):
        return iter(self._cp.sections())

    def load(self):
        """Initializes logging and loads the configs."""
        self.loadLoggingConfig()
        self.loadConfigs()

    def loadConfigs(self):
        """Loads all configurations"""
        if self.config_file:
            self._cp.read(self.config_file)
        else:
            config_paths = reversed(
                [os.path.join(p, '{}.ini'.format(self.resource_name))
                 for p in self.loadConfigPaths()])
            self._cp.read(config_paths)

    def loadLoggingConfig(self):
        """Initializes logging.

        The twisted PythonLoggingObserver is initialized, then the config
        paths are searched for a ${RESOURCE_NAME}/logging.ini, failing that,
        logging.basicConfig() is called with no arguments so that some sort of
        logging occurs.
        """
        observer = log.PythonLoggingObserver()
        observer.start()
        for path in self.loadConfigPaths():
            if os.path.exists(os.path.join(path, 'logging.ini')):
                logging.config.fileConfig(os.path.join(path, 'logging.ini'))

                return
        logging.basicConfig()

    def openConfigFile(self, name, mode):
        """Opens a file in the user config directory, with the given mode.

        :param name: the name of the config file to open
        :type name: str
        :param mode: mode to  open file with
        :type mode: str
        :return: file object opened with the config file
        :rtype: file

        """
        return open(
            os.path.join(self.saveConfigPath(), name), mode)

    def openDataFile(self, name, mode, *args, **kwargs):
        """Opens a file in the user data directory, with the given mode.

        :param name: the name of the data file to open
        :type name: str
        :param mode: mode to  open file with
        :type mode: str
        :return: file object opened with the data file
        :rtype: file

        """
        return open(os.path.join(self.saveDataPath(), name), mode, *args, **kwargs)

    def saveConfigPath(self, name=''):
        """Ensures the user save config path exists, and returns the path.

        Optionally also provide a filename, to receive a full path to that
        file in the data directory.

        Ensure ``$XDG_CONFIG_HOME/logsnarf/`` exists, and return its path.
        Use this when saving or updating application configuration.

        :param str name: the name of the file
        :return: path to the directory, or, if given, file
        :rtype: str

        """
        if name:
            return os.path.join(
                BaseDirectory.save_config_path(self.resource_name), name)
        else:
            return BaseDirectory.save_config_path(self.resource_name)

    def saveDataPath(self, name=''):
        """Ensures the user save data path exists, and returns the path to it.

        Optionally also provide a filename, to receive a full path to that
        file in the data directory.

        Ensure ``$XDG_DATA_HOME/logsnarf/`` exists, and return its path.
        Use this when saving or updating application data.

        :param str name: the name of the file
        :return: path to the directory, or, if given, file
        :rtype: str

        """
        if name:
            return os.path.join(
                BaseDirectory.save_data_path(self.resource_name), name)
        else:
            return BaseDirectory.save_data_path(self.resource_name)

    def loadConfigPaths(self):
        """Returns the configuration paths for the resource.

        Returns an iterator which gives each directory named 'logsnarf' in the
        configuration search path. Information provided by earlier directories
        should take precedence over later ones, and the user-specific config
        dir comes first.
        """
        return BaseDirectory.load_config_paths(self.resource_name)


from Cryptodome.Math.Numbers import Integer
from Cryptodome.Hash.SHA256 import SHA256Hash
from random import randint

class BasePoint:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def toElPoint(self, ec):
        assert ec.check(self), 'ElPoint is not on ElCurve'
        return ElPoint(self.x % ec.p, self.y % ec.p, ec)

    def json(self):
        return {
            "x": self.x,
            "y": self.y
        }

class ElCurve():
    def __init__(self, A, B, p):
        if (A < 0): A %= p
        self.A = A
        if (B < 0): B %= p
        self.B = B
        self.p = p
        self._O = BasePoint(0, 0)
        pass

    def __get_O(self):
        return ElPoint(self._O.x, self._O.y, self)
    O = property(__get_O)

    def check(self, point):
        if (point.x == 0 and point.y == 0):
            return True
        return (point.y**2 - point.x**3 - self.A*point.x - self.B) %self.p == 0

    def checkAB(self):
        return (4*self.A**3 - 27*self.B**2) % self.p

    def __str__(self):
        return '\n'.join([
            'Elliptic Curve:',
            '  A = ' + str(self.A),
            '  B = ' + str(self.B)
        ])

    def json(self):
        return {
            "A": self.A,
            "B": self.B,
            "p": self.p
        }

class ElPoint(BasePoint):
    def __init__(self, x, y, curve):
        super().__init__(x, y)
        self.curve = curve
        pass

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __ne__(self, other):
        return not self.__eq__(other)

    def __neg__(self):
        return ElPoint(self.x, -self.y, self.curve)

    def __add__(self, other):
        if (self == self.curve.O):
            return other
        if (other == self.curve.O):
            return self
        p = self.curve.p
        if (self.x == other.x):
            if ((self.y + other.y) % p == 0):
                return self.curve.O
            else:
                l = (((3*self.x**2 + self.curve.A) % p) * int(Integer(2*self.y).inverse(p))) % p
        else:
            l = ((other.y - self.y) * int(Integer(other.x - self.x).inverse(p))) % p
        x = (pow(l,2,p) - self.x - other.x) % p
        y = (l*(self.x - x) - self.y) % p
        return ElPoint(x, y, self.curve)

    def __rmul__(self, val : int):
        if (val == 0):
            return self.curve.O
        Q = self.curve.O
        for i in bin(val)[2:]:
            Q = Q + Q
            if (i == '1'):
                Q = Q + self
        return Q

    def __mul__(self, val : int):
        return self.__rmul__(val)

    def __str__(self):
        if self == self.curve.O:
            return '(+oo, +oo)'
        else:
            return str((self.x, self.y))

    def __repr__(self):
        if self == self.curve.O:
            return '(+oo, +oo)'
        else:
            return repr((self.x, self.y))

    def hash(self):
        sha = SHA256Hash(self.x.to_bytes((self.x.bit_length() + 7) // 8, byteorder="big"))
        sha.update(self.y.to_bytes((self.y.bit_length() + 7) // 8, byteorder="big"))
        return sha.digest()

    def project(self):
        if (self == self.curve.O):
            return ElPointProject(0, 0, 0, self.curve)
        return ElPointProject(self.x, self.y, 1, self.curve)
    pass

class ElPointProject():
    def __init__(self, x, y, z, curve):
        self.x = x
        self.y = y
        self.z = z
        self.curve = curve
        pass

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y and self.z == other.z

    def __ne__(self, other):
        return not self.__eq__(other)

    def __neg__(self):
        return ElPointProject(self.x, -self.y, self.z, self.curve)

    def __add__(self, other):
        if (self.z == 0):
            return other
        if (other.z == 0):
            return self

        x1, y1, z1 = self.x, self.y, self.z
        x2, y2, z2 = other.x, other.y, other.z
        A = self.curve.A
        B = self.curve.B
        p = self.curve.p
        if (self == other):
            x = (2*y1*z1*((3*x1**2 + A*z1**2)**2 - 8*x1*y1**2*z1)) % p
            y = (4*y1**2*z1*(3*x1*(3*x1**2 + A*z1**2) - 2*y1**2*z1)-(3*x1**2 + A*z1**2)**3) % p
            z = (8*y1**3*z1**3) % p
        else:
            x = ((x2*z1 - x1*z2)*(z1*z2*(y2*z1-y1*z2)**2 - (x2*z1+x1*z2)*(x2*z1-x1*z2)**2)) % p
            y = ((x2*z1 - x1*z2)**2*(y2*z1*(x2*z1 + 2*x1*z2)-y1*z2*(x1*z2+2*x2*z1)) - z1*z2*(y2*z1 - y1*z2)**3) % p
            z = (z1*z2*(x2*z1 - x1*z2)**3) % p
        return ElPointProject(x, y, z, self.curve)
    def __rmul__(self, val : int):
        if (val == 0):
            return self.curve.O
        Q = self.curve.O.project()
        for i in bin(val)[2:]:
            Q = Q + Q
            if (i == '1'):
                Q = Q + self
        return Q

    def check_mul(self, val : int, n : Integer):
        Q = self.curve.O.project()
        while val:
            if val & 1:
                Q = Q + self
                assert Q.z != 0 and n.gcd(Q.z)
            self = self + self
            val >>= 1
        return Q

    def __mul__(self, val : int):
        return self.__rmul__(val)

    def __str__(self):
        return str((self.x, self.y, self.z))

    def __repr__(self):
        return repr((self.x, self.y, self.z))

    def toElPoint(self):
        if (self.z == 0):
            return self.curve.O
        z_inv = int(Integer(self.z).inverse(self.curve.p))
        x = self.x * z_inv % self.curve.p
        y = self.y * z_inv % self.curve.p
        return ElPoint(x, y, self.curve)

def generate(Q, n):
    A = randint(1, n - 1)
    B = (Q.y**2 - Q.x**3 - A*Q.x) % n
    ec = ElCurve(A, B, n)
    if not ec.checkAB():
        return None
    return ec


import numerical_integrators
import numpy as np
import matplotlib.pyplot as plt
import math
from matplotlib import rc

#V : Viewed
#N : Not viewed
#ideas: more than one sigma
#V/j*(N/k) gets sigma1 V/(V-j)*(1-(N/K)) gets sigma^2
#sigma_1 only friends , but, note assumptions: still randomly mixed group of groups of friends!
#sigma_2 mass platforms, but, assumption is it will reach everyone.
#sigma: Sharing rate
#assumptions: make sure V/j < ...
#assumptions: once you've seen it from one person, that's it
#asumption: "People's friends" and "general public" are separate groups

def dV_dt(V_t, N_t, sigma_1, sigma_2, j=1, k=1):
    #rate of Viewing sigma
    if (j >= 1 or k >= 1):
        print("j and k must be fractions less than 1 (and greater than 0)")
        return None
    else:
        try:
            dV = sigma_1*((j*V_t)*(N_t*k)) + sigma_2*((V_t-(V_t*j))*(N_t-(N_t*k)))
        except OverflowError:
            dV = 0
        if (np.isnan(dV) or np.isinf(dV)):
            dV = 0
        return dV

def prop_memes_euler(T, V_0, N_0, sigma_1, sigma_2, V_partition_frac, N_partition_frac, step_size_h, steps):
    V_current = V_0
    N_current = N_0
    V_vec=[V_current]
    N_vec=[N_current]
    time = 0
    time_vec = [0]
    for t in range(1, math.floor(steps/step_size_h)):
            dV_dt_current = dV_dt(V_current, N_current, sigma_1, sigma_2, V_partition_frac, N_partition_frac)
            if dV_dt_current is None:
                return None
            V_plus_t = numerical_integrators.euler_step(step_size_h, V_current, dV_dt_current)
            V_vec.append(V_plus_t)
            N_vec.append(T-V_plus_t)
            V_current=V_vec[-1]
            N_current=N_vec[-1]
            time += step_size_h
            time_vec.append(time)
    time_vec = time_vec[:len(V_vec)]
    rc('font', **{'family': 'sans-serif', 'sans-serif': ['Helvetica']})
    rc('text', usetex=True)
    plt.plot(time_vec[1:], V_vec[1:], alpha=0.6, lw=2, label=make_label(sigma_1, sigma_2, V_partition_frac, N_partition_frac))
    plt.xlabel('Log time t with step size '+str(step_size_h))
    plt.ylabel('$V$: number who have viewed the meme')
    plt.legend(loc='lower right')
    return V_vec

def make_label(sigma_1, sigma_2, V_frac, N_frac):
    label = '$\\sigma_1=$' + str(sigma_1) + ', $\\sigma_2=$' + str(sigma_2) + ', $j=$'+str(V_frac)+', $k=$'+str(N_frac)
    return label


# -*- coding: utf-8 -*-

import sys
from colorama import Fore as clr, Style, Back

if sys.platform.lower().startswith(('os', 'win', 'darwin', 'ios')):
    cyan = green = yellow = red = bright = blue = reset = backred = progress = magenta = ''
else:
    cyan = clr.CYAN
    green = clr.LIGHTGREEN_EX
    yellow = clr.LIGHTYELLOW_EX
    red = clr.RED
    bright = Style.BRIGHT
    blue = clr.BLUE
    reset = Style.RESET_ALL
    backred = Back.RED
    progress = ("[" + blue + bright +'INF' + reset + "] ")
    magenta = clr.LIGHTMAGENTA_EX

banner = f"""{bright}            ___
          ___H___
 _____ _____[{backred}%{reset}{bright}]_____         _ _
|     | __  [{backred}\{reset}{bright}]   __|___ _ _|_| |_ ___
|   --|    -[{backred}#{reset}{bright}]   __|_ -| | | |  _| -_|
|_____|__|__[{backred};{reset}{bright}]__|  |___|___|_|_| |___|
             V                        v2.5.2
                {reset}({green}\x1B[3mBy Nefcore Security\x1B[0m{reset})
"""

def good(msg):
    """
    if URL is vulnerable
    """
    print("[" + green + bright +'VLN' + reset + '] '+msg)

def bad(msg):
    """
    if URL is not vulnerable
    """
    print("[" + magenta + bright + 'NOT VLN' + reset + '] '+msg)

def error(msg):
    """
    if any error occurs
    """
    print("[" + red + bright + 'ERR' + reset + ']',msg)

def info(msg):
    """
    basic informations
    """
    print("[" + blue + bright +'INF' + reset + "] "+msg)

def warn(msg):
    """
    warnings
    """
    print("[" + yellow + bright +'WRN' + reset + "] "+msg)

def args_info(url, urls, stdin, nout, jout, method, data, cookies, timeout, verify, threads, verbosity, delay):
    """
    Prints information about user supplied arguments
    """
    if url:
        print(':: TARGET     : %s' % url)
    elif urls:
        print(':: TARGET     : %s' % urls)
    elif stdin:
        print(':: TARGET     : Stdin')
    else:
        print(':: TARGET     : None')
    if nout:
        print(':: OUTPUT     : %s' % nout)
    elif jout:
        print(':: OUTPUT     : %s' % jout)

    print(':: THREADS    : %i' % threads)
    print(':: METHOD     : %s' % method)

    if data:
        print(':: DATA       : %s' % data)

    print(':: Delay      : %s' % delay)

    if cookies:
        print(':: COOKIES    : %s' % cookies)

    print(':: TIMEOUT    : %i' % timeout)

    if verify:
        print(':: VERIFY     : True')
    else:
        print(':: VERIFY     : False')
    if verbosity:
        print(':: Verbosity  : %i' % verbosity)
    print('')


from enum import Enum, EnumMeta
from six import with_metaclass

class _CaseInsensitiveEnumMeta(EnumMeta):
    def __getitem__(self, name):
        return super().__getitem__(name.upper())

    def __getattr__(cls, name):
        """Return the enum member matching `name`
        We use __getattr__ instead of descriptors or inserting into the enum
        class' __dict__ in order to support `name` and `value` being both
        properties for enum members (which live in the class' __dict__) and
        enum members themselves.
        """
        try:
            return cls._member_map_[name.upper()]
        except KeyError:
            raise AttributeError(name)

class CostThresholdStatus(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """Indicates whether this threshold will be displayed on cost charts.
    """

    ENABLED = "Enabled"
    DISABLED = "Disabled"

class CostType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The type of the cost.
    """

    UNAVAILABLE = "Unavailable"
    REPORTED = "Reported"
    PROJECTED = "Projected"

class CustomImageOsType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The OS type of the custom image (i.e. Windows, Linux)
    """

    WINDOWS = "Windows"
    LINUX = "Linux"
    NONE = "None"

class EnableStatus(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """If notifications are enabled for this schedule (i.e. Enabled, Disabled).
    """

    ENABLED = "Enabled"
    DISABLED = "Disabled"

class EnvironmentPermission(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The access rights to be granted to the user when provisioning an environment
    """

    READER = "Reader"
    CONTRIBUTOR = "Contributor"

class FileUploadOptions(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """Options for uploading the files for the artifact. UploadFilesAndGenerateSasTokens is the
    default value.
    """

    UPLOAD_FILES_AND_GENERATE_SAS_TOKENS = "UploadFilesAndGenerateSasTokens"
    NONE = "None"

class HostCachingOptions(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """Caching option for a data disk (i.e. None, ReadOnly, ReadWrite).
    """

    NONE = "None"
    READ_ONLY = "ReadOnly"
    READ_WRITE = "ReadWrite"

class HttpStatusCode(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The status code for the operation.
    """

    CONTINUE_ENUM = "Continue"
    SWITCHING_PROTOCOLS = "SwitchingProtocols"
    OK = "OK"
    CREATED = "Created"
    ACCEPTED = "Accepted"
    NON_AUTHORITATIVE_INFORMATION = "NonAuthoritativeInformation"
    NO_CONTENT = "NoContent"
    RESET_CONTENT = "ResetContent"
    PARTIAL_CONTENT = "PartialContent"
    MULTIPLE_CHOICES = "MultipleChoices"
    MOVED_PERMANENTLY = "MovedPermanently"
    REDIRECT = "Redirect"
    SEE_OTHER = "SeeOther"
    NOT_MODIFIED = "NotModified"
    USE_PROXY = "UseProxy"
    UNUSED = "Unused"
    TEMPORARY_REDIRECT = "TemporaryRedirect"
    BAD_REQUEST = "BadRequest"
    UNAUTHORIZED = "Unauthorized"
    PAYMENT_REQUIRED = "PaymentRequired"
    FORBIDDEN = "Forbidden"
    NOT_FOUND = "NotFound"
    METHOD_NOT_ALLOWED = "MethodNotAllowed"
    NOT_ACCEPTABLE = "NotAcceptable"
    PROXY_AUTHENTICATION_REQUIRED = "ProxyAuthenticationRequired"
    REQUEST_TIMEOUT = "RequestTimeout"
    CONFLICT = "Conflict"
    GONE = "Gone"
    LENGTH_REQUIRED = "LengthRequired"
    PRECONDITION_FAILED = "PreconditionFailed"
    REQUEST_ENTITY_TOO_LARGE = "RequestEntityTooLarge"
    REQUEST_URI_TOO_LONG = "RequestUriTooLong"
    UNSUPPORTED_MEDIA_TYPE = "UnsupportedMediaType"
    REQUESTED_RANGE_NOT_SATISFIABLE = "RequestedRangeNotSatisfiable"
    EXPECTATION_FAILED = "ExpectationFailed"
    UPGRADE_REQUIRED = "UpgradeRequired"
    INTERNAL_SERVER_ERROR = "InternalServerError"
    NOT_IMPLEMENTED = "NotImplemented"
    BAD_GATEWAY = "BadGateway"
    SERVICE_UNAVAILABLE = "ServiceUnavailable"
    GATEWAY_TIMEOUT = "GatewayTimeout"
    HTTP_VERSION_NOT_SUPPORTED = "HttpVersionNotSupported"

class LinuxOsState(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The state of the Linux OS (i.e. NonDeprovisioned, DeprovisionRequested, DeprovisionApplied).
    """

    NON_DEPROVISIONED = "NonDeprovisioned"
    DEPROVISION_REQUESTED = "DeprovisionRequested"
    DEPROVISION_APPLIED = "DeprovisionApplied"

class NotificationChannelEventType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The event type for which this notification is enabled (i.e. AutoShutdown, Cost)
    """

    AUTO_SHUTDOWN = "AutoShutdown"
    COST = "Cost"

class PolicyEvaluatorType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The evaluator type of the policy (i.e. AllowedValuesPolicy, MaxValuePolicy).
    """

    ALLOWED_VALUES_POLICY = "AllowedValuesPolicy"
    MAX_VALUE_POLICY = "MaxValuePolicy"

class PolicyFactName(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The fact name of the policy (e.g. LabVmCount, LabVmSize, MaxVmsAllowedPerLab, etc.
    """

    USER_OWNED_LAB_VM_COUNT = "UserOwnedLabVmCount"
    USER_OWNED_LAB_PREMIUM_VM_COUNT = "UserOwnedLabPremiumVmCount"
    LAB_VM_COUNT = "LabVmCount"
    LAB_PREMIUM_VM_COUNT = "LabPremiumVmCount"
    LAB_VM_SIZE = "LabVmSize"
    GALLERY_IMAGE = "GalleryImage"
    USER_OWNED_LAB_VM_COUNT_IN_SUBNET = "UserOwnedLabVmCountInSubnet"
    LAB_TARGET_COST = "LabTargetCost"
    ENVIRONMENT_TEMPLATE = "EnvironmentTemplate"
    SCHEDULE_EDIT_PERMISSION = "ScheduleEditPermission"

class PolicyStatus(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The status of the policy.
    """

    ENABLED = "Enabled"
    DISABLED = "Disabled"

class PremiumDataDisk(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The setting to enable usage of premium data disks.
    When its value is 'Enabled', creation of standard or premium data disks is allowed.
    When its value is 'Disabled', only creation of standard data disks is allowed.
    """

    DISABLED = "Disabled"
    ENABLED = "Enabled"

class ReportingCycleType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """Reporting cycle type.
    """

    CALENDAR_MONTH = "CalendarMonth"
    CUSTOM = "Custom"

class SourceControlType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The artifact source's type.
    """

    VSO_GIT = "VsoGit"
    GIT_HUB = "GitHub"

class StorageType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The storage type for the disk (i.e. Standard, Premium).
    """

    STANDARD = "Standard"
    PREMIUM = "Premium"
    STANDARD_SSD = "StandardSSD"

class TargetCostStatus(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """Target cost status
    """

    ENABLED = "Enabled"
    DISABLED = "Disabled"

class TransportProtocol(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The transport protocol for the endpoint.
    """

    TCP = "Tcp"
    UDP = "Udp"

class UsagePermissionType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The permission policy of the subnet for allowing public IP addresses (i.e. Allow, Deny)).
    """

    DEFAULT = "Default"
    DENY = "Deny"
    ALLOW = "Allow"

class VirtualMachineCreationSource(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """Tells source of creation of lab virtual machine. Output property only.
    """

    FROM_CUSTOM_IMAGE = "FromCustomImage"
    FROM_GALLERY_IMAGE = "FromGalleryImage"
    FROM_SHARED_GALLERY_IMAGE = "FromSharedGalleryImage"

class WindowsOsState(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)):
    """The state of the Windows OS (i.e. NonSysprepped, SysprepRequested, SysprepApplied).
    """

    NON_SYSPREPPED = "NonSysprepped"
    SYSPREP_REQUESTED = "SysprepRequested"
    SYSPREP_APPLIED = "SysprepApplied"


#!/usr/bin/env python

#
# copy firmware to remote octopi host with marlin usb connection
#

import os
import sys
import time
import logging
import paramiko
import argparse
import functools
import subprocess

logging.basicConfig(
    level=logging.INFO,
    datefmt='%Y-%m-%d %H:%M:%S',
    format='%(asctime)s %(levelname)-8s %(message)s',
)

logger = logging.getLogger(__name__)

parser = argparse.ArgumentParser()
parser.add_argument('--user_name', dest="user_name", default="pi")
parser.add_argument('--host_name', dest="host_name", default="octopi2")
parser.add_argument('--disk_label', dest="disk_label", default="MKS-BASE")
parser.add_argument('--firmware_path', dest="firmware_path", required=True)

params = parser.parse_args()

logger.info(f"params report:")
for key, value in vars(params).items():
    logger.info(f"   {key}={value}")

def trace(func):

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        id = func.__name__
        try:
            logger.info(f"{id}")
            return func(*args, *kwargs)
        except Exception as error:
            logger.exception(error)
            raise error

    return wrapper

@trace
def disk_find_name(label:str) -> str:
    "resolve disk label into disk name"
    result = invoke_ssh(f"sudo lsblk -n -l -o name,label | grep {label} | head -n 1")
    if result.returncode == 0:
        part_list = result.stdout.split()
        if len(part_list) == 2:
            disk_name = part_list[0].decode('utf-8')
            return disk_name
        else:
            return None
    else:
        return None

@trace
def disk_has_point(disk_point:str) -> bool:
    "verify if mount point is present"
    result = invoke_ssh(f"cat /proc/mounts | grep {disk_point}")
    return result.returncode == 0

@trace
def disk_point_create(disk_point) -> None:
    invoke_ssh(f"mkdir -p {disk_point}")

@trace
def disk_point_delete(disk_point) -> None:
    invoke_ssh(f"rm -rf {disk_point}")

@trace
def disk_file_copy(local_path:str, remote_dir:str) -> None:
    local_base = os.path.basename(local_path)
    source_path = local_path
    target_path = os.path.join(remote_dir, local_base)
    invoke_scp(source_path, target_path)

@trace
def disk_point_mount(disk_point:str, disk_path:str) -> None:
    if disk_has_point(disk_point) is False:
        invoke_ssh(f"sudo mount {disk_path} {disk_point} -o uid=$USER,gid=$USER")

@trace
def disk_point_unmount(disk_point:str) -> None:
    if disk_has_point(disk_point) is True:
        invoke_ssh(f"sudo umount {disk_point}")

@trace
def disk_setup(disk_name:str, firmware_path:str) -> None:
    disk_path = f"/dev/{disk_name}"
    disk_point = f"/tmp/disk-point/{disk_name}"
    disk_point_unmount(disk_point)
    disk_point_create(disk_point)
    disk_point_mount(disk_point, disk_path)
    disk_file_copy(firmware_path, disk_point)
    disk_point_unmount(disk_point)
    disk_point_delete(disk_point)

def shell(script):
    result = subprocess.run(script, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    return result

def has_host(host_name):
    result = shell(f"ping -c 1 {host_name}")
    return result.returncode == 0

class Result() :
    returncode = 0
    stdout = ""
    stderr = ""

def invoke_ssh(script):
    stdin, stdout, stderr = ssh_client.exec_command(script)
    stdin.flush()
    result = Result()
    result.returncode = stdout.channel.recv_exit_status()
    result.stdout = stdout.read()
    result.stderr = stderr.read()
    return result

def invoke_scp(source_path, target_path):
    ftp_client = ssh_client.open_sftp()
    ftp_client.put(source_path, target_path)
    ftp_client.close()

#
#
#

if not has_host(params.host_name):
    logger.info(f"missing host={params.host_name}")
    sys.exit()

ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(username=params.user_name, hostname=params.host_name,)

disk_name = disk_find_name(params.disk_label)

if disk_name is None:
    logger.info(f"missing disk={params.disk_label}")
    sys.exit()

disk_setup(disk_name, params.firmware_path)


import time
import random
import requests
import tkinter as tk
from tkinter import ttk, messagebox
from tkinter.messagebox import showinfo
from PIL import Image, ImageTk
# from modules.banner import *
from tkinter import filedialog as fd
from modules.views import viewUrl
import threading
from modules.data import useragent_path, proxies_path

# Create variables
success = 0
fails = 0
useragent = 'loading...'
proxies = 'loading...'
running = True

# Functions
def btns_disable():
    StartBtnTabOne["state"] = "disabled"
    ClearAll["state"] = "disabled"
    ResetProxy["state"] = "disabled"
    ThreadingTabOne["state"] = "disabled"
    UrlTabOne["state"] = "disabled"
    TimesTabOne["state"] = "disabled"

def btns_enable():
    StartBtnTabOne["state"] = "enabled"
    ClearAll["state"] = "normal"
    ResetProxy["state"] = "normal"
    ThreadingTabOne["state"] = "normal"
    UrlTabOne["state"] = "normal"
    TimesTabOne["state"] = "normal"

def clearAll():
    UrlTabOne.delete(0, tk.END)
    TimesTabOne.delete(0, tk.END)

def resetProxy():
    global useragent, proxies
    with open(useragent_path , encoding="utf-8") as f:
        useragent = random.choice(f.readlines()).split("\n")[0]

    with open("./files/proxies.txt" , encoding="utf-8") as f:
        proxies = random.choice(f.readlines()).split("\n")[0]

    ProxyStatus['text'] = 'Proxy: %s' % proxies

def finishRun(x):
    timer = round((time.time() - x) ,2)
    TimeCount['text'] = 'Time: %ss' % timer
    ProgressStatus['text'] = 'Status: Finished!'
    btns_enable()

def checkViewUrl():

    global success, fails

    # Validate user input
    if len(UrlTabOne.get()) == 0 or len(TimesTabOne.get()) == 0:
        messagebox.showwarning("Dumb alert!", "Empty input... Use brain!")
        return False

    # Reset these
    success = 0
    fails = 0
    TextSuccess['text'] = 'Success: 0'
    TextFailed['text'] = 'Failed: 0'
    TimeCount['text'] = 'Time: Measurement...'
    ProgessBarTabOne['value'] = 0

    ProgressStatus['text'] = 'Progress: Preparing...'

    # Disable buttons
    btns_disable()

    # Setup
    limit = int(TimesTabOne.get())
    ProgessBarTabOne['maximum'] = limit
    ProxyStatus['text'] = 'Proxy: %s' % proxies

    # Check for threading option
    if checkVar.get() == 0:
        ProgressStatus['text'] = 'Status: Running...'
        start_time = time.time()
        for i in range(limit):
            cmd = viewUrl(UrlTabOne.get(), useragent, proxies)
            if cmd == True:
                success = success + 1
                TextSuccess['text'] = 'Success: %s' % success
                ProgessBarTabOne['value'] = success
                root.update()
            else:
                fails = fails + 1
                TextFailed['text'] = 'Fails: %s' % fails
                ProgessBarTabOne['value'] += 1
                root.update()
        finishRun(start_time)
    else:
        cmd = viewUrl(UrlTabOne.get(), useragent, proxies)
        threads = []
        start_time = time.time()
        ProgressStatus['text'] = 'Status: Running threads...'

        for i in range(limit):
            threads.append(threading.Thread(target=viewUrl, args=(UrlTabOne.get(), useragent, proxies)))
            if cmd == True:
                success = success + 1
                TextSuccess['text'] = 'Success: %s' % success
                ProgessBarTabOne['value'] = success
                root.update()
            else:
                fails = fails + 1
                TextFailed['text'] = 'Fails: %s' % fails
                ProgessBarTabOne['value'] += 1
                root.update()

        for thread in threads:
            thread.start()
        finishRun(start_time)

root = tk.Tk()
style = ttk.Style()
root.iconbitmap("./icon/seeker_icon.ico")
root.title("Tab Widget")
tabControl = ttk.Notebook(root)

root.title('SeaFrog v1.0')
root.geometry("850x650")
root.resizable(False, False)

tab1 = ttk.Frame(tabControl)
tab2 = ttk.Frame(tabControl)

tabControl.add(tab1, text='Views bot')
tabControl.add(tab2, text='About')

Banner = ImageTk.PhotoImage(Image.open('./icon/banner.png'))
LabelImage = ttk.Label(tab1, image=Banner)
UrlLabelTabOne = ttk.Label(tab1, text='Enter Your URL:')
UrlTabOne = ttk.Entry(tab1, width=50)
UrlTabOne.insert(0, 'https://example.com') # Placeholder
TimesLabelTabOne = ttk.Label(tab1, text='Views:')
TimesTabOne = ttk.Entry(tab1, width=10)
TimesTabOne.insert(1, '100') # Placeholder

checkVar = tk.IntVar()
ThreadingTabOne = ttk.Checkbutton(tab1, text='Multi-Threading (beta)', onvalue=1, offvalue=0, variable=checkVar)

ClearAll = ttk.Button(tab1, text='Clear', command=clearAll)
StartBtnTabOne = ttk.Button(tab1, text='Start', command=checkViewUrl)
ResetProxy = ttk.Button(tab1, text='Reset proxy', command=resetProxy)

ProgessBarTabOne = ttk.Progressbar(tab1, orient='horizontal', mode='determinate', length=400, value=0)
TextFailed = ttk.Label(tab1, text='Failed: 0')
TextSuccess = ttk.Label(tab1, text='Success: 0')
TimeCount = ttk.Label(tab1, text='Time: none')
ProgressStatus = ttk.Label(tab1, text='Status: none')
ProxyStatus = ttk.Label(tab1, text=f'Proxy: {proxies}')

LabelImage.place(relx=.5, rely=.1, anchor="center")

UrlLabelTabOne.place(relx=.3, rely=.3, anchor="center")
UrlTabOne.place(relx=.6, rely=.3, anchor="center")

TimesLabelTabOne.place(relx=.3, rely=.4, anchor="center")
TimesTabOne.place(relx=.6, rely=.4, anchor="center")

ThreadingTabOne.place(relx=.5, rely=.5, anchor="center")

ClearAll.place(relx=.4, rely=.6, anchor="center")
StartBtnTabOne.place(relx=.5, rely=.6, anchor="center")
ResetProxy.place(relx=.6, rely=.6, anchor="center")

ProgessBarTabOne.place(relx=.5, rely=.7, anchor="center")

TextFailed.place(relx=.4, rely=.8, anchor="center")
TextSuccess.place(relx=.6, rely=.8, anchor="center")
TimeCount.place(relx=.3, rely=.9, anchor="center")
ProgressStatus.place(relx=.5, rely=.9, anchor="center")
ProxyStatus.place(relx=.7, rely=.9, anchor="center")

# Second tab

nowarranty = '''No Warranty. LICENSOR PROVIDES THE LICENSED PROPERTY AND LICENSED IP ON AN "AS IS" BASIS WITHOUT WARRANTY OF ANY KIND. LICENSOR EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THE LICENSED PROPERTY AND LICENSED IP, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, NONINFRINGEMENT, TITLE AND FITNESS FOR A PARTICULAR PURPOSE, OR ARISING OUT OF A COURSE OF DEALING, USAGE OR TRADE PRACTICE. LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTY THAT THE FUNCTIONS CONTAINED IN THE IT PROPERTY WILL MEET ASPENTECH'S REQUIREMENTS OR WILL OPERATE IN COMBINATIONS OR IN A MANNER SELECTED FOR USE BY ASPENTECH, OR THAT THE OPERATION OF ANY LICENSED PROPERTY WILL BE UNINTERRUPTED OR ERROR FREE.'''

Info = ttk.Label(tab2, text='Created by @cr4sh https://github.com/cr4sh/seafrog')
Warranty = tk.Text(tab2, height=8, width=80)
scroll_bar = tk.Scrollbar(tab2)

Warranty.config(state='normal')
Warranty.insert(tk.END, nowarranty)
Warranty.config(state='disabled')

scroll_bar.config(command=Warranty.yview)

Info.place(relx=.5, rely=.2, anchor="center")
Warranty.place(relx=.5, rely=.5, anchor="center")
scroll_bar.place(relx=.9, rely=.5, anchor="center")

tabControl.pack(expand=1, fill='both')

# Set proxy and useragent for the first time
resetProxy()

root.mainloop()