import pandas as pd
import numpy as np
from io import StringIO
import math
import ast
import matplotlib.pyplot as plt
from wordcloud import WordCloud
import statistics
from sklearn import preprocessing
from sklearn.preprocessing import StandardScaler
from scipy import stats
import matplotlib.pyplot as plt
import ruptures as rpt

import plotly.express as px

# Famous Players
nba_1 = pd.read_csv("/Users/dannysimon/Documents/QARIK/OPUS/src/nba_kingjames.csv", index_col=[0])
nba_1 = nba_1.append(pd.read_csv("/Users/dannysimon/Documents/QARIK/OPUS/src/nba_damianlillard.csv", index_col=[0]), ignore_index = True)
nba_1 = nba_1.append(pd.read_csv("/Users/dannysimon/Documents/QARIK/OPUS/src/nba_giannis_an34_ygtrece.csv", index_col=[0]), ignore_index = True)
nba_1 = nba_1.append(pd.read_csv("/Users/dannysimon/Documents/QARIK/OPUS/src/nba_kyrieirving_EasyMoneySniper_jharden13_cp3_zo.csv", index_col=[0]), ignore_index = True)
nba_1 = nba_1.append(pd.read_csv("/Users/dannysimon/Documents/QARIK/OPUS/src/nba_stephencurry30_russwest44.csv", index_col=[0]), ignore_index = True)
nba_1 = nba_1.append(pd.read_csv("/Users/dannysimon/Documents/QARIK/OPUS/src/nba_new_players_jordan_poole_jokicnikolaofficial_melo.csv", index_col=[0]), ignore_index = True)
nba_1 = nba_1.append(pd.read_csv("/Users/dannysimon/Documents/QARIK/OPUS/src/nba_new_players_jamorant_anthony.csv", index_col=[0]), ignore_index = True)
nba_1['posts'] = [ast.literal_eval(x) for x in nba_1['posts']]
nba_final_df = nba_1

import plotly.express as px

def df_maker_1(df, ma, momentum, entity):
  df_entity_posts = df.loc[df.insta_handle == entity]['posts'].item()
  df_entity_posts.reverse()

  df_list = []
  df_nan_list = []
  df_nan_2_list = []

  value_list = []
  value_list_nan = []
  value_list_nan_2 = []

  momentum_value = 0
  momentum_value_nan = ma

  count = 0
  index_count = 1
  for post in df_entity_posts:
    _, values = zip(*post.items())
    if (values[0]['type'] == 'photo') and (values[0]['post_date'] > '2020-05-10'):  # 2020-04-20
      df_dict = {}
      try:
        value_list.append(values[0]['likes'])
        if count >= momentum:
          df_dict['momentum'] = values[0]['likes'] - value_list[momentum_value]
          momentum_value += 1
        else:
          df_dict['momentum'] = np.nan
        count += 1
        df_dict['index'] = index_count
        df_dict['insta_handle'] = entity
        df_dict['date'] = values[0]['post_date']
        df_dict['date_month'] = values[0]['post_date']
        df_dict['likes'] = values[0]['likes']
        df_list.append(df_dict)
      except:
        likes_got = statistics.mean(value_list)
        value_list.append(likes_got)
        if count >= momentum:
          df_dict['momentum'] = likes_got - value_list[momentum_value]
          momentum_value += 1
        else:
          df_dict['momentum'] = np.nan
        count += 1
        df_dict['insta_handle'] = entity
        df_dict['date'] = values[0]['post_date']
        df_dict['date_month'] = values[0]['post_date']
        df_dict['likes'] = likes_got
        df_list.append(df_dict)

  df_new = pd.DataFrame(df_list).sort_values(by=['date'])
  df_new['date'] = pd.to_datetime(df_new['date'])
  df_new['date_month'] = pd.to_datetime(df_new['date_month'])
  df_new = df_new.set_index('date')

  df_ma = df_new.copy()
  df_ma['likes'] = df_ma['likes'].rolling(window=ma, min_periods = 10).mean() #

  df_resample = df_new.copy()
  df_resample = df_resample.groupby('insta_handle').resample('D').mean().fillna(0)
  df_resample['likes'] = df_resample['likes'].rolling(window=ma).mean()
  df_resample = df_resample.reset_index()

  df_resample_nan = df_new.copy()
  df_resample_nan = df_resample_nan.groupby('insta_handle').resample('D').mean().fillna(0)
  # print(df_resample_nan.head(20))
  # df_resample_nan['likes'] = df_resample_nan['likes'].rolling(window=ma).mean()
  df_resample_nan = df_resample_nan.reset_index()

  count_nan = 0
  for index, row in df_resample_nan.iterrows():
    df_nan_dict = {}
    value_list_nan.append(row['likes'])

    df_nan_dict['date'] = row['date']
    df_nan_dict['insta_handle'] = entity
    if count_nan >= ma:
      df_nan_dict['likes'] = (np.nan if (sum(value_list_nan[-(ma+1):])) == 0 else (sum(value_list_nan[-(ma+1):]))) / ma
      df_nan_dict['likes_nan'] = (np.nan if sum(value_list_nan[-(ma+1):]) == 0 else sum(value_list_nan[-(ma+1):])) / (1 if (ma - value_list_nan[-(ma+1):].count(0)) == 0 else (ma - value_list_nan[-(ma+1):].count(0)))  # ma+1 or just ma
    else:
      df_nan_dict['likes'] = np.nan
      df_nan_dict['likes_nan'] = np.nan

    count_nan += 1
    df_nan_list.append(df_nan_dict)
  df_resample_nan_2 = pd.DataFrame(df_nan_list).sort_values(by=['date'])
  df_resample_nan_2['date'] = pd.to_datetime(df_resample_nan_2['date'])

  count_nan_2 = 0
  for index, row_2 in df_resample_nan_2.iterrows():
    df_nan_2_dict = {}
    value_list_nan_2.append(row_2['likes_nan'])

    df_nan_2_dict['date'] = row_2['date']
    df_nan_2_dict['insta_handle'] = entity
    df_nan_2_dict['likes'] = row_2['likes']
    df_nan_2_dict['likes_nan'] = row_2['likes_nan']
    if (count_nan_2 >= (momentum+ma)):
      if not math.isnan(value_list_nan_2[-(momentum+momentum+1)]):
        df_nan_2_dict['momentum_absolute'] = row_2['likes_nan'] - value_list_nan_2[-(momentum+momentum+1)]
        # print(entity, row_2['date']  ,row_2['likes_nan'], value_list_nan_2[-(momentum+momentum+1)])
        df_nan_2_dict['momentum_relative'] = (row_2['likes_nan'] - ((0 if ((math.isnan(value_list_nan_2[-(momentum+momentum+1)])) or (value_list_nan_2[-(momentum+momentum+1)] == 0))  else value_list_nan_2[-(momentum+momentum+1)]))) / ((1 if ((math.isnan(value_list_nan_2[-(momentum+momentum+1)])) or (value_list_nan_2[-(momentum+momentum+1)] == 0))  else value_list_nan_2[-(momentum+momentum+1)]))
        momentum_value_nan += 1
    else:
      df_nan_2_dict['momentum_absolute'] = np.nan
      df_nan_2_dict['momentum_relative'] = np.nan

    count_nan_2 += 1
    value_list_nan_2.append(row_2['likes_nan'])
    df_nan_2_list.append(df_nan_2_dict)
  df_resample_nan_3 = pd.DataFrame(df_nan_2_list).sort_values(by=['date'])
  df_resample_nan_3['date'] = pd.to_datetime(df_resample_nan_3['date'])

  df_grouped = df_new.groupby([(df_new.date_month.dt.year), (df_new.date_month.dt.month)]).agg('count')

  return df_new, df_ma, df_resample, df_resample_nan_2, df_resample_nan_3, df_grouped

def plot_maker_1(df, ma, momentum, entity = False):
  if entity:
    df_new, df_ma, df_resample, df_resample_nan_2, df_resample_nan_3, df_grouped = df_maker_1(df, ma, momentum, entity)

    fig_1 = px.line(df_new, x=df_new.index, y="likes", title='Instagram Post Likes VS Date')
    fig_1.show()

    fig_2 = px.line(df_ma, x=df_ma.index, y="likes", title='Instagram Post Likes VS Date (RMA - post focused)')
    fig_2.show()

    fig_3 = px.line(df_resample, x='date', y="likes", title='Instagram Post Likes VS Date (RMA - Time focused)')
    fig_3.show()

    fig_4 = px.line(df_ma, x='date_month', y="momentum", title='Instagram Post Likes VS Date (momentum - post focused)')
    fig_4.show()

    fig_4_b = px.line(df_resample, x='date', y="momentum", title='Instagram Post Likes VS Date (momentum - Time focused)')
    fig_4_b.show()

    fig_5 = px.line(df_resample_nan_2, x='date', y="likes_nan", title='Instagram Post Likes VS Date (RMA - considers nan, Time period focused)')
    fig_5.show()

    fig_6 = px.histogram(df_ma, x="date_month", y="likes",
             color='insta_handle', barmode='group', title='Month-Wise Total Like received',
             height=400)
    fig_6.show()

    fig_7 = px.line(df_resample_nan_3, x='date', y="momentum_absolute", title='Instagram Post Likes VS Date (Absolute Momentum)')
    fig_7.show()

    fig_8 = px.line(df_resample_nan_3, x='date', y="momentum_relative", title='Instagram Post Likes VS Date (Relative Momentum)')
    fig_8.show()

  else:
    df_new, df_ma, df_resample, df_resample_nan_2, df_resample_nan_3, df_grouped = df_maker_1(df, ma, momentum, 'kingjames') # change entity? jordan_poole. kingjames
    entities = df.insta_handle.unique()
    for entity in entities[1:]:
        df_new_e, df_ma_e, df_resample_e, df_resample_nan_2_e, df_resample_nan_3_e, df_grouped_e = df_maker_1(df, ma, momentum, entity)
        df_new = df_new.append(df_new_e)
        df_ma = df_ma.append(df_ma_e)
        df_resample = df_resample.append(df_resample_e)
        df_resample_nan_2 = df_resample_nan_2.append(df_resample_nan_2_e)
        df_resample_nan_3 = df_resample_nan_3.append(df_resample_nan_3_e)
        df_grouped = df_grouped.append(df_resample_e)
    fig_1 = px.line(df_new, x='date_month', y='likes', color = 'insta_handle',
                  hover_data={"date_month": "|%B %d, %Y"},
                  title='Instagram Post Likes VS Date')
    fig_1.update_xaxes(
        dtick="M1",
        tickformat="%b\n%Y")
    fig_1.show()

    fig_2 = px.line(df_ma, x='date_month', y='likes', color = 'insta_handle',
                  hover_data={"date_month": "|%B %d, %Y"},
                  title='Instagram Post Likes VS Date (RMA - post focused)')
    fig_2.update_xaxes(
        dtick="M1",
        tickformat="%b\n%Y")
    fig_2.show()

    fig_3 = px.line(df_resample, x='date', y='likes', color = 'insta_handle',
                  hover_data={"date": "|%B %d, %Y"},
                  title='Instagram Post Likes VS Date (RMA - Time period focused)')
    fig_3.update_xaxes(
        dtick="M1",
        tickformat="%b\n%Y")
    fig_3.show()

    fig_4 = px.line(df_ma, x='date_month', y='momentum', color = 'insta_handle',
                  hover_data={"date_month": "|%B %d, %Y"},
                  title='Instagram Post Likes VS Date (momentum - post focused)')
    fig_4.update_xaxes(
        dtick="M1",
        tickformat="%b\n%Y")
    fig_4.show()

    fig_4_b = px.line(df_resample, x='date', y='momentum', color = 'insta_handle',
                  hover_data={"date": "|%B %d, %Y"},
                  title='Instagram Post Likes VS Date (momentum - Time focused)')
    fig_4_b.update_xaxes(
        dtick="M1",
        tickformat="%b\n%Y")
    fig_4_b.show()

    fig_5 = px.line(df_resample_nan_2, x='date', y='likes_nan', color = 'insta_handle',
                  hover_data={"date": "|%B %d, %Y"},
                  title='Instagram Post Likes VS Date (RMA - considers nan, Time focused)')
    fig_5.update_xaxes(
        dtick="M1",
        tickformat="%b\n%Y")
    fig_5.show()

    fig_6 = px.histogram(df_ma, x="date_month", y="likes",
             color='insta_handle', barmode='group',
             title='Month-Wise Total Like received',
             height=400)
    fig_6.show()

    fig_7 = px.line(df_resample_nan_3, x='date', y='momentum_absolute', color = 'insta_handle',
              hover_data={"date": "|%B %d, %Y"},
              title='Instagram Post Likes VS Date ((Absolute Momentum))')
    fig_7.update_xaxes(
        dtick="M1",
        tickformat="%b\n%Y")
    fig_7.show()

    fig_8 = px.line(df_resample_nan_3, x='date', y='momentum_relative', color = 'insta_handle',
              hover_data={"date": "|%B %d, %Y"},
              title='Instagram Post Likes VS Date ((Relative Momentum))')
    fig_8.update_xaxes(
        dtick="M1",
        tickformat="%b\n%Y")
    fig_8.show()

    import pandas as pd
    import plotly.graph_objects as go
    from plotly.offline import iplot
    from plotly.subplots import make_subplots

    for entity_x in df_resample_nan_2.insta_handle.unique().tolist():
      df_resample_nan_2_entity =  df_resample_nan_2.loc[df_resample_nan_2.insta_handle == entity_x]
      df_resample_nan_3_entity =  df_resample_nan_3.loc[df_resample_nan_3.insta_handle == entity_x]
      # dict for the dataframes and their names
      dfs = {"Moving Average" : df_resample_nan_2_entity, "Relative Momentum": df_resample_nan_3_entity}

      # plot the data
      fig = go.Figure()
      fig = make_subplots(specs=[[{"secondary_y": True}]])

      for i in dfs:
        if i == 'Moving Average':
          fig.add_trace(go.Scatter(x = dfs[i]["date"],
                                        y = dfs[i]["likes_nan"],
                                        name = i), secondary_y=False)
        elif i == 'Relative Momentum':
          fig.add_trace(go.Scatter(x = dfs[i]["date"],
                                        y = dfs[i]["momentum_relative"],
                                        name = i), secondary_y=True)
      # Add figure title
      fig.update_layout(
          title_text=f"{entity_x}"
      )

      # Set x-axis title
      fig.update_xaxes(title_text="xaxis title")

      # Set y-axes titles
      fig.update_yaxes(title_text= f"Rolling Moving Average ({ma} Days)", secondary_y=False)
      fig.update_yaxes(title_text= f"Relative Momentum ({momentum} frame)", secondary_y=True)

      fig.show()
      try:
        points=np.array(dfs[i]["likes_nan"])
        #Changepoint detection with window-based search method
        model = "l2"
        algo = rpt.Window(width=40, model=model).fit(points)
        my_bkps = algo.predict(n_bkps=10)
        rpt.show.display(points, my_bkps, figsize=(40, 7))
        plt.title('Change Point Detection: Window-Based Search Method')
        plt.show()

        points=np.array(df_new.loc[df_new.insta_handle==entity_x]["likes"])
        #Changepoint detection with window-based search method
        model = "l2"
        algo = rpt.Window(width=40, model=model).fit(points)
        my_bkps = algo.predict(n_bkps=10)
        rpt.show.display(points, my_bkps, figsize=(40, 7))
        plt.title('Change Point Detection: Window-Based Search Method')
        plt.show()
      except:
        pass
    print(entities)

    return df_resample_nan_3

momentum_frame = 30
rolling_movinge_average_frame = 90
# nba_final_df = pd.read_csv("/Users/dannysimon/Documents/QARIK/OPUS/src/nba_final_df.csv")
#Give a instahandle id in entity to see player focused plots, else keep it as false
entity = False
# entity = 'kingjames'

# Run this function
# Give Entity a insta handle value to plot individually
momentum_df_1 = plot_maker_1(nba_final_df, rolling_movinge_average_frame, momentum_frame,entity)
sdbadsb


import pytest

from oilanalytics.highfreq import ara, singapore

@pytest.mark.skip("Eikon required")
def test_ara_data():
    res = ara.ara_data(start_date="2022-01-01")
    assert "Jet" in res.columns
    assert res["Jet"].loc["2022-01-06"] == pytest.approx(7.06, 0.01)
    # Note freq might not be consistent across time, so this won't be true across history
    # self.assertEqual(pd.infer_freq(res.index), 'W-THU')

@pytest.mark.skip("Eikon required")
def test_sing_data():
    res = singapore.singapore_data(start_date="2022-01-01")
    assert "LightDistillates" in res.columns


"""Test configuration"""
import os
import shutil

import nmigen.sim
import pytest

VCD_TOP_DIR = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        "tests",
        "vcd")

def vcd_path(node):
    directory = os.path.join(VCD_TOP_DIR, node.fspath.basename.split(".")[0])
    os.makedirs(directory, exist_ok=True)
    return os.path.join(directory, node.name + ".vcd")

@pytest.fixture(scope="session", autouse=True)
def clear_vcd_directory():
    shutil.rmtree(VCD_TOP_DIR, ignore_errors=True)

@pytest.fixture
def comb_sim(request):

    def run(fragment, process):
        sim = nmigen.sim.Simulator(fragment)
        sim.add_process(process)
        with sim.write_vcd(vcd_path(request.node)):
            sim.run_until(100e-6)

    return run

@pytest.fixture
def sync_sim(request):

    def run(fragment, process):
        sim = nmigen.sim.Simulator(fragment)
        sim.add_sync_process(process)
        sim.add_clock(1 / 10e6)
        with sim.write_vcd(vcd_path(request.node)):
            sim.run()

    return run


#first import the logo and print it
from art import logo,vs
import random
from replit import clear
from game_data import data
print(logo)
decision =0
score=0
#print(f"You are {decision}, your current score is {score}")

def format_data(random_choice):
  """ format name in printable form"""
  random_choice_Name = random_choice["name"]
  random_choice_Description = random_choice["description"]
  random_choice_Country = random_choice["country"]

  return f"{random_choice_Name}, a {random_choice_Description}, from {random_choice_Country}"

def check_Answer(answer,Follower_CountA,Follower_CountB):
  """Takes the user answer and follower count and returns if the user guessed it correctly or not"""
  if Follower_CountA > Follower_CountB:
    if(answer == 'a'):
      return True
    else:
      return False
  else:
    if(answer =='b'):
      return True
    else:
      return False

game_should_continue = True
random_choiceB = random.choice(data)
#do this stuff repeatidly until the user get's wrong answer
while game_should_continue:

  #generate a random number

  random_choiceA = random_choiceB
  random_choiceB = random.choice(data)
  if random_choiceA == random_choiceB:
    random_choiceB = random.choice(data)

  print(f"Compare A: {format_data(random_choiceA)}")

  #print vs
  print(vs)

  print(f"Compare B: {format_data(random_choiceB)} ")

  #Ask user for a guessA

  answer = input("Who has more followers. A or B. Type 'A' or 'B'\n").lower()

  #Check if the user is right or wrong
  #get follower count of each account
  Follower_CountA = random_choiceA["follower_count"]
  Follower_CountB = random_choiceB["follower_count"]

  is_correct = check_Answer(answer,Follower_CountA,Follower_CountB)
  #Clear the screen
  clear()
  print(logo)
  # Give user feedback on their guess
  if is_correct:
    score = score+1
    print(f"You are right, Your current score is :{score}")

  else:
    print(f"Sorry! that's worng, your final score is: {score}")
    game_should_continue = False


import sys
import time
import requests
from urllib.error import URLError
from json.decoder import JSONDecodeError
from http.client import RemoteDisconnected
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from django.conf import settings
from tecqii.models import User

class Crawler():

    def __init__(self):
        self.driver = webdriver.PhantomJS(settings.PHANTOMJS_PATH)  # VPS用
        self.driver.set_window_size(1400, 1000)
        self.driver.implicitly_wait(10)

    def tear_down(self):
        self.driver.close()

    def crawl_qiita_user_ranking(self, page):
        QIITA_USER_RANKING_URL = 'https://qiita-user-ranking.herokuapp.com/'
        try:
            print('page: ',page,' --------------')
            self.driver.get(QIITA_USER_RANKING_URL+'?page='+str(page))
            element = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, '/html/body/main/h2')))
            user_ids = self.driver.find_elements_by_xpath('/html/body/main/p[4<position()<24]/a')
            for user_id in user_ids:
                print(user_id.text.strip())
                User.objects.update_or_create(
                    user_id=user_id.text.strip(),
                )
        except TimeoutException:
            print('loading took too much time')
            return False

    # calls the internal api
    def crawl_qiita_users(self, char='A', page=1):
        QIITA_USERS_URL = 'https://qiita.com/users'
        QIITA_INTERNALAPI_HOVERCARD = 'https://qiita.com/api/internal/hovercard_users/'
        try:
            print('char: ', char, 'page: ', page)
            self.driver.get(QIITA_USERS_URL + '?char=' + char + '&page=' + str(page))
            WebDriverWait(self.driver, 30).until(EC.presence_of_element_located((By.XPATH, '//*[@id="main"]/div/div/div[1]/h2')))
        except TimeoutException:
            print('loading took too much time')
        else:
            user_ids = self.driver.find_elements_by_xpath('//*[@id="main"]/div/div/div[2]/div[*]/div/div/p[1]/a')
            for user_id in user_ids:
                try:
                    hover_card = requests.request('GET', QIITA_INTERNALAPI_HOVERCARD+user_id.text.strip()) # using internal api.
                    hover_card_json = hover_card.json()
                    user = User.objects.update_or_create(
                        user_id=user_id.text.strip(),
                        defaults={
                            'items_count': hover_card_json['articles_count'],
                            'contribution_count': int(hover_card_json['contribution']),
                            'permanent_id': int(hover_card_json['id']),
                            'name': hover_card_json['name'],
                            'profile_image_url': hover_card_json['profile_image_url']
                        }
                    )
                except JSONDecodeError:
                    user = User.objects.update_or_create(
                        user_id=user_id.text.strip(),
                    )
                    print(user, ' JSONDecodeError')
                except RemoteDisconnected:
                    print('RemoteDisconnected. will wait 1 minute.')
                    break
                except URLError:
                    print('URLError. will wait 1 minute.')
                    break
            try:
                self.driver.find_element_by_xpath('//*[@id="main"]/div/div/div[2]/div[101]/ul/li[2]/a')
            except NoSuchElementException:
                print('no next button, will switch to next char.')
                return False
            except:
                print(sys.exc_info()[1])
            else:
                return True

    # not calling the internal api
    def crawl_qiita_users_light(self, char='A', page=1):
        QIITA_USERS_URL = 'https://qiita.com/users'
        try:
            print('char: ', char, 'page: ', page)
            self.driver.get(QIITA_USERS_URL + '?char=' + char + '&page=' + str(page))
            WebDriverWait(self.driver, 30).until(EC.presence_of_element_located((By.XPATH, '//*[@id="main"]/div/div/div[1]/h2')))
        except TimeoutException:
            print('loading took too much time')
        else:
            time.sleep(1)
            user_ids = self.driver.find_elements_by_xpath('//*[@id="main"]/div/div/div[2]/div[*]/div/div/p[1]/a')
            for user_id in user_ids:
                user = User.objects.update_or_create(
                    user_id=user_id.text.strip()
                )
            try:
                self.driver.find_element_by_xpath('//*[@id="main"]/div/div/div[2]/div[101]/ul/li[2]/a')
            except NoSuchElementException:
                print('no next button, will switch to next char.')
                return False
            except:
                print(sys.exc_info()[1])
            else:
                return True

    def crawl_qiita_user(self, user_id):
        QIITA_URL = 'https://qiita.com/'
        try:
            print('user_id: ',user_id)
            self.driver.get(QIITA_URL + user_id)
            WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#main > div > div > div.col-md-3.col-sm-3.col-xs-12.newUserPageProfile > div.newUserPageProfile_avatar > img')))
        except TimeoutException:
            print('loading took too much time')
        except NoSuchElementException: # Consider the user no longer exists.
            deleted_user = User.objects.get(user_id=user_id)
            deleted_user.delete()
        else:
            try:
                description = self.driver.find_element_by_class_name('newUserPageProfile_description')
                description = description.text
            except NoSuchElementException:
                description = ''
            try:
                facebook_id = self.driver.find_element_by_css_selector(
                    '#main > div > div > div.col-md-3.col-sm-3.col-xs-12.newUserPageProfile > div.newUserPageProfile_header > ul > li.newUserPageProfile_socialLink-facebook > a')
                facebook_id = facebook_id.get_attribute('href')
                facebook_id = facebook_id.replace('https://facebook.com/', '')
            except NoSuchElementException:
                facebook_id = ''
            try:
                followees_count = self.driver.find_elements_by_class_name('userActivityChart_statCount')[2]
                followees_count = int(followees_count.text)
            except NoSuchElementException:
                followees_count = 0
            try:
                followers_count = self.driver.find_element_by_css_selector('#main > div > div > div.col-md-3.col-sm-3.col-xs-12.newUserPageProfile > div:nth-child(6) > div.newUserPageProfile_info_heading > span > a')
                followers_count = followers_count.text
            except NoSuchElementException:
                followers_count = 0
            try:
                github_login_name = self.driver.find_element_by_css_selector('#main > div > div > div.col-md-3.col-sm-3.col-xs-12.newUserPageProfile > div.newUserPageProfile_header > ul > li.newUserPageProfile_socialLink-github > a')
                github_login_name = github_login_name.get_attribute('href')
                github_login_name = github_login_name.replace('https://github.com/', '')
            except NoSuchElementException:
                github_login_name = ''
            try:
                items_count = self.driver.find_elements_by_class_name('userActivityChart_statCount')[0]
                items_count = int(items_count.text)
            except NoSuchElementException:
                items_count = 0
            try:
                linkedin_id = self.driver.find_element_by_css_selector('#main > div > div > div.col-md-3.col-sm-3.col-xs-12.newUserPageProfile > div.newUserPageProfile_header > ul > li.newUserPageProfile_socialLink-linkedin > a')
                linkedin_id = linkedin_id.get_attribute('href')
                linkedin_id = linkedin_id.replace('https://www.linkedin.com/in/','')
            except NoSuchElementException:
                linkedin_id = ''
            try:
                location = self.driver.find_element_by_css_selector('#main > div > div > div.col-md-3.col-sm-3.col-xs-12.newUserPageProfile > div:nth-child(3) > div:nth-child(4)')
                location = location.text
            except NoSuchElementException:
                location = ''
            try:
                name = self.driver.find_element_by_class_name('newUserPageProfile_fullName')
                name = name.text
            except NoSuchElementException:
                name = ''
            try:
                organization = self.driver.find_element_by_css_selector('#main > div > div > div.col-md-3.col-sm-3.col-xs-12.newUserPageProfile > div:nth-child(3) > div:nth-child(3)')
                organization = organization.text
            except NoSuchElementException:
                organization = ''
            try:
                profile_image_url = self.driver.find_element_by_css_selector('#main > div > div > div.col-md-3.col-sm-3.col-xs-12.newUserPageProfile > div.newUserPageProfile_avatar > img')
                profile_image_url = profile_image_url.get_attribute('src')
            except NoSuchElementException:
                profile_image_url = ''
            try:
                twitter_screen_name = self.driver.find_element_by_css_selector('#main > div > div > div.col-md-3.col-sm-3.col-xs-12.newUserPageProfile > div.newUserPageProfile_header > ul > li.newUserPageProfile_socialLink-twitter > a')
                twitter_screen_name = twitter_screen_name.get_attribute('href')
                twitter_screen_name = twitter_screen_name.replace('https://twitter.com/','')
            except NoSuchElementException:
                twitter_screen_name = ''
            try:
                website_url = self.driver.find_element_by_css_selector('#main > div > div > div.col-md-3.col-sm-3.col-xs-12.newUserPageProfile > div:nth-child(3) > div:nth-child(2) > a')
                website_url = website_url.get_attribute('href')
            except NoSuchElementException:
                website_url = ''
            try:
                contribution_count = self.driver.find_elements_by_class_name('userActivityChart_statCount')[1]
                contribution_count = contribution_count.text
            except NoSuchElementException:
                contribution_count = 0

            User.objects.update_or_create(
                user_id=user_id,
                defaults={
                    'description': description,
                    'facebook_id': facebook_id,
                    'followees_count': followees_count,
                    'followers_count': followers_count,
                    'github_login_name': github_login_name,
                    'items_count': items_count,
                    'linkedin_id': linkedin_id,
                    'location': location,
                    'name': name,
                    'organization': organization,
                    'profile_image_url': profile_image_url,
                    'twitter_screen_name': twitter_screen_name,
                    'website_url': website_url,
                    'contribution_count': contribution_count,
                }
            )


import xlrd  # xlrd库
from django.db import transaction  # 数据库事物
from competition.models import ChoiceInfo, FillInBlankInfo, Subject, QuestionGroupInfo  # 题目数据模型
from django.db.models import Q

def check_vals(val):  # 检查值是否被转换成float，如果是，将.0结尾去掉
    val = str(val)
    if val.endswith('.0'):
        val = val[:-2]
    return val

def check_subject_vals(val):  # 匹配科目类型，是否需要匹配科室？
    val = check_vals(val)
    try:
        subject = Subject.objects.filter(Q(subject_name=val) | Q(subject_name_abb=val)).first()
    except Subject.DoesNotExist:
        return 0
    # print(val)
    return subject.id

@transaction.atomic
def upload_questions(file_path=None, bank_info=None):
    book = xlrd.open_workbook(file_path)  # 读取文件
    table = book.sheets()[0]  # 获取第一张表
    nrows = table.nrows  # 获取行数
    A1_choice_num = 0  # 选择题数量
    A2_choice_num = 0  # 选择题数量
    A3_choice_num = 0  # 选择题数量
    B_choice_num = 0  # 选择题数量
    G_fillinblank_num = 0  # 填空题数量
    for i in range(1, nrows):
        rvalues = table.row_values(i)  # 获取行中的值
        if (not rvalues[0]) or rvalues[0].startswith('说明'):  # 取出多余行
            break

        subjectId=check_subject_vals(rvalues[0])
        if 0 == subjectId:
            return "subject not found", "subject not found"

        if '##' in rvalues[0]:  # 选择题 如果已经存在完全相同的题就不创建
            FillInBlankInfo.objects.select_for_update().create(
                bank_id=bank_info.bank_id,
                subject_id=subjectId,
                question=check_vals(rvalues[1]),
                answer=check_vals(rvalues[2]),
                # image_url=rvalues[4],
                source=rvalues[5]
            )
            G_fillinblank_num += 1  # 填空题数加1
        else:  # 填空题 如果已经存在完全相同的题就不创建
            tcode = check_vals(rvalues[1])
            codeArr = tcode.split("-")
            # print(tcode)
            if 1 == len(codeArr):
                ctype = tcode
                if "A1" == ctype:
                    A1_choice_num += 1
                    ctype = 1
                elif "A2" == ctype:
                    A2_choice_num += 1
                    ctype = 2

                question_group_order=0
                question_group_id=0

            elif 3 == len(codeArr):
                group_question_code = codeArr[0] + "_" + codeArr[1] + "_" + bank_info.bank_id
                question_group_order=codeArr[2]
                group_question_txt=check_vals(rvalues[2])

                oldQuestionGroupInfo = QuestionGroupInfo.objects.filter(group_question_code=group_question_code).first()
                if oldQuestionGroupInfo:
                    question_group_id=oldQuestionGroupInfo.id
                    oldQuestionGroupInfo.group_question_count += 1
                    oldQuestionGroupInfo.save()
                else:
                    if "A3" == codeArr[0]:
                        question_group_type = 1
                        ctype = 3
                        A3_choice_num += 1
                    elif "B" == codeArr[0]:
                        question_group_type = 2
                        B_choice_num += 1
                        ctype = 4
                    newQuestionGroupInfo = QuestionGroupInfo.objects.select_for_update().create(
                        question_group_type=question_group_type,
                        bank_id=bank_info.bank_id,
                        group_question_code=group_question_code,
                        group_question_txt=group_question_txt,
                        group_question_count=1,
                        )
                    question_group_id=newQuestionGroupInfo.id

            ChoiceInfo.objects.select_for_update().create(
                bank_id=bank_info.bank_id,
                subject_id=subjectId,
                ctype=ctype,
                question=check_vals(rvalues[4]),
                answer=check_vals(rvalues[6]),
                select_items=check_vals(rvalues[7]),
                source=check_vals(rvalues[3]),

                expound=check_vals(rvalues[8]),
                question_group_id= question_group_id,
                question_group_order=question_group_order,
                # image_url='',
            )
    bank_info.A1_choice_num = A1_choice_num
    bank_info.A2_choice_num = A2_choice_num
    bank_info.A3_choice_num = A3_choice_num
    bank_info.B_choice_num = B_choice_num
    bank_info.G_fillinblank_num = G_fillinblank_num
    bank_info.save()
    # print(A1_choice_num)
    # print(A2_choice_num)
    # print(A3_choice_num)
    # print(B_choice_num)
    return A1_choice_num, A2_choice_num, A3_choice_num, B_choice_num, G_fillinblank_num


import numpy as np
import matplotlib.pyplot as plt

def main():
    x = np.array(
        [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0])
    p = np.array(
        [0.0, 0.41, 0.79, 1.13, 1.46, 1.76, 2.04, 2.3, 2.55, 2.79, 3.01])
    k = 9
    m = 4.5
    y = np.zeros(len(x))
    for i in range(len(x)):
        y[i] = p[i] + ((-1) ** 9) * 4.5

    lagrange_poly = lagrange(x, y)
    newton_poly = newton(x, y)
    best_poly = np.poly1d(np.polyfit(x, y, 10))
    print_res(lagrange_poly, newton_poly, best_poly, x, y)

    print("Test 1")
    x = np.array(
        [-1.5, -0.75, 0, 0.75, 1.5]
    )
    y = np.array(
        [-14.1014, -0.931596, 0, 0.931596, 14.1014]
    )
    lagrange_poly = lagrange(x, y)
    newton_poly = newton(x, y)
    best_poly = np.poly1d(np.polyfit(x, y, 3))
    print_res(lagrange_poly, newton_poly, best_poly, x, y)

    print("Test 2")
    x = np.arange(0.1, 2.1, 0.1)
    y = np.zeros(len(x))
    for i in range(len(x)):
        y[i] = 1 / x[i]
    lagrange_poly = lagrange(x, y)
    newton_poly = newton(x, y)
    print_res(lagrange_poly, newton_poly, best_poly, x, y)

    print("Test 3")
    x3 = np.arange(0.0, 9.1, 0.5)
    y3 = np.zeros(len(x3))
    for i in range(len(x3)):
        y3[i] = x3[i] ** (1/2)
    lagrange_poly = lagrange(x3, y3)
    newton_poly = newton(x3, y3)
    print_res(lagrange_poly, newton_poly, best_poly, x3, y3)

def print_res(lagrange_poly, newton_poly, best_poly, x, y):
    print("Многочлен Лагранжа")
    print(lagrange_poly)
    print("\nМногочлен Ньютона")
    print(newton_poly)
    print("\nМногочлен наилучшего приближения")
    print(best_poly)
    print("\nЗначение в точке 0.47(многочлен Ньютона):")
    print(lagrange_poly(0.47))
    print("Значение в точке 0.47(многочлен Лагранжа):")
    print(newton_poly(0.47))
    print("Значение в точке 0.47(многочлен наилучшего приближения):")
    print(best_poly(0.47))
    y_plot = lagrange_poly(x)
    plt.plot(x, y, 'o', x, y_plot)
    plt.grid(True)
    plt.show()

def lagrange(x_values, y_values):
    res_poly = np.poly1d(0)

    for j in range(len(y_values)):
        poly = np.poly1d(1)
        for i in range(len(x_values)):
            if i != j:
                poly = np.polymul(poly, np.poly1d([x_values[i]], True) / (
                x_values[j] - x_values[i]))
        res_poly = np.polyadd(res_poly, y_values[j] * poly)
    return res_poly

def newton(x_values, y_values):
    res_poly = np.poly1d(0)
    x = x_values.copy()
    y = y_values.copy()
    for i in range(1, len(x)):
        y[i:len(x)] = (y[i:len(x)] - y[i - 1]) / (x[i:len(x)] - x[i - 1])
    for i in range(len(y)):
        poly = np.poly1d(1)
        for j in range(i):
            poly *= np.poly1d([x[j]], True)
        poly *= y[i]
        res_poly += poly
    return res_poly

if __name__ == '__main__':
    main()


import time
import pytest
from pages.profile_page import ProfilePage
from tests.test_login_page import test_go_to_login

@pytest.mark.smoke
@pytest.mark.regression
def test_go_to_quit_button(browser):
    test_go_to_login(browser)
    link = 'http://34.141.58.52:8080/#/profile'
    page = ProfilePage(browser, link)
    page.open()
    page.go_to_quit_button()
    browser.save_screenshot('quit_btn_screen.png')

@pytest.mark.regression
def test_go_to_edit_pet_profile(browser):
    test_go_to_login(browser)
    link = 'http://34.141.58.52:8080/#/profile'
    page = ProfilePage(browser, link)
    page.open()
    page.go_to_edit_pet_profile()
    browser.save_screenshot('edit_profile_screen.png')

@pytest.mark.smoke
@pytest.mark.regression
def test_go_to_add_pet(browser):
    test_go_to_login(browser)
    link = 'http://34.141.58.52:8080/#/profile'
    page = ProfilePage(browser, link)
    page.open()
    page.go_to_add_pet_btn()
    page.go_to_add_new_name()
    page.go_to_add_new_age()
    page.choose_new_pet_type()
    page.choose_new_pet_type_dog()
    page.choose_new_pet_gender()
    page.choose_new_pet_gender_male()
    page.go_to_submit_add_pet_btn()
    page.open()
    time.sleep(2)
    browser.save_screenshot('add_pet_screen.png')


# %% importing libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression

# %% dataset
data = pd.read_csv('Salary_Data.csv')
data
# %% separating data variables
x = data.iloc[:, 0].values
y = data.iloc[:, 1].values

x = x.reshape(-1,1)
y = y.reshape(-1,1)
# %% dataset division
training_x, test_x, training_y, test_y = train_test_split(x, y, test_size=0.3, random_state=0)
len(training_x)

# %% testing

lin = LinearRegression()
lin.fit(training_x, training_y)

# %% prediction

pred_y = lin.predict(test_x)

# %% comparing values

print(test_y[4])
print(pred_y[4])

# %% ploting values

plt.scatter(training_x, training_y, color='red')
plt.plot(training_x, lin.predict(training_x), color='orange')
plt.title('training data')
plt.ylabel('salary')
plt.xlabel('exp')
plt.show()

plt.scatter(test_x, test_y, color='blue')
plt.plot(test_x, pred_y)
plt.title('testing data')
plt.ylabel('salary')
plt.xlabel('exp')
plt.show()

# %% equation verification

# equation :- y = mx + c

print(lin.coef_)
print(lin.intercept_)
print(lin.coef_*10.3 + lin.intercept_)
print(data)


import csv
import json
import xml.etree.ElementTree as ET
from inventory_report.reports.simple_report import SimpleReport
from inventory_report.reports.complete_report import CompleteReport

class Inventory:
    @classmethod
    def import_data(cls, path_to_file: str, report_type: str) -> str:
        with open(path_to_file, mode="r") as data:
            products = Inventory.get_products_from_file(path_to_file, data)

            if report_type == 'simples':
                return SimpleReport.generate(products)

            return CompleteReport.generate(products)

    @classmethod
    def get_products_from_file(cls, path_to_file: str, data) -> list:
        if path_to_file.endswith('.csv'):
            products = list(csv.DictReader(data))
        elif path_to_file.endswith('.json'):
            products = json.load(data)
        else:
            tree = ET.parse(data)
            root = tree.getroot()
            records = [child for child in root]
            products = []
            for record in records:
                product = {}
                for child in record:
                    product[child.tag] = child.text
                products.append(product)

        return products


from lxml import etree

from zeep.xsd import Schema

def test_parse_response():
    schema_node = etree.fromstring(
        b"""
        <?xml version="1.0"?>
        <wsdl:definitions
            xmlns="http://www.w3.org/2001/XMLSchema"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:tns="http://tests.python-zeep.org/">
          <wsdl:types>
            <schema targetNamespace="http://tests.python-zeep.org/"
                xmlns:tns="http://tests.python-zeep.org/"
                elementFormDefault="qualified">
              <complexType name="Item">
                <sequence>
                  <element minOccurs="0" maxOccurs="1" name="Key" type="string" />
                  <element minOccurs="1" maxOccurs="1" name="Value" type="int" />
                </sequence>
              </complexType>
              <complexType name="ArrayOfItems">
                <sequence>
                  <element minOccurs="0" maxOccurs="unbounded" name="Item" nillable="true" type="tns:Item" />
                </sequence>
              </complexType>
              <complexType name="ZeepExampleResult">
                <sequence>
                  <element minOccurs="1" maxOccurs="1" name="SomeValue" type="int" />
                  <element minOccurs="0" maxOccurs="1" name="Results"
                    type="tns:ArrayOfItems" />
                </sequence>
              </complexType>
              <element name="ZeepExampleResponse">
                <complexType>
                  <sequence>
                    <element minOccurs="0" maxOccurs="1" name="ZeepExampleResult" type="tns:ZeepExampleResult" />
                  </sequence>
                </complexType>
              </element>
            </schema>
          </wsdl:types>
        </wsdl:definitions>
    """.strip()
    )  # noqa

    response_node = etree.fromstring(
        b"""
        <?xml version="1.0" encoding="utf-8"?>
        <soap:Envelope
            xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <soap:Body>
            <ZeepExampleResponse xmlns="http://tests.python-zeep.org/">
              <ZeepExampleResult>
                <SomeValue>45313</SomeValue>
                <Results>
                  <Item>
                    <Key>ABC100</Key>
                    <Value>10</Value>
                  </Item>
                  <Item>
                    <Key>ABC200</Key>
                    <Value>20</Value>
                  </Item>
                </Results>
              </ZeepExampleResult>
            </ZeepExampleResponse>
          </soap:Body>
        </soap:Envelope>
    """.strip()
    )
    schema = Schema(schema_node.find("*/{http://www.w3.org/2001/XMLSchema}schema"))
    assert schema
    response_type = schema.get_element(
        "{http://tests.python-zeep.org/}ZeepExampleResponse"
    )

    nsmap = {
        "soap": "http://schemas.xmlsoap.org/soap/envelope/",
        "tns": "http://tests.python-zeep.org/",
    }
    node = response_node.find("soap:Body/tns:ZeepExampleResponse", namespaces=nsmap)
    assert node is not None
    obj = response_type.parse(node, schema)
    assert obj.ZeepExampleResult.SomeValue == 45313
    assert len(obj.ZeepExampleResult.Results.Item) == 2
    assert obj.ZeepExampleResult.Results.Item[0].Key == "ABC100"
    assert obj.ZeepExampleResult.Results.Item[0].Value == 10
    assert obj.ZeepExampleResult.Results.Item[1].Key == "ABC200"
    assert obj.ZeepExampleResult.Results.Item[1].Value == 20


import json

# Read the file
with open('chatgpt_plugins.json', 'r', encoding='utf-8') as f:
    data = f.read()

# Escape control characters
cleaned_data = json.dumps(data)

# Write the cleaned data back to the file
with open('chatgpt_plugins.json', 'w', encoding='utf-8') as f:
    f.write(cleaned_data)


from uuid import uuid4

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, UserManager

class User(AbstractBaseUser):
    id = models.UUIDField(primary_key=True, editable=False, default=uuid4)
    email = models.EmailField(unique=True)

    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'email'

    objects = UserManager()

    class Meta:
        app_label = 'v2'
        default_related_name = 'users'

    def __str__(self):
        return self.email

class TextBlockManager(models.Manager):

    @staticmethod
    def find_root(block_id):
        """Recursively finds the root of the block"""
        return TextBlock.objects.raw('''
                WITH RECURSIVE block(id, parent) AS (
                      SELECT id, parent
                      FROM v2_textblock
                      WHERE id = %s
                    UNION ALL
                      SELECT tb.id, tb.parent
                      FROM v2_textblock AS tb, block AS b
                      WHERE tb.id = b.parent
                    )
                SELECT * FROM v2_textblock
            ''', [block_id, ])

class TextBlock(models.Model):
    id = models.UUIDField(primary_key=True, editable=False, default=uuid4)
    title = models.CharField(max_length=255, default='Untitled')
    text = models.TextField(blank=True)

    parent = models.ForeignKey('TextBlock', on_delete=models.CASCADE,
                               null=True)

    objects = TextBlockManager()

    class Meta:
        app_label = 'v2'
        default_related_name = 'children'

    def __str__(self):
        return self.title

class PermissionBlock(models.Model):
    class PermissionEnum(models.TextChoices):
        VIEW = 'View', 'View'
        EDITOR = 'Editor', 'Editor'
        OWNER = 'Owner', 'Owner'

    id = models.UUIDField(primary_key=True, editable=False, default=uuid4)
    permission = models.CharField(choices=PermissionEnum.choices,
                                  max_length=255)

    block = models.ForeignKey(TextBlock, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    @property
    def parent(self):
        """For compatibility with TextBlock permissions"""
        return self.block

    class Meta:
        app_label = 'v2'
        default_related_name = 'permission_blocks'

    def __str__(self):
        return f'{self.permission} - {self.block} - {self.user}'


from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.tokens import default_token_generator
from django.core.mail import send_mail
from django.db.models import Avg
from django.shortcuts import get_object_or_404
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters, status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import (AllowAny, IsAuthenticated,
                                        IsAuthenticatedOrReadOnly)
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.tokens import AccessToken

from api.filters import FilterByTitle
from api.permissions import (IsAdmin, IsAdministratorOrReadOnly,
                             IsAuthorModeratorAdminOrReadOnly)
from api.serializers import (CategoryReadSerializer, CommentSerializer,
                             GenreSerializer, MeSerializer, ReviewSerializer,
                             SignupSerializer, TitleCreateUpdateSerializer,
                             TitleSerializer, TokenSerializer, UserSerializer)
from api.utils import GenreCategoryBaseViewSet
from reviews.models import Category, Genre, Review, Title

User = get_user_model()

class ReviewViewSet(viewsets.ModelViewSet):
    """Отзывы"""

    serializer_class = ReviewSerializer
    permission_classes = (
        IsAuthorModeratorAdminOrReadOnly,
        IsAuthenticatedOrReadOnly
    )
    http_method_names = ('get', 'post', 'patch', 'delete')

    def get_title(self):
        return get_object_or_404(Title, id=self.kwargs.get('title_id'))

    def get_queryset(self):
        return self.get_title().reviews.all()

    def perform_create(self, serializer):
        serializer.save(author=self.request.user, title=self.get_title())

class CommentViewSet(viewsets.ModelViewSet):
    """Комментарии"""

    serializer_class = CommentSerializer
    permission_classes = (
        IsAuthorModeratorAdminOrReadOnly,
        IsAuthenticatedOrReadOnly
    )
    http_method_names = ('get', 'post', 'patch', 'delete')

    def get_review(self):
        return get_object_or_404(
            Review,
            id=self.kwargs.get('review_id'),
            title=self.kwargs.get('title_id')
        )

    def get_queryset(self):
        return self.get_review().comments.all()

    def perform_create(self, serializer):
        serializer.save(author=self.request.user, review=self.get_review())

class CategoryViewSet(GenreCategoryBaseViewSet):
    """Категории произведений"""

    queryset = Category.objects.all()
    serializer_class = CategoryReadSerializer

class GenreViewSet(GenreCategoryBaseViewSet):
    """Жанры произведений"""

    queryset = Genre.objects.all()
    serializer_class = GenreSerializer

class TitleViewSet(viewsets.ModelViewSet):
    """Произведения"""

    queryset = Title.objects.annotate(
        rating=Avg('reviews__score')).order_by('name')
    permission_classes = (IsAdministratorOrReadOnly,)
    filter_backends = (DjangoFilterBackend,)
    filterset_class = FilterByTitle
    http_method_names = ('get', 'post', 'patch', 'delete')

    def get_serializer_class(self):
        if self.action in ['list', 'retrieve']:
            return TitleSerializer
        return TitleCreateUpdateSerializer

class UserViewSet(viewsets.ModelViewSet):
    """Работа с пользователями"""

    lookup_field = 'username'
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsAdmin,)
    http_method_names = ('get', 'post', 'patch', 'delete')
    filter_backends = (filters.SearchFilter,)
    search_fields = ('username',)

    @action(
        methods=['GET', 'PATCH'],
        detail=False,
        permission_classes=(IsAuthenticated,)
    )
    def me(self, request):
        """Метод редактирования при запросе на users/me/"""

        if request.method == 'GET':
            serializer = UserSerializer(request.user)
            return Response(serializer.data, status=status.HTTP_200_OK)

        serializer = MeSerializer(
            request.user, data=request.data, partial=True
        )
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_200_OK)

class SignupView(APIView):
    """Создание пользователя и отправка кода подтверждения."""

    permission_classes = (AllowAny,)

    def post(self, request):
        serializer = SignupSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user, _ = User.objects.get_or_create(
            **serializer.validated_data,
        )
        confirmation_code = default_token_generator.make_token(user)
        send_mail(
            'Код подтверждения.',
            f'Код для регистрации: {confirmation_code}',
            settings.EMAIL,
            [f'{user.email}'],
            fail_silently=False,
        )
        return Response(serializer.data, status=status.HTTP_200_OK)

class TokenView(APIView):
    """Получение JWT токена."""

    permission_classes = (AllowAny,)

    def post(self, request):
        serializer = TokenSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        username = serializer.validated_data.get('username')
        confirmation_code = serializer.validated_data.get('confirmation_code')
        user = get_object_or_404(User, username=username)

        if not default_token_generator.check_token(user, confirmation_code):
            message = 'Неверный код подтверждения'
            return Response(message, status=status.HTTP_400_BAD_REQUEST)
        message = {'token': str(AccessToken.for_user(user))}
        return Response(message, status=status.HTTP_200_OK)


import numpy as np
from flask import Flask, request, jsonify, render_template
import pickle

app = Flask(__name__)
model = pickle.load(open('model.pkl', 'rb'))

@app.route('/')  #This is home page and '/' will render my index.html page
def home():      #check index.html page where 3 input features were given experience,test score and interview score
    return render_template('index.html')

@app.route('/predict',methods=['POST'])  #this used to give input to my model.pkl file
def predict():
    '''
    For rendering results on HTML GUI
    '''
    int_features = [int(x) for x in request.form.values()]
    final_features = [np.array(int_features)]
    prediction = model.predict(final_features)

    output = round(prediction[0], 2)

    return render_template('index.html', prediction_text='Employee Salary should be $ {}'.format(output))

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


import pandas as pd
import numpy as np
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import time
import matplotlib.pyplot as plt
import cv2
import seaborn as sns
sns.set_style('darkgrid')
import shutil
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.model_selection import train_test_split
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.layers import Dense, Activation,Dropout,Conv2D, MaxPooling2D,BatchNormalization
from tensorflow.keras.optimizers import Adam, Adamax
from tensorflow.keras.metrics import categorical_crossentropy
from tensorflow.keras import regularizers
from tensorflow.keras.models import Model
from tensorflow.keras import backend as K
import time
from tqdm import tqdm
from sklearn.metrics import f1_score
from IPython.display import YouTubeVideo
import sys
if not sys.warnoptions:
    import warnings
    warnings.simplefilter("ignore")
pd.set_option('display.max_columns', None)  # or 1000
pd.set_option('display.max_rows', None)  # or 1000
pd.set_option('display.max_colwidth', None)  # or 199
print ('Modules loaded')

def print_in_color(txt_msg,fore_tupple=(0,255,255),back_tupple=(100,100,100)):
    #prints the text_msg in the foreground color specified by fore_tupple with the background specified by back_tupple
    #text_msg is the text, fore_tupple is foregroud color tupple (r,g,b), back_tupple is background tupple (r,g,b)
    # default parameter print in cyan foreground and gray background
    rf,gf,bf=fore_tupple
    rb,gb,bb=back_tupple
    msg='{0}' + txt_msg
    mat='\33[38;2;' + str(rf) +';' + str(gf) + ';' + str(bf) + ';48;2;' + str(rb) + ';' +str(gb) + ';' + str(bb) +'m'
    print(msg .format(mat), flush=True)
    print('\33[0m', flush=True) # returns default print color to back to black
    return

# example default print
msg='test of default colors'
print_in_color(msg)

def make_dataframes(sdir):
    filepaths=[]
    labels=[]
    classlist=sorted(os.listdir(sdir) )
    for klass in classlist:
        classpath=os.path.join(sdir, klass)
        if os.path.isdir(classpath):
            flist=sorted(os.listdir(classpath))
            desc=f'{klass:25s}'
            for f in tqdm(flist, ncols=130,desc=desc, unit='files', colour='blue'):
                fpath=os.path.join(classpath,f)
                filepaths.append(fpath)
                labels.append(klass)
    Fseries=pd.Series(filepaths, name='filepaths')
    Lseries=pd.Series(labels, name='labels')
    df=pd.concat([Fseries, Lseries], axis=1)
    train_df, dummy_df=train_test_split(df, train_size=.7, shuffle=True, random_state=123, stratify=df['labels'])
    valid_df, test_df=train_test_split(dummy_df, train_size=.5, shuffle=True, random_state=123, stratify=dummy_df['labels'])
    classes=sorted(train_df['labels'].unique())
    class_count=len(classes)
    sample_df=train_df.sample(n=50, replace=False)
    # calculate the average image height and with
    ht=0
    wt=0
    count=0
    for i in range(len(sample_df)):
        fpath=sample_df['filepaths'].iloc[i]
        try:
            img=cv2.imread(fpath)
            h=img.shape[0]
            w=img.shape[1]
            wt +=w
            ht +=h
            count +=1
        except:
            pass
    have=int(ht/count)
    wave=int(wt/count)
    aspect_ratio=have/wave
    print('number of classes in processed dataset= ', class_count)
    counts=list(train_df['labels'].value_counts())
    print(counts[0], type(counts[0]))
    print('the maximum files in any class in train_df is ', max(counts), '  the minimum files in any class in train_df is ', min(counts))
    print('train_df length: ', len(train_df), '  test_df length: ', len(test_df), '  valid_df length: ', len(valid_df))
    print('average image height= ', have, '  average image width= ', wave, ' aspect ratio h/w= ', aspect_ratio)
    return train_df, test_df, valid_df, classes, class_count

sdir=r'C:\Users\FRANCIS\Downloads\CT-KIDNEY-DATASET-Normal-Cyst-Tumor-Stone\CT-KIDNEY-DATASET-Normal-Cyst-Tumor-Stone'
train_df, test_df, valid_df, classes, class_count=make_dataframes(sdir)

def trim(df, max_samples, min_samples, column):
    df=df.copy()
    classes=df[column].unique()
    class_count=len(classes)
    length=len(df)
    print ('dataframe initially is of length ',length, ' with ', class_count, ' classes')
    groups=df.groupby(column)
    trimmed_df = pd.DataFrame(columns = df.columns)
    groups=df.groupby(column)
    for label in df[column].unique():
        group=groups.get_group(label)
        count=len(group)
        if count > max_samples:
            sampled_group=group.sample(n=max_samples, random_state=123,axis=0)
            trimmed_df=pd.concat([trimmed_df, sampled_group], axis=0)
        else:
            if count>=min_samples:
                sampled_group=group
                trimmed_df=pd.concat([trimmed_df, sampled_group], axis=0)
    print('after trimming, the maximum samples in any class is now ',max_samples, ' and the minimum samples in any class is ', min_samples)
    classes=trimmed_df[column].unique()# return this in case some classes have less than min_samples
    class_count=len(classes) # return this in case some classes have less than min_samples
    length=len(trimmed_df)
    print ('the trimmed dataframe now is of length ',length, ' with ', class_count, ' classes')
    return trimmed_df, classes, class_count

max_samples=500
min_samples=500
column='labels'
train_df, classes, class_count=trim(train_df, max_samples, min_samples, column)

def balance(df, n, working_dir, img_size):
    df=df.copy()
    print('Initial length of dataframe is ', len(df))
    aug_dir=os.path.join(working_dir, 'aug')# directory to store augmented images
    if os.path.isdir(aug_dir):# start with an empty directory
        shutil.rmtree(aug_dir)
    os.mkdir(aug_dir)
    for label in df['labels'].unique():
        dir_path=os.path.join(aug_dir,label)
        os.mkdir(dir_path) # make class directories within aug directory
    # create and store the augmented images
    total=0
    gen=ImageDataGenerator(horizontal_flip=True,  rotation_range=20, width_shift_range=.2,
                                  height_shift_range=.2, zoom_range=.2)
    groups=df.groupby('labels') # group by class
    for label in df['labels'].unique():  # for every class
        group=groups.get_group(label)  # a dataframe holding only rows with the specified label
        sample_count=len(group)   # determine how many samples there are in this class
        if sample_count< n: # if the class has less than target number of images
            aug_img_count=0
            delta=n - sample_count  # number of augmented images to create
            target_dir=os.path.join(aug_dir, label)  # define where to write the images
            msg='{0:40s} for class {1:^30s} creating {2:^5s} augmented images'.format(' ', label, str(delta))
            print(msg, '\r', end='') # prints over on the same line
            aug_gen=gen.flow_from_dataframe( group,  x_col='filepaths', y_col=None, target_size=img_size,
                                            class_mode=None, batch_size=1, shuffle=False,
                                            save_to_dir=target_dir, save_prefix='aug-', color_mode='rgb',
                                            save_format='jpg')
            while aug_img_count<delta:
                images=next(aug_gen)
                aug_img_count += len(images)
            total +=aug_img_count
    print('Total Augmented images created= ', total)
    # create aug_df and merge with train_df to create composite training set ndf
    aug_fpaths=[]
    aug_labels=[]
    classlist=os.listdir(aug_dir)
    for klass in classlist:
        classpath=os.path.join(aug_dir, klass)
        flist=os.listdir(classpath)
        for f in flist:
            fpath=os.path.join(classpath,f)
            aug_fpaths.append(fpath)
            aug_labels.append(klass)
    Fseries=pd.Series(aug_fpaths, name='filepaths')
    Lseries=pd.Series(aug_labels, name='labels')
    aug_df=pd.concat([Fseries, Lseries], axis=1)
    df=pd.concat([df,aug_df], axis=0).reset_index(drop=True)
    print('Length of augmented dataframe is now ', len(df))
    return df

def make_gens(batch_size, train_df, test_df, valid_df, img_size):
    trgen=ImageDataGenerator()
    t_and_v_gen=ImageDataGenerator()
    msg='{0:70s} for train generator'.format(' ')
    print(msg, '\r', end='') # prints over on the same line
    train_gen=trgen.flow_from_dataframe(train_df, x_col='filepaths', y_col='labels', target_size=img_size,
                                       class_mode='categorical', color_mode='rgb', shuffle=True, batch_size=batch_size)
    msg='{0:70s} for valid generator'.format(' ')
    print(msg, '\r', end='') # prints over on the same line
    valid_gen=t_and_v_gen.flow_from_dataframe(valid_df, x_col='filepaths', y_col='labels', target_size=img_size,
                                       class_mode='categorical', color_mode='rgb', shuffle=False, batch_size=batch_size)
    # for the test_gen we want to calculate the batch size and test steps such that batch_size X test_steps= number of samples in test set
    # this insures that we go through all the sample in the test set exactly once.
    length=len(test_df)
    test_batch_size=sorted([int(length/n) for n in range(1,length+1) if length % n ==0 and length/n<=80],reverse=True)[0]
    test_steps=int(length/test_batch_size)
    msg='{0:70s} for test generator'.format(' ')
    print(msg, '\r', end='') # prints over on the same line
    test_gen=t_and_v_gen.flow_from_dataframe(test_df, x_col='filepaths', y_col='labels', target_size=img_size,
                                       class_mode='categorical', color_mode='rgb', shuffle=False, batch_size=test_batch_size)
    # from the generator we can get information we will need later
    classes=list(train_gen.class_indices.keys())
    class_indices=list(train_gen.class_indices.values())
    class_count=len(classes)
    labels=test_gen.labels
    print ( 'test batch size: ' ,test_batch_size, '  test steps: ', test_steps, ' number of classes : ', class_count)
    return train_gen, test_gen, valid_gen, test_steps

batch_size=30
img_size=(224,250) # reduce image size to reduce training time at expense of model accuracy
train_gen, test_gen, valid_gen, test_steps =make_gens(batch_size, train_df, test_df, valid_df, img_size)

def show_image_samples(gen ):
    t_dict=gen.class_indices
    classes=list(t_dict.keys())
    images,labels=next(gen) # get a sample batch from the generator
    plt.figure(figsize=(25, 25))
    length=len(labels)
    if length<25:   #show maximum of 25 images
        r=length
    else:
        r=25
    for i in range(r):
        plt.subplot(5, 5, i + 1)
        image=images[i] /255
        plt.imshow(image)
        index=np.argmax(labels[i])
        class_name=classes[index]
        plt.title(class_name, color='blue', fontsize=18)
        plt.axis('off')
    plt.show()
show_image_samples(train_gen )

def F1_score(y_true, y_pred): #taken from old keras source code
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
    precision = true_positives / (predicted_positives + K.epsilon())
    recall = true_positives / (possible_positives + K.epsilon())
    f1_val = 2*(precision*recall)/(precision+recall+K.epsilon())
    return f1_val

def make_model(img_size, lr, mod_num=3):
    img_shape=(img_size[0], img_size[1], 3)
    if mod_num == 0:
        base_model=tf.keras.applications.efficientnet.EfficientNetB0(include_top=False, weights="imagenet",input_shape=img_shape, pooling='max')
        msg='Created EfficientNet B0 model'
    elif mod_num == 3:
        base_model=tf.keras.applications.efficientnet.EfficientNetB3(include_top=False, weights="imagenet",input_shape=img_shape, pooling='max')
        msg='Created EfficientNet B3 model'
    elif mod_num == 5:
        base_model=tf.keras.applications.efficientnet.EfficientNetB5(include_top=False, weights="imagenet",input_shape=img_shape, pooling='max')
        msg='Created EfficientNet B5 model'

    else:
        base_model=tf.keras.applications.efficientnet.EfficientNetB7(include_top=False, weights="imagenet",input_shape=img_shape, pooling='max')
        msg='Created EfficientNet B7 model'

    base_model.trainable=True
    x=base_model.output
    x=BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001 )(x)
    x = Dense(256, kernel_regularizer = regularizers.l2(l = 0.016),activity_regularizer=regularizers.l1(0.006),
                    bias_regularizer=regularizers.l1(0.006) ,activation='relu')(x)
    x=Dropout(rate=.4, seed=123)(x)
    output=Dense(class_count, activation='softmax')(x)
    model=Model(inputs=base_model.input, outputs=output)
    model.compile(Adamax(learning_rate=lr), loss='categorical_crossentropy', metrics=['accuracy', F1_score])
    msg=msg + f' with initial learning rate set to {lr}'
    print_in_color(msg)
    return model

lr=.001
model=make_model(img_size, lr)

class LR_ASK(keras.callbacks.Callback):
    def __init__ (self, model, epochs,  ask_epoch, dwell=True, factor=.4): # initialization of the callback
        super(LR_ASK, self).__init__()
        self.model=model
        self.ask_epoch=ask_epoch
        self.epochs=epochs
        self.ask=True # if True query the user on a specified epoch
        self.lowest_vloss=np.inf
        self.lowest_aloss=np.inf
        self.best_weights=self.model.get_weights() # set best weights to model's initial weights
        self.best_epoch=1
        self.plist=[]
        self.alist=[]
        self.dwell= dwell
        self.factor=factor

    def get_list(self): # define a function to return the list of % validation change
        return self.plist, self.alist
    def on_train_begin(self, logs=None): # this runs on the beginning of training
        if self.ask_epoch == 0:
            print('you set ask_epoch = 0, ask_epoch will be set to 1', flush=True)
            self.ask_epoch=1
        if self.ask_epoch >= self.epochs: # you are running for epochs but ask_epoch>epochs
            print('ask_epoch >= epochs, will train for ', epochs, ' epochs', flush=True)
            self.ask=False # do not query the user
        if self.epochs == 1:
            self.ask=False # running only for 1 epoch so do not query user
        else:
            msg =f'Training will proceed until epoch {ask_epoch} then you will be asked to'
            print_in_color(msg )
            msg='enter H to halt training or enter an integer for how many more epochs to run then be asked again'
            print_in_color(msg)
            if self.dwell:
                msg='learning rate will be automatically adjusted during training'
                print_in_color(msg, (0,255,0))
        self.start_time= time.time() # set the time at which training started

    def on_train_end(self, logs=None):   # runs at the end of training
        msg=f'loading model with weights from epoch {self.best_epoch}'
        print_in_color(msg, (0,255,255))
        self.model.set_weights(self.best_weights) # set the weights of the model to the best weights
        tr_duration=time.time() - self.start_time   # determine how long the training cycle lasted
        hours = tr_duration // 3600
        minutes = (tr_duration - (hours * 3600)) // 60
        seconds = tr_duration - ((hours * 3600) + (minutes * 60))
        msg = f'training elapsed time was {str(hours)} hours, {minutes:4.1f} minutes, {seconds:4.2f} seconds)'
        print_in_color (msg) # print out training duration time

    def on_epoch_end(self, epoch, logs=None):  # method runs on the end of each epoch
        vloss=logs.get('val_loss')  # get the validation loss for this epoch
        aloss=logs.get('loss')
        if epoch >0:
            deltav = self.lowest_vloss- vloss
            pimprov=(deltav/self.lowest_vloss) * 100
            self.plist.append(pimprov)
            deltaa=self.lowest_aloss-aloss
            aimprov=(deltaa/self.lowest_aloss) * 100
            self.alist.append(aimprov)
        else:
            pimprov=0.0
            aimprov=0.0
        if vloss< self.lowest_vloss:
            self.lowest_vloss=vloss
            self.best_weights=self.model.get_weights() # set best weights to model's initial weights
            self.best_epoch=epoch + 1
            msg=f'\n validation loss of {vloss:7.4f} is {pimprov:7.4f} % below lowest loss, saving weights from epoch {str(epoch + 1):3s} as best weights'
            print_in_color(msg, (0,255,0)) # green foreground
        else: # validation loss increased
            pimprov=abs(pimprov)
            msg=f'\n validation loss of {vloss:7.4f} is {pimprov:7.4f} % above lowest loss of {self.lowest_vloss:7.4f} keeping weights from epoch {str(self.best_epoch)} as best weights'
            print_in_color(msg, (255,255,0)) # yellow foreground
            if self.dwell: # if dwell is True when the validation loss increases the learning rate is automatically reduced and model weights are set to best weights
                lr=float(tf.keras.backend.get_value(self.model.optimizer.lr)) # get the current learning rate
                new_lr=lr * self.factor
                msg=f'learning rate was automatically adjusted from {lr:8.6f} to {new_lr:8.6f}, model weights set to best weights'
                print_in_color(msg) # cyan foreground
                tf.keras.backend.set_value(self.model.optimizer.lr, new_lr) # set the learning rate in the optimizer
                self.model.set_weights(self.best_weights) # set the weights of the model to the best weights

        if aloss< self.lowest_aloss:
            self.lowest_aloss=aloss
        if self.ask: # are the conditions right to query the user?
            if epoch + 1 ==self.ask_epoch: # is this epoch the one for quering the user?
                msg='press enter to continue or enter a comment  below '
                print_in_color(msg)
                comment=input(' ')
                if comment !='':
                    print_in_color(comment, (155,245,66))
                msg='\n Enter H to end training or  an integer for the number of additional epochs to run then ask again'
                print_in_color(msg) # cyan foreground
                ans=input()

                if ans == 'H' or ans =='h' or ans == '0': # quit training for these conditions
                    msg=f'you entered {ans},  Training halted on epoch {epoch+1} due to user input\n'
                    print_in_color(msg)
                    self.model.stop_training = True # halt training
                else: # user wants to continue training
                    self.ask_epoch += int(ans)
                    if self.ask_epoch > self.epochs:
                        print('\nYou specified maximum epochs of as ', self.epochs, ' cannot train for ', self.ask_epoch, flush =True)
                    else:
                        msg=f'you entered {ans} Training will continue to epoch {self.ask_epoch}'
                        print_in_color(msg) # cyan foreground
                        if self.dwell==False:
                            lr=float(tf.keras.backend.get_value(self.model.optimizer.lr)) # get the current learning rate
                            msg=f'current LR is  {lr:8.6f}  hit enter to keep  this LR or enter a new LR'
                            print_in_color(msg) # cyan foreground
                            ans=input(' ')
                            if ans =='':
                                msg=f'keeping current LR of {lr:7.5f}'
                                print_in_color(msg) # cyan foreground
                            else:
                                new_lr=float(ans)
                                tf.keras.backend.set_value(self.model.optimizer.lr, new_lr) # set the learning rate in the optimizer
                                msg=f' changing LR to {ans}'
                                print_in_color(msg)

epochs=40
ask_epoch=5
ask=LR_ASK(model, epochs,  ask_epoch)
callbacks=[ask]
history=model.fit(x=train_gen,  epochs=epochs, verbose=1, callbacks=callbacks,  validation_data=valid_gen,
                 shuffle=False,  initial_epoch=0)


from loguru import logger
from cfg.botConfig import BotConfig
from bson.objectid import ObjectId
import pymongo

config = BotConfig.load_config()
client = pymongo.MongoClient(
    "mongodb://"+config["mongdb"]["user"]+":" + config["mongdb"]["pwd"]+"@" +
    config["mongdb"]["host"]+":"+str(config["mongdb"]["port"])+"/bot")

db = client.bot
coll_msg = db.msg  # 消息列表
coll_botmsg = db.botmsg  # bot发言列表
coll_repeatmsg = db.repeatmsg  # 重复消息列表
coll_offline_file = db.offline_file  # 离线文件列表
coll_task = db.task  # 任务列表

def find_repeatmsg(gid):  # 查询重复消息
    msg_json = {"gid": gid}
    result = coll_repeatmsg.find_one(msg_json)
    if result == None:
        logger.info("未查询到重复消息")
    return result

def add_repeatmsg(msg, gid):  # 添加重复消息
    coll_repeatmsg.delete_one({"gid": gid})
    msg_json = {"gid": gid, "msg": msg, "repeated": False}
    coll_repeatmsg.insert_one(msg_json)

def mark_repeatmsg(msg,  gid):  # 标记为已复读
    msgjson = {"gid": gid, "msg": msg}
    coll_repeatmsg.update_one(msgjson, {"$set": {"repeated": True}})
    logger.info("已复读：{}", gid)

def add_botmsg(msg, msgid, uid, gid):
    msg_json = {"uid": uid, "msgid": msgid, "gid": gid, "msg": msg}
    result = coll_botmsg.insert_one(msg_json)
    logger.info("bot消息加载到数据库：{}", result.inserted_id)

def add_msg(msg):
    result = coll_msg.insert_one(msg)
    logger.info("加载到数据库：{}", result.inserted_id)

def find_msg_by_id(msgid):
    msg = {"message_id": msgid}
    result = coll_msg.find_one(msg)
    if result != None:
        logger.info("查询到数据库：{}", result["_id"])
    else:
        logger.info("未查询到数据库")
    return result

def find_botmsg_by_id(msgid):
    msg = {"msgid": msgid}
    result = coll_botmsg.find_one(msg)
    if result != None:
        logger.info("查询到数据库：{}", result["_id"])
    else:
        logger.info("未查询到发言")
    return result

def add_offline_file(uid, time, name, size, url):
    result = coll_offline_file.insert_one(
        {"uid": uid, "time": time, "name": name, "size": size, "url": url})
    logger.info("加载离线文件到数据库：{}", result.inserted_id)

def find_offline_file(uid, name):
    result = coll_offline_file.find_one({"uid": int(uid), "name": name})
    if result != None:
        logger.info("查询到离线文件：{}", result["_id"])
        return True
    else:
        logger.info("未查询到离线文件")
        return False

def find_latest_file(uid):
    results = coll_offline_file.find(
        {"uid": int(uid)}).sort('_id', -1).limit(1)
    result = next(results)
    if result != None:
        logger.info("查询到离线文件：{}", result["_id"])
        return result
    else:
        logger.info("未查询到离线文件")
        return None

def offer_offline_file(uid, name):
    result = coll_offline_file.find_one({"uid": uid, "name": name})
    if result != None:
        result["_id"] = str(result["_id"])
        logger.info("查询到离线文件：{}", result["_id"])
        return result
    else:
        logger.info("未查询到离线文件")
        return None

def add_task(model, infile, subtype, uid, gid, taskargs):
    result = coll_task.insert_one(
        {"model": model, "status": None, "process": "", "infile": infile,
         "subftype": subtype, "uid": uid, "gid": gid, "taskargs": taskargs})
    logger.info("加载任务到数据库：{}", result.inserted_id)
    return result.inserted_id

def update_task(taskid, status, process):
    result = coll_task.update_one({"_id": ObjectId(taskid)}, {
                                  "$set": {"status": status, "process": process}})
    logger.info("更新任务状态：{}", result.matched_count)

def get_task(model):
    result = coll_task.find_one({"model": model, "status": None})
    result["_id"] = str(result["_id"])
    logger.info("查询到任务：{}", result["_id"])
    return result

if __name__ == '__main__':
    # add_msg(imsg)
    # find_msg_by_id(-1726724172)
    #add_repeatmsg("123",  123)
    mark_repeatmsg("123",  123)
    # pass