#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Extract zeta time series from regions of the hycom forcing.
The goal is to develop background information in support of an
improved open boundary condition in the Northern Strait of Georgia.

Note that Days 200-250 are a fairly stable time to explore a solution
(2017.07.20 to 2017.09.08).  This is also a time period where
DT was generally long (0 or 1 blowups).

"""

from datetime import datetime, timedelta
import argparse
import pandas as pd
import pickle
import numpy as np

import os
import sys
pth = os.path.abspath('../alpha')
if pth not in sys.path:
    sys.path.append(pth)
import Lfun
import zfun

# Command line arguments
parser = argparse.ArgumentParser()
# standard arguments
parser.add_argument('-g', '--gridname', nargs='?', type=str, default='cas4')
parser.add_argument('-t', '--tag', nargs='?', type=str, default='v2')
parser.add_argument('-0', '--date_string0', nargs='?', type=str, default='2018.11.26')
parser.add_argument('-1', '--date_string1', nargs='?', type=str, default='2018.12.25')
args = parser.parse_args()

# use some arguments
Ldir = Lfun.Lstart(args.gridname, args.tag)
dt0 = datetime.strptime(args.date_string0, '%Y.%m.%d')
dt1 = datetime.strptime(args.date_string1, '%Y.%m.%d')

# make a list of model date strings
mds_list = []
mdt = dt0
while mdt <= dt1:
    mds_list.append(datetime.strftime(mdt, '%Y.%m.%d'))
    mdt = mdt + timedelta(days=1)

# extractions
zdf = pd.DataFrame(columns=['z_jdf', 'z_sog', 'z_off'])

print('== looping over dates ==')
# loop over dates
for mds in mds_list:

    indir0 = Ldir['LOo'] + Ldir['gtag'] + '/f' + mds + '/'

    # specify which ocn forcing to look in
    get_data = True
    if os.path.isdir(indir0 + 'ocn3'):
        ocn = 'ocn3'
        print(' - ' + mds + ': using ocn3')
    elif os.path.isdir(indir0 + 'ocn2'):
        ocn = 'ocn2'
        print(' - ' + mds + ': using ocn2')
    else:
        print(' - ' + mds + ': no ocn directory')
        get_data = False

    if get_data:

        # get coordinates
        indir = indir0 + ocn + '/Data/'
        coord_dict = pickle.load(open(indir + 'coord_dict.p', 'rb'))
        lon = coord_dict['lon']
        lat = coord_dict['lat']

        # get fields
        # note that when we use the "xfh" fields there should be no nans
        xfh = pickle.load(open(indir + '/xfh' + mds + '.p', 'rb'))
        zeta = xfh['ssh']

        # get indices around certain regions, and their data
        #
        # (a) Mouth of Strait of Juan de Fuca
        i0, i1, fr = zfun.get_interpolant(np.array([-124.7, -124.5]), lon, extrap_nan=False)
        j0, j1, fr = zfun.get_interpolant(np.array([48.4, 48.6]), lat, extrap_nan=False)
        zeta_jdf = zeta[j0[0]:j1[1]+1, i0[0]:i1[1]+1]
        #
        # (b) Northern Strait of Georgia
        i0, i1, fr = zfun.get_interpolant(np.array([-125.5, -124.5]), lon, extrap_nan=False)
        j0, j1, fr = zfun.get_interpolant(np.array([50.25, 50.45]), lat, extrap_nan=False)
        zeta_sog = zeta[j0[0]:j1[1]+1, i0[0]:i1[1]+1]
        #
        # (c) Offshore
        i0, i1, fr = zfun.get_interpolant(np.array([-127, -126]), lon, extrap_nan=False)
        j0, j1, fr = zfun.get_interpolant(np.array([46, 47]), lat, extrap_nan=False)
        zeta_off = zeta[j0[0]:j1[1]+1, i0[0]:i1[1]+1]

        mdt = datetime.strptime(mds,'%Y.%m.%d')
        zdf.loc[mdt, 'z_jdf'] = zeta_jdf.mean()
        zdf.loc[mdt, 'z_sog'] = zeta_sog.mean()
        zdf.loc[mdt, 'z_off'] = zeta_off.mean()

# save output
outdir = Ldir['LOo'] + 'misc/'
Lfun.make_dir(outdir)
zdf.to_pickle(outdir + 'zeta_df.p')


# -*- coding: utf-8 -*-
__author__ = 'simon'

import urllib

from AlipayConfig import AlipayConfig
from AlipayCore import AlipayCore
import xml.etree.ElementTree as ET
from md5 import MD5

class AlipaySubmit(object):
    @staticmethod
    def build_request_my_sign(str_para):
        '''
        生成签名结果
        :param str_para:要签名的数组
        :return:签名结果字符串
        '''
        pre_str = AlipayCore.create_link_string(str_para)

        my_sign = ""

        if AlipayConfig.sign_type == 'MD5':
            my_sign = MD5.sign(pre_str, AlipayConfig.key, AlipayConfig.input_charset)
        if AlipayConfig.sign_type == "0001":
            my_sign = ""

            # print(my_sign.decode('utf-8'))
            # my_sign = my_sign.encode('utf-8').decode('utf-8')
        return str(my_sign)

    '''
        <form id="alipaysubmit" name="alipaysubmit" action="https://mapi.alipay.com/gateway.do?_input_charset=utf-8" method="get">
        <input type="hidden" name="seller_email" value="emma-xu319@163.com"/>
        <input type="hidden" name="orderId" value="192"/>
        <input type="hidden" name="_input_charset" value="utf-8"/>
        <input type="hidden" name="subject" value="威悦餐饮"/>
        <input type="hidden" name="sign" value="9253dda915e5f55f719e38bd05931900"/>
        <input type="hidden" name="royalty_type" value="10"/>
        <input type="hidden" name="notify_url" value="http://192.168.146.141:8088/notify_url.jsp"/>
        <input type="hidden" name="body" value="威悦账单"/>
        <input type="hidden" name="royalty_parameters" value="469380879@qq.com^0.00^ "/>
        <input type="hidden" name="payment_type" value="1"/>
        <input type="hidden" name="out_trade_no" value="390"/>
        <input type="hidden" name="partner" value="2088011763438960"/>
        <input type="hidden" name="service" value="create_direct_pay_by_user"/>
        <input type="hidden" name="total_fee" value="0.01"/>
        <input type="hidden" name="return_url" value="http://192.168.146.141:8088/return_url"/>
        <input type="hidden" name="sign_type" value="MD5"/>
        <input type="submit" value="确认" style="display:none;">
        </form><script>document.forms['alipaysubmit'].submit();</script>
    '''

    @staticmethod
    def build_request_para(str_para_temp):
        '''
        生成要请求给支付宝的参数数组
        :param spara_temp: 请求前的参数数组
        :return: 要请求的参数数组
        '''
        # 除去数组中的空值和签名参数
        para_dict_without_sign = AlipayCore.para_filter(str_para_temp)
        # 生成签名结果
        my_sign = AlipaySubmit.build_request_my_sign(para_dict_without_sign)
        # 签名结果与签名方式加入请求提交参数组中
        para_dict = para_dict_without_sign
        para_dict['sign'] =  my_sign

        if not para_dict.get('service') == 'alipay.wap.trade.create.direct' and \
                not para_dict.get('service') == 'alipay.wap.auth.authAndExecute':
            para_dict['sign_type'] = AlipayConfig.sign_type

        return para_dict

    @staticmethod
    def build_request(alipay_gateway_new, str_para_temp):
        '''
        建立请求，以表单HTML形式构造（默认）
        :param alipay_gateway_new:支付宝网关地址
        :param str_para_temp:请求参数数组

        :return:提交表单HTML文本
        '''

        str_para_temp = AlipaySubmit.build_request_para(str_para_temp)
        # 请求
        params = urllib.urlencode(str_para_temp)
        res = urllib.urlopen(alipay_gateway_new,params).read()

        res_html = urllib.unquote(res).decode('utf-8')
        #res_html = res.decode('utf-8')

        request_token = AlipaySubmit.get_request_token(res_html)

        return request_token

    @staticmethod
    def checkout(alipay_gateway_new, str_para_temp):

        sbHtml = ""
        sbHtml = sbHtml + "<form id=\"alipaysubmit\" name=\"alipaysubmit\" action=\"" + alipay_gateway_new + "_input_charset" + AlipayConfig.input_charset \
                 + "\" method=\"" + "get" \
                 + "\">"

        lens = len(str_para_temp)
        for num, key in enumerate(str_para_temp):
            sbHtml = sbHtml + "<input type=\"hidden\" name=\"" + str(key) + "\" value=\"" + str(
                str_para_temp[key]) + "\"/>"

        sbHtml = sbHtml + "<input type=\"submit\" value=\"" + "confirm" + "\" style=\"display:none;\"></form>"
        sbHtml = sbHtml + "<script>document.forms['alipaysubmit'].submit();</script>"

        return sbHtml

    @staticmethod
    def get_request_token(text):
        '''
        解析远程模拟提交后返回的信息，获得token
        :param text: 要解析的字符串
        :return:解析结果
        '''
        request_token = ""

        str_split_text = text.split("&")

        para_text = {}

        for item in str_split_text:
            e_pos = item.find('=')
            key = item[0:e_pos]
            value = item[e_pos + 1:]

            para_text[key] = value

        res_data = para_text.get('res_data')
        print("res_data==>" , res_data)
        if res_data:
            # token从res_data中解析出来（也就是说res_data中已经包含token的内容）
            res_data = res_data.replace('+',' ')
            root = ET.fromstring(res_data)
            for child in root:
                if child.tag == "request_token":
                    request_token = child.text
                    break
        return request_token


import ast
import json
import base64

import panel as pn
import param
from eve.io.mongo.validation import Validator
from panel.widgets import LiteralInput

class LiteralSchemaInputBase(LiteralInput):
    """[summary]

    Args:
        LiteralInput ([type]): [description]
    """
    def validate_schema(self, value):
        return True

    def _process_property_change(self, msg):
        msg = super(LiteralSchemaInputBase, self)._process_property_change(msg)
        if msg['value'] == self.value:
            return msg
        new_state = ''
        if 'value' in msg:
            value = msg.pop('value')
            if not self.validate_schema(value):
                new_state = ' (invalid)'
                value = self.value
            msg['value'] = value
            msg['name'] = msg.get('title', self.name).replace(
                self._state, '').replace(new_state, '') + new_state
            self._state = new_state
            self.param.trigger('name')
        return msg

def LiteralSchemaInput(name, schema, type_=None):
    validator = Validator({"value": schema})

    def validate_schema(self, value):
        return validator.validate({"value": value})

    params = {
        "validate_schema": validate_schema,
        "type": type_,
    }
    return type(name + "InputWidget", (LiteralSchemaInputBase, ), params)

def PDFViewer(pdf, width=800, height=500):
    if isinstance(pdf, bytes):
        pdf = base64.b64encode(pdf).decode()
    return pn.pane.HTML(f'',
                   width=1000,sizing_mode="stretch_both")

def PNGViewer(png, width=800, height=500):
    if isinstance(png, bytes):
        png = base64.b64encode(png).decode()
    src = f"data:image/png;base64,{png}"
    return pn.pane.HTML(f"")

class FileInputPreview(pn.widgets.FileInput):

    @param.depends('value')
    def preview(self):
        if not self.filename:
            return pn.Column()
        if self.filename.endswith(".png"):
            return PNGViewer(self.value)
        elif self.filename.endswith(".pdf"):
            return PDFViewer(self.value)

    def _repr_mimebundle_(self, include=None, exclude=None):
        return pn.Column(self, self.preview)

WIDGET_MAPPING = {
    "media": {"type": pn.widgets.FileInput, "align": "end"},
}

def get_widget(name, schema):
    if schema.get('type', 'string') == "dict" and "schema" in schema:
        return LiteralSchemaInput(name, schema, dict)
    elif schema.get('type', 'string') == "list" and "schema" in schema:
        return LiteralSchemaInput(name, schema, list)
    else:
        return WIDGET_MAPPING.get(schema.get('type', 'string'), None)

class Progress(param.Parameterized):
    value = param.Integer(0)
    total = param.Integer(100)
    active = param.Boolean(False)
    desc = param.String("Loading")
    unit = param.String("iterations")

    def __call__(self, **params):
        self.param.set_param(**params)
        return self

    @param.depends("value", "total", "active")
    def view(self):
        perc = int(100*self.value/self.total)
        text = f"{perc}% [{self.value}/{self.total} {self.unit}]"
        ind = pn.indicators.Progress(value=perc, active=self.active, sizing_mode="stretch_width")

        return pn.Row(self.desc, ind, text, sizing_mode="stretch_width")

    def update(self, inc=1):
        self.value = self.value + inc

    def reset(self):
        self.value = 0


#! -*- coding: utf-8 -*-
import torch
import json
import torch.nn as nn
from fantasybert.models.model_building import build_bert_model
from fantasybert.models.modeling_utils import Bertpooling
from fantasybert.core.trainer import Trainer
from fantasybert.core.loss_main import LossBase
from fantasybert.core.data_utils import set_seed, TrainerState, DataSetGetter
from fantasybert.tokenization.tokenizers import BertTokenizer

args = TrainerState(
    learning_rate=2.5e-5,
    n_epochs=10,
    max_len=120,
    batch_size=64,
    patience=10,
    metric_key='spearman_correlation',
    save_path="S:/Myproject/experiments/outputs/consent_afqmc",
    model_path="S:/Myproject/resources/chinese-roberta-wwm-ext",
    data_dir="S:/Myproject/datasets/afqmc/"
)

set_seed(args)
tokenizer = BertTokenizer(args.model_path + "/vocab.txt")

class MyDataset(DataSetGetter):
    @staticmethod
    def load_data(filename):
        D, total_labels = [], None
        with open(args.data_dir + filename, "r", encoding="utf-8") as f:
            for line in f.readlines():
                line = json.loads(line)
                text_a = line['sentence1']
                text_b = line['sentence2']
                label = line['label']
                D.append((text_a, int(label)))
                D.append((text_b, int(label)))
        return D, total_labels

class TestDataset(DataSetGetter):
    @staticmethod
    def load_data(filename):
        D, total_labels = [], None
        with open(args.data_dir + filename, "r", encoding="utf-8") as f:
            for line in f.readlines():
                line = json.loads(line)
                text_a = line['sentence1']
                text_b = line['sentence2']
                label = line['label']
                D.append((text_a, text_b, float(label)))
        return D, total_labels

train_dataset, dev_dataset = MyDataset('train.json'), TestDataset('dev.json')

def train_collate_fn(batch):
    texts, labels = [t[0] for t in batch], [t[1] for t in batch]
    encodings = tokenizer(texts, max_length=args.max_len, padding='batch_longest', truncation=True, return_tensors='pt')
    return {'input_ids': encodings['input_ids'], 'label': torch.tensor(labels)}

def eval_collate_fn(batch):
    text_a, text_b, labels = [_[0] for _ in batch], [_[1] for _ in batch], [_[2] for _ in batch]
    encodings_a = tokenizer(text_a, max_length=args.max_len, padding=True, return_tensors='pt', truncation=True)
    encodings_b = tokenizer(text_b, max_length=args.max_len, padding=True, return_tensors='pt', truncation=True)
    return {'text_a_input_ids': encodings_a["input_ids"],'text_b_input_ids': encodings_b["input_ids"],'label':torch.tensor(labels)}

class CosentModel(nn.Module):
    def __init__(self):
        super(CosentModel, self).__init__()
        self.bert = build_bert_model(args.model_path)

    def forward(self, input_ids=None, **inputs):
        output = self.bert(input_ids=input_ids, output_hidden_states=True)
        pooled_output = Bertpooling(output, pool_type='first-last-avg')
        return {'pred': pooled_output}

    def predict(self, text_a_input_ids, text_b_input_ids):
        out_a = self.bert(input_ids=text_a_input_ids, output_hidden_states=True)
        vec_a = Bertpooling(out_a, pool_type='first-last-avg')
        out_b = self.bert(input_ids=text_b_input_ids, output_hidden_states=True)
        vec_b = Bertpooling(out_b, pool_type='first-last-avg')
        return {'pred': (vec_a, vec_b)}

class CosentLoss(LossBase):
    def __init__(self, pred=None, target=None, **kwargs):
        super(CosentLoss, self).__init__()
        self._init_param_map(pred=pred, target=target)

    def compute_loss(self, y_pred, y_true):
        # 1. 取出真实的标签
        y_true = y_true[::2]  # tensor([1, 0, 1]) 真实的标签

        # 2. 对输出的句子向量进行l2归一化   后面只需要对应为相乘  就可以得到cos值了
        norms = (y_pred ** 2).sum(axis=1, keepdims=True) ** 0.5
        # y_pred = y_pred / torch.clip(norms, 1e-8, torch.inf)
        y_pred = y_pred / norms

        # 3. 奇偶向量相乘
        y_pred = torch.sum(y_pred[::2] * y_pred[1::2], dim=1) * 20  # 奇/偶数位分别是是句子对的两个句子

        # 4. 取出负例-正例的差值
        y_pred = y_pred[:, None] - y_pred[None, :]  # 这里是算出所有位置 两两之间余弦的差值
        # 矩阵中的第i行j列  表示的是第i个余弦值-第j个余弦值

        # print(y_true[:, None])   [[1.],[0.],[0.],[1.],...]   (1,bs)
        # print(y_true[None, :])   [[1., 0., 0., 1.,...]]      (bs,1)
        # None是增加维度的作用，类似unsqueeze
        y_true = y_true[:, None] < y_true[None, :]  # 例如对于上面的[1.]就和[1., 0., 0., 1.,...]进行比较得到一行
        # print(y_true.size())    bs*bs  里面的值为True/False
        y_true = y_true.float()  # True/False转为1/0

        y_pred = y_pred - (1 - y_true) * 1e12
        # 标签为1的sample cosine值应大于标签为0的sample
        # 具体就是标签为0与标签为1的值为cosine差值，标签相同值为-e12，不用更新loss

        y_pred = y_pred.view(-1)
        if torch.cuda.is_available():
            y_pred = torch.cat((torch.tensor([0]).float().cuda(), y_pred),
                               dim=0)  # 这里加0是因为e^0 = 1相当于在log中加了1，对应blog公式(6)
        else:
            y_pred = torch.cat((torch.tensor([0]).float(), y_pred), dim=0)

        return torch.logsumexp(y_pred, dim=0)

    def get_loss(self, pred, target, batch_dict):
        loss = self.compute_loss(pred, target)
        return loss

model = CosentModel()
trainer = Trainer(model, args, train_dataset, loss=CosentLoss(), eval_loss='none',
                  dev_data=dev_dataset, validate_every=100,
                  train_collate_fn=train_collate_fn, eval_collate_fn=eval_collate_fn, metrics='spearman')

if __name__ == "__main__":
    trainer.train()
    # lcqmc  loss7.39  0.7906852422718601
    # bert4torch lqcmc 0.79386  loss 7.898897


import time
from selenium import webdriver
import uuid
import urls
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException

def helperGet(id, max_delay=10):
    try:
        element = WebDriverWait(browser, max_delay).until(
            EC.presence_of_element_located((By.ID, id))
        )
        return browser.find_element_by_id(id)
    except TimeoutException:
        print("Loading took too much time for id :" + id)

def helperGetByName(name, max_delay=10):
    try:
        element = WebDriverWait(browser, max_delay).until(
            EC.presence_of_element_located((By.NAME, name))
        )
        return browser.find_element_by_name(name)
    except TimeoutException:
        print("Loading took too much time for name :" + name)

def do_navi_bar_click_test(menu):
    helperGet("navi_" + menu).click()
    time.sleep(4)
    # The page should be redirected to login page.

def search_and_goto_wall(username):
    helperGet('search_bar').send_keys(username[0:4])
    helperGet('search_btn').click()
    time.sleep(2)
    find = False
    searchnum = 0
    for i in range(30):
        if helperGet('search_result_user' + str(i)).text == username:
            searchnum = i
            find = True
            break

    if not find:
        print('error: cannot find user {0}'.format(username))
        exit(1)

    helperGet('search_result_user' + str(searchnum)).click()
    assert helperGet('wall_title').text == 'This is ' + username + '\'s wall'

def go_to_my_wall():
    do_navi_bar_click_test("profile")

def log_out():
    do_navi_bar_click_test("logout")
    time.sleep(1)

def login(username, pwd):
    do_navi_bar_click_test("login")
    time.sleep(1)
    helperGet('username_field').send_keys(username)
    helperGet('password_field').send_keys(pwd)
    helperGet('login_submit').click()

def post(text):
    helperGet('text').send_keys(text)
    time.sleep(4)
    helperGet('post_btn').click()
    time.sleep(6)

def signup(username, userpwd):
    helperGet('signup_page_link').click()
    helperGet('username_field').send_keys(username)
    helperGet('email_field').send_keys(username + "@test.com")
    helperGet('password_field').send_keys(userpwd)
    helperGet('password_confirm_field').send_keys(userpwd)
    helperGet('signup_submit').click()

def make_test_id():
    testid = str(uuid.uuid4())
    testid = testid[0:7]
    username = testid
    return username

def scenario_1():
    print("@ scenario 1: friend request accepted")

    print(">>> send the request : test1 -> test2")
    ###
    print('... login as test1')
    login(test1, '1234')
    time.sleep(2)

    print("... go to test2's wall")
    search_and_goto_wall(test2)
    time.sleep(2)

    print("... click send friend request")
    helperGetByName("navi_add_friends").click()
    time.sleep(2)
    ###
    print('... logout')
    log_out()
    time.sleep(2)

    print(">>> accept the request : test2 accepts")
    ###
    print('... login as test2')
    login(test2, '1234')
    time.sleep(2)

    print('... go to my wall')
    go_to_my_wall()
    time.sleep(2)

    print('... click view friend request')
    helperGetByName("navi_view_requests").click()
    time.sleep(2)

    print("... locate test1's request and accept")
    helperGetByName("add_" + test1).click()
    time.sleep(4)
    helperGet("confirm").click()
    time.sleep(2)

    print("... click friend list")
    helperGetByName("navi_view_friend_list").click()
    time.sleep(3)

    print("... friendship established")
    helperGetByName("confirm").click()
    time.sleep(2)

    print('... logout')
    log_out()
    time.sleep(2)

def scenario_2():
    print("@ scenario 2: friend request declined")
    print(">>> send the request : test3 -> test2")
    print('... login as test3')
    login(test3, '1234')
    print("... go to test2's wall")
    search_and_goto_wall(test2)
    time.sleep(2)
    print("... click send friend request")
    helperGetByName("navi_add_friends").click()
    time.sleep(2)
    print("... logout")
    log_out()

    print(">>> decline the request : test2 declines")
    print('... login as test2')
    login(test2, '1234')
    print('... go to my wall')
    go_to_my_wall()
    print('... click view friend request')
    helperGetByName("navi_view_requests").click()
    time.sleep(2)
    print("... locate test1's request and decline")
    helperGetByName("decline_" + test3).click()
    time.sleep(3)
    helperGet("confirm").click()
    time.sleep(2)
    print('... logout')
    log_out()
    time.sleep(2)

def scenario_3():
    print("@ scenario 3: cancel sent friend request(other's wallpage)")
    print(">>> send the request : test4 -> test2")
    print('... login as test4')
    login(test4, '1234')
    time.sleep(2)
    print("... go to test2's wall")
    search_and_goto_wall(test2)
    time.sleep(2)
    print("... click send friend request")
    helperGetByName("navi_add_friends").click()
    time.sleep(2)

    print(">>> cancel the request : test4 cancels")
    print('... click cancel button')
    helperGetByName("navi_cancel_request").click()
    time.sleep(2)
    print('... logout')
    log_out()
    time.sleep(2)

def scenario_4():
    print("@ scenario 4: cancel sent friend request(my wallpage)")
    print(">>> send the request : test5 -> test2")
    print('... login as test5')
    login(test5, '1234')
    print("... go to test2's wall")
    search_and_goto_wall(test2)
    time.sleep(2)
    print("... click send friend request")
    helperGetByName("navi_add_friends").click()
    time.sleep(2)
    print(">>> cancel the request : test5 cancels")
    print('... go to my wall')
    go_to_my_wall()
    time.sleep(2)
    print('... click view friend request')
    helperGetByName("navi_view_requests").click()
    time.sleep(2)
    print("... locate request made to test2 and cancel")
    helperGetByName("cancel_" + test2).click()
    time.sleep(3)
    helperGet("confirm").click()
    time.sleep(2)
    print("... logout")
    log_out()

def scenario_5():
    print("@ scenario 5: we are no longer friends :( (my wall page)")
    print('... login as test2')
    login(test1, '1234')
    time.sleep(2)
    print('... go to my wall')
    go_to_my_wall()
    time.sleep(2)
    print('... click view friend request')
    helperGetByName("navi_view_friend_list").click()
    time.sleep(2)
    print("... locate test2 and unfriend")
    helperGetByName("unfriend_" + test2).click()
    time.sleep(3)
    helperGetByName("confirm").click()
    time.sleep(2)
    print("... logout")
    log_out()

# get host url
url = urls.host_url()
browser = webdriver.Chrome('/usr/local/bin/chromedriver')
# go to the url
browser.get(url)

# make 4 test users
usernames = []
for i in range(5):
    usernames.append(make_test_id())

# do signup
print("... do sign up")
for name in usernames:
    print("signup test id: "+name)
    signup(name, '1234')

# test
test1 = usernames[0]
test2 = usernames[1]
test3 = usernames[2]
test4 = usernames[3]
test5 = usernames[4]

# send the request : test1 -> test2
# accept the request : test2 accepts
scenario_1()
# send the request : test3 -> test2
# decline the request : test2 declines
scenario_2()
# send the request : test4 -> test2
# cancels the request : test4 cancels (from test2's wall page)
scenario_3()
# send the request : test5 -> test2
# cancels the request : test5 cancels (from my wall page)
scenario_4()
# unfriend : test1 unfriends test2
scenario_5()

browser.quit()

print("done testing friend functionality")


from django.http import HttpResponse
import pandas as pd
from ..models import *
from ..constant import *
import datetime
import csv

def trade_position_list(request):
    if request.method == "GET":
        strategy_id = request.GET.get('strategy_id')
        day = int(request.GET.get('day'))
        all_date = StrategyTradePositionList.objects.order_by("create_date").values("create_date").distinct()
        #print(all_date[len(all_date)-1]["create_date"])
        target_position = StrategyTradePositionList.objects.filter(create_date=all_date[len(all_date)-1+day]["create_date"],strategy_id=strategy_id).values()
        hold_position = StrategyTradePositionList.objects.filter(create_date=all_date[len(all_date)-1-1+day]["create_date"],strategy_id=strategy_id).values()
        df_order = generate_order(target_position,hold_position)
        print(df_order)
        return HttpResponse(df_order,content_type='text/csv')
    else:
        strategy_id = request.GET.get('strategy_id')
        file = request.FILES.get('upload_file', None)
        df = pd.read_csv(file,encoding="gb2312")

        date = file.name.split('.')[0].split('_')[1]
        StrategyTradePositionList.objects.filter(create_date=date,strategy_id=strategy_id).delete()

        for index,row in df.iterrows():
            position = StrategyTradePositionList(
                create_date=date,
                code=row[4],
                position=row[5] if row[5]>0 else row[6],
                direction= Direction.LONG.value if row[5]>0 else Direction.SHORT.value,
                strategy_id=strategy_id
            )
            position.save()
        return HttpResponse("put trade list succeed")

def generate_order(target_position,hold_position):
    orders = []
    long = Direction.LONG.value
    short = Direction.SHORT.value
    for hp in hold_position:
        order = {}
        shold_close = True
        # 调整现有仓位
        for tp in target_position:
            if tp['code'] == hp['code'] and tp['direction'] == hp['direction'] :
                diff = tp['position'] - hp['position']
                order['合约id'] = tp['code']
                order['开平（开仓；平仓；平今；平昨）'] = Offset.OPEN if diff>=0 else Offset.CLOSE

                if order['开平（开仓；平仓；平今；平昨）'] == Offset.OPEN:
                    if tp['direction'] == long:
                        order['买卖（买；卖）'] = long
                    else:
                        order['买卖（买；卖）'] = short
                else:
                    if tp['direction'] == long:
                        order['买卖（买；卖）'] = short
                    else:
                        order['买卖（买；卖）'] = long

                order['数量'] = abs(diff)
                if diff != 0:
                    orders.append(order)
                shold_close = False
                break

        # 平老仓位
        if shold_close:
            order['合约id'] = hp['code']
            order['开平（开仓；平仓；平今；平昨）'] = Offset.CLOSE
            order['买卖（买；卖）'] = long if hp['direction'] == short else short
            order['数量'] = hp['position']
            orders.append(order)

    for tp in target_position:

        shold_open = True
        for hp in hold_position:
            if hp['code'] == tp['code'] and hp['direction'] == tp['direction'] :
                shold_open = False
                break

        #开新仓位
        if shold_open:
            order = {}
            order['合约id'] = tp['code']
            order['开平（开仓；平仓；平今；平昨）'] = Offset.OPEN
            order['买卖（买；卖）'] = short if tp['direction'] == short else long
            order['数量'] = tp['position']
            orders.append(order)

    for order in orders:
        order['C\S（本地；云端）'] = "本地"
        order['触发日期（年月日；例如：2019.3.15）'] = datetime.date.today().strftime('%Y.%m.%d')
        order['触发时间（时分秒；例如：13:25）'] = '9:11:23'
        order['附加条件（是；否）'] = '否'
        order['触发价类型（附加条件）（最新价；买一价；卖一价）'] = ''
        order['触发价方向（附加条件）（向上突破；向下跌破；大于等于；小于等于；大于；小于）'] = ''
        order['触发线（附加条件）'] = ''
        order['委托价（最新价；对手价；市价；自定义）'] = '对手价'
        order['超价'] = ''
        order['自定义委托价'] = ''
        order['追单（是；否）'] = '是'
        order['投保（投机；套保）'] = '投机'
        order['买卖（买；卖）'] = "买" if order['买卖（买；卖）']==long else "卖"
        order['开平（开仓；平仓；平今；平昨）'] = "开仓" if order['开平（开仓；平仓；平今；平昨）'] == Offset.OPEN else "平仓"

    order_context = HttpResponse(content_type='text/csv',charset='gb2312')  # 告诉浏览器是text/csv格式
    order_context['Content-Disposition'] = 'attachment; filename="somefilename.csv"'  # csv文件名，不影响

    writer = csv.writer(order_context)

    columns = ["合约id","C\S（本地；云端）","触发日期（年月日；例如：2019.3.15）","触发时间（时分秒；例如：13:25）","附加条件（是；否）","触发价类型（附加条件）（最新价；买一价；卖一价）",
     "触发价方向（附加条件）（向上突破；向下跌破；大于等于；小于等于；大于；小于）","触发线（附加条件）","买卖（买；卖）","开平（开仓；平仓；平今；平昨）","委托价（最新价；对手价；市价；自定义）","超价","自定义委托价",
               "数量","追单（是；否）","投保（投机；套保）"]

    writer.writerow(columns)
    for order in orders:
        writer.writerow([order[column] for column in columns])
    return order_context


"""文本处理相关工具集."""
import re
from typing import List, Optional, Tuple

import numpy as np
from LAC import LAC
from transformers.tokenization_utils import PreTrainedTokenizer

def cut_sent(para: str) -> List[str]:
    """分字并处理标点符号."""
    para = re.sub('([，。！？,\\.\\?!])([^”’])', r"\1\n\2", para)  # 单字符断句符
    para = re.sub('(\\.{6})([^”’])', r"\1\n\2", para)  # 英文省略号
    para = re.sub('(\\…{2})([^”’])', r"\1\n\2", para)  # 中文省略号
    para = re.sub('([。！？\\?][”’])([^，。！？\\?])', r'\1\n\2', para)
    # 如果双引号前有终止符，那么双引号才是句子的终点，把分句符\n放到双引号后，注意前面的几句都小心保留了双引号
    para = para.rstrip()  # 段尾如果有多余的\n就去掉它
    # 很多规则中会考虑分号;，但是这里我把它忽略不计，破折号、英文双引号等同样忽略，需要的再做些简单调整即可。
    return para.split("\n")

lac_seg = LAC(mode='lac')

def segment_text(text: str,
                 tokenizer: Optional[PreTrainedTokenizer] = None) -> List[str]:
    """分词

    输入一句话，返回一句经过处理的分词列表: 为了支持中文全称mask，将被分开的词，将上特殊标记("#")，
    使得后续处理模块，能够知道哪些字是属于同一个词的。

    Args:
        text (str): 待分词字符串
        tokenizer (Optional[PreTrainedTokenizer], optional):
            用于分词的tokenizer. Defaults to None.

    Returns:
        List[str]: 分词后的token列表

    Todo:
        - [ ] (Jiang Yuzhen) 可读性和函数结构待优化
    """
    # text = "".join(cut_sent(text)) # 处理标点符号
    seq_cws = lac_seg.run(text)[0]
    seq_cws_dict = {x: 1 for x in seq_cws}  # 分词后的词加入到词典dict
    segment: List[str] = []
    i = 0
    while i < len(text):  # 从句子的第一个字开始处理，知道处理完整个句子
        # 如果找不到中文的，原文加进去即不用特殊处理。
        # if len(re.findall('[\u4E00-\u9FA5]', text[i])) == 0:
        #     new_text.append(text[i])
        #     i += 1
        #     continue

        # 由于LAC对于像2018或者abc这种非中文字符会直接切分成单个字符，
        # 所以这里加入连续非中文字符的识别，然后使用bert的分词器进行重新切分
        non_chinese = []
        while (i < len(text)
               and len(re.findall('[\u4E00-\u9FA5]', text[i])) == 0):
            non_chinese.append(text[i])
            i += 1
        if non_chinese:
            tokens = tokenizer.tokenize(
                ''.join(non_chinese)) if tokenizer else non_chinese
            segment.extend(tokens)
        if i >= len(text):
            break
        has_add = False
        for length in range(3, 0, -1):
            if i + length > len(text):
                continue
            if ''.join(text[i:i + length]) in seq_cws_dict:
                segment.append(text[i])
                for j in range(1, length):
                    segment.append('##' + text[i + j])
                i += length
                has_add = True
                break
        if not has_add:
            segment.append(text[i])
            i += 1
    return segment

def text_2_training_instance(
    text: str,
    max_length: int,
    tokenizer: PreTrainedTokenizer,
    index: Optional[int] = None
) -> Tuple[List[str], Optional[bool]]:  # type: ignore
    """文本转训练样本.

    Args:
        text (str): 文本字符串
        max_length (int): 长度上限
        tokenizer (PreTrainedTokenizer):
        index (Optional[int], optional): 样本对应id. Defaults to None.

    Returns:
        Tuple[List[str], Optional[bool]]: (token列表, is_random_next)

    Todo:
        - [ ] (Jiang Yuzhen) 可读性和函数结构待优化
    """
    # char_list = segment_text(text, tokenizer) .   # 用来分句的
    char_list = [segment_text(sen, tokenizer) for sen in cut_sent(text)]
    max_num_tokens = max_length - 3
    target_seq_length = max_num_tokens
    if index is None:
        index = np.random.randint(1, 10000)
    rng = np.random.RandomState(seed=((1234 + index) % 2**32))  # type: ignore
    current_chunk = []  # 当前处理的文本段，包含多个句子
    current_length = 0
    i = 0

    tokens = []
    is_random_next = None

    while i < len(char_list):  # 从文档的第一个位置开始，按个往下看
        # segment是列表，代表的是按字分开的一个完整句子，
        # segment=['我', '是', '一', '爷', '##们',
        # '，', '我', '想', '我', '会', '给', '我',
        # '媳', '##妇', '最', '##好', '的', '##幸',
        # '##福', '。']
        segment = char_list[i]

        current_chunk.append(segment)  # 将一个独立的句子加入到当前的文本块中
        current_length += len(segment)  # 累计到为止位置接触到句子的总长度
        if i == len(char_list) - 1 or current_length >= target_seq_length:
            # 如果累计的序列长度达到了目标的长度，或当前走到了文档结尾==>构造并添加到“A[SEP]B“中的A和B中；
            if current_chunk:  # 如果当前块不为空
                a_end = 1
                # 当前块，如果包含超过两个句子，取当前块的一部分作为“A[SEP]B“中的A部分
                if len(current_chunk) > 2:
                    a_end = rng.randint(1, len(current_chunk) - 1)
                elif len(current_chunk) == 2:
                    a_end = 1

                # 将当前文本段中选取出来的前半部分，赋值给A即tokens_a
                tokens_a = []
                for j in range(a_end):
                    tokens_a.extend(current_chunk[j])

                # 构造“A[SEP]B“中的B部分(有一部分是正常的当前文档中的后半部;在原BERT的实现中一部分是随机的从另一个文档中选取的，）
                tokens_b = []
                for j in range(a_end, len(current_chunk)):
                    tokens_b.extend(current_chunk[j])

                # 有百分之50%的概率交换一下tokens_a和tokens_b的位置
                # print("tokens_a length1:",len(tokens_a))
                # print("tokens_b length1:",len(tokens_b)) # len(tokens_b) = 0

                if len(tokens_a) == 0 or len(tokens_b) == 0:
                    tokens = tokens_a[:max_num_tokens]
                    tokens.append('[SEP]')
                    return tokens, None

                if rng.random() < 0.5:  # 交换一下tokens_a和tokens_b
                    is_random_next = True
                    temp = tokens_a
                    tokens_a = tokens_b
                    tokens_b = temp
                else:
                    is_random_next = False

                truncate_seq_pair(tokens_a, tokens_b, max_num_tokens, rng)

                assert len(tokens_a) >= 1
                assert len(tokens_b) >= 1

                # 把tokens_a & tokens_b加入到按照bert的风格，
                # 即以[CLS]tokens_a[SEP]tokens_b[SEP]的形式，结合到一起，
                # 作为最终的tokens; 也带上segment_ids，前面部分segment_ids的值是0，后面部分的值是1.
                tokens = []
                segment_ids = []
                segment_ids.append(0)
                for token in tokens_a:
                    tokens.append(token)
                    segment_ids.append(0)

                tokens.append("[SEP]")
                segment_ids.append(0)

                for token in tokens_b:
                    tokens.append(token)
                    segment_ids.append(1)
                segment_ids.append(1)

            return tokens, is_random_next

        i += 1  # 接着文档中的内容往后看
    return tokens, None

def truncate_seq_pair(tokens_a, tokens_b, max_num_tokens, rng):
    """Truncates a pair of sequences to a maximum sequence length."""
    while True:
        total_length = len(tokens_a) + len(tokens_b)
        if total_length <= max_num_tokens:
            break

        trunc_tokens = tokens_a if len(tokens_a) > len(tokens_b) else tokens_b
        assert len(trunc_tokens) >= 1

        # We want to sometimes truncate from the front and sometimes from the
        # back to add more randomness and avoid biases.
        if rng.random() < 0.5:
            del trunc_tokens[0]
        else:
            trunc_tokens.pop()