import asyncio
import os
from math import floor
from typing import Sequence

import youtube_title_parse as ytp
import yt_dlp
from youtubesearchpython.__future__ import VideosSearch

from serenityapp.db import DBLink
import serenityapp.records as records
from serenityapp.config import (DOWNLOAD_PATH, DOWNLOADS_CODEC, UNKNOWN_ARTIST,
                                light_wait, path_exists)

class VoidLogger(object):

    def debug(msg):
        pass

    def warning(msg):
        pass

    def error(msg):
        pass

class AudioDL:

    audio_codec = 'mp3'
    current_title = ''
    __download_percent = 0
    __download_index = -1
    __downloading_titles = []
    __converting_titles = []
    __downloading = False
    __finished = True

    yt_dlp_options = {  # IMPORTANT. No OUTTMPL info.
        'extractaudio': True,
        'quiet': True,
        'format': 'bestaudio/best',
        'playlist': True,
        'logger': VoidLogger,
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': audio_codec,
            'preferredquality': '192'
        }]
    }

    def set_codec(codec):
        AudioDL.audio_codec = codec
        AudioDL.yt_dlp_options['postprocessors']['preferredcodec'] = codec

    def __prog_hook(d: dict):
        if d['status'] == 'finished':
            AudioDL.__download_index -= 1
            if AudioDL.__downloading_titles:
                AudioDL.__downloading_titles.pop()
                light_wait()
                AudioDL.__download_percent = 0
            else:
                AudioDL.__download_percent = 100
        if d['status'] == 'downloading':
            p = d['_percent_str']
            p = floor(float(p[0:-1]))
            if AudioDL.__download_index >= len(AudioDL.__downloading_titles)-1:
                AudioDL.__download_percent = p

    def validate_title(title: str) -> str:
        if title is None:
            return None
        txt = title.replace("|", "¦")
        txt = txt.encode('ascii', 'ignore').decode()
        return "".join(i for i in txt if i not in r'\/:*?"<>')

    def scrape_title(url: str, force_title: str = ''):
        if force_title != '':
            return force_title
        else:
            return yt_dlp.YoutubeDL(
                {
                    'logger': VoidLogger,
                    'skip_download': True,
                    'quiet': True
                }
            ).extract_info(url, download=False).get('title', None)

    def get_online_data(valid_title: str):
        options = {
            'defaultArtist': UNKNOWN_ARTIST,
            'defaultTitle': valid_title
        }
        artist, track = ytp.get_artist_title(valid_title, options)
        return [artist, track, 0, valid_title]

    async def __search_youtube(query):
        try:
            videosSearch = VideosSearch(query, limit=1)
            videosResult = await videosSearch.next()
            return [videosResult['result'][0]['link'],
                    videosResult['result'][0]['title']]
        except Exception:
            return [None, None]

    def get_link_and_title(query):
        loop = asyncio.new_event_loop()
        return loop.run_until_complete(AudioDL.__search_youtube(query))

    def download(urls: list, data: Sequence):
        artist, track, _, title = data
        if title == '':
            return
        options = AudioDL.yt_dlp_options.copy()
        dl_path = DOWNLOAD_PATH + artist + os.sep + track
        options['outtmpl'] = dl_path + '.%(ext)s'
        downloader = yt_dlp.YoutubeDL(options)
        full_path = "{}.{}".format(dl_path, DOWNLOADS_CODEC)
        if not path_exists(full_path):
            os.makedirs(os.path.dirname(full_path), exist_ok=True)
            with downloader as dl:
                appended_c = False
                appended_d = False
                try:
                    dl.add_progress_hook(AudioDL.__prog_hook)
                    AudioDL.__download_index += 1
                    AudioDL.__downloading_titles.append(title)
                    appended_d = True
                    AudioDL.__downloading = False
                    AudioDL.__finished = False
                    AudioDL.__converting_titles.append(title)
                    dl.download(urls)
                    appended_c = True
                    if not AudioDL.__downloading_titles:
                        AudioDL.__downloading = False
                    dbLink = DBLink()
                    records.add_downloaded_song(full_path, data, dbLink)
                    light_wait()
                    if AudioDL.__converting_titles:
                        AudioDL.__converting_titles.pop()
                    AudioDL.__finished = (not AudioDL.__converting_titles
                                          and not AudioDL.__downloading_titles)
                except Exception:
                    if appended_c is True:
                        if AudioDL.__converting_titles:
                            AudioDL.__converting_titles.pop()
                    if appended_d is True:
                        if AudioDL.__downloading_titles:
                            AudioDL.__downloading_titles.pop()

    def download_percent():
        return AudioDL.__download_percent

    def is_downloading():
        return AudioDL.__downloading

    def download_started():
        return len(AudioDL.__downloading_titles) != 0

    def is_finished():
        return AudioDL.__finished

    def active_titles():
        return AudioDL.__converting_titles

    def data_on_disk(data):
        ''' Returns true if there is a file matching the data on disk. '''
        artist, track, _, _ = data
        dl_path = DOWNLOAD_PATH + os.sep + artist + os.sep + track
        full_path = "{}.{}".format(dl_path, DOWNLOADS_CODEC)
        return path_exists(full_path)


f = open("clsfun.py")
lineNo = 0
a = list(map(str,f))

i = 0
while i < len(a):
    temp = a[i]
    temp = temp.strip()
    #print(temp)

    if "class" in temp:
        if "\\n" not in a[i+1]:
            print("Suggested Blank line between class definition next loc.")
    i += 1


# -*- coding: utf-8 -*-
"""
Created on Wed May 29 17:42:47 2019

@author: KIIT
"""

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
from sklearn.metrics import confusion_matrix
from sklearn.preprocessing import StandardScaler
import numpy as np

df=pd.read_csv('tree_addhealth.csv')
df=df.replace(np.nan,df.mean())

features=df.iloc[:,[0,1,2,3,4,5,6,8,9,10,11,12,13,14,15]].values
labels=df.iloc[:,7:8].values

for i in range (0,13):
    if (i==6):
        continue
    onehotencoder=OneHotEncoder(categorical_features=[i])
    features=onehotencoder.fit_transform(features).toarray()
    features=features[:,1:]
features_train,features_test,labels_train,labels_test=train_test_split(features,labels,test_size=0.2,random_state=0)
sc = StandardScaler()
features_train = sc.fit_transform(features_train)
features_test = sc.transform(features_test)
classifier=LogisticRegression()
classifier.fit(features_train,labels_train)
pred=classifier.predict(features_test)
result=pd.DataFrame(labels_test,pred)
print(result)
cm=list(confusion_matrix(labels_test,pred))
print(cm)
total=cm[0].sum()+cm[1].sum()
success=cm[0][0]+cm[1][1]
print('model success percent:',(success/total)*100)


f = open('tags.txt', 'r')

x = []
lines = f.readlines()

for line in lines:
    x.append([0, line.replace('\n', '')])

raw = open('final.csv', 'r')
lines = raw.readlines()
for i in x:
    for j in lines:
        if j.find(i[1]) != -1:
            i[0] += 1;

x.sort(reverse=True)
for i in x:
    print(i)

f.close()


# -*- coding: utf-8 -*-
"""
verdi daemon cli utilities
"""
from aiida.common import aiidalogger

logger = aiidalogger.getChild('workflowmanager')

def is_daemon_user():
    """
    Return True if the user is the current daemon user, False otherwise.
    """
    from aiida.backends.utils import get_daemon_user
    from aiida.common.utils import get_configured_user_email

    daemon_user = get_daemon_user()
    this_user = get_configured_user_email()

    return daemon_user == this_user

def get_env_with_venv_bin():
    """get an environment to run the daemon in that respects the current virtualenvs"""
    import os
    import sys
    pybin = os.path.dirname(sys.executable)
    currenv = os.environ.copy()
    currenv['PATH'] = pybin + ':' + currenv['PATH']
    return currenv

def get_conffile_full_path():
    """Get the full path to the config file"""
    from os.path import expanduser, join
    from aiida.common import setup
    return expanduser(join(
        setup.AIIDA_CONFIG_FOLDER,
        setup.DAEMON_SUBDIR,
        setup.DAEMON_CONF_FILE))

def get_pid_full_path():
    """
    Return the full path of the supervisord.pid file.
    """
    from os.path import normpath, expanduser, join
    from aiida.common import setup

    return normpath(expanduser(
        join(setup.AIIDA_CONFIG_FOLDER,
             setup.DAEMON_SUBDIR, "supervisord.pid")))

def get_sock_full_path():
    """
    Return the full path of the supervisord.sock file.
    """
    from os.path import normpath, expanduser, join
    from aiida.common import setup

    return normpath(expanduser(
        join(setup.AIIDA_CONFIG_FOLDER,
             setup.DAEMON_SUBDIR, "supervisord.sock")))

def get_daemon_pid():
    """
    Return the daemon pid, as read from the supervisord.pid file.
    Return None if no pid is found (or the pid is not valid).
    """
    from os.path import isfile
    if isfile(get_pid_full_path()):
        try:
            return int(open(get_pid_full_path(), 'r').read().strip())
        except (ValueError, IOError):
            return None
    else:
        return None

def _clean_sock_files():
    """
    Tries to remove the supervisord.pid and .sock files from the .aiida/daemon
    subfolder. This is typically needed when the computer is restarted with
    the daemon still on.
    """
    import errno
    import os

    try:
        os.remove(get_sock_full_path())
    except OSError as e:
        # Ignore if errno = errno.ENOENT (2): no file found
        if e.errno != errno.ENOENT:  # No such file
            raise

    try:
        os.remove(get_pid_full_path())
    except OSError as e:
        # Ignore if errno = errno.ENOENT (2): no file found
        if e.errno != errno.ENOENT:  # No such file
            raise

def kill_daemon():
    """
    This is the actual call that kills the daemon.

    There are some print statements inside, but no sys.exit, so it is
    safe to be called from other parts of the code.
    """
    import click
    from signal import SIGTERM
    import errno
    import os

    pid = get_daemon_pid()
    if pid is None:
        click.echo("Daemon not running (cannot find the PID for it)")
        return

    click.echo("Shutting down AiiDA Daemon ({})...".format(pid))
    try:
        os.kill(pid, SIGTERM)
    except OSError as e:
        if e.errno == errno.ESRCH:  # No such process
            click.echo("The process {} was not found! Assuming it was already stopped.".format(pid))
            click.echo("Cleaning the .pid and .sock files...")
            _clean_sock_files()
        else:
            raise


__author__ = 'dmxjhg'
__date__ = '2019/8/13 19:50'

from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator

from .models import UserFav, Questionnaire, Route
from .models import UserLeavingMessage

from article.serializers import ArticleSerializer

class UserFavSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )  # 获取当前用户，drf文档中看用法，如果不这样，post的时候还需要传用户，这是不合理的

    class Meta:
        model = UserFav
        fields = ("user", "article", "id")  # id是为了删除操作
        validators = [
            UniqueTogetherValidator(
                queryset=UserFav.objects.all(),
                fields=('user', 'article'),
                message="已经收藏"
            )
        ]

class UserFavDetailSerializer(serializers.ModelSerializer):
    article = ArticleSerializer()

    class Meta:
        model = UserFav
        fields = ("article", "id")

class LeavingMessageSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )
    add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M')

    class Meta:
        model = UserLeavingMessage
        fields = ("user", "message", "add_time")

class QuestionnaireSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )
    add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M')

    class Meta:
        model = Questionnaire
        fields = ("user", "choose", "add_time", "id")

class RouteListSerializer(serializers.ModelSerializer):
    questionnaire = QuestionnaireSerializer()
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )
    add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M')
    route = serializers.CharField(read_only=True, )

    class Meta:
        model = Route
        fields = ("user", "questionnaire", "route", "add_time")


#!/usr/bin/env python

import collections
import random
import time

from prometheus_client import Gauge, start_http_server

cpu_metrics = Gauge(
    'instance_fake_cpu_seconds_total', 'Fake amount of CPU used',
    ['project_id', 'resource_type', 'resource_id', 'resource_name']
)

memory_metrics = Gauge(
    'instance_fake_memory_usage_bytes', 'Fake amount of memory used',
    ['project_id', 'resource_type', 'resource_id', 'resource_name']
)

def update_stats():
    cpu_data = collections.defaultdict(int)

    for project in ('my-project0', 'my-project1', 'my-project2'):
        for node in range(10):
            val = int(random.random() * 100)

            cpu_data[node] += val

            print(f'Set cpu={cpu_data[node]} and memory={val} for {node}')
            cpu_metrics.labels(
                project_id=project,
                resource_type='instance_fake_monitoring',
                resource_id=f'fffffff-fffff-{node}',
                resource_name=f'Server {node}'
            ).set(cpu_data[node])

            memory_metrics.labels(
                project_id=project,
                resource_type='instance_fake_monitoring',
                resource_id=f'fffffff-fffff-{node}',
                resource_name=f'Server {node}'
            ).set(val)

if __name__ == '__main__':
    start_http_server(8000)
    while True:
        update_stats()
        time.sleep(1)


#!/usr/bin/env python

import mirheo as mir
import numpy as np
import sys

from parameters import (PipeFlowParams,
                        load_parameters)

def get_pv_num_particles(pv):
    return len(pv.getCoordinates())

def run_capillary_flow(p: 'PipeFlowParams',
                       *,
                       no_visc: bool,
                       ranks: tuple=(1,1,1),
                       restart_directory: str=None,
                       checkpoint_directory: str=None):
    """
    Arguments:
        p: the simulation parameters (see parameters.py).
        no_visc: if True, disable the viscosity of membrane.
        ranks: number of ranks per dimension.
        restart_directory: if set, specify from which directory to restart.
        checkpoint_directory: if set, specify to which directory to dump checkpoints.
    """

    rc   = p.rc
    L    = p.L
    R    = p.R
    Vmax = p.Vmax
    RA   = p.RA

    dt_solv = min([dpd.get_max_dt() for dpd in [p.dpd_ii, p.dpd_oo, p.dpd_rbco, p.dpd_rbci]])

    if no_visc:
        p.rbc_params.set_viscosity(0)

    tend = 5000 * R / Vmax

    domain = (L, 2*R + 4*rc, 2*R + 4*rc)

    if checkpoint_directory is not None:
        u = mir.Mirheo(ranks, domain, debug_level=3, log_filename='log', checkpoint_every=10000, checkpoint_folder=checkpoint_directory)
    else:
        u = mir.Mirheo(ranks, domain, debug_level=3, log_filename='log')

    vv = mir.Integrators.VelocityVerlet('vv')
    u.registerIntegrator(vv)

    # Membranes

    mesh_rbc = mir.ParticleVectors.MembraneMesh(p.mesh_ini.vertices.tolist(),
                                                p.mesh_ref.vertices.tolist(),
                                                p.mesh_ini.faces.tolist())
    pv_rbc = mir.ParticleVectors.MembraneVector('rbc', mass=p.m, mesh=mesh_rbc)
    u.registerParticleVector(pv_rbc, mir.InitialConditions.Restart('generate_ic'))

    # Solvent

    pv_outer = mir.ParticleVectors.ParticleVector('outer', mass=p.m)
    ic_outer = mir.InitialConditions.Uniform(number_density=p.nd)
    u.registerParticleVector(pv=pv_outer, ic=ic_outer)

    rbc_checker = mir.BelongingCheckers.Mesh('rbc_checker')
    u.registerObjectBelongingChecker(rbc_checker, pv_rbc)
    pv_inner = u.applyObjectBelongingChecker(rbc_checker, pv_outer, inside='inner', correct_every=10000)

    rbc_bouncer = mir.Bouncers.Mesh("rbc_bouncer", "bounce_maxwell", kBT=p.kBT)
    u.registerBouncer(rbc_bouncer)

    # Interactions

    dpd_oo = mir.Interactions.Pairwise('dpd_oo', rc=rc, kind="DPD", **p.dpd_oo.to_interactions())
    dpd_ii = mir.Interactions.Pairwise('dpd_ii', rc=rc, kind="DPD", **p.dpd_ii.to_interactions())
    dpd_io = mir.Interactions.Pairwise('dpd_io', rc=rc, kind="DPD", **p.dpd_io.to_interactions())

    u.registerInteraction(dpd_oo)
    u.registerInteraction(dpd_ii)
    u.registerInteraction(dpd_io)

    dpd_rbco = mir.Interactions.Pairwise('dpd_rbco', rc=rc, kind="DPD", **p.dpd_rbco.to_interactions())
    dpd_rbci = mir.Interactions.Pairwise('dpd_rbci', rc=rc, kind="DPD", **p.dpd_rbci.to_interactions())

    # Walls

    wall = mir.Walls.Cylinder('pipe', center=(domain[1]/2, domain[2]/2),
                              radius=R, axis='x', inside=True)
    u.registerWall(wall)
    frozen = u.makeFrozenWallParticles("frozen", walls=[wall], interactions=[dpd_oo], integrator=vv, number_density=p.nd, nsteps=int(1.0/dt_solv), dt=dt_solv)
    u.setWall(wall, pv_outer)

    # Set interactions between pvs

    u.registerInteraction(dpd_rbco)
    u.registerInteraction(dpd_rbci)

    u.setInteraction(dpd_oo, pv_outer, pv_outer)
    u.setInteraction(dpd_ii, pv_inner, pv_inner)
    u.setInteraction(dpd_io, pv_inner, pv_outer)

    u.setInteraction(dpd_rbco, pv_rbc, pv_outer)
    u.setInteraction(dpd_rbci, pv_rbc, pv_inner)

    u.setInteraction(dpd_oo, pv_outer, frozen)
    u.setInteraction(dpd_io, pv_inner, frozen)
    u.setInteraction(dpd_rbco, pv_rbc, frozen)

    # set bouncers
    u.setBouncer(rbc_bouncer, pv_rbc, pv_inner)
    u.setBouncer(rbc_bouncer, pv_rbc, pv_outer)

    # Integrators

    u.setIntegrator(vv, pv_outer)
    u.setIntegrator(vv, pv_inner)

    dt_rbc_el = p.rbc_params.get_max_dt_elastic(mass=p.m)
    substeps = 1 + int(dt_solv / dt_rbc_el)
    dt = dt_solv

    if no_visc:
        rbc_int = mir.Interactions.MembraneForces('int_rbc', **p.rbc_params.to_interactions(), stress_free=True)
        u.registerInteraction(rbc_int)

        if substeps == 1:
            u.setIntegrator(vv, pv_rbc)
            u.setInteraction(rbc_int, pv_rbc, pv_rbc)
        else:
            vv_rbc = mir.Integrators.SubStep("vv_rbc", substeps, fastForces=[rbc_int])
            u.registerIntegrator(vv_rbc)
            u.setIntegrator(vv_rbc, pv_rbc)

    else: # we use Shardlow integration
        dt_rbc_visc = p.rbc_params.get_max_dt_visc(mass=p.m)

        rbc_int = mir.Interactions.MembraneForces('int_rbc', **p.rbc_params.to_interactions_zero_visc(), stress_free=True)
        u.registerInteraction(rbc_int)

        vv_rbc = mir.Integrators.SubStepShardlowSweep("vv_rbc", substeps=10, fastForces=rbc_int, nsweeps=20, **p.rbc_params.to_viscous())
        u.registerIntegrator(vv_rbc)
        u.setIntegrator(vv_rbc, pv_rbc)

    # Plugins

    t_dump_every = 0.2 * R / Vmax
    dump_every = int(t_dump_every/dt)
    stats_every = dump_every

    h = 0.1 * rc
    u.registerPlugins(mir.Plugins.createWallRepulsion("wall_force", pv_rbc, wall, C=p.max_contact_force/h, h=h, max_force=p.max_contact_force))

    # estimate the number density of particles, accounting for pv_rbcs
    rho = p.nd

    f = (p.pressure_gradient / p.nd, 0, 0)
    u.registerPlugins(mir.Plugins.createAddForce("body_force_solvent", pv_outer, f))
    u.registerPlugins(mir.Plugins.createAddForce("body_force_hemoglobine", pv_inner, f))

    u.registerPlugins(mir.Plugins.createDumpMesh("mesh_dump", pv_rbc, dump_every, 'ply/'))
    u.registerPlugins(mir.Plugins.createStats("stats", every=stats_every, filename='stats.csv', pvs=[pv_inner, pv_outer, pv_rbc]))
    u.registerPlugins(mir.Plugins.createDumpObjectStats("rbc_stats", ov=pv_rbc, dump_every=stats_every, path="obj_stats"))

    if u.isMasterTask():
        print(f"tend = {tend}")
        print(f"dt = {dt}")
        print(f"substeps = {substeps}")
        sys.stdout.flush()

    u.dumpWalls2XDMF([wall], h=(1,1,1), filename='h5/wall')

    if restart_directory is not None:
        u.restart(restart_directory)

    u.run(int(tend/dt), dt)

def main(argv):
    import argparse
    parser = argparse.ArgumentParser(description='Run RBCs flowing in a capillary pipe.')
    parser.add_argument('--params', type=str, default="parameters.pkl", help="Parameters file.")
    parser.add_argument('--ranks', type=int, nargs=3, default=(1, 1, 1), help="Ranks in each dimension.")
    parser.add_argument('--no-visc', action='store_true', default=False, help="Set zero membrane viscosity.")
    parser.add_argument('--restart-dir', type=str, default=None, help="The restart directory name (no restart if not set)")
    parser.add_argument('--checkpoint-dir', type=str, default=None, help="The checkpoint directory name (no checkpoint if not set)")
    args = parser.parse_args(argv)

    p = load_parameters(args.params)

    run_capillary_flow(p,
                       no_visc = args.no_visc,
                       ranks=tuple(args.ranks),
                       restart_directory=args.restart_dir,
                       checkpoint_directory=args.checkpoint_dir)

if __name__ == '__main__':
    main(sys.argv[1:])


import unittest
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression

class LinearRegressionTest(unittest.TestCase):
    def test_train_test_split(self):
        X, y = np.arange(10).reshape((5,2)), range(5)
        print(X, y)
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
        print(X_train, y_train)
        print(X_test, y_test)

        # Fit Training data
        regression = LinearRegression()
        regression.fit(X_train, y_train)

        # Predicting labels on the test set
        print(regression.predict(X_test))

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


import datetime
import os
import sys
import webbrowser
from typing import Any, Callable

import PySide2.QtCore as QtCore
import PySide2.QtGui as QtGui
import PySide2.QtWidgets as QtWidgets
from fbs_runtime.application_context.PySide2 import ApplicationContext
from loguru import logger

import dialogs.error_dialogs as error_dialogs
import dialogs.information_dialogs as information_dialogs
import dialogs.question_dialogs as question_dialogs
import dialogs.warning_dialogs as warning_dialogs
import lib.config as config
import lib.files as files
import lib.flight_sim as flight_sim
import lib.thread as thread
import lib.version as version
from dialogs.version_check_dialog import version_check_dialog
from widgets.about_widget import about_widget
from widgets.info_widget import info_widget
from widgets.main_table import main_table
from widgets.progress_widget import progress_widget
from widgets.versions_widget import versions_widget

ARCHIVE_FILTER = "Archives (*.zip *.rar *.tar *.bz2 *.7z)"

class main_widget(QtWidgets.QWidget):
    def __init__(
        self, parent: QtWidgets.QWidget = None, appctxt: ApplicationContext = None
    ) -> None:
        """Main application widget."""
        QtWidgets.QWidget.__init__(self)
        self.parent = parent  # type: ignore
        self.appctxt = appctxt

    def build(self) -> None:
        """Build layout."""
        self.layout = QtWidgets.QGridLayout()  # type: ignore

        self.install_button = QtWidgets.QPushButton("Install", self)
        self.layout.addWidget(self.install_button, 0, 0)  # type: ignore

        self.uninstall_button = QtWidgets.QPushButton("Uninstall", self)
        self.layout.addWidget(self.uninstall_button, 0, 1)  # type: ignore

        self.enable_button = QtWidgets.QPushButton("Enable", self)
        self.layout.addWidget(self.enable_button, 0, 4)  # type: ignore

        self.disable_button = QtWidgets.QPushButton("Disable", self)
        self.layout.addWidget(self.disable_button, 0, 5)  # type: ignore

        self.info_button = QtWidgets.QPushButton("Info", self)
        self.layout.addWidget(self.info_button, 0, 8)  # type: ignore

        self.refresh_button = QtWidgets.QPushButton("Refresh", self)
        self.layout.addWidget(self.refresh_button, 0, 9)  # type: ignore

        self.sublayout = QtWidgets.QHBoxLayout()  # type: ignore

        self.search_label = QtWidgets.QLabel("Search:", self)
        self.sublayout.addWidget(self.search_label)

        self.search_field = QtWidgets.QLineEdit(self)
        self.sublayout.addWidget(self.search_field)

        self.clear_button = QtWidgets.QPushButton("Clear", self)
        self.sublayout.addWidget(self.clear_button)

        self.layout.addLayout(self.sublayout, 1, 6, 1, 4)

        self.main_table = main_table(self)
        self.layout.addWidget(self.main_table, 2, 0, 1, 10)  # type: ignore

        self.setLayout(self.layout)

        # buttons
        self.install_button.clicked.connect(self.install_archive)  # type: ignore
        self.uninstall_button.clicked.connect(self.uninstall)  # type: ignore
        self.enable_button.clicked.connect(self.enable)  # type: ignore
        self.disable_button.clicked.connect(self.disable)  # type: ignore
        self.refresh_button.clicked.connect(self.refresh)  # type: ignore
        self.info_button.clicked.connect(self.info)  # type: ignore
        self.main_table.doubleClicked.connect(self.info)  # type: ignore

        self.clear_button.clicked.connect(self.clear_search)  # type: ignore
        self.search_field.textChanged.connect(self.search)  # type: ignore

        # shortcuts
        self.shortcut_delete = QtWidgets.QShortcut(
            QtGui.QKeySequence(QtCore.Qt.Key_Delete), self  # type: ignore
        )
        self.shortcut_delete.activated.connect(self.uninstall)  # type: ignore

        # handle to data
        self.flight_sim = flight_sim.flight_sim()

    # ======================
    # Sim Functions
    # ======================

    def find_sim(self) -> None:
        """Sets the path to the simulator root folder."""

        def user_selection() -> None:
            """Function to keep user in a loop until they select correct folder."""
            # prompt user to select
            self.flight_sim.sim_packages_folder = (
                QtWidgets.QFileDialog.getExistingDirectory(
                    parent=self,
                    caption="Select the root Microsoft Flight Simulator directory",
                    dir=os.getenv("APPDATA"),  # type: ignore
                )
            )

            if not self.flight_sim.sim_packages_folder.strip():
                sys.exit()

            elif self.flight_sim.is_sim_packages_folder(
                self.flight_sim.sim_packages_folder
            ):
                # save the config file
                config.set_key_value(
                    config.SIM_FOLDER_KEY,
                    self.flight_sim.sim_packages_folder,
                    path=True,
                )

            elif self.flight_sim.is_sim_packages_folder(
                os.path.join(self.flight_sim.sim_packages_folder, "Packages")
            ):
                # save the config file
                config.set_key_value(
                    config.SIM_FOLDER_KEY,
                    os.path.join(self.flight_sim.sim_packages_folder, "Packages"),
                    path=True,
                )

            else:
                # show error
                warning_dialogs.sim_path_invalid(self)
                # send them through again
                user_selection()

        # try to automatically find the sim
        (
            success,
            self.flight_sim.sim_packages_folder,  # type: ignore
        ) = self.flight_sim.find_sim_packages_folder()

        if not self.flight_sim.sim_packages_folder:
            # show error
            warning_dialogs.sim_not_detected(self)
            # let user select folder
            user_selection()

        elif not success:
            # save the config file
            config.set_key_value(
                config.SIM_FOLDER_KEY, self.flight_sim.sim_packages_folder, path=True
            )
            # notify user
            information_dialogs.sim_detected(self, self.flight_sim.sim_packages_folder)

    def select_mod_install(self) -> None:
        """Allow user to select new mod install folder."""
        old_install = files.get_mod_install_folder()

        information_dialogs.mod_install_folder(self)

        new_install = QtWidgets.QFileDialog.getExistingDirectory(
            parent=self,
            caption="Select mod install folder",
            dir=os.path.dirname(old_install),
        )

        def core(progress: Callable) -> None:
            # setup mover thread
            mover = flight_sim.move_mod_install_folder_thread(
                self.flight_sim, old_install, new_install
            )
            mover.activity_update.connect(progress.set_activity)  # type: ignore

            def failed(err: Exception) -> None:
                typ = type(err)
                message = str(err)

                logger.exception("Failed to move mod install folder")
                error_dialogs.general(self, typ, message)

            # start the thread
            with thread.thread_wait(
                mover.finished,
                failed_signal=mover.failed,
                failed_func=failed,
                update_signal=mover.activity_update,
            ):
                mover.start()

            # done
            information_dialogs.mod_install_folder_set(self, new_install)

        if not new_install:
            # cancel if no folder selected
            return

        if files.check_same_path(old_install, new_install):
            # cancel if new folder is same as old folder
            warning_dialogs.mod_install_folder_same(self)
            return

        if files.check_in_path(new_install, self.flight_sim.get_sim_mod_folder()):
            # cancel if new folder is in sim packages folder
            warning_dialogs.mod_install_folder_in_sim_path(self)
            return

        if not question_dialogs.mod_install_folder_move(self, old_install, new_install):
            # last sanity check
            return

        self.base_action(core)

    # ======================
    # Inherited Functions
    # ======================

    def base_fail(self, error: Exception, mapping: dict, fallback_text: str) -> None:
        """Base thread failure function."""
        typ = type(error)
        if typ not in mapping:
            logger.error(fallback_text)
            message = str(error)

            logger.error("{}: {}", typ, message)
            error_dialogs.general(self, typ, message)
        else:
            func = mapping[typ]
            func()

    def base_action(
        self,
        core_func: Callable,
        button: QtWidgets.QPushButton = None,
        sanity_dialog: Callable = None,
        empty_check: bool = False,
        empty_val: Any = None,
        refresh: bool = True,
    ):
        """Base function for GUI actions."""
        if empty_check and not empty_val:
            return

        if button:
            button.setEnabled(False)

        # sanity check
        if sanity_dialog:
            question = sanity_dialog()
            if not question:
                # cancel
                button.setEnabled(True)
                return

        # build progress widget
        progress = progress_widget(self, self.appctxt)
        progress.set_mode(progress.INFINITE)

        # execute the core function
        core_func(progress)
        progress.close()

        # refresh the data
        if refresh:
            self.refresh(automated=True)

        # cleanup
        if button:
            button.setEnabled(True)

    # ======================
    # Version Check
    # ======================

    def check_version(self) -> None:
        """Checks the application version and allows user to open browser to update."""
        installed = version.is_installed()
        return_url = version.check_version(self.appctxt, installed)  # type: ignore

        def core(progress: Callable) -> None:
            progress.set_mode(progress.PERCENT)
            progress.set_activity("Downloading latest version ({})".format(return_url))

            # setup downloader thread
            downloader = version.download_new_version_thread(return_url)  # type: ignore
            downloader.percent_update.connect(progress.set_percent)  # type: ignore

            def failed(err: Exception) -> None:
                typ = type(err)
                message = str(err)

                logger.exception("Failed to download new version")
                error_dialogs.general(self, typ, message)

            # start the thread
            with thread.thread_wait(
                downloader.finished,
                finish_func=version.install_new_version,
                failed_signal=downloader.failed,
                failed_func=failed,
                update_signal=downloader.percent_update,
            ):
                downloader.start()

        if not return_url:
            return

        result, remember = version_check_dialog(self, installed).exec_()
        if result:
            if installed:
                self.base_action(core, refresh=False)
            else:
                webbrowser.open(return_url)  # type: ignore
        elif remember:
            config.set_key_value(config.NEVER_VER_CHEK_KEY, True)

    # ======================
    # Data Operations
    # ======================

    def install_archive(self) -> None:
        """Installs selected mod archives."""

        # first, let user select multiple archives
        mod_archives = QtWidgets.QFileDialog.getOpenFileNames(
            parent=self,
            caption="Select mod archive(s)",
            dir=files.get_last_open_folder(),
            filter=ARCHIVE_FILTER,
        )[0]

        succeeded = []

        def core(progress: Callable) -> None:
            # for each archive, try to install it
            for mod_archive in mod_archives:

                def finish(result: list) -> None:
                    # this function is required as the results will be a list,
                    # which is not a hashable type
                    succeeded.extend(result)

                def failed(err: Exception) -> None:
                    message = str(err)

                    mapping = {
                        files.ExtractionError: lambda: error_dialogs.archive_extract(
                            self, mod_archive, message
                        ),
                        flight_sim.NoManifestError: lambda: warning_dialogs.mod_parsing(
                            self, [mod_archive]
                        ),
                        files.AccessError: lambda: error_dialogs.permission(
                            self, mod_archive, message
                        ),
                        flight_sim.NoModsError: lambda: error_dialogs.no_mods(
                            self, mod_archive
                        ),
                    }

                    self.base_fail(
                        err,
                        mapping,
                        "Failed to install mod archive",
                    )

                # setup installer thread
                installer = flight_sim.install_mod_archive_thread(
                    self.flight_sim, mod_archive
                )
                installer.activity_update.connect(progress.set_activity)  # type: ignore
                installer.percent_update.connect(progress.set_percent)  # type: ignore

                # start the thread
                with thread.thread_wait(
                    installer.finished,
                    finish_func=finish,
                    failed_signal=installer.failed,
                    failed_func=failed,
                    update_signal=installer.activity_update,
                    timeout=1200000,
                ):
                    installer.start()

        self.base_action(
            core,
            button=self.install_button,
            empty_check=True,
            empty_val=mod_archives,
        )

        if succeeded:
            config.set_key_value(
                config.LAST_OPEN_FOLDER_KEY, os.path.dirname(mod_archives[0]), path=True
            )
            information_dialogs.mods_installed(self, succeeded)

    def install_folder(self) -> None:
        """Installs selected mod folders."""

        # first, let user select a folder
        mod_folder = QtWidgets.QFileDialog.getExistingDirectory(
            parent=self,
            caption="Select mod folder",
            dir=files.get_last_open_folder(),
        )

        succeeded = []

        def core(progress: Callable) -> None:
            def finish(result: list) -> None:
                # this function is required as the results will be a list,
                # which is not a hashable type
                succeeded.extend(result)

            def failed(err: Exception) -> None:
                message = str(err)

                mapping = {
                    flight_sim.NoManifestError: lambda: warning_dialogs.mod_parsing(
                        self, [mod_folder]
                    ),
                    files.AccessError: lambda: error_dialogs.permission(
                        self, mod_folder, message
                    ),
                    flight_sim.NoModsError: lambda: error_dialogs.no_mods(
                        self, mod_folder
                    ),
                }

                self.base_fail(
                    err,
                    mapping,
                    "Failed to install mod folder",
                )

            # setup installer thread
            installer = flight_sim.install_mods_thread(self.flight_sim, mod_folder)
            installer.activity_update.connect(progress.set_activity)  # type: ignore

            # start the thread
            with thread.thread_wait(
                installer.finished,
                finish_func=finish,
                failed_signal=installer.failed,
                failed_func=failed,
                update_signal=installer.activity_update,
            ):
                installer.start()

        self.base_action(
            core,
            button=self.install_button,
            empty_check=True,
            empty_val=mod_folder,
        )

        if succeeded:
            config.set_key_value(
                config.LAST_OPEN_FOLDER_KEY, os.path.dirname(mod_folder), path=True
            )
            information_dialogs.mods_installed(self, succeeded)

    def uninstall(self) -> None:
        """Uninstalls selected mods."""
        selected = self.main_table.get_selected_rows()

        def core(progress: Callable) -> None:
            for i, _id in enumerate(selected):
                # first, get the mod name and enabled status
                (folder, enabled) = self.main_table.get_basic_info(_id)
                mod_folder = self.flight_sim.get_mod_folder(folder, enabled)

                # setup uninstaller thread
                uninstaller = flight_sim.uninstall_mod_thread(
                    self.flight_sim, mod_folder
                )
                uninstaller.activity_update.connect(progress.set_activity)  # type: ignore

                def failed(err: Exception) -> None:
                    self.base_fail(err, {}, "Failed to uninstall mod")

                # start the thread
                with thread.thread_wait(
                    uninstaller.finished,
                    failed_signal=uninstaller.failed,
                    failed_func=failed,
                    update_signal=uninstaller.activity_update,
                ):
                    uninstaller.start()

                progress.set_percent(i, total=len(selected) - 1)

        self.base_action(
            core,
            button=self.uninstall_button,
            sanity_dialog=lambda: question_dialogs.mod_delete(self, len(selected)),
            empty_check=True,
            empty_val=selected,
        )

    def enable(self) -> None:
        """Enables selected mods."""
        selected = self.main_table.get_selected_rows()

        def core(progress: Callable) -> None:
            for i, _id in enumerate(selected):
                # first, get the mod name and enabled status
                (folder, enabled) = self.main_table.get_basic_info(_id)

                if enabled:
                    continue

                # setup enabler thread
                enabler = flight_sim.enable_mod_thread(self.flight_sim, folder)
                enabler.activity_update.connect(progress.set_activity)  # type: ignore

                def failed(err: Exception) -> None:
                    self.base_fail(err, {}, "Failed to enable mod")

                # start the thread
                with thread.thread_wait(
                    enabler.finished,
                    failed_signal=enabler.failed,
                    failed_func=failed,
                    update_signal=enabler.activity_update,
                ):
                    enabler.start()

                progress.set_percent(i, total=len(selected) - 1)

        self.base_action(
            core, button=self.enable_button, empty_check=True, empty_val=selected
        )

    def disable(self) -> None:
        """Disables selected mods."""
        selected = self.main_table.get_selected_rows()

        def core(progress: Callable) -> None:
            for i, _id in enumerate(selected):
                # first, get the mod name and disable status
                (folder, enabled) = self.main_table.get_basic_info(_id)

                if not enabled:
                    continue

                # setup disabler thread
                disabler = flight_sim.disable_mod_thread(self.flight_sim, folder)
                disabler.activity_update.connect(progress.set_activity)  # type: ignore

                def failed(err: Exception) -> None:
                    self.base_fail(err, {}, "Failed to disable mod")

                # start the thread
                with thread.thread_wait(
                    disabler.finished,
                    failed_signal=disabler.failed,
                    failed_func=failed,
                    update_signal=disabler.activity_update,
                ):
                    disabler.start()

                progress.set_percent(i, total=len(selected) - 1)

        self.base_action(
            core, button=self.disable_button, empty_check=True, empty_val=selected
        )

    def create_backup(self) -> None:
        """Creates a backup of all enabled mods."""

        archive = QtWidgets.QFileDialog.getSaveFileName(
            parent=self,
            caption="Save Backup As",
            dir=os.path.join(
                config.BASE_FOLDER,
                "msfs-mod-backup-{}.zip".format(
                    datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
                ),
            ),
            filter=ARCHIVE_FILTER,
        )[0]

        succeeded = []

        def core(progress: Callable) -> None:
            # setup backuper thread
            backuper = flight_sim.create_backup_thread(self.flight_sim, archive)
            backuper.activity_update.connect(progress.set_activity)  # type: ignore

            def finish(result: list) -> None:
                # this function is required as the results will be a list,
                # which is not a hashable type
                succeeded.extend(result)

            def failed(err: Exception) -> None:
                message = str(err)

                mapping = {
                    files.ExtractionError: lambda: error_dialogs.archive_create(
                        self, archive, message
                    )
                }

                self.base_fail(
                    err,
                    mapping,
                    "Failed to create backup",
                )

            # start the thread, with no timeout
            with thread.thread_wait(
                backuper.finished,
                timeout=None,
                finish_func=finish,
                failed_signal=backuper.failed,
                failed_func=failed,
                update_signal=backuper.activity_update,
            ):
                backuper.start()

        self.base_action(
            core,
            empty_check=True,
            empty_val=archive,
        )

        if succeeded:
            # open resulting directory
            question = question_dialogs.backup_success(self, archive)

            if question:
                # this will always be opening a folder and therefore is safe
                os.startfile(os.path.dirname(archive))  # nosec

    def refresh(self, first: bool = False, automated: bool = False) -> None:
        """Refreshes all mod data."""

        """This is not a separate thread, as the time it takes to parse each manifest
        is so low, that the GUI will easily stay responsive, even running in
        the foreground thread. I believe Windows gives applications around
        4 seconds to respond to incoming events before being marked as unresponsive,
        which should never happen in the process of parsing manifest.json files"""

        def core(progress: Callable) -> None:
            # temporarily clear search so that header resizing doesn't get borked
            self.search(override="")

            progress.set_mode(progress.PERCENT)

            def update(message: str, percent: int, total: int) -> None:
                progress.set_activity(message)
                progress.set_percent(percent, total)
                # make sure the progress bar gets updated.
                self.appctxt.app.processEvents()

            # clear mod cache if a human clicked the button
            if not automated:
                self.flight_sim.clear_mod_cache()

            # build list of mods
            all_mods_data, all_mods_errors = self.flight_sim.get_all_mods(
                progress_func=update
            )

            # set data
            self.main_table.set_data(all_mods_data, first=first)
            self.main_table.set_colors(self.parent.theme_menu_action.isChecked())

            # display errors
            if all_mods_errors:
                warning_dialogs.mod_parsing(self, all_mods_errors)

            # put the search back to how it was
            self.search()

        self.base_action(
            core,
            button=self.refresh_button,
            refresh=False,
        )

    # ======================
    # Child Widgets
    # ======================

    def info(self) -> None:
        """Open dialog to view mod info."""
        # self.info_button.setEnabled(False)

        selected = self.main_table.get_selected_rows()

        if not selected:
            return

        (folder, enabled) = self.main_table.get_basic_info(selected[0])
        mod_folder = self.flight_sim.get_mod_folder(folder, enabled)

        wid = info_widget(self.flight_sim, self, self.appctxt)
        wid.set_data(
            self.flight_sim.parse_mod_manifest(mod_folder),
            self.flight_sim.parse_mod_files(mod_folder),
        )
        wid.show()

        # self.info_button.setEnabled(True)

    def about(self) -> None:
        """Launch the about widget."""
        about_widget(self, self.appctxt).exec_()

    def versions(self) -> None:
        """Launch the versions widget."""
        versions_widget(self.flight_sim, self, self.appctxt).exec_()

    # ======================
    # Search
    # ======================

    def search(self, override: str = None) -> None:
        """Filter rows to match search term."""
        # strip
        term = self.search_field.text().strip()
        # override
        if override is not None:
            term = override

        # search
        self.main_table.search(term)

    def clear_search(self) -> None:
        """Clear the search field."""
        self.search_field.clear()


import math
import time

def func1(x):
    return x * math.exp(x)

def func2(x):
    return math.exp(x)

def func3(x):
    assert x <= 1
    x = math.exp(x) * math.sqrt(1 - math.pow(x, 2))
    return x

def func4(x):
    return math.pi / 4 * math.sin(math.pi / 4 + math.pi / 4 * x)

def gauss_ch1(func, n: int):
    result = 0.0
    for k in range(1, n + 1):
        new_x = math.cos(((2 * k - 1) / (2 * n)) * math.pi)
        result += func(new_x)
    result = result * math.pi / n
    return result

def gauss_ch2(func, n: int):
    result = 0.0
    for k in range(1, n + 1):
        new_x = math.cos((k * math.pi) / (n + 1))
        result += func(new_x) * math.pow(math.sin((k * math.pi) / (n + 1)), 2)
    result = result * math.pi / (n + 1)
    return result

def Tn(func, a: float, b: float, n=1):
    assert b >= a
    assert n == 1 or n % 2 == 0
    Ts = []
    h_n = (b - a) / 1
    s = func(a + 1 * h_n)
    # 计算T1
    T_n = h_n / 2 * (func(a) + func(b) + 2 * s)
    Ts.append(T_n)
    if n == 1:
        return Ts

    j = 1
    while j != n:
        s2 = 0.0
        for k in range(0, j):
            x_k = a + k * h_n
            x_k_pulus_1 = a + (k + 1) * h_n
            x_k_half = (x_k + x_k_pulus_1) / 2
            s2 += func(x_k_half)
        T_2n = T_n / 2 + h_n / 2 * s2

        # 更新数据
        T_n = T_2n
        h_n = h_n / 2
        j = j * 2
        Ts.append(T_n)
    return Ts

def com_trep(func, a: float, b: float):
    error = 5e-8
    assert b >= a
    n = 1
    h_n = (b - a) / n
    s = 0
    for k in range(1, n):
        x_k = a + k * h_n
        s += func(x_k)
    T_n = h_n / 2 * (func(a) + func(b) + 2 * s)

    flag = True
    while flag:
        s2 = 0.0
        for k in range(0, n):
            x_k = a + k * h_n
            x_k_pulus_1 = a + (k + 1) * h_n
            x_k_half = (x_k + x_k_pulus_1) / 2
            s2 += func(x_k_half)
        T_2n = T_n / 2 + h_n / 2 * s2
        if abs(T_2n - T_n) < 3 * error:
            flag = False

        T_n = T_2n
        h_n = h_n / 2
        n = n * 2
    return T_n

def romberg(func, a: float, b: float):
    n = 2**16
    Ts = Tn(func, a, b, n)
    Ss = []
    for k in range(len(Ts) - 1):
        Ss.append(4 / 3 * Ts[k + 1] - 1 / 3 * Ts[k])
    Cs = []
    for k in range(len(Ss) - 1):
        Cs.append(16 / 15 * Ss[k + 1] - 1 / 15 * Ss[k])
    Rs = []
    for k in range(len(Cs) - 1):
        Rs.append(16 / 15 * Cs[k + 1] - 1 / 15 * Cs[k])
    return Rs[-1]

def gauss_leg_9(func):
    xk_coff = [(0.9681602395, 0.0812743884), (0.8360311073, 0.1806481607),
               (0.6133714327, 0.2606106964), (0.3242534234, 0.3123470770),
               (0, 0.3302393550)]
    result = 0.0
    for k in range(len(xk_coff)):
        xk = xk_coff[k][0]
        Ak = xk_coff[k][1]
        if xk != 0:
            result += Ak * (func(xk) + func(-xk))
        else:
            result += Ak * (func(xk))

    return result

if __name__ == '__main__':
    begin_time = time.time()*1000
    r = gauss_ch1(func1, 15)
    end_time = time.time()*1000
    t = end_time - begin_time
    print(str(r)+'\t'+str(t))

    begin_time = time.time()*1000
    r = gauss_ch2(func2, 15)
    end_time = time.time()*1000
    t = end_time - begin_time
    print(str(r)+'\t'+str(t))

    begin_time = time.time()*1000
    r = com_trep(func3, -1, 1)
    end_time = time.time()*1000
    t = end_time - begin_time
    print(str(r)+'\t'+str(t))

    begin_time = time.time()*1000
    r = romberg(func3, -1, 1)
    end_time = time.time()*1000
    t = end_time - begin_time
    print(str(r)+'\t'+str(t))

    begin_time = time.time()*1000
    r = gauss_leg_9(func3)
    end_time = time.time()*1000
    t = end_time - begin_time
    print(str(r)+'\t'+str(t))

    print("======================================================")
    begin_time = time.time()*1000
    r = com_trep(math.sin, 0, math.pi/2)
    end_time = time.time()*1000
    t = end_time - begin_time
    print(str(r)+'\t'+str(t))

    begin_time = time.time()*1000
    r = romberg(math.sin, 0, math.pi/2)
    end_time = time.time()*1000
    t = end_time - begin_time
    print(str(r)+'\t'+str(t))

    begin_time = time.time()*1000
    r = gauss_leg_9(func4)
    end_time = time.time()*1000
    t = end_time - begin_time
    print(str(r)+'\t'+str(t))