import keras
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from keras.layers import Dense
from sklearn.preprocessing import MinMaxScaler
from keras import regularizers

google_stock = pd.read_excel('道琼斯综合.xls')
print(google_stock.tail())
print(google_stock.head())

time_stamp = 50
google_stock = google_stock[['开盘价(元/点)_OpPr']]
train = google_stock[0:7000 + time_stamp]
valid = google_stock[7000 - time_stamp:8500 + time_stamp]
test = google_stock[8500 - time_stamp:]

print(train.head())

scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(train)
x_train, y_train = [], []

for i in range(time_stamp, len(train) - 5):
    x_train.append(scaled_data[i - time_stamp:i])
    y_train.append(scaled_data[i:i + 5])

#print(x_train[0:10])
#print(y_train[0:10])
x_train, y_train = np.array(x_train), np.array(y_train).reshape(-1, 5)

#print(y_train[0:10])

scaled_data = scaler.fit_transform(valid)
x_valid, y_valid = [], []
for i in range(time_stamp, len(valid) - 5):
    x_valid.append(scaled_data[i - time_stamp:i])
    y_valid.append(scaled_data[i: i + 5])
x_valid, y_valid = np.array(x_valid), np.array(y_valid).reshape(-1, 5)

scaled_data = scaler.fit_transform(test)
x_test, y_test = [], []
for i in range(time_stamp, len(test) - 5):
    x_test.append(scaled_data[i - time_stamp:i])
    y_test.append(scaled_data[i: i + 5])
x_test, y_test = np.array(x_test), np.array(y_test).reshape(-1, 5)

def create_model():
    model = keras.Sequential()
    model.add(keras.layers.LSTM(64, return_sequences=True, input_shape=(x_train.shape[1:])))
    model.add(keras.layers.LSTM(64, return_sequences=True))
    model.add(keras.layers.LSTM(32))
    model.add(keras.layers.Dropout(0.1))
    model.add(keras.layers.Dense(5))
    model.compile(optimizer='adam', loss='mae', metrics=['accuracy'])

    return model

learning_rate_reduction = keras.callbacks.ReduceLROnPlateau(monitor='val_loss', patience=3, factor=0.7,
                                                            min_lr=0.000000005)

lstm_model = create_model()

history = lstm_model.fit(x_train,y_train,batch_size=128,epochs=70,
                         validation_data=(x_valid,y_valid),
                         callbacks=[learning_rate_reduction])

plt.plot(history.history['loss'],label='training loss')
plt.plot(history.history['val_loss'], label='val loss')
plt.legend()
plt.show()

closing_price = lstm_model.predict(x_test)
lstm_model.evaluate(x_test)
scaler.fit_transform(pd.DataFrame(valid['开盘价(元/点)_OpPr'].values))

closing_price = scaler.inverse_transform(closing_price.reshape(-1,5)[:,0].reshape(1,-1)) #只取第一列
y_test = scaler.inverse_transform(y_test.reshape(-1,5)[:,0].reshape(1,-1))

rms = np.sqrt(np.mean(np.power((y_test[0:1,5:] - closing_price[0:1,5:] ), 2)))
print(rms)
print(closing_price.shape)
print(y_test.shape)

plt.figure(figsize=(16,8))
dict_data = {
    'Predictions': closing_price.reshape(1,-1)[0],
    '开盘价(元/点)_OpPr': y_test[0]
}
data_pd = pd.DataFrame(dict_data)
plt.plot(data_pd[['开盘价(元/点)_OpPr']],linewidth=3,alpha=0.8)
plt.plot(data_pd[['Predictions']],linewidth=1.2)
plt.show()

学习-pycharm/机器学习极简入门/第十章/Kreas基于LSTM的股市预测.py


# Programa para obtener dos matrices, una con los n-gramas distintos
# y otra con (el nombre de) los n-gramas iguales
# de cada categoría de virus con cada una de las demás

# Julia Quero Pérez - 792310

#Librerías necesarias
import csv
from collections import Counter, defaultdict
from nltk.util import ngrams

#Longitud de los ngramas
#N = 3
N = int(input('Longitud de los ngramas: '))

forma = input('¿Quieres trabajar con API o con Cat?: ')
def entrada(f):
    if f == 'API':
        return 'tratado_API_dataset.csv'
    else:
        return 'tratado_Cat_dataset.csv'
def salida1(f):
    if f == 'API':
        return 'tablas/nom_diff_matrix_API.txt'
    else:
        return 'tablas/nom_diff_matrix_Cat.txt'
def salida2(f):
    if f == 'API':
        return 'tablas/nom_same_matrix_API.txt'
    else:
        return 'tablas/nom_same_matrix_Cat.txt'

# Parte del total de las trazas en las que ha de aparecer un ngrama para considerarse relevante
#sesgo_percent = 0.61
sesgo_percent = float(input('Porcentaje a considerar: '))

# Diccionario para contar ocurrencias de cada virus
cat_count = {'Backdoor':0, 'Worm':0, 'Packed':0, 'Trojan':0, 'PUP':0, 'Benigno':0}

with open(entrada(forma),'r',newline='') as file:
    reader = csv.reader(file)

    # Guarda el número de trazas en las que aparece cierto ngrama para cada categoría
    data_traza = defaultdict()
    # Guarda el número ocurrencias totales para cierto ngrama para cada categoría
    data_ocur  = defaultdict()

    for row in reader:

        #Guardo en un counter las APIs del virus row[0]
        lista = list(ngrams(row[2:len(row)],N))
        traza = Counter(lista)

        # Sumo a la cuenta
        cat_count[row[0]] += 1

        # Añado al diccionario
        if row[0] in data_traza:
            for k in traza:
                if k in data_traza[row[0]]:
                    data_traza[row[0]][k]+=1
                    data_ocur[row[0]][k]+=traza[k]
                else:
                    data_traza[row[0]][k]=1
                    data_ocur[row[0]][k] = traza[k]
        else:
            data_traza.update({row[0]:dict()})
            data_ocur.update({row[0]:dict()})
            for k in traza:
                data_traza[row[0]][k] = 1
                data_ocur[row[0]][k] = traza[k]

#-------------------------------------------------------------
# Ahora hago el tratamiento: guardo los más comunes
data_res = dict()
for cat in data_traza:
    data_res[cat] = list()
    sesgo = cat_count[cat]*sesgo_percent
    for ngr in data_traza[cat]:
        if data_traza[cat][ngr] > sesgo:
            data_res[cat].append(ngr)
#-------------------------------------------------------------

#-------------------------------------------------------------
# Parte de análisis cuantitativo conjunto
# Algoritmo de fuerza bruta.
# Nótese que la matriz data_same es simétrica, por lo que existe un algoritmo mejor.

# Ahora guardo los ngramas distintas
# También guardo los ngramas iguales
data_diff = defaultdict()
data_same = defaultdict()
for kRow in data_res:
    data_diff[kRow] = dict()
    data_same[kRow] = dict()
    for kCol in data_res:
        data_diff[kRow][kCol] = list()
        data_same[kRow][kCol] = list()
        for el in data_res[kRow]:
            if el not in data_res[kCol]:
                data_diff[kRow][kCol].append(el)
            else:
                data_same[kRow][kCol].append(el)

#-------------------------------------------------------------

#-------------------------------------------------------------
# Escritura de los resultados.
# Pongo en un txt los nombre{n-gramas distintos}
out = open(salida1(forma),'w',newline='')
for key in data_diff:
    for jey in data_diff:
        if jey != key:
            out.write(key)
            out.write(' se diferencia a ')
            out.write(jey)
            out.write(' en: ')
            out.write('\n')
            for el in data_diff[key][jey]:
                out.write(str(el))
                out.write('\n')
            out.write('\n')
            out.write('\n')
out.close()

# Pongo en un txt los nombre{n-gramas iguales}
out = open(salida2(forma),'w',newline='')
keyList = list(data_same.keys())
for i in range(0,len(keyList)):
    for j in range(i+1,len(keyList)):
        out.write(keyList[i])
        out.write(' coincide con ')
        out.write(keyList[j])
        out.write(' en: ')
        out.write('\n')
        for el in data_same[keyList[i]][keyList[j]]:
            out.write(str(el))
            out.write('\n')
        out.write('\n')
        out.write('\n')
out.close()

#-------------------------------------------------------------


from collections import Counter

assignments = []
rows = 'ABCDEFGHI'
cols = '123456789'

def cross(A, B):
    "Cross product of elements in A and elements in B."
    return [s+t for s in A for t in B]

boxes = cross(rows,cols)
row_units = [cross(r, cols) for r in rows]

column_units = [cross(rows, c) for c in cols]
square_units = [cross(rs, cs) for rs in ('ABC','DEF','GHI') for cs in ('123','456','789')]
diagonal_units = [[(rows[i]+cols[i]) for i in range(0, len(rows))], [(rows[8-i] + cols[i]) for i in range(0, len(rows))]]
unitlist = row_units + column_units + square_units + diagonal_units

units = dict((s, [u for u in unitlist if s in u]) for s in boxes)
peers = dict((s, set(sum(units[s],[]))-set([s])) for s in boxes)

def assign_value(values, box, value):
    """
    Please use this function to update your values dictionary!
    Assigns a value to a given box. If it updates the board record it.
    """
    values[box] = value
    if len(value) == 1:
        assignments.append(values.copy())
    return values

def naked_twins(values):
    """
    Eliminate values using the naked twins strategy.
    Args:
        values(dict): sudoku in dictionary form
    Returns:
        values(dict): resulting sudoku in dictionary form.
    """
    # Create a list of potential twins
    potential_twins = [box for box in values.keys() if len(values[box]) == 2]

    # Create an array of tuples (value, unit) that contain the twin pairs
    tuple_array = []

    for unit in unitlist:

        # Create a Counter for boxes that have two items in length
        item_count = Counter()

        # Search through boxes in each unit
        for box in unit:
            if box in potential_twins:
                item_count[values[box]] += 1

        # Iterate through boxes with 2 nunmbers inside of them
        for key in item_count.keys():
            if item_count[key] == 2:
                tuple_array.append((key, unit))

    # Remove numbers in naked twins from the peers
    for tup in tuple_array:
        key = tup[0]
        unit = tup[1]

        for box in unit:
            if values[box] != key:
                    assign_value(values, box, values[box].replace(key[0], '').replace(key[1], ''))

    return values

def grid_values(grid):
    """
    Convert grid into a dict of {square: char} with '123456789' for empties.
    Args:
        grid(string) - A grid in string form.
    Returns:
        A grid in dictionary form
            Keys: The boxes, e.g., 'A1'
            Values: The value in each box, e.g., '8'. If the box has no value, then the value will be '123456789'.
    """
    box_dict = {}
    for idx, box in enumerate(boxes):
        if grid[idx] == '.':
            assign_value(box_dict, box, '123456789')
        else:
            assign_value(box_dict, box, grid[idx])

    return box_dict

def display(values):
    """
    Display the values as a 2-D grid.
    Args:
        values(dict): The sudoku in dictionary form
    """
    width = 1+max(len(values[s]) for s in boxes)
    line = '+'.join(['-'*(width*3)]*3)
    for r in rows:
        print(''.join(values[r+c].center(width)+('|' if c in '36' else '')
                      for c in cols))
        if r in 'CF': print(line)

def eliminate(values):
    """
    Remove the solved boxes value from its peers
    Args:
        values(dict): sudoku in dictionary form.
    Returns:
        values(dict): resulting sudoku in dictionary form.
    """
    solved_values = [box for box in values.keys() if len(values[box]) == 1]
    for box in solved_values:
        digit = values[box]
        for peer in peers[box]:
            assign_value(values, peer, values[peer].replace(digit,''))
    return values

def only_choice(values):
    """
    Set the value of boxes that can only be one value in relation to other boxes in the unit
    Args:
        values(dict): A sudoku in dictionary form.
    Returns:
        values(dict): The resulting sudoku in dictionary form.
    """
    for unit in unitlist:
        for digit in '123456789':
            dplaces = [box for box in unit if digit in values[box]]
            if len(dplaces) == 1:
                values[dplaces[0]] = digit
    return values

def reduce_puzzle(values):
    """
    Iterate eliminate(), naked_twins() and only_choice() to eliminate uncertain boxes

    Args:
        values(dict): sudoku in dictionary form.
    Returns:
        values(dict): resulting sudoku in dictionary form.
    """
    solved_values = [box for box in values.keys() if len(values[box]) == 1]
    stalled = False
    while not stalled:
        solved_values_before = len([box for box in values.keys() if len(values[box]) == 1])
        values = eliminate(values)
        values = naked_twins(values)
        values = only_choice(values)
        solved_values_after = len([box for box in values.keys() if len(values[box]) == 1])
        stalled = solved_values_before == solved_values_after
        if len([box for box in values.keys() if len(values[box]) == 0]):
            return False
    return values

def search(values):
    """
    Using depth-first search and constraint propagation, try all possible values.
    Args:
        values(dict): sudoku in dictionary form.
    Returns:
        resulting sudoku in dictionary form if successful, otherwise return False
    """
    values = reduce_puzzle(values)
    if values is False:
        return False
    if all(len(values[s]) == 1 for s in boxes):
        return values

    n,s = min((len(values[s]), s) for s in boxes if len(values[s]) > 1)
    for value in values[s]:
        new_sudoku = values.copy()
        new_sudoku[s] = value
        attempt = search(new_sudoku)
        if attempt:
            return attempt

def solve(grid):
    """
    Find the solution to a Sudoku grid.
    Args:
        grid(string): a string representing a sudoku grid.
            Example: '2.............62....1....7...6..8...3...9...7...6..4...4....8....52.............3'
    Returns:
        resulting sudoku in dictionary form if successful, otherwise return False
    """
    values = grid_values(grid)
    values = search(values)
    return values

if __name__ == '__main__':
    diag_sudoku_grid = '2.............62....1....7...6..8...3...9...7...6..4...4....8....52.............3'
    display(solve(diag_sudoku_grid))
    try:
        from visualize import visualize_assignments
        visualize_assignments(assignments)

    except SystemExit:
        pass
    except:
        print('We could not visualize your board due to a pygame issue. Not a problem! It is not a requirement.')


# -*- coding: utf-8 -*-
# (c) 2020 Miquel March <m.marchpuig@gmail.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import logging
from odoo.exceptions import ValidationError
from datetime import datetime
from odoo import api, models, fields

_logger = logging.getLogger(__name__)

class PartnerEmployeeCreateWizard(models.TransientModel):
    """
    Assistent per crear al mateix temps: l'empleat i el contacte
    """
    _name = "partner.employee.create.wizard"

    image = fields.Binary("Image", attachment=True, help="Limitat a 1024x1024px.")

    nom = fields.Char("Nom")
    vat = fields.Char("NIF")
    email = fields.Char("Email")
    phone = fields.Char("Teléfon")
    carrer = fields.Char("Carrer")
    carrer2 = fields.Char("Carrer 2")
    zip_id = fields.Many2one("res.better.zip", "Zip")
    nom_croquis = fields.Char(string="Nom del croquis", help="Nom que apareix en els croquis")
    data_inscripcio = fields.Date(string="Data inscripció")
    data_naixement = fields.Date(string="Data de naixement")
    notes = fields.Text(string="Notes")
    colla_id = fields.Many2one("res.partner", "Colla", default=1, readonly=True)

    gender = fields.Selection([
        ('male', 'Male'),
        ('female', 'Female'),
        ('other', 'Other')
    ], string="Génere")
    marital_status = fields.Selection([
        ('single', 'Single'),
        ('married', 'Married'),
        ('cohabitant', 'Legal Cohabitant'),
        ('widower', 'Widower'),
        ('divorced', 'Divorced')
    ], string="Estat civil")

    employee_skill_ids = fields.One2many("partner.employee.create.wizard.line", "wizard_id", string="Posicions")

    height = fields.Integer("Height")
    alsada_muscle = fields.Integer(string="Alçada muscle")
    alsada_bras = fields.Integer(string="Alçada braços")
    weight = fields.Float(string="Weight", digits=(4, 1))

    @api.model
    def default_get(self, fields_list):
        """
        Alguns valors per defecte
        """
        res = super(PartnerEmployeeCreateWizard, self).default_get(fields_list)
        res.update({'data_inscripcio': datetime.today().date()})
        return res

    def create_partner_employee(self):
        """
        Crea al mateix temps: el contacte i l'empleat
        """
        partner_obj = self.env['res.partner']
        employee_obj = self.env['hr.employee']
        emp_skill_obj = self.env['hr.employee.skill']
        anthropometry_obj = self.env['hr.employee.anthropometry']

        data = {
            'company_type': 'person',
            'name': self.nom,
            'image': self.image,
            'muixeranguera': True,
            'colla_id': self.colla_id.id,
            'email': self.email,
            'mobile': self.phone,
            'vat': self.vat,
            'street': self.carrer,
            'street2': self.carrer2,
            'zip': self.zip_id.name,
            'zip_id': self.zip_id.id,
            'city': self.zip_id.city,
            'country_id': self.zip_id.country_id.id,
            'state_id': self.zip_id.state_id.id,
            'comment': self.notes,
        }
        partner = partner_obj.create(data)
        _logger.info("Creant contacte: {}❗".format(partner.name))

        data_inscripcio = self.data_inscripcio or datetime.today().date().__str__()

        data = {
            'name': self.nom,
            'image': partner.image,
            'nom_croquis': self.nom_croquis,
            'address_home_id': partner.id,
            'gender': self.gender,
            'marital': self.marital_status,
            'birthday': self.data_naixement,
            'data_inscripcio': data_inscripcio,
            'notes': self.notes,
        }
        employee = employee_obj.create(data)
        partner.membre_id = employee.id
        _logger.info("Creant empleat: {}❗".format(employee.name))

        lines = self.employee_skill_ids
        skills = emp_skill_obj
        for line in lines:
            data = {
                'employee_id': employee.id,
                'skill_id': line.skill_id.id,
                'level': line.level,
            }
            skills += emp_skill_obj.create(data)

        mesura = True
        if bool(self.height) and bool(self.weight):
            data = {
                'data': data_inscripcio,
                'employee_id': employee.id,
                'height': self.height,
                'weight': self.weight,
                'alsada_muscle': self.alsada_muscle,
                'alsada_bras': self.alsada_bras,
            }
            mesura = anthropometry_obj.create(data)

        res = bool(partner) and bool(employee) and bool(skills) and bool(mesura)
        return res

class PartnerEmployeeCreateWizardLine(models.TransientModel):
    _name = "partner.employee.create.wizard.line"

    wizard_id = fields.Many2one("partner.employee.create.wizard", "Wizard")
    skill_id = fields.Many2one("hr.skill", string="Posició")
    level = fields.Selection(
        [('0', 'Junior'),
         ('1', 'Intermediate'),
         ('2', 'Senior'),
         ('3', 'Expert')], 'Nivell', default='0')


# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf8')

from flask import redirect, session, url_for, render_template, \
    flash, abort, request, current_app, jsonify, make_response

from . import main, forms
from .. import db, csrf
from ..models import User, Permission, Role, Answer, Question, Vote, Comment
from ..decorators import permission_required, admin_required
from flask_login import login_required, current_user
from .forms import EditProfileForm, EditProfileAdminForm, QuestionForm, AnswerForm, CommentForm
from flask_wtf.csrf import validate_csrf, ValidationError

@main.route('/', methods=['POST', 'GET'])
def index():
    form = QuestionForm()
    if current_user.can(Permission.WRITE_ARTICLES) and form.validate_on_submit():
        q = Question(author=current_user._get_current_object(), body=form.body.data, title=form.title.data)
        db.session.add(q)
        return redirect(url_for('.index'))
    show_followed_answers = False
    if current_user.is_authenticated:
        show_followed_answers = bool(request.cookies.get('show_followed_answers', ''))
    if show_followed_answers:
        query = current_user.followed_answers
    else:
        query = Answer.query
    page = request.args.get('page', 1, type=int)
    pagination = query.order_by(Answer.timestamp.desc()).paginate(page, per_page=50, error_out=False)
    answers = pagination.items
    return render_template('index.html', form=form, page=page, answers=answers,
                           pagination=pagination, show_followed_answers=show_followed_answers)

@main.route('/all_answers')
@login_required
def show_all_answers():
    resp = make_response(redirect(url_for('.index')))
    resp.set_cookie('show_followed_answers', '', max_age=30*24*60*60)
    return resp

@main.route('/followed_answers')
@login_required
def show_followed_answers():
    resp = make_response(redirect(url_for('.index')))
    resp.set_cookie('show_followed_answers', '1', max_age=30 * 24 * 60 * 60)
    return resp

@main.route('/questions')
def questions():
    page = request.args.get('page', 1, type=int)
    pagination = Question.query.order_by(Question.timestamp.desc())\
        .paginate(page, per_page=20, error_out=False)
    qs = pagination.items
    return render_template('questions.html', page=page, questions=qs,
                           pagination=pagination)

@main.route('/question/<int:id>')
def question(id):
    the_question = Question.query.get_or_404(id)
    answers = the_question.answers.all()
    return render_template('question.html', question=the_question, answers=answers)

@main.route('/question-modify/<int:id>', methods=['POST', 'GET'])
@login_required
@permission_required(Permission.WRITE_ARTICLES)
def question_modify(id):
    the_question = Question.query.get_or_404(id)
    form = QuestionForm()
    if form.validate_on_submit():
        the_question.title = form.title.data
        the_question.body = form.body.data
        return redirect(url_for('main.question', id=id))
    form.title.data = the_question.title
    form.body.data = the_question.body
    return render_template('edit_question.html', form=form, question=the_question)

@main.route('/answer/<int:id>', methods=['POST', 'GET'])
@login_required
def answer(id):
    answer = Answer.query.get_or_404(id)
    form = CommentForm()
    if form.validate_on_submit():
        comment = Comment(body=form.body.data,
                          answer=answer,
                          author=current_user._get_current_object())
        db.session.add(comment)
        flash('评论已提交')
        return redirect(url_for('.answer', id=id))
    page = request.args.get('page', 1, type=int)
    if page == -1:
        page = (Answer.comments.count() - 1) / 20
    pagination = answer.comments.order_by(Comment.timestamp.asc()).paginate(
        page, per_page=20, error_out=False)
    comments = pagination.items
    return render_template('answer.html', answers=[answer], form=form,
                           comments=comments, pagination=pagination)

@main.route('/answer_edit/<int:id>', methods=['POST', 'GET'])
@login_required
@permission_required(Permission.WRITE_ARTICLES)
def answer_edit(id):
    the_question = Question.query.get_or_404(id)
    old_answer = the_question.answers.filter_by(answerer=current_user).first()
    form = AnswerForm()
    if form.validate_on_submit():
        if old_answer is not None:
            old_answer.body = form.body.data
            db.session.add(old_answer)
        else:
            answer = Answer(body=form.body.data, q_answer=the_question, answerer=current_user._get_current_object())
            db.session.add(answer)
        return redirect(url_for('main.question', id=id))
    if old_answer is not None:
        form.body.data = old_answer.body
    return render_template('edit_answer.html', question=the_question, form=form)

@main.route('/user/<nickname>')
def user(nickname):
    user = User.query.filter_by(nickname=nickname).first()
    if user is None:
        abort(404)

    return render_template('user.html', user=user)

@main.route('/focus/<int:id>')
@login_required
@permission_required(Permission.FOLLOW)
def focus(id):
    q = Question.query.get_or_404(id)
    if current_user.is_focus(q):
        flash('已关注此问题！')
        return redirect(url_for('.question', id=id))
    current_user.focus(q)
    flash('关注问题成功！')
    return redirect(url_for('.question', id=id))

@main.route('/unfocus/<int:id>')
@login_required
@permission_required(Permission.FOLLOW)
def unfocus(id):
    q = Question.query.get_or_404(id)
    if current_user.is_focus(q):
        current_user.unfocus(q)
        flash('取消关注成功')
        return redirect(url_for('.question', id=id))
    flash('未关注此问题')
    return redirect(url_for('.question', id=id))

@main.route('/follow/<nickname>')
@login_required
@permission_required(Permission.FOLLOW)
def follow(nickname):
    user = User.query.filter_by(nickname=nickname).first()
    if user is None:
        flash('不存在的用户！')
        return redirect(url_for('.index'))
    if current_user.is_following(user):
        flash('你已关注此用户！')
        return redirect(url_for('.user', nickname=nickname))
    current_user.follow(user)
    flash('已关注 %s' % nickname)
    return redirect(url_for('.user', nickname=nickname))

@main.route('/unfollow/<nickname>')
@login_required
@permission_required(Permission.FOLLOW)
def unfollow(nickname):
    user = User.query.filter_by(nickname=nickname).first()
    if user is None:
        flash('该用户不存在')
        return redirect(url_for('.index'))
    if not current_user.is_following(user):
        flash('你尚未关注此用户.')
        return redirect(url_for('.user', nickname=nickname))
    current_user.unfollow(user)
    flash('你已不再关注 %s.' % nickname)
    return redirect(url_for('.user', nickname=nickname))

@main.route('/followers/<nickname>')
@login_required
def followers(nickname):
    user = User.query.filter_by(nickname=nickname).first()
    if user is None:
        flash('不存在此用户')
        return redirect(url_for('.index'))
    page = request.args.get('page', 1, type=int)
    pagination = user.followers.paginate(page, per_page=20, error_out=False)
    follows = [{'user': item.follower, 'timestamp': item.timestamp}
               for item in pagination.items]
    return render_template('followers.html', user=user, title='关注了',
                           endpoint='.followers', pagination=pagination,follows=follows)

@main.route('/followed-by/<nickname>')
@login_required
def followed_by(nickname):
    user = User.query.filter_by(nickname=nickname).first()
    if user is None:
        flash('不存在此用户')
        return redirect(url_for('.index'))
    page = request.args.get('page', 1, type=int)
    pagination = user.followed.paginate(
        page, per_page=20,
        error_out=False)
    follows = [{'user': item.followed, 'timestamp': item.timestamp}
               for item in pagination.items]
    return render_template('followers.html', user=user, title='被关注',
                           endpoint='.followed_by', pagination=pagination,
                           follows=follows)

@main.route('/edit-profile', methods=['GET', 'POST'])
@login_required
def edit_profile():
    form = EditProfileForm()
    if form.validate_on_submit():
        current_user.name = form.name.data
        current_user.location = form.location.data
        current_user.about_me = form.about_me.data
        db.session.add(current_user)
        flash('个人信息已更新。')
        return redirect(url_for('.user', nickname=current_user.nickname))
    form.name.data = current_user.name
    form.location.data = current_user.location
    form.about_me.data = current_user.about_me
    return render_template('edit_profile.html', form=form)

@main.route('/edit-profile/<int:id>', methods=['GET', 'POST'])
@login_required
@admin_required
def edit_profile_admin(id):
    user = User.query.get_or_404(id)
    form = EditProfileAdminForm(user=user)
    if form.validate_on_submit():
        user.email = form.email.data
        user.nickname = form.nickname.data
        user.confirmed = form.confirmed.data
        user.role = Role.query.get(form.role.data)
        user.name = form.name.data
        user.location = form.location.data
        user.about_me = form.about_me.data
        db.session.add(user)
        flash('信息已更新')
        return redirect(url_for('.user', nickname=user.nickname))
    form.email.data = user.email
    form.nickname.data = user.nickname
    form.confirmed.data = user.confirmed
    form.role.data = user.role_id
    form.name.data = user.name
    form.location.data = user.location
    form.about_me.data = user.about_me
    return render_template('edit_profile.html', form=form, user=user)

@main.route('/vote-post', methods=['POST'])
@csrf.exempt
# @login_required
def vote_post():
    # 如果用户未登录，返回相关信息给AJAX，手动处理重定向。
    # 如果交给@login_required自动重定向的话，
    # AJAX不能正确处理这个重定向
    if not current_user.is_authenticated:
        return jsonify({
            'status': 302,
            'location': url_for(
                'auth.login',
                next=request.referrer.replace(
                    url_for('.index', _external=True)[:-1], ''))
        })
    # 以post方式传的数据在存储在的request.form中，以get方式传输的在request.args中~~
    # 同理，csrf token认证也要手动解决重定向
    try:
        validate_csrf(request.headers.get('X-CSRFToken'))
    except ValidationError:
        return jsonify({
            'status': 400,
            'location': url_for(
                'auth.login',
                next=request.referrer.replace(
                    url_for('.index', _external=True)[:-1], ''))
        })
    answer = Answer.query.get_or_404(int(request.form.get('id')))
    if current_user.id == answer.answerer_id:
        return 'disable'
    if current_user.vote_answer(answer):
        return 'vote'
    else:
        return 'cancel'


import importlib.machinery
import importlib.util
import inspect
import os
from io import StringIO
from typing import List, Callable, Any, Union

import typing

from termcolor import colored

class StubGenerator:
    """
    This class takes a file as input and generates the corresponding stub file for each defined type
    (generic variables, functions, classes, etc.) at run time.
    This means that the file is not statically parsed, but it is executed and
    then the types are dynamically created and analyzed to produce the stub file.
    The only items to be analyzed are those defined in the input file, while whose imported from other modules are ignored.
    To include members defined in other modules, you have to specify their names in the constructor.
    """
    def __init__(self, file_path: str, members_from_other_modules: List[str] = []):
        """
        Initializes the StubGenerator.
        :param file_path: the file path
        :type file_path: str
        :param members_from_other_modules: the names of the members defined in other module to be analyzed
        :type members_from_other_modules: List[str]
        """
        self._file_path: str = file_path
        if not os.path.exists(self._file_path):
            raise FileNotFoundError
        loader = importlib.machinery.SourceFileLoader('imported', self._file_path)
        spec = importlib.util.spec_from_loader(loader.name, loader)
        module = importlib.util.module_from_spec(spec)
        loader.exec_module(module)
        self._module = module

        # Check of the members from other modules are contained in the given file
        self._members: List[str] = []
        for item in members_from_other_modules:
            if item not in module.__dict__.keys():
                print(colored('The member {0} is not contained in the input file: it is ignored'.format(item), 'yellow'))

        # Remove members that are not defined in self._file_path: all fields with module == None are defined in this file
        self._members += [item for item in module.__dict__.keys() if item in members_from_other_modules or (not item.startswith('__') and inspect.getmodule(getattr(module, item)) == None)]
        self._modules: List[str] = [getattr(module, item).__name__ for item in module.__dict__.keys() if inspect.ismodule(getattr(module, item))]
        self._stubs_strings: List[str] = []

    def _get_element_name_with_module(self, element: Union[type, Any]) -> str:
        """
        Returns the element name with the relative module and adds the module to the imports (if it is not yet present)
        :param element: the element
        :return:
        :rtype: str
        """
        # The element can be a string, for example "def f() -> 'SameClass':..."
        if isinstance(element, str):
            return element
        elif isinstance(element, type):
            module = inspect.getmodule(element)
            if module is None or module.__name__ == 'builtins' or module.__name__ == '__main__':
                return element.__name__

            module_name = module.__name__
            if module_name not in self._modules:
                self._modules.append(module_name)

            return '{0}.{1}'.format(module_name, element.__name__)
        elif inspect.getmodule(element) == inspect.getmodule(typing):
            module_name = str(element).split('.')[0]
            if module_name not in self._modules:
                self._modules.append(module_name)

            return str(element)

    def _generate_class_stub(self, name: str, clazz: type) -> str:
        """
        Generates the stub string for the given class
        :param name: the class name
        :type name: str
        :param clazz: the class to generate stub
        :type clazz: type
        :return: the str which contains the stub
        :rtype: str
        """
        buff = StringIO()

        # Class prototype
        buff.write('class ' + name.split('.')[-1] + '(')

        # Add super classes
        for c in clazz.__bases__:
            name_with_module = self._get_element_name_with_module(c)
            buff.write(name_with_module + ', ')

        # Add metaclass
        name_with_module = self._get_element_name_with_module(clazz.__class__)
        buff.write('metaclass=' + name_with_module + '):\n')

        for key, element in clazz.__dict__.items():
            if inspect.isfunction(element):
                buff.write(self._generate_function_stub(key, element, indentation='\t'))

        buff.write('\t...\n')

        return buff.getvalue()

    def _generate_function_stub(self, name: str, func: Callable, indentation: str = '') -> str:
        """
        Generates the stub string for the given function
        :param name: the function name
        :type name: str
        :param func: the function to generate stub
        :type func: Callable
        :param indentation: the string used to correctly align the function stub
        :return: the str which contains the stub
        :rtype: str
        """
        def exploit_annotation(annotation: Any, starting: str = ': ') -> str:
            annotation_string = ''
            if annotation != inspect._empty:
                annotation_string += starting + self._get_element_name_with_module(annotation)
            return annotation_string

        buff = StringIO()
        sign = inspect.signature(func)

        buff.write(indentation + 'def ' + name + '(')
        for i, (par_name, parameter) in enumerate(sign.parameters.items()):
            annotation = exploit_annotation(parameter.annotation)
            default = ''
            if parameter.default != parameter.empty and type(parameter.default).__module__ == 'builtins' and not str(parameter.default).startswith('<'):
                default = ' = ' + str(parameter.default) if not isinstance(parameter.default, str) else ' = \'' + parameter.default + '\''

            buff.write(par_name + annotation + default)

            if i < len(sign.parameters) - 1:
                buff.write(', ')
        ret_annotation = exploit_annotation(sign.return_annotation, starting=' -> ')
        buff.write(')' + ret_annotation + ':\n')

        if func.__doc__ is not None:
            buff.write(indentation + '\t"""\n')
            for line in func.__doc__.split('\n')[1:-1]:
                buff.write(indentation + '\t' + line.strip().rstrip() + '\n')
            buff.write(indentation + '\t\"\"\"\n')
        buff.write(indentation + '\t...\n')
        return buff.getvalue()

    def _generate_generic_stub(self, element_name: str, element: Any) -> str:
        """
        Generates the stub for a generic variable
        :param element_name: the name of the element
        :type element_name: str
        :param element: the element
        :type element: Any
        :return: the stub as a string
        :rtype: str
        """
        return '{0}: {1}\n'.format(element_name, self._get_element_name_with_module(type(element)))

    def get_stubs(self) -> List[str]:
        """
        Returns a list containing the generated stub strings
        :return: a list containing the generated stub strings
        :rtype: List[str]
        """
        return self._stubs_strings

    def generate_stubs(self) -> 'StubGenerator':
        """
        Generates the stubs for the types collected in the input file
        :return: the stub generator
        :rtype StubGenerator
        """
        for member_name in self._members:
            attr = getattr(self._module, member_name)
            if inspect.isclass(attr):
                self._stubs_strings.append(self._generate_class_stub(member_name, attr))
            elif inspect.isfunction(attr):
                self._stubs_strings.append(self._generate_function_stub(member_name, attr))
            elif not inspect.ismodule(attr):
                self._stubs_strings.append(self._generate_generic_stub(member_name, attr))

        return self

    def write_to_file(self):
        """
        Writes the stub files in the same location as the input file
        :return: None
        """
        with open(self._file_path + 'i', mode='w') as f:
            f.write('#######################################################\n'
                    '# This stub file is automatically generated by stub-generator\n'
                    '# https://pypi.org/project/stub-generator/\n'
                    '########################################################\n\n')
            for module in self._modules:
                f.write('import ' + module + '\n')
            f.write('\n')
            for stub in self._stubs_strings:
                f.write(stub + '\n')


import PySide6.QtWidgets as QtWidgets

class RenameProjectDialog(QtWidgets.QDialog):
    def __init__(self, current_name):
        super(RenameProjectDialog, self).__init__()
        self.setWindowTitle("Rename selected project")

        submit_buttons = QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel

        self.button_box = QtWidgets.QDialogButtonBox(submit_buttons)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)

        self.main_layout = QtWidgets.QFormLayout()

        project_name_label = QtWidgets.QLabel("Project name")
        self.project_name_line_edit = QtWidgets.QLineEdit(current_name)

        self.main_layout.addWidget(project_name_label)
        self.main_layout.addWidget(self.project_name_line_edit)
        self.main_layout.addWidget(self.button_box)

        self.setLayout(self.main_layout)

    def get_value(self):
        return self.project_name_line_edit.text()