"""Metrics to assess performance on classification task given scores

Functions named as ``*_score`` return a scalar value to maximize: the higher
the better

Function named as ``*_error`` or ``*_loss`` return a scalar value to minimize:
the lower the better
"""

# Authors: Alexandre Gramfort <alexandre.gramfort@inria.fr>
#          Mathieu Blondel <mathieu@mblondel.org>
#          Olivier Grisel <olivier.grisel@ensta.org>
#          Arnaud Joly <a.joly@ulg.ac.be>
#          Jochen Wersdorfer <jochen@wersdoerfer.de>
#          Lars Buitinck
#          Joel Nothman <joel.nothman@gmail.com>
#          Noel Dawe <noel@dawe.me>
#          Xing David Wang
# License: BSD 3 clause

from functools import partial

import numpy as np

from sklearn.utils import assert_all_finite
from sklearn.utils import check_consistent_length
from sklearn.utils import column_or_1d
from sklearn.utils.multiclass import type_of_target
from sklearn.utils.extmath import stable_cumsum
from sklearn.utils.validation import _deprecate_positional_args

from sklearn.metrics._base import _average_binary_score

@_deprecate_positional_args
def average_precision_score(y_true, y_score, *, average="macro", pos_label=1,
                            sample_weight=None):
    """Compute average precision (AP) from prediction scores

    AP summarizes a precision-recall curve as the weighted mean of precisions
    achieved at each threshold, with the increase in recall from the previous
    threshold used as the weight:

    .. math::
        \\text{AP} = \\sum_n (R_n - R_{n-1}) P_n

    where :math:`P_n` and :math:`R_n` are the precision and recall at the nth
    threshold [1]_. This implementation is not interpolated and is different
    from computing the area under the precision-recall curve with the
    trapezoidal rule, which uses linear interpolation and can be too
    optimistic.

    Note: this implementation is restricted to the binary classification task
    or multilabel classification task.

    Read more in the :ref:`User Guide <precision_recall_f_measure_metrics>`.

    Parameters
    ----------
    y_true : array, shape = [n_samples] or [n_samples, n_classes]
        True binary labels or binary label indicators.

    y_score : array, shape = [n_samples] or [n_samples, n_classes]
        Target scores, can either be probability estimates of the positive
        class, confidence values, or non-thresholded measure of decisions
        (as returned by "decision_function" on some classifiers).

    average : string, [None, 'micro', 'macro' (default), 'samples', 'weighted']
        If ``None``, the scores for each class are returned. Otherwise,
        this determines the type of averaging performed on the data:

        ``'micro'``:
            Calculate metrics globally by considering each element of the label
            indicator matrix as a label.
        ``'macro'``:
            Calculate metrics for each label, and find their unweighted
            mean.  This does not take label imbalance into account.
        ``'weighted'``:
            Calculate metrics for each label, and find their average, weighted
            by support (the number of true instances for each label).
        ``'samples'``:
            Calculate metrics for each instance, and find their average.

        Will be ignored when ``y_true`` is binary.

    pos_label : int or str (default=1)
        The label of the positive class. Only applied to binary ``y_true``.
        For multilabel-indicator ``y_true``, ``pos_label`` is fixed to 1.

    sample_weight : array-like of shape (n_samples,), default=None
        Sample weights.

    Returns
    -------
    average_precision : float

    References
    ----------
    .. [1] `Wikipedia entry for the Average precision
           <https://en.wikipedia.org/w/index.php?title=Information_retrieval&
           oldid=793358396#Average_precision>`_

    See also
    --------
    roc_auc_score : Compute the area under the ROC curve

    precision_recall_curve :
        Compute precision-recall pairs for different probability thresholds

    Examples
    --------
    >>> import numpy as np
    >>> from sklearn.metrics import average_precision_score
    >>> y_true = np.array([0, 0, 1, 1])
    >>> y_scores = np.array([0.1, 0.4, 0.35, 0.8])
    >>> average_precision_score(y_true, y_scores)
    0.83...

    Notes
    -----
    .. versionchanged:: 0.19
      Instead of linearly interpolating between operating points, precisions
      are weighted by the change in recall since the last operating point.
    """
    def _binary_uninterpolated_average_precision(
            y_true, y_score, pos_label=1, sample_weight=None):
        precision, recall, _ = precision_recall_curve(
            y_true, y_score, pos_label=pos_label, sample_weight=sample_weight)
        # Return the step function integral
        # The following works because the last entry of precision is
        # guaranteed to be 1, as returned by precision_recall_curve
        return -np.sum(np.diff(recall) * np.array(precision)[:-1])

    y_type = type_of_target(y_true)
    if y_type == "multilabel-indicator" and pos_label != 1:
        raise ValueError("Parameter pos_label is fixed to 1 for "
                         "multilabel-indicator y_true. Do not set "
                         "pos_label or set pos_label to 1.")
    elif y_type == "binary":
        present_labels = np.unique(y_true)
        if len(present_labels) == 2 and pos_label not in present_labels:
            raise ValueError("pos_label=%r is invalid. Set it to a label in "
                             "y_true." % pos_label)
    average_precision = partial(_binary_uninterpolated_average_precision,
                                pos_label=pos_label)
    return _average_binary_score(average_precision, y_true, y_score,
                                 average, sample_weight=sample_weight)

@_deprecate_positional_args
def precision_recall_curve(y_true, probas_pred, *, pos_label=None,
                           sample_weight=None):
    """Compute precision-recall pairs for different probability thresholds

    Note: this implementation is restricted to the binary classification task.

    The precision is the ratio ``tp / (tp + fp)`` where ``tp`` is the number of
    true positives and ``fp`` the number of false positives. The precision is
    intuitively the ability of the classifier not to label as positive a sample
    that is negative.

    The recall is the ratio ``tp / (tp + fn)`` where ``tp`` is the number of
    true positives and ``fn`` the number of false negatives. The recall is
    intuitively the ability of the classifier to find all the positive samples.

    The last precision and recall values are 1. and 0. respectively and do not
    have a corresponding threshold.  This ensures that the graph starts on the
    y axis.

    Read more in the :ref:`User Guide <precision_recall_f_measure_metrics>`.

    Parameters
    ----------
    y_true : array, shape = [n_samples]
        True binary labels. If labels are not either {-1, 1} or {0, 1}, then
        pos_label should be explicitly given.

    probas_pred : array, shape = [n_samples]
        Estimated probabilities or decision function.

    pos_label : int or str, default=None
        The label of the positive class.
        When ``pos_label=None``, if y_true is in {-1, 1} or {0, 1},
        ``pos_label`` is set to 1, otherwise an error will be raised.

    sample_weight : array-like of shape (n_samples,), default=None
        Sample weights.

    Returns
    -------
    precision : array, shape = [n_thresholds + 1]
        Precision values such that element i is the precision of
        predictions with score >= thresholds[i] and the last element is 1.

    recall : array, shape = [n_thresholds + 1]
        Decreasing recall values such that element i is the recall of
        predictions with score >= thresholds[i] and the last element is 0.

    thresholds : array, shape = [n_thresholds <= len(np.unique(probas_pred))]
        Increasing thresholds on the decision function used to compute
        precision and recall.

    See also
    --------
    average_precision_score : Compute average precision from prediction scores

    roc_curve : Compute Receiver operating characteristic (ROC) curve

    Examples
    --------
    >>> import numpy as np
    >>> from sklearn.metrics import precision_recall_curve
    >>> y_true = np.array([0, 0, 1, 1])
    >>> y_scores = np.array([0.1, 0.4, 0.35, 0.8])
    >>> precision, recall, thresholds = precision_recall_curve(
    ...     y_true, y_scores)
    >>> precision
    array([0.66666667, 0.5       , 1.        , 1.        ])
    >>> recall
    array([1. , 0.5, 0.5, 0. ])
    >>> thresholds
    array([0.35, 0.4 , 0.8 ])

    """
    fps, tps, thresholds = _binary_clf_curve(y_true, probas_pred,
                                             pos_label=pos_label,
                                             sample_weight=sample_weight)
    # print(len(fps))
    # print(fps)
    # print(len(tps))
    # print(tps)
    # print(len(thresholds))
    # print(thresholds)
    # fps = fps[:-1]
    # tps[-1] = tps[-2]
    # thresholds = thresholds[:-1]
    tps[-1] = np.count_nonzero(y_true)

    precision = tps / (tps + fps)
    precision[np.isnan(precision)] = 0
    precision[-1] = 0
    recall = tps / tps[-1]
    # print(list(zip(precision, recall, tps, fps, thresholds)))
    # print(tps[-1])
    # stop when full recall attained
    # and reverse the outputs so recall is decreasing
    last_ind = tps.searchsorted(tps[-1])
    sl = slice(last_ind, None, -1)
    return np.r_[precision[sl], 1], np.r_[recall[sl], 0], thresholds[sl]

def _binary_clf_curve(y_true, y_score, pos_label=None, sample_weight=None):
    """Calculate true and false positives per binary classification threshold.

    Parameters
    ----------
    y_true : array, shape = [n_samples]
        True targets of binary classification

    y_score : array, shape = [n_samples]
        Estimated probabilities or decision function

    pos_label : int or str, default=None
        The label of the positive class

    sample_weight : array-like of shape (n_samples,), default=None
        Sample weights.

    Returns
    -------
    fps : array, shape = [n_thresholds]
        A count of false positives, at index i being the number of negative
        samples assigned a score >= thresholds[i]. The total number of
        negative samples is equal to fps[-1] (thus true negatives are given by
        fps[-1] - fps).

    tps : array, shape = [n_thresholds <= len(np.unique(y_score))]
        An increasing count of true positives, at index i being the number
        of positive samples assigned a score >= thresholds[i]. The total
        number of positive samples is equal to tps[-1] (thus false negatives
        are given by tps[-1] - tps).

    thresholds : array, shape = [n_thresholds]
        Decreasing score values.
    """
    # Check to make sure y_true is valid
    y_type = type_of_target(y_true)
    if not (y_type == "binary" or (y_type == "multiclass" and pos_label is not None)):
        raise ValueError("{0} format is not supported".format(y_type))

    check_consistent_length(y_true, y_score, sample_weight)
    y_true = column_or_1d(y_true)
    y_score = column_or_1d(y_score)
    assert_all_finite(y_true)
    # assert_all_finite(y_score)

    if sample_weight is not None:
        sample_weight = column_or_1d(sample_weight)

    # ensure binary classification if pos_label is not specified
    # classes.dtype.kind in ('O', 'U', 'S') is required to avoid
    # triggering a FutureWarning by calling np.array_equal(a, b)
    # when elements in the two arrays are not comparable.
    classes = np.unique(y_true)
    if (pos_label is None and (classes.dtype.kind in ('O', 'U', 'S')
       or not (np.array_equal(classes, [0, 1])
       or np.array_equal(classes, [-1, 1])
       or np.array_equal(classes, [0])
       or np.array_equal(classes, [-1])
       or np.array_equal(classes, [1])))):
        classes_repr = ", ".join(repr(c) for c in classes)
        raise ValueError("y_true takes value in {{{classes_repr}}} and "
                         "pos_label is not specified: either make y_true "
                         "take value in {{0, 1}} or {{-1, 1}} or "
                         "pass pos_label explicitly.".format(
                             classes_repr=classes_repr))
    elif pos_label is None:
        pos_label = 1.

    # make y_true a boolean vector
    y_true = (y_true == pos_label)

    # sort scores and corresponding truth values
    desc_score_indices = np.argsort(y_score, kind="mergesort")[::-1]
    y_score = y_score[desc_score_indices]
    y_true = y_true[desc_score_indices]
    # print(list(zip(desc_score_indices, y_score, y_true)))
    if sample_weight is not None:
        weight = sample_weight[desc_score_indices]
    else:
        weight = 1.

    # y_score typically has many tied values. Here we extract
    # the indices associated with the distinct values. We also
    # concatenate a value for the end of the curve.
    distinct_value_indices = np.where(np.diff(y_score))[0]
    threshold_idxs = np.r_[distinct_value_indices, y_true.size - 1]

    # accumulate the true positives with decreasing threshold
    tps = stable_cumsum(y_true * weight)[threshold_idxs]
    if sample_weight is not None:
        # express fps as a cumsum to ensure fps is increasing even in
        # the presence of floating point errors
        fps = stable_cumsum((1 - y_true) * weight)[threshold_idxs]
    else:
        fps = 1 + threshold_idxs - tps
    return fps, tps, y_score[threshold_idxs]


#!/usr/bin/python2
# coding: utf-8
# vim:ts=4 sts=4 tw=100:

__version__ = "1.5.0"
__author__  = "Borja Ruiz"
__email__   = "borja [at] libcrack [dot] so"
__url__     = "https://www.github.com/libcrack/peid"

import logging
import peutils
import pefile
import sys
import os

try:
    import argparse
except ImportError as e:
    logger.error('Missing needed module: easy_install argparse')
    halt = True

try:
    import pefile
except ImportError as e:
    logger.error('Missing mandatory module: easy_install pefile')
    halt = True

CWD = os.path.abspath(os.path.dirname(__file__))
USERDB = os.path.join(CWD, os.path.normpath("data/UserDB.TXT"))

parser = argparse.ArgumentParser()
parser.add_argument("-a", "--all", dest="show_all", help="show all PE info", default=False, action="store_true")
parser.add_argument("-d", "--database", dest="database", help="signature database file", metavar="DB")
parser.add_argument("-m", "--matches", dest="show_matches", help="show all signature matches", default=False, action="store_true")
parser.add_argument("-v", "--version", dest="version", help="show version number", default=False, action="store_true")
parser.add_argument("-f", "--file", dest="file", help="target PE file", required=True, action="store")
args = parser.parse_args()

logging.basicConfig(level=logging.ERROR)

print("\033[91m")
print(" _____  ______ _ _____  ")
print("|  __ \|  ____(_)  __ \ ")
print("| |__) | |__   _| |  | |")
print("|  ___/|  __| | | |  | |")
print("| |    | |____| | |__| |")
print("|_|    |______|_|_____/ ")
print("\033[0m")
print("User DB: %s" % USERDB)
print("Author:  Borja Ruiz <borja@libcrack.so>")
print("License: GPL3\n")

if args.version:
    print("{0} version {1}",__file__,  __version__)
    sys.exit(0)

if args.database:
    USERDB = args.database

with open(USERDB, 'rt') as f:
    sig_data = f.read()
signatures = peutils.SignatureDatabase(data=sig_data)

try:
    pe = pefile.PE(args.file)
except:
    logging.error("cannot open file %s" % args.file)

if args.show_all|args.show_matches:
    matches = signatures.match_all(pe, ep_only = True)
else:
    matches = signatures.match(pe, ep_only = True)

print(matches)

if args.show_all:
    print(pe.dump_info())


from fileinput import filename
from flask import jsonify, request, current_app, url_for, g
from sqlalchemy import true
from . import api
from ..models import User, Problem, Code, Comment, Log, Room, Regist, TA, Video
import os
from werkzeug.utils import secure_filename
from flask import send_file, send_from_directory, flash
import shutil
from flask_login import current_user, login_required
from .decorators import admin_required_vs, permission_required_vs, prof_required_vs, moderator_required_vs
import subprocess
from .. import db
from io import BytesIO
from collections import OrderedDict

path = os.path.dirname(os.path.abspath(__file__))  # /home/codelab/ver1/app/api
# /home/codelab/ver1/app/api/problems
problems_path = os.path.join(path, "problems")
codes_path = os.path.join(path, "codes")  # /home/codelab/ver1/app/api/codes
grading_path = os.path.join(path, "grading")
videos_path = os.path.join(path, 'videos')

@api.route('/temp', methods=['GET'])  # 수정바람
def grading():
    filepath = os.path.join(path, "grading/")
    username = g.current_user.username
    id = g.current_user.id
    problem_id = Problem.query.filter_by(title='B001')  # 수정바람
    error = None

    sourcecode = 1  # 수정바람
    if not sourcecode:
        error = 'Sourcecode is required'

    if error is not None:
        flash(error)
    else:
        filename = 'bracket'

        subprocess.call(filepath + "compile.sh " +
                        filename + " " + str(id), shell=True)
        # resf = open(filepath + "results/result_" + filename + ".txt", 'r')
        # result = resf.readline().strip()
        # print(result + "Aa")

    return '', 200

@api.route('/users/<int:id>')
def get_user(id):
    user = User.query.get_or_404(id)
    print(path)
    return jsonify(user.to_json())

@api.route('problems/<lab>/<id>', methods=['GET'])  # 문제 file list 반납
def get_filenames(lab, id):
    problem_path = os.path.join(problems_path, lab, id, '')

    file_list = os.listdir(problem_path)

    if len(file_list) >= 1:
        return {'file_list': file_list}, 200
    else:
        return '', 404

# 문제 파일 다운로드
@api.route('problems/<labname>/<id>/<filename>', methods=['GET'])
def get_problem(id, filename, labname):
    problem_path = os.path.join(problems_path, labname, id)

    file = os.path.join(problems_path, labname, id, secure_filename(filename))

    if file:
        return send_file(file, download_name=filename, as_attachment=True, attachment_filename=filename)
    else:
        return '', 404

## pdf 다운로드
@api.route('problems/<lab>/<id>/<filename>.pdf', methods=['GET'])
def get_problem2(lab, id, filename):
    problem_path = os.path.join(problems_path, lab, id)

    file = os.path.join(problems_path, lab, id, secure_filename(filename))

    if file:
        return send_file(file, download_name=filename, as_attachment=True, attachment_filename=filename, mimetype="application/pdf")
    else:
        return '', 404

## 비디오 다운로드
@api.route('video/<lab>/<video_name>', methods=['GET'])
def get_video(lab, video_name):

    room = Room.query.filter_by(room_name=lab).first()

    student_id = str(Video.query.filter_by(video_name=video_name, room_id=room.id).first().id)

    video = Video.query.filter_by(video_name=video_name, room_id=room.id).first()

    problem_path = os.path.join(videos_path, lab)

    file = os.path.join(problem_path, secure_filename(video_name))

    is_ta = TA.query.filter_by(user_id=g.current_user.id, room_id=room.id).first()

    if file and is_ta is not None:
        video.flag = 1
        db.session.add(video)
        db.session.commit()
        return send_file(file, download_name=video_name, as_attachment=True, attachment_filename=video_name, mimetype="video/mp4")
    elif file and is_ta is None:
        video.flag = 2
        db.session.add(video)
        db.session.commit()
        return send_file(file, download_name=video_name, as_attachment=True, attachment_filename=video_name, mimetype="video/mp4")
    else:
        return '', 404

@api.route('video/<lab>', methods=['GET'])
def get_studentVideoList(lab):

    room_id = str(Room.query.filter_by(room_name=lab).first().id)

    video_path = os.path.join(videos_path, lab)

    file_list = os.listdir(video_path)

    print('file_list: ')
    print(file_list)

    if len(file_list) >= 1:
        return {'file_list': file_list}, 200
    else:
        return '', 404

# @api.route('video/<lab>/<id>', methods=['GET'])  # 문제 file list 반납
# def get_studentsVideo(lab, id):

#     code_path = os.path.join(videos_path, lab, id, '')

#     dir_list = os.listdir(code_path)

#     email_list = []

#     for i in range(len(dir_list)):
#         email = User.query.filter_by(id=int(dir_list[i])).first().email
#         email_list.append(email)

#     if len(dir_list) >= 1:
#         return {'dir_list': dir_list, 'email_list': email_list}, 200
#     else:
#         return '', 404

ALLOWED_EXTENSIONS = set(
    ['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'c', 'md', 'h'])

STUDENT_ALLOWED_EXTENSIONS = set(['c', 'h'])

def allowed_file(filename):
    return ('.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS) or 'Makefile'
def student_allowed_file(filename):
    return ('.' in filename and filename.rsplit('.', 1)[1].lower() in STUDENT_ALLOWED_EXTENSIONS)

# 교수 문제 제출
@api.route('problems/<labname>/<problem_title>', methods=['POST'])
@prof_required_vs
def upload_problem(labname, problem_title):
    problem_path = os.path.join(problems_path, labname, problem_title)
    grading_problem_path = os.path.join(grading_path, labname, problem_title)
    data = request.get_json()

    room = Room.query.filter_by(room_name=labname).first().id

    filenames = data['files']['filename'] # file명
    filedatas = data['files']['file'] # file 데이터

    for idx, filename in enumerate(filenames):
        filenames[idx] = secure_filename(filename)

    if not os.path.isdir(os.path.join(problems_path, labname)):
        resp.status_code = 404
        return resp

    if not os.path.isdir(problem_path):
        os.mkdir(problem_path)
        os.chmod(problem_path, 0o777)

        os.mkdir(grading_problem_path)
        os.mkdir(os.path.join(grading_problem_path, 'cases'))
        os.mkdir(os.path.join(grading_problem_path, 'results'))
        os.mkdir(os.path.join(grading_problem_path, 'src'))
        os.mkdir(os.path.join(grading_problem_path, 'cases', 'programs'))

    prof_filelist = ['input.txt', 'output.txt', 'makefile', problem_title.lower()] # 교수가 제출하면 grading으로 갈 파일리스트

    flag = False
    for filename, filedata in zip(filenames, filedatas):
        txtfilename = None

        if allowed_file(filename):
            if filename.lower() in prof_filelist:
                if filename == 'input.txt':
                    txtfilename = os.path.join(grading_problem_path, 'cases', 'input.txt')
                elif filename == 'Makefile':
                    # 학생도 받을 수 있도록
                    txtfilename = os.path.join(problem_path, filename)
                    f = open(txtfilename, "w+", encoding='utf-8')
                    f.write(filedata)
                    f.close()

                    txtfilename = os.path.join(grading_problem_path, 'src', 'Makefile')
                elif filename.lower() == problem_title.lower() or 'output.file':
                    txtfilename = os.path.join(grading_problem_path, 'cases', 'programs', filename.lower())
            else: # 학생에게 줄 파일들
                txtfilename = os.path.join(problem_path, filename)

            f = open(txtfilename, "w+", encoding='utf-8')
            f.write(filedata)
            f.close()
            flag = True

            if filename.lower() == problem_title.lower(): # 실행파일 권한 주기
                os.chmod(txtfilename, 0o777)

    if flag:
        # db 문제 등록
        if Problem.query.filter_by(title=problem_title, room_id=room).first() is not None:
            db.session.delete(Problem.query.filter_by(title=problem_title, room_id=room).first())
            db.session.commit()

        problem = Problem(title=problem_title, room_id=room)
        db.session.add(problem)
        db.session.commit()

        problem_id = Problem.query.filter_by(title=problem_title, room_id=room).first().id
        code = Code(problem_id = problem_id, user_id=g.current_user.id)
        db.session.add(code)
        db.session.commit()
        # users = User.query.all()
        # for user in users:
        #     code = Code(problem_id=problem_id, user_id=user.id)
        #     db.session.add(code)
        # db.session.commit()

        resp = jsonify({'message': 'Problem successfully uploaded'})
        resp.status_code = 201
    else:
        resp = jsonify(
            {'message': 'Allowed file types are txt, pdf, png, jpg, jpeg, gif, c, md'})
        resp.status_code = 400
    return resp

ALLOWED_PDF_EXTENSIONS = ['pdf']
def allowed_pdf(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_PDF_EXTENSIONS

## pdf 올리기
@api.route('problems/<labname>/<problem_title>/pdf', methods=['POST'])
@prof_required_vs
def upload_pdf(labname, problem_title):
    user_id = str(g.current_user.id)

    problem_path = os.path.join(problems_path, labname, problem_title)
    # student_path = os.path.join(problem_path, labname, user_id)

    if 'file' not in request.files:
        resp = jsonify({'message': 'Not video file'})
        resp.status_code = 404
        return resp

    if not os.path.isdir(problem_path):
        os.mkdir(problem_path)
        os.chmod(problem_path, 0o777)
    # if not os.path.isdir(student_path):
    #     os.mkdir(student_path)
    #     os.chmod(student_path, 0o777)

    file = request.files['file']

    if file.filename == '':
        resp = jsonify({'message': 'Not video filename'})
        resp.status_code = 404
        return resp

    if file and allowed_pdf(file.filename):
        filename = secure_filename(file.filename)
        file.save(os.path.join(problem_path, filename))

    resp = jsonify({'message': 'Success upload Pdf'})
    resp.status_code = 200
    return resp

# 교수 문제 삭제
@api.route('problems/<lab>/<problem_title>', methods=['DELETE'])
@prof_required_vs
def delete_problem(lab, problem_title):
    print('delete problem')
    problem_path = os.path.join(problems_path, lab, problem_title)
    grading_problem_path = os.path.join(grading_path, lab, problem_title)

    problem_code_path = os.path.join(codes_path, lab, problem_title)
    print(problem_code_path)

    room_id = Room.query.filter_by(room_name=lab).first().id
    # db 문제 삭제, problem
    problem = Problem.query.filter_by(title=problem_title, room_id=room_id).first()
    # print(problem.code) ## 이걸 해야지 삭제가 된다.... 중요!!!
    if problem:
        db.session.delete(problem)
        db.session.commit()

    if os.path.isdir(problem_code_path):
        shutil.rmtree(problem_code_path)
        codes = Code.query.filter_by(problem_id=problem.id).all()
        for code in codes:
            db.session.delete(code)
        db.session.commit()

    if os.path.isdir(problem_path):
        shutil.rmtree(problem_path)
        shutil.rmtree(grading_problem_path)

        resp = jsonify({'message': 'Problem successfully delete'})
        resp.status_code = 200
        return resp
    else:
        resp = jsonify({'message': 'Not exist problem ID'})
        resp.status_code = 200
        return resp

# 학생코드 삭제
@api.route('student_codes/<username>/<problem_title>', methods=['DELETE'])
@moderator_required_vs
def delete_code(username, problem_title):
    user_id = str(g.current_user.id)
    problem_path = os.path.join(codes_path, problem_title)
    student_code_path = os.path.join(problem_path, user_id)
    grading_src_path = os.path.join(path, "grading", problem_title, "src")

    problem_id = Problem.query.filter_by(title=problem_title).first().id

    code = Code.query.filter_by(problem_id=problem_id, user_id=g.current_user.id).first()

    if os.path.isdir(student_code_path):
        shutil.rmtree(student_code_path)

    if code:
        db.session.delete(code)
        db.session.commit()

        if os.path.isdir(grading_src_path):
            grading_src_list = os.listdir(grading_src_path)
            for file in grading_src_list:
                if file != 'Makefile':
                    os.remove(os.path.join(grading_src_path, file))

        resp = jsonify({'message': 'Code successfully delete'})
        resp.status_code = 200
        return resp
    else:
        resp = jsonify({'message': 'Not exist Code'})
        resp.status_code = 200
        return resp

# 학생코드 제출
@api.route('student_codes/<lab>/<problem_title>', methods=['POST'])
def upload_code(lab, problem_title):
    data = request.get_json()
    filenames = data['files']['filename'] # file명
    filedatas = data['files']['file'] # file 데이터
    user_id = str(g.current_user.id)
    username = g.current_user.username
    executable_file = None

    room_id = Room.query.filter_by(room_name=lab).first().id

    # /home/codelab/ver1/app/api/codes/<lab>/<problem_title>
    problem_path = os.path.join(codes_path, lab, problem_title)
    # /home/codelab/ver1/app/api/codes/<lab>/<problem_title>/<username>
    student_code_path = os.path.join(problem_path, user_id)
    grading_src_path = os.path.join(path, "grading", lab, problem_title, "src")

    problem_id = Problem.query.filter_by(title=problem_title).first().id

    code = Code.query.filter_by(problem_id=problem_id, user_id=g.current_user.id).first()
    if code is None:
        code = Code(problem_id=problem_id, user_id=g.current_user.id)
        db.session.add(code)
        db.session.commit()

    problem_first_path = os.path.join(codes_path, lab)
    student_first_code_path = os.path.join(problem_first_path, lab)

    if not os.path.isdir(problem_first_path):
        os.mkdir(problem_first_path)
        os.chmod(problem_first_path, 0o777)

    # dir없으면 생성
    if not os.path.isdir(problem_path):
        os.mkdir(problem_path)
        os.chmod(problem_path, 0o777)
    if not os.path.isdir(student_code_path):
        os.mkdir(student_code_path)
        os.chmod(student_code_path, 0o777)

    for filename, filedata in zip(filenames, filedatas):
        if allowed_file(filename):
            if student_allowed_file(filename):
                # grading에 저장
                txtfilename = os.path.join(grading_src_path, filename)
                f = open(txtfilename, "w+", encoding='utf-8')
                f.write(filedata)
                f.close()

                # code에 저장
                txtfilename = os.path.join(student_code_path, filename)
                f = open(txtfilename, "w+", encoding='utf-8')
                f.write(filedata)
                f.close()

        else:
            resp = jsonify(
                {'message': 'Allowed file types are txt, pdf, png, jpg, jpeg, gif, c, h'})
            resp.status_code = 400
            return resp

    # 채점
    filepath = os.path.join(path, "grading/")

    error = None
    sourcecode = 1  # 수정바람
    if not sourcecode:
        error = 'Sourcecode is required'

    if error is not None:
        flash(error)
    else:
        executable_file = problem_title.lower() + '_' + user_id
        print(grading_src_path, executable_file) ## /home/codelab/ver1/app/api/grading/DS/Bracket/src  bracket_1
        subprocess.call("make -C " + grading_src_path, shell=True) # 학생 코드 makefile 실행
        os.rename(os.path.join(grading_src_path, problem_title.lower()), os.path.join(grading_src_path, problem_title.lower()) + '_' + user_id)
        subprocess.call(filepath + "compile.sh " +
                        executable_file + " " + user_id + " " + problem_title + " " + lab, shell=True)

    out = os.system("diff -bZ {} {}".format(os.path.join(grading_path, lab, problem_title, "results", "result_" + user_id + ".txt"), os.path.join(grading_path, lab, problem_title, "cases", "programs", "output.txt")))

    message = None
    if out != 0:
        print("Wrong Answer\n")
        message = "Wrong Answer"
        body = g.current_user.email + '
' + problem_title + '
'  + message
        # comment_chat = Comment(username='Chat Bot', body=body)
        # db.session.add(comment_chat)
        # db.session.commit()
        code = Code.query.filter_by(problem_id=problem_id, user_id=g.current_user.id).first()
        code.pf = False
    else:
        print("맞았습니다\n")
        message = "Correct Answer"
        body = g.current_user.email + '
' + problem_title + '
' + message
        # comment_chat = Comment(username='Chat Bot', body=body)
        # db.session.add(comment_chat)
        # db.session.commit()
        code = Code.query.filter_by(problem_id=problem_id, user_id=g.current_user.id).first()
        code.pf = True
    db.session.commit()

    resp = jsonify({'message': message})
    resp.status_code = 200
    return resp

# 문제 리스트 가져오기
@api.route('info', methods=['GET'])
def problem_list():
    # return '',200 # 임시
    labs = []
    roles = []

    ## Regist에서 유저아이디가 current_user.id인거 다 가져와
    ## 그 중에서 룸 아이디 다 가져와
    ## 가져온 룸 아이디와 매칭된 룸 네임 다 가져와 -> lab이라는 리스트에 저장

    isRegist_all = Regist.query.filter_by(user_id=g.current_user.id).all()
    for i, room in enumerate(isRegist_all):
        room_name = Room.query.filter_by(id=room.room_id).first().room_name
        labs.append({"lab": room_name, "problems": [], "members": [], "videos": []})
        ## lab => DS
        # labs_lab.append(room_name)
        ## problem에서 룸 네임이 room_name인거 다 가져와 (일단 그냥 등록하자)
        problem_in_lab = Problem.query.filter_by(room_id=room.room_id).all()
        for j, problem in enumerate(problem_in_lab):
            ## title => Bracket
            labs[i]["problems"].append({"title":problem.title})

            code = Code.query.filter_by(problem_id=problem.id, user_id=g.current_user.id).first()
            if code is not None:
                if code.pf == True:
                    ## evaluation => correct
                    labs[i]["problems"][j]["evaluation"] = "correct"
                else:
                    labs[i]["problems"][j]["evaluation"] = "wrong"
            else:
                labs[i]["problems"][j]["evaluation"] = "not yet"

            ## 제출한놈들 가져오기
            code_all = Code.query.filter_by(problem_id=problem.id).all()
            # regist_all = Regist.query.filter_by(room_id=room.room_id).all()
            labs[i]["problems"][j]["submission"] = []
            for k, code_name in enumerate(code_all):
                user_name = User.query.filter_by(id=code_name.user_id).first().username
                print(user_name)
                labs[i]["problems"][j]["submission"].append({"name": user_name})
                code_submission = Code.query.filter_by(problem_id=problem.id, user_id=User.query.filter_by(id=code_name.user_id).first().id).first()
                if code_submission is not None:
                    if code_submission.pf == True:
                        labs[i]["problems"][j]["submission"][k]['evaluation'] = "correct"
                    elif code_submission.pf == False:
                        labs[i]["problems"][j]["submission"][k]['evaluation'] = "wrong"
                else:
                    labs[i]["problems"][j]["submission"][k]['evaluation'] = "not yet"

        ## member
        ## 이 방에 속한 아이들 전부 가져와야함
        ## 내가 들어있는 지금 이 방
        isRegist_all_members = Regist.query.filter_by(room_id=room.room_id).all()
        # isMember = []
        # isMember.append(Regist.query.filter_by(room_id=isRegist_all_members.room_id).first())
        for j, member in enumerate(isRegist_all_members):
            user_name = User.query.filter_by(id=member.user_id).first().username
            labs[i]["members"].append({"name": user_name})
            if User.query.filter_by(id=member.user_id).first().role_id == 3:
                labs[i]["members"][j]["role"] = "Professor"
            elif TA.query.filter_by(room_id=member.room_id, user_id=member.user_id).first():
                labs[i]["members"][j]["role"] = "TA"
            else:
                labs[i]["members"][j]["role"] = "Student"

        ## 비디오 목록 가져오기 (현재 내가 등록된 방에서)
        videos = Video.query.filter_by(room_id=room.room_id).all()
        ## 현재 내가 ta로 등록된 방
        tas = TA.query.filter_by(room_id=room.room_id, user_id=g.current_user.id).first()

        for j, video in enumerate(videos):
            if tas is not None:
                if video is not None and video.room_id == tas.room_id:
                    ## 비디오가 현재 ta로 등록된 방에 있으면 다 가져와
                    print(video.video_name)
                    labs[i]["videos"].append({"name": video.video_name})
                    if video.flag == 0:
                        labs[i]["videos"][j]["status"] = "Waiting"
                    elif video.flag == 1:
                        labs[i]["videos"][j]["status"] = "Processing"
                    elif video.flag == 2:
                        labs[i]["videos"][j]["status"] = "Done"
            else:
                if video is not None and (video.user_id == g.current_user.id or video.target_id == g.current_user.id):
                    ## 내가 ta로 등록은 안되있는데 그 비디오 주인이 나거나 그 비디오 target_id가 나면 다 가져와
                    labs[i]["videos"].append({"name": video.video_name})
                    if video.flag == 0:
                        labs[i]["videos"][j]["status"] = "Waiting"
                    elif video.flag == 1:
                        labs[i]["videos"][j]["status"] = "Processing"
                    elif video.flag == 2:
                        labs[i]["videos"][j]["status"] = "Done"

    regists = Regist.query.filter_by(user_id=g.current_user.id).all()
    for regist in regists:
        room_id = regist.room_id
        if TA.query.filter_by(user_id=g.current_user.id, room_id=room_id).first():
            roles.append('admin')
        else:
            roles.append('student')

    return jsonify({"labs": labs, "roles": roles}), 200

    # codes = Code.query.filter_by(user_id=g.current_user.id).all()

    # all_list = []
    # unresolved_list = []
    # resolved_list = []
    # print(g.current_user.id)
    # for code in codes:
    #     title = Problem.query.filter_by(id=code.problem_id).first().title
    #     question = Problem.query.filter_by(id=code.problem_id).first()

    #     if g.current_user.role.name == 'Administrator' or g.current_user.role.name == 'Prof':
    #         all_list.append(title)
    #     elif question.permission == True:
    #         all_list.append(title)

    #     if code.pf == False and question.permission == True:
    #         unresolved_list.append(title)
    #     elif code.pf == True and question.permission == True:
    #         resolved_list.append(title)

    # return jsonify({"All_Problems": all_list, "Solved_Problems": unresolved_list, "Resolved_Problems": resolved_list}), 200

ALLOWED_VIDEO_EXTENSIONS = ['mp4', 'zip']
def allowed_video_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_VIDEO_EXTENSIONS

# video 업로드 학생
@api.route('video/<lab>', methods=['POST'])
def upload_video(lab):
    user_id = str(g.current_user.id)

    problem_video_path = os.path.join(videos_path, lab)
    # student_video_path = os.path.join(problem_video_path, user_id)

    room_id = Room.query.filter_by(room_name=lab).first().id

    if 'file' not in request.files:
        resp = jsonify({'message': 'Not video file'})
        resp.status_code = 404
        return resp

    if not os.path.isdir(problem_video_path):
        os.mkdir(problem_video_path)
        os.chmod(problem_video_path, 0o777)
    # if not os.path.isdir(student_video_path):
    #     os.mkdir(student_video_path)
    #     os.chmod(student_video_path, 0o777)

    file = request.files['file']

    if file.filename == '':
        resp = jsonify({'message': 'Not video filename'})
        resp.status_code = 404
        return resp

    if file and allowed_video_file(file.filename):
        filename = secure_filename(file.filename)
        file.save(os.path.join(problem_video_path, filename))
        video = Video(user_id=g.current_user.id, video_name=filename, room_id=room_id, flag = 0)
        db.session.add(video)
        db.session.commit()

    resp = jsonify({'message': 'Success upload video'})
    resp.status_code = 200
    return resp

# video 업로드 TA
@api.route('video/<lab>/<video_name>', methods=['POST'])
def upload_video_ta(lab, video_name):
    # user_id = str(User.query.filter_by(username=username).first().id)

    video_id = str(Video.query.filter_by(video_name=video_name).first().id)

    video_student = Video.query.filter_by(video_name=video_name).first()

    problem_video_path = os.path.join(videos_path, lab)
    # student_video_path = os.path.join(problem_video_path, user_id)

    room_id = Room.query.filter_by(room_name=lab).first().id
    user_id = str(User.query.filter_by(id=video_student.user_id).first().id)

    if 'file' not in request.files:
        resp = jsonify({'message': 'Not video file'})
        resp.status_code = 404
        return resp

    if not os.path.isdir(problem_video_path):
        os.mkdir(problem_video_path)
        os.chmod(problem_video_path, 0o777)
    # if not os.path.isdir(student_video_path):
    #     os.mkdir(student_video_path)
    #     os.chmod(student_video_path, 0o777)

    file = request.files['file']

    if file.filename == '':
        resp = jsonify({'message': 'Not video filename'})
        resp.status_code = 404
        return resp

    if file and allowed_video_file(file.filename):
        filename = secure_filename(file.filename)
        print(filename)
        file.save(os.path.join(problem_video_path, filename))
        video = Video(user_id=g.current_user.id, video_name=filename, room_id=room_id, target_id=user_id, flag=0)
        db.session.add(video)
        db.session.commit()

    video_student = Video.query.filter_by(video_name=video_name, room_id=room_id).first()
    video_student.flag = 2
    db.session.commit()

    # video_student = Video.query.filter_by()

    resp = jsonify({'message': 'Success upload video'})
    resp.status_code = 200
    return resp

# video delete
@api.route('video/<lab>/<video_name>', methods=['DELETE'])
def delete_video(lab, video_name):

    user_id = str(User.query.filter_by(id=g.current_user.id).first().id)

    user_id_int = User.query.filter_by(id=g.current_user.id).first().id

    problem_video_path = os.path.join(videos_path, lab)
    student_video_path = os.path.join(problem_video_path, video_name)

    room_id = Room.query.filter_by(room_name=lab).first().id

    video = Video.query.filter_by(room_id=room_id, video_name=video_name).first()

    is_ta = TA.query.filter_by(user_id=g.current_user.id, room_id=room_id).first()

    if os.path.isfile(student_video_path) and (video.user_id == g.current_user.id or is_ta.user_id is not None):
        os.remove(student_video_path)

    if video.user_id == g.current_user.id or is_ta.user_id is not None:
        db.session.delete(video)
        db.session.commit()

    resp = jsonify({'message': 'Success delete video'})
    resp.status_code = 200
    return resp

#학생 코드 받는거
@api.route('student_codes/<lab>/<id>/<student_id>/<filename>', methods=['GET'])
@prof_required_vs
def get_student_code(lab, id, student_id, filename):

    print(lab)
    print(id)
    print(student_id)
    print(filename)

    code_path = os.path.join(codes_path, lab, id, student_id)

    file = os.path.join(code_path, secure_filename(filename))

    if file:
        return send_file(file, download_name=filename, as_attachment=True, attachment_filename=filename)
    else:
        return '', 404

@api.route('student_codes/<lab>/<id>', methods=['GET'])
def get_student_all(lab, id):
    code_path = os.path.join(codes_path, lab, id, '')

    dir_list = os.listdir(code_path)

    print(dir_list)

    email_list = []

    for i in range(len(dir_list)):
        email = User.query.filter_by(id=int(dir_list[i])).first().username
        email_list.append(email)

    if len(dir_list) >= 1:
        return {'dir_list': dir_list, 'email_list': email_list}, 200
    else:
        return '', 404

@api.route('student_codes/<lab>/<id>/<student_id>', methods=['GET'])  # 문제 file list 반납
def get_student_filelist(lab, id, student_id):
    code_path = os.path.join(codes_path, lab, id, student_id)

    file_list = os.listdir(code_path)

    if len(file_list) >= 1:
        return {'file_list': file_list}, 200
    else:
        return '', 404

# log 초기화
@api.route('logs/<lab>', methods=['DELETE'])
@prof_required_vs
def initialize_logs(lab):
    room_id = Room.query.filter_by(room_name=lab).first().id

    logs = Log.query.filter_by(room_id=room_id).all()

    for log in logs:
        db.session.delete(log)
    db.session.commit()

    resp = jsonify({'message': "success"})
    resp.status_code = 200
    return resp

# log 보내기
@api.route('logs/<lab>', methods=['POST'])
def post_logs(lab):
    student_id = str(g.current_user.id)
    data = request.get_json()
    flag = True if data['flag'] == 1 else False
    room = Room.query.filter_by(room_name=lab).first()
    code = data['code']
    length = data['length'] // 2
    username = User.query.filter_by(id=student_id).first().username

    log = Log(user_id=student_id, code=code, flag=flag, length=length, username=username, room_id=room.id)
    db.session.add(log)
    db.session.commit()
    print('-----------------------------------------------')
    print(log.length)
    print('-----------------------------------------------')

    resp = jsonify({'message': "success"})
    resp.status_code = 200
    return resp

# log 받기
@api.route('logs/<lab>', methods=['GET'])
@prof_required_vs
def get_logs(lab):
    users = Log.query.group_by(Log.user_id).all()
    user_list = []
    log = []
    for user in users:
        user_list.append(user.user_id)

## 랩 이름 받아서 등록
@api.route('labs', methods=['POST'])
@prof_required_vs
def makeLab():
    user_id = User.query.filter_by(id=g.current_user.id).first().id
    data = request.get_json()
    labName = data['labName']
    if Room.query.filter_by(room_name=labName).first():
        return 'The same name lab is exist', 404

    lab_name = Room(room_name=labName, host_id=user_id)
    db.session.add(lab_name)
    db.session.commit()
    ## 룸 등록

    room_id = Room.query.filter_by(room_name=labName).first().id
    host_id = User.query.filter_by(id=g.current_user.id).first().id

    ta = TA(user_id=g.current_user.id, room_id=room_id)

    regist_room = Regist(room_id=room_id, user_id=host_id)
    db.session.add(regist_room)
    db.session.add(ta)
    db.session.commit()

    user = User.query.filter_by(id=g.current_user.id).first()

    log_init = Log(user_id=g.current_user.id, username=user.username, code='Init Log', length=0, total_length=0, room_id=room_id)

    problem_path = os.path.join(problems_path, labName)
    if not os.path.isdir(problem_path):
        os.mkdir(problem_path)
        os.chmod(problem_path, 0o777)

    grading_problem_path = os.path.join(grading_path, labName)
    if not os.path.isdir(grading_problem_path):
        os.mkdir(grading_problem_path)
        os.chmod(grading_problem_path, 0o777)

    resp = jsonify({'lab_name': labName})
    resp.status_code = 200
    return resp

## 등록된 랩 이름 보내주기, 전부 보내주면 될듯
@api.route('labs', methods=['GET'])
def postLab():

    user_id = g.current_user.id

    ## room id 전부
    room_ids = [regists.room_id for regists in  Regist.query.filter_by(user_id=user_id).all()]

    ## room_id 로 찾아야함
    labName = [Room.query.filter_by(id=room_id).first().room_name for room_id in room_ids]

    resp = jsonify({'lab_name': labName})
    resp.status_code = 200
    return resp

## 지울 랩이름 받기
@api.route('labs/delete', methods=['POST'])
@prof_required_vs
def get_deleteLab():

    user_id = User.query.filter_by(id=g.current_user.id).first().id
    data = request.get_json()
    labName = data['deleteLab']

    problem_path = os.path.join(problems_path, labName)
    grading_problem_path = os.path.join(grading_path, labName)

    video_path = os.path.join(videos_path, labName)
    code_path = os.path.join(codes_path, labName)

    room = Room.query.filter_by(room_name=labName).first()
    regists = Regist.query.filter_by(room_id=room.id).all()
    tas = TA.query.filter_by(room_id=room.id).all()
    problems = Problem.query.filter_by(room_id=room.id).all()

    comments = Comment.query.filter_by(room_id=room.id).all()
    for comment in comments:
        db.session.delete(comment)
    db.session.commit()

    if os.path.isdir(video_path):
        shutil.rmtree(video_path)

    if os.path.isdir(code_path):
        shutil.rmtree(code_path)

    # db 문제 삭제, problem
    if room:
        db.session.delete(room)
        for regist in regists:
            db.session.delete(regist)
        for ta in tas:
            db.session.delete(ta)
        for problem in problems:
            db.session.delete(problem)
            problem_code_path = os.path.join(codes_path, labName)
            if os.path.isdir(problem_code_path):
                shutil.rmtree(problem_path)
            codes = Code.query.filter_by(problem_id=problem.id).all()
            for code in codes:
                db.session.delete(code)
        db.session.commit()

    if os.path.isdir(problem_path):
        shutil.rmtree(problem_path)

        if os.path.isdir(grading_problem_path):
            shutil.rmtree(grading_problem_path)

        resp = jsonify({'message': 'Problem successfully delete'})
        resp.status_code = 200
        return resp
    else:
        resp = jsonify({'message': 'Not exist problem ID'})
        resp.status_code = 200
        return resp

## 학생 이메일 받아서 랩에 초대
@api.route('invite', methods=['POST'])
def inviteStudent():
    data = request.get_json()
    email = data['email']
    lab = data['lab']

    addStudent = User.query.filter_by(email=email).first().id
    addRoom = Room.query.filter_by(room_name=lab).first().id
    student = User.query.filter_by(email=email).first()

    ## Regist에 추가
    addStudent2Lab = Regist(room_id=addRoom, user_id=addStudent)
    db.session.add(addStudent2Lab)
    db.session.commit()

    addStudent2Log = Log(user_id=addStudent, username=student.username, code='', length=0, total_length=0, room_id=addRoom)
    db.session.add(addStudent2Log)
    db.session.commit()

    resp = jsonify({'Success': 'Success'})
    resp.status_code = 200
    return resp

## 학생 이메일 받아서 TA권한 주기 (랩에도 바로 추가)
@api.route('inviteTA', methods=['POST'])
def inviteTA():
    data = request.get_json()
    email = data['email']
    lab = data['lab']

    addStudent = User.query.filter_by(email=email).first().id
    addRoom = Room.query.filter_by(room_name=lab).first().id

    ## Regist에 추가
    if Regist.query.filter_by(room_id=addRoom, user_id=addStudent).first() is None:
        addStudent2Lab = Regist(room_id=addRoom, user_id=addStudent)
        db.session.add(addStudent2Lab)
        db.session.commit()

    addTA = TA(user_id=addStudent, room_id=addRoom)
    db.session.add(addTA)
    db.session.commit()

    resp = jsonify({'Success': 'Success'})
    resp.status_code = 200
    return resp

## 학생 이메일 받아서 랩에서 지우기
@api.route('deleteStudentFromLab', methods=['POST'])
def deleteStudentFromLab():
    data = request.get_json()
    username = data['username']
    lab = data['lab']

    ## 지울 학생 아이디
    deleteStudent = User.query.filter_by(username=username).first().id
    ## 지울 랩 아이디
    deleteRoom = Room.query.filter_by(room_name=lab).first().id
    ## 지울 학생 쿼리
    student = User.query.filter_by(username=username).first()

    ## Regist에 있는 거 지움
    ## 지울 학생의 regist (룸 아이디는 지울 랩 아이디, 유저 아이디는 지울 학생 아이디 => 지울 학생이 해당룸에 속해있다.)
    if Room.query.filter_by(room_name=deleteRoom, host_id=g.current_user.id).first():
        return 'He is Professor'

    if Regist.query.filter_by(room_id=deleteRoom, user_id=deleteStudent).first():
        deleteStudent2Lab = Regist.query.filter_by(room_id=deleteRoom, user_id=deleteStudent).first()
        db.session.delete(deleteStudent2Lab)
        db.session.commit()

    ## 해당 학생이 TA라면
    if TA.query.filter_by(user_id=deleteStudent, room_id=deleteRoom).first():
        deleteTA = TA.query.filter_by(user_id=deleteStudent, room_id=deleteRoom).first()
        db.session.delete(deleteTA)
        db.session.commit()

    deleteStudent2Log = Log.query.filter_by(user_id=deleteStudent, username=student.username, room_id=deleteRoom).first()
    if deleteStudent2Log is not None:
        db.session.delete(deleteStudent2Log)
        db.session.commit()

    resp = jsonify({'Success': 'Success'})
    resp.status_code = 200
    return resp


from datetime import datetime

from app import app, db
from app.database import commit_eou_record, db_commit, delete_customized_tag, \
  get_all_customized_tag, get_email_and_itv, \
  get_eou_record, get_scn_ids_by_uuid, \
  get_rtn_ids_by_uuid, record_consented, record_finish_time, record_tag_reason, \
  update_customized_tag, \
  update_email_itv, update_itv, \
  record_multi_scn_stt_scores_w_reason
from app.models import FinishForm, ReasoningForm, Users, RoutineTag, UUIDForm
from app.system import get_user_scn_outcome
from app.utils import *

from flask import render_template, request, redirect, jsonify, flash, session, url_for

@app.before_request
def before_request_func():
  pass

@app.route('/', methods=['GET', 'POST'])
def index():
  uuid = None
  form = UUIDForm()
  if form.validate_on_submit():
    # TODO(@ry): check to database and record to database
    uuid = form.uuid.data
    user = Users.query.get(uuid)
    if user is None:
      scn_ids, rtn_ids = get_random_scn_rtn_ids()
      user = Users(uuid=uuid,
                   scn_ids=','.join([str(v) for v in scn_ids]),
                   rtn_ids=','.join([str(v) for v in rtn_ids]))
      db.session.add(user)
    elif not user.scn_ids:
      scn_ids, rtn_ids = get_random_scn_rtn_ids()
      user.scn_ids = ','.join([str(v) for v in scn_ids])
      user.rtn_ids = ','.join([str(v) for v in rtn_ids])
    # Update survey start time
    user.date_added = datetime.utcnow()
    db.session.commit()
    flash("Welcome!")
    session['uuid'] = uuid
    form.uuid.data = ''
    return render_template('consent_form.html', uuid=uuid, consented=None)
  return render_template('id_validation.html', uuid=uuid, form=form)

@app.route('/consented', methods=['GET', 'POST'])
def consented():
  consent = request.form.get('consent')
  record_consented(session['uuid'], (consent == 'y'))
  if consent == 'y':
    return render_template('background.html')
  else:
    return render_template('finish.html', finished=False)

@app.route('/tag/<int:idx>', methods=['GET', 'POST'])
def tag(idx):
  # Get all long routines for the specific user.
  rtn_ids = get_rtn_ids_by_uuid(session['uuid'])
  rtn_ids, rtn_info = get_all_rtn_info(rtn_ids)
  total_rtn = len(rtn_ids)
  if idx < 1 or idx > total_rtn:
    return redirect(url_for('tag', idx=1))

  rid = rtn_ids[idx - 1]
  reason_form = ReasoningForm()
  print("Current idx: " + str(idx) + " Total rtn: ", total_rtn)
  if request.method == 'POST' and 'tag-page-action' in request.form:
    reason = reason_form.reason.data
    record_tag_reason(session['uuid'], rid, reason)

    action = request.form['tag-page-action']
    if action == 'Previous':
      return redirect(url_for('tag', idx=idx-1))
    elif action == 'Next':
      return redirect(url_for('tag', idx=idx+1))
    elif action == 'Finish':
      return redirect(url_for('scenario', idx=0))

  # Start to show the page.
  rtn_tags = RoutineTag.query.get((session['uuid'], rid))
  if rtn_tags is None:
    rtn_tags = RoutineTag(uuid=session['uuid'], rtn_id=rid)
    db.session().add(rtn_tags)
    db.session().commit()

  all_cus_tag_list = get_all_customized_tag(session['uuid'])
  rtn_cus_tags = rtn_tags.rtn_cus_tags.split(',') if rtn_tags.rtn_cus_tags else []
  rtn_sys_tag = tag_display_name(rtn_tags.rtn_sys_tag)
  cmd1_tag = tag_display_name(rtn_tags.cmd1_tag)
  cmd2_tag = tag_display_name(rtn_tags.cmd2_tag)
  reason_form.reason.data = rtn_tags.tag_reason
  return render_template('tagging.html',
                         rtn_info=rtn_info[rid],
                         idx=idx,
                         rid=rid,
                         rtn_sys_tag=rtn_sys_tag,
                         all_cus_tag=all_cus_tag_list,
                         rtn_cus_tags=rtn_cus_tags,
                         cmd1_tag=cmd1_tag,
                         cmd2_tag=cmd2_tag,
                         total_rtn=total_rtn,
                         reason_form=reason_form)

@app.route('/create-tag', methods=['GET', 'POST'])
def create_cus_tag():
  data = request.get_json()
  tag_name, priority = data['tag_name'], data['priority']
  status = update_customized_tag(session['uuid'], tag_name, priority)
  if status == 'empty name':
    flash('Tag name cannot be empty.')
  result = {'success': True, 'response': 'Done'}
  return jsonify(result)

@app.route('/edit-tag', methods=['GET', 'POST'])
def edit_cus_tag():
  data = request.get_json()
  tag_name, priority = data['tag_name'], data['priority']
  update_customized_tag(session['uuid'], tag_name, priority)
  result = {'success': True, 'response': 'Done'}
  return jsonify(result)

@app.route('/delete-tag', methods=['GET', 'POST'])
def delete_cus_tag():
  data = request.get_json()
  tag_name = data['tag_name']
  delete_customized_tag(session['uuid'], tag_name)
  result = {'success': True, 'response': 'Done'}
  return jsonify(result)

@app.route('/update-sys-tag', methods=['GET', 'POST'])
def update_sys_tag():
  data = request.get_json()
  item, rid = data['item'], data['rid']
  item = internal_sys_name(item)
  rtn_tags = RoutineTag.query.get((session['uuid'], rid))
  if item in ['Uninterruptible', 'Pausable']:
    rtn_tags.rtn_sys_tag = item
    rtn_tags.cmd1_tag = item
    rtn_tags.cmd2_tag = item
  else:
    if rtn_tags.rtn_cus_tags:
      if item not in rtn_tags.rtn_cus_tags.split(','):
        rtn_tags.rtn_cus_tags += ',' + item
    else:
      rtn_tags.rtn_cus_tags = item

  db_commit()
  result = {'success': True, 'response': 'Done'}
  return jsonify(result)

@app.route('/update-cmd1-tag', methods=['GET', 'POST'])
def update_cmd1_tag():
  data = request.get_json()
  item, rid = data['item'], data['rid']
  item = internal_sys_name(item)
  rtn_tags = RoutineTag.query.get((session['uuid'], rid))
  if item in ['Uninterruptible', 'Pausable']:
    rtn_tags.cmd1_tag = item
    # Update routine level system tag accordingly.
    if rtn_tags.cmd1_tag == rtn_tags.cmd2_tag:
      rtn_tags.rtn_sys_tag = rtn_tags.cmd1_tag
    else:
      rtn_tags.rtn_sys_tag = ''
  else:
    flash("Self-defined tag can only be assigned to routines, not commands.")
  db_commit(success_msg="Update CMD1 system tag successfully",
            fail_msg="[ERROR] CMD1 sys tag update failed")
  result = {'success': True, 'response': 'Done'}
  return jsonify(result)

@app.route('/update-cmd2-tag', methods=['GET', 'POST'])
def update_cmd2_tag():
  data = request.get_json()
  item, rid = data['item'], data['rid']
  item = internal_sys_name(item)
  rtn_tags = RoutineTag.query.get((session['uuid'], rid))
  if item in ['Uninterruptible', 'Pausable']:
    rtn_tags.cmd2_tag = item
    if rtn_tags.cmd1_tag == rtn_tags.cmd2_tag:
      rtn_tags.rtn_sys_tag = rtn_tags.cmd2_tag
    else:
      rtn_tags.rtn_sys_tag = ''
  else:
    flash("Customized tag can only be put for routine!")

  db_commit(success_msg="Update CMD2 system tag successfully",
            fail_msg="[ERROR] CMD2 sys tag update failed")
  result = {'success': True, 'response': 'Done'}
  return jsonify(result)

@app.route('/remove-rtn-sys-tag/<int:rid>/<int:idx>', methods=['GET', 'POST'])
def remove_rtn_sys_tag(rid, idx):
  rtn_tags = RoutineTag.query.get((session['uuid'], rid))
  rtn_tags.rtn_sys_tag = ''
  rtn_tags.cmd1_tag = ''
  rtn_tags.cmd2_tag = ''
  db_commit(success_msg="RTN {0} system tag removed".format(rid),
            fail_msg="[ERROR] RTN sys tag remove failed")
  return redirect(url_for('tag', idx=idx))

@app.route('/remove-cus-tag/<int:rid>/<int:idx>/<string:tag_name>',
           methods=['GET', 'POST'])
def remove_cus_tag(rid, idx, tag_name):
  rtn_tags = RoutineTag.query.get((session['uuid'], rid))
  rtn_tags.rtn_cus_tags = remove_cus_tag_in_string(
    rtn_tags.rtn_cus_tags, tag_name)
  db_commit(success_msg="RTN {0} cus tag {1} removed".format(rid, tag),
            fail_msg="[ERROR] RTN customized tag remove failed")
  return redirect(url_for('tag', idx=idx))

@app.route('/remove-cmd1-tag/<int:rid>/<int:idx>', methods=['GET', 'POST'])
def remove_cmd1_tag(rid, idx):
  rtn_tags = RoutineTag.query.get((session['uuid'], rid))
  rtn_tags.cmd1_tag = ''
  rtn_tags.rtn_sys_tag = ''
  db_commit(success_msg="RTN {0} (rid {1}) CMD1 tag removed".format(idx, rid),
            fail_msg="[ERROR] RTN {0} CMD1 tag remove failed".format(rid))
  return redirect(url_for('tag', idx=idx))

@app.route('/remove-cmd2-tag/<int:rid>/<int:idx>', methods=['GET', 'POST'])
def remove_cmd2_tag(rid, idx):
  rtn_tags = RoutineTag.query.get((session['uuid'], rid))
  rtn_tags.cmd2_tag = ''
  rtn_tags.rtn_sys_tag = ''
  db_commit(success_msg="RTN {0} (rid {1}) CMD2 tag removed".format(idx, rid),
            fail_msg="[ERROR] RTN {0} CMD2 tag remove failed".format(rid))
  return redirect(url_for('tag', idx=idx))

@app.route('/scenario/<int:idx>', methods=['GET', 'POST'])
def scenario(idx):
  scn_ids = get_scn_ids_by_uuid(session['uuid'])
  total_scn = len(scn_ids)
  if idx < 1 or idx > total_scn:
    return redirect(url_for('scenario', idx=1))

  # Read user record if they've filled for this scenario
  # no matter whether it has been pushed to database.
  sid = scn_ids[idx - 1]
  scn_info = get_scenario_by_id(sid)
  outcomes, scores, strategies = get_user_scn_outcome(
    session['uuid'], sid, scn_info)

  fst_oc_form = FstOutcomeForm()
  snd_oc_form = SndOutcomeForm() if len(scores) > 1 else None
  reason_form = ReasoningForm()
  if request.method == 'POST' and 'scn-page-action' in request.form:
    # Record user choice
    scores = [fst_oc_form.oc1.data]
    if snd_oc_form:
      scores.append(snd_oc_form.oc2.data)
    reason = reason_form.reason.data
    record_multi_scn_stt_scores_w_reason(
      session['uuid'], sid, strategies, scores, reason)

    # Navigate among scenarios
    action = request.form['scn-page-action']
    if action == 'Previous':
      return redirect(url_for('scenario', idx=idx-1))
    elif action == 'Next':
      return redirect(url_for('scenario', idx=idx+1))
    elif action == 'Finish':
      return redirect(url_for('ease_of_use'))

  fst_oc_form, snd_oc_form = get_outcome_forms(scores)
  print("Scenario internal id:", scn_info['scn_id'],
        "strategies: ", strategies)
  return render_template('scenario.html',
                         idx=idx,
                         sid=sid,
                         scn_description=scn_info['scn_description'],
                         outcome=outcomes,
                         total_scn=total_scn,
                         fst_oc_form=fst_oc_form,
                         snd_oc_form=snd_oc_form,
                         reason_form=reason_form)

@app.route('/ease-of-use', methods=['GET', 'POST'])
def ease_of_use():
  descriptions = [
    'I think that I would like to use this system frequently.',
    'I found the system unnecessarily complex.',
    'I thought the system was easy to use.',
    'I think that I would need the support of a technical person to be able to use this system.',
    'I found the various functions in this system were well integrated.',
    'I thought there was too much inconsistency in this system.',
    'I would imagine that most people would learn to use this system very quickly.',
    'I found the system very cumbersome to use.',
    'I felt very confident using the system.'
  ]
  num_q = len(descriptions)
  form = EaseOfUseForm()

  if form.validate_on_submit():
    # Fetch ease-of-use responses
    responses = {}
    for i in range(num_q):
      exec('responses[{0}] = form.q{0}.data'.format(i))
    # commit to database
    responses['open'] = form.open_ended.data
    responses['tag'] = form.tag_potential.data
    commit_eou_record(session['uuid'], responses)
    return redirect(url_for('finish', status=1))

  eou_scores = get_eou_record(session['uuid'])
  form = get_eou_form(eou_scores)
  return render_template('easy_of_use.html',
                         form=form,
                         eou_scores=eou_scores,
                         descriptions=descriptions)

@app.route('/finish/<int:status>', methods=['GET', 'POST'])
def finish(status):
  form = FinishForm()
  email, itv = get_email_and_itv(session['uuid']) if status >= 1 else [None, None]
  if status == 3:
    record_finish_time(session['uuid'])

  if form.validate_on_submit():
    e_confirm = form.email_confirm.data if email is not None else 0
    # Deal with last step refresh
    if e_confirm is None:
      e_confirm = 1 if email is not None else 0
    itv_interest = int(form.interview.data)
    if int(e_confirm):
      update_itv(session['uuid'], itv_interest)
      form.interview.data = None
      return redirect(url_for('finish', status=3))
    if not int(e_confirm) and form.email.data:
      email = form.email.data
      update_email_itv(session['uuid'], email, itv_interest)
      form.email.data = None
      form.interview.data = None
      return redirect(url_for('finish', status=3))
    if not int(e_confirm) and not form.email.data:
      flash('Please input your email address.')
      return redirect(url_for('finish', status=2))
  return render_template('finish.html', finished=status,
                         email=email, form=form)


import numpy as np
import random
import pandas as pd
import os
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn import preprocessing
from sklearn.metrics import f1_score
from sklearn.utils.class_weight import compute_class_weight

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader

from tqdm.auto import tqdm
from transformers import *
from torch.utils.data import Dataset, TensorDataset, DataLoader, RandomSampler, SequentialSampler

import time
from datetime import datetime

device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")

# naive train/test split
df = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")

train, val, _, _ = train_test_split(df, df["label"], test_size=0.2)

# simple data preprocessing
train_sentences = train["문장"].values
train_Y1 = train["유형"].values
train_Y2 = train["극성"].values
train_Y3 = train["시제"].values
train_Y4 = train["확실성"].values

val_sentences = val["문장"].values
val_Y1 = val["유형"].values
val_Y2 = val["극성"].values
val_Y3 = val["시제"].values
val_Y4 = val["확실성"].values

Y1_dict = {"대화형": 0, "사실형": 1, "예측형": 2, "추론형": 3}
Y2_dict = {"긍정": 0, "미정": 1, "부정": 2}
Y3_dict = {"과거": 0, "미래": 1, "현재": 2}
Y4_dict = {"불확실": 0, "확실": 1}

Y1_dict_rev = {0: "대화형", 1: "사실형", 2: "예측형", 3: "추론형"}
Y2_dict_rev = {0: "긍정", 1: "미정", 2: "부정"}
Y3_dict_rev = {0: "과거", 1: "미래", 2: "현재"}
Y4_dict_rev = {0: "불확실", 1: "확실"}

train_Y1_cat = []
for i in range(len(train_Y1)):
    train_Y1_cat.append(Y1_dict[train_Y1[i]])

train_Y2_cat = []
for i in range(len(train_Y2)):
    train_Y2_cat.append(Y2_dict[train_Y2[i]])

train_Y3_cat = []
for i in range(len(train_Y3)):
    train_Y3_cat.append(Y3_dict[train_Y3[i]])

train_Y4_cat = []
for i in range(len(train_Y4)):
    train_Y4_cat.append(Y4_dict[train_Y4[i]])

val_Y1_cat = []
for i in range(len(val_Y1)):
    val_Y1_cat.append(Y1_dict[val_Y1[i]])

val_Y2_cat = []
for i in range(len(val_Y2)):
    val_Y2_cat.append(Y2_dict[val_Y2[i]])

val_Y3_cat = []
for i in range(len(val_Y3)):
    val_Y3_cat.append(Y3_dict[val_Y3[i]])

val_Y4_cat = []
for i in range(len(val_Y4)):
    val_Y4_cat.append(Y4_dict[val_Y4[i]])

# define tokenizer
tokenizer = AutoTokenizer.from_pretrained("snunlp/KR-SBERT-V40K-klueNLI-augSTS")

# define model
class MeanPooling(nn.Module):
    def __init__(self):
        super(MeanPooling, self).__init__()
    def forward(self, last_hidden_state, attention_masks):
        input_mask_expanded = attention_masks.unsqueeze(-1).expand(last_hidden_state.size()).float()
        sum_embeddings = torch.sum(last_hidden_state * input_mask_expanded, 1)
        sum_mask = input_mask_expanded.sum(1)
        sum_mask = torch.clamp(sum_mask, min=1e-9)
        mean_embeddings = sum_embeddings / sum_mask
        return mean_embeddings

class MultiSampleDropout(nn.Module):
    def __init__(self, max_dropout_rate, num_samples, classifier):
        super(MultiSampleDropout, self).__init__()
        self.dropout = nn.Dropout
        self.classifier = classifier
        self.max_dropout_rate = max_dropout_rate
        self.num_samples = num_samples
    def forward(self, out):
        return torch.mean(torch.stack([self.classifier(self.dropout(p=self.max_dropout_rate)(out)) for _, rate in enumerate(np.linspace(0, self.max_dropout_rate, self.num_samples))], dim=0), dim=0)

class NeuralCLF(nn.Module):
    def __init__(self, num_classes, plm="snunlp/KR-SBERT-V40K-klueNLI-augSTS"):
        super(NeuralCLF, self).__init__()
        self.config = AutoConfig.from_pretrained(plm)
        self.model = AutoModel.from_pretrained(plm, config=self.config)
        self.tokenizer = AutoTokenizer.from_pretrained(plm)
        self.mean_pooler = MeanPooling()
        self.fc = nn.Linear(self.config.hidden_size, num_classes)
        self._init_weights(self.fc)
        self.multi_dropout = MultiSampleDropout(0.2, 8, self.fc)
        self.metric = nn.CrossEntropyLoss()
    def _init_weights(self, module):
        if isinstance(module, nn.Linear):
            module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
            if module.bias is not None:
                module.bias.data.zero_()
    def forward(self, input_ids, attn_masks):
        x = self.model(input_ids, attn_masks)[0]
        x = self.mean_pooler(x, attn_masks)
        x = self.multi_dropout(x)
        return x

class WeightedFocalLoss(nn.Module):
    def __init__(self, alpha, gamma=2):
        super(WeightedFocalLoss, self).__init__()
        self.alpha = alpha
        self.device = torch.device("cuda")
        self.alpha = self.alpha.to(self.device)
        self.gamma = gamma
    def forward(self, inputs, targets):
        CE_loss = nn.CrossEntropyLoss()(inputs, targets)
        targets = targets.type(torch.long)
        at = self.alpha.gather(0, targets.data.view(-1))
        pt = torch.exp(-CE_loss)
        F_loss = at * (1-pt)**self.gamma * CE_loss
        return F_loss.mean()

def flat_accuracy(preds, labels):
    pred_flat = np.argmax(preds, axis=1).flatten()
    labels_flat = labels.flatten()
    return np.sum(pred_flat == labels_flat) / len(labels_flat)

train_input_ids, train_attn_masks = [], []
for i in tqdm(range(len(train_sentences))):
    encoded_inputs = tokenizer(train_sentences[i], max_length=256, truncation=True, padding='max_length')
    train_input_ids.append(encoded_inputs["input_ids"])
    train_attn_masks.append(encoded_inputs["attention_mask"])

val_input_ids, val_attn_masks = [], []
for i in tqdm(range(len(val_sentences))):
    encoded_inputs = tokenizer(val_sentences[i], max_length=256, truncation=True, padding='max_length')
    val_input_ids.append(encoded_inputs["input_ids"])
    val_attn_masks.append(encoded_inputs["attention_mask"])

train_input_ids = torch.tensor(train_input_ids, dtype=int)
train_attn_masks = torch.tensor(train_attn_masks, dtype=int)

val_input_ids = torch.tensor(val_input_ids, dtype=int)
val_attn_masks = torch.tensor(val_attn_masks, dtype=int)

train_Y1_labels = torch.tensor(train_Y1_cat, dtype=int)
val_Y1_labels = torch.tensor(val_Y1_cat, dtype=int)

train_Y2_labels = torch.tensor(train_Y2_cat, dtype=int)
val_Y2_labels = torch.tensor(val_Y2_cat, dtype=int)

train_Y3_labels = torch.tensor(train_Y3_cat, dtype=int)
val_Y3_labels = torch.tensor(val_Y3_cat, dtype=int)

train_Y4_labels = torch.tensor(train_Y4_cat, dtype=int)
val_Y4_labels = torch.tensor(val_Y4_cat, dtype=int)

# start of the inference loop
num_classes_list = [4, 3, 3, 2]
dict_list = [Y1_dict, Y2_dict, Y3_dict, Y4_dict]
rev_dict_list = [Y1_dict_rev, Y2_dict_rev, Y3_dict_rev, Y4_dict_rev]
cat_labels_list = [train_Y1_cat, train_Y2_cat, train_Y3_cat, train_Y4_cat]
train_labels_list = [train_Y1_labels, train_Y2_labels, train_Y3_labels, train_Y4_labels]
val_labels_list = [val_Y1_labels, val_Y2_labels, val_Y3_labels, val_Y4_labels]

full_predictions = []
checkpoints = ["Model1_val_acc:0.8858635355029586_val_loss:0.023926928197712326.pt",
               "Model2_val_acc:0.9741586538461539_val_loss:0.0020506795306512405.pt",
               "Model3_val_acc:0.9034069896449703_val_loss:0.022876849130625487.pt",
               "Model4_val_acc:0.9359975961538461_val_loss:0.008119990593627335.pt"]

test_sentences = test["문장"].values

test_input_ids, test_attn_masks = [], []
for i in tqdm(range(len(test_sentences))):
    encoded_inputs = tokenizer(test_sentences[i], max_length=256, truncation=True, padding='max_length')
    test_input_ids.append(encoded_inputs["input_ids"])
    test_attn_masks.append(encoded_inputs["attention_mask"])

test_input_ids = torch.tensor(test_input_ids, dtype=int)
test_attn_masks = torch.tensor(test_attn_masks, dtype=int)

batch_size = 32
test_data = TensorDataset(test_input_ids, test_attn_masks)
test_sampler = SequentialSampler(test_data)
test_dataloader = DataLoader(test_data, sampler=test_sampler, batch_size=batch_size)

for J in range(len(num_classes_list)):
    print(f"===== Training for category {J+1} =====")
    model = NeuralCLF(num_classes=num_classes_list[J])
    checkpoint = torch.load(checkpoints[J])
    model.load_state_dict(checkpoint)
    model.eval()
    model.cuda()

    predictions = []

    for step, batch in tqdm(enumerate(test_dataloader), position=0, leave=True, total=len(test_dataloader)):
        batch = tuple(t.to(device) for t in batch)
        b_input_ids, b_input_mask = batch
        with torch.no_grad():
            outputs = model(b_input_ids, b_input_mask)
        classes = nn.Softmax()(outputs)
        classes = torch.argmax(classes, dim=1)
        classes = classes.detach().cpu().numpy()
        predictions.extend(classes)

    predictions_string = []
    for p in predictions:
        predictions_string.append(rev_dict_list[J][p])

    full_predictions.append(predictions_string)

print(len(full_predictions))
print(len(full_predictions[0]),len(full_predictions[1]), len(full_predictions[2]), len(full_predictions[3]))

answers = []
for i in range(len(full_predictions[0])):
    x1 = full_predictions[0][i]
    x2 = full_predictions[1][i]
    x3 = full_predictions[2][i]
    x4 = full_predictions[3][i]
    answer_str = str(x1) + "-" + str(x2) + "-" + str(x3) + "-" + str(x4)
    answers.append(answer_str)

print(len(answers))

submission = pd.read_csv("sample_submission.csv")
submission["label"] = answers

submission.to_csv("KRSBERT_baseline.csv",index=False)

print("done!")


import logging
from asyncio import Event
from socket import AF_INET, SOCK_STREAM, socket
from threading import Thread

from utils.utils_socket import get_socket

class ChatPeer:
    def __init__(self, type: str, name: str, id: str):
        self.type = type
        self.name = name
        self.id = id

        type = type.upper()
        if type in ['SERVER', 'CLIENT']:
            self.type = type
        else:
            raise NotImplementedError("Argument 'type' must be either 'SERVER' or 'CLIENT'.")

        self.identify_string = f"{ self.type } { self.name }({ self.id })"

class SendThread(Thread):
    def __init__(self, conn_socket: socket, msg_str: str, handler=None, fail_handler=None):
        super().__init__()

        self.conn_socket = conn_socket
        self.msg_str = msg_str
        self.handler = handler
        self.fail_handler = fail_handler

    def run(self):
        try:
            self.conn_socket.send(self.msg_str.encode('utf-8'))
            logging.info(f"Sent message to { self.conn_socket.getpeername() }")

            if self.handler is not None:
                self.handler(self.conn_socket)
        except Exception as ex:
            logging.error(f"Failed to send message. { ex }")
            if self.fail_handler is not None:
                self.fail_handler(None)


from pydub import AudioSegment
import numpy as np

def find_max(list_):
    index=0
    for i in range(0,len(list_)):
        if(list_[i]>list_[index]):
            index=i
    return index

src = "EverlastingTruth.mp3"
audio = AudioSegment.from_file(src,"mp3")
#raw_audio_data = audio.raw_data
#decibel = audio[4900:5000].dBFS
#data = np.fromstring(audio._data, np.int16)
data_length = len(audio)
print(data_length)

#每500ms=0.5s算一个音
note_time = 500
bar = data_length//note_time + 1
note_decibel = []

for i in range(0,bar):
    note_decibel.append((audio[500*i:500*(i+1)]).dBFS)
note_num=len(note_decibel)
print(note_num)

#设置每7s为一个小节
piece_time = 7000
note_every_piece = piece_time // note_time
piece_num = 500*len(note_decibel)//piece_time
piece_max=[]
point_max=[]

for i in range(0,piece_num):
    piece_max.append(max(note_decibel[i*note_every_piece:(i+1)*note_every_piece]))
    point_max.append(find_max(note_decibel[i*note_every_piece:(i+1)*note_every_piece]))

print(len(piece_max))
print(piece_max)

stress_time=[]
print("Stress time:")
for i in range(0,len(point_max)):
    stress_time.append(i*7+0.5*point_max[i])
    print(i*7+0.5*point_max[i],"s")

#print(max(note_decibel))
#
#decibel_time = 500
#print(len(audio._data))
#print(len(raw_audio_data))

"""
print(decibel)
loudness = audio.dBFS
print(loudness)
data = np.fromstring(loudness,np.int16)
print(data)
length = len(data)
for i in data:
    if(i!=0):
        print(i)
print(data[100:200])

"""


#!/usr/bin/python
# coding=utf-8

import urllib3
import datetime
import time
import urllib

# 创建连接特定主机的连接池
http_pool = urllib3.HTTPConnectionPool('ent.qq.com')
# 获取开始时间
now = time.localtime(time.time())
strStart = time.strftime("%Y/%m/%d %H:%M:%S", now)

for i in range(0, 100, 1):
    print(i)
    # 组合URL字符串
    url = 'http://ent.qq.com/a/20111216/%06d.htm' % i
    print(url)

    # 开始同步获取内容
    r = http_pool.urlopen('GET', url, redirect=False)
    print(r.status, r.headers, len(r.data))

# 打印时间
print('start time : ', strStart)

now = time.localtime(time.time())
strEnd = time.strftime("%Y/%m/%d %H:%M:%S", now)
print('end time : ', strEnd)


#! /usr/bin/env python2.6
# -*- coding: utf-8 -*-

__author__ = 'Justin S Bayer, <bayer.justin@googlemail.com>'

import cStringIO as StringIO
import json
import unittest

import drecks

class DrecksTest(unittest.TestCase):

  def setUp(self):
    self.stream = StringIO.StringIO()

  def test_json_reporter(self):
    self.logger = drecks.Logger()
    self.logger.register_reporter(drecks.JsonReporter(stream=self.stream))
    self.logger.log(('error', 'critical'), message='blablabla')
    self.logger.log(('error', 'network'), message='blablabla2')
    data = self.stream.getvalue()
    lines = data.split('\n')
    recovered1 = json.loads(lines[0][5:])
    self.assertEqual(recovered1['labels'], ['error', 'critical'])
    self.assertEqual(recovered1['message'], 'blablabla')

    recovered2 = json.loads(lines[1][5:])
    self.assertEqual(recovered2['labels'], ['error', 'network'])
    self.assertEqual(recovered2['message'], 'blablabla2')

  def test_filter(self):
    logger = drecks.Logger()
    r = drecks.ListReporter()
    r.filters.append(lambda l, i, t: 'error' in l)
    logger.register_reporter(r)
    logger.log(('error',), message="foo")
    logger.log(('no-error',), message="foo")
    self.assertEqual(r.items[0][0], ('error',))

  def test_getlogger(self):
    logger1 = drecks.get_logger('one')
    logger2 = drecks.get_logger('one')
    self.assertEqual(id(logger1), id(logger2))
    self.assertEqual(id(drecks._loggers.values()[0]), id(logger1))

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


import datetime

import requests

# response = requests.get(url="http://api.open-notify.org/iss-now.json")
# response.raise_for_status()
# response = response.json()
# long = response["iss_position"]["longitude"]
# print(f"The ISS is at Longitude:{long}")

# r = requests.get(url="https://api.kanye.rest")
# r = r.json()
# print(r)

MY_LAT = 52.375893
MY_LONG = 9.732010

parameters = {
    "lat": MY_LAT,
    "lng": MY_LONG,
    "formatted": 0,

}

r = requests.get(url="https://api.sunrise-sunset.org/json", params=parameters)
r.raise_for_status()
r = r.json()["results"]["sunrise"]
print(r)
print(datetime.datetime.now())


from flask_jwt_extended import JWTManager
import redis

jwt = JWTManager()
jwt_redis_blocklist = redis.StrictRedis(
    host="localhost", port=6379, db=0, decode_responses=True
)

@jwt.token_in_blocklist_loader
def check_if_token_is_revoked(jwt_header, jwt_payload):
    jti = jwt_payload["jti"]
    token_in_redis = jwt_redis_blocklist.get(jti)
    return token_in_redis is not None


import copy
import numpy # needed (don't change it)
import importlib
import os
import sys
import socket
mammoth_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(mammoth_path)
sys.path.append(mammoth_path + '/datasets')
sys.path.append(mammoth_path + '/backbone')
sys.path.append(mammoth_path + '/models')

from datasets import NAMES as DATASET_NAMES
from models import get_all_models
from argparse import ArgumentParser
from utils.args import add_management_args
from datasets import ContinualDataset
from datasets import get_dataset
from models import get_model
from utils.training import run_epoch, evaluate, print_mean_accuracy
from utils.best_args import best_args
from utils.conf import set_random_seed, base_path, set_base_path
from utils.callbacks import FintuneCallback, CheckpointCallback
from utils.wandb_logger import WandbLogger
from backbone import get_classifier
from backbone.MNISTMLP import MNISTMLP
from backbone.ConvNet import ConvNet

import numpy as np
import torch
import uuid
import datetime
import wandb

time_suffix = datetime.datetime.now().strftime('%y%m%d%H%M%S')

def lecun_fix():
    # Yann moved his website to CloudFlare. You need this now
    from six.moves import urllib
    opener = urllib.request.build_opener()
    opener.addheaders = [('User-agent', 'Mozilla/5.0')]
    urllib.request.install_opener(opener)

def parse_args(to_parse=None):
    parser = ArgumentParser(description='mammoth', allow_abbrev=False)
    parser.add_argument('--model', type=str, required=True,
                        help='Model name.', choices=get_all_models())
    parser.add_argument('--dataset', type=str, required=True,
                        choices=DATASET_NAMES,
                        help='Which dataset to perform experiments on.')
    parser.add_argument('--load_best_args', action='store_true',
                        help='Loads the best arguments for each method, '
                             'dataset and memory buffer.')
    torch.set_num_threads(4)
    add_management_args(parser)
    args = parser.parse_known_args(to_parse)[0]
    mod = importlib.import_module('models.' + args.model)

    if args.load_best_args:

        if hasattr(mod, 'Buffer'):
            parser.add_argument('--buffer_size', type=int, required=True,
                                help='The size of the memory buffer.')

        # Up to this point, the parsed arguments are only basic ones and used for get the best args
        args = parser.parse_known_args(to_parse)[0]

        # get the best args for the given model, dataset and buffer size
        best = best_args[args.dataset][args.model]

        if hasattr(mod, 'Buffer'):
            best = best[args.buffer_size]
        else:
            best = best[-1]

        # Get the parser from the specific model and dataset
        get_parser = getattr(mod, 'get_parser')
        parser = get_parser()

        # Modified the input arguments according to best_args
        if to_parse is None:
            to_parse = sys.argv[1:]

        to_parse = to_parse + ['--' + k + '=' + str(v)
                               for k, v in best.items()
                               if '--' + k not in to_parse]

        to_parse.remove('--load_best_args')

        # Parse the arguments
        args = parser.parse_args(to_parse)
    else:
        get_parser = getattr(mod, 'get_parser')
        parser = get_parser()
        args = parser.parse_args(to_parse)

    if args.model == 'joint' and args.dataset == 'mnist-360':
        args.model = 'joint_gcl'

    if args.seed is not None:
        set_random_seed(args.seed)

    exp_name = f'{args.model}-{args.dataset}'
    if 'buffer_size' in vars(args).keys():
        exp_name += f'-buf_{args.buffer_size}'
    if args.exp_suffix is not None:
        exp_name += f'-{args.exp_suffix}'

    if args.time_suffix is not None:
        exp_name += "-" + args.time_suffix
    else:
        exp_name += "-" + time_suffix

    args.exp_name = exp_name

    return args

def process_args(args):
    # Set environment variables for ComputeCanada
    if "SLURM_TMPDIR" in os.environ:
        args.base_path = os.path.join(os.environ["SLURM_TMPDIR"], 'data/')
        args.ckpt_folder = os.path.join(os.environ["SLURM_TMPDIR"], 'ckpt/')

    set_base_path(args.base_path)

    return args

def get_backbone(args, dataset):
    if args.backbone == 'convnet':
        im_size = get_dataset(args).IMG_SIZE
        channel = get_dataset(args).N_CHANNELS
        num_classes = get_dataset(args).N_CLASSES
        backbone = ConvNet(channel=channel,
                        num_classes=num_classes,
                        net_width=args.net_width,
                        net_depth=args.net_depth,
                        net_act='relu',
                        net_norm=args.net_norm,
                        net_pooling=args.net_pooling,
                        im_size=im_size,
                        )

    elif args.backbone == 'mnistmlp':
        backbone = MNISTMLP(28 * 28, 10)
    else:
        backbone = dataset.get_backbone(args)

    # Change the classification layer of the backbone according to the arguments
    if args.classifier_type is not None:
        backbone.classifier = get_classifier(args.classifier_type, backbone.feat_dim, backbone.num_classes)

    # Used for loading pretrained models
    if args.load_backbone_weights is not None:
        print("Loading weights from", args.load_backbone_weights)
        ckpt = torch.load(args.load_backbone_weights)
        backbone.load_state_dict(ckpt['state_dict'])

    print("Using backbone", type(backbone).__name__)

    return backbone

def create_or_restore_training_state(args, ckpt_path=None):
    if ckpt_path is not None:
        ckpt = torch.load(ckpt_path)
        args.exp_name = ckpt['args'].exp_name
    else:
        ckpt = None

    # Build dataset class (for meta data only)
    dataset = get_dataset(args)

    # Build backbone network and continual model
    backbone = get_backbone(args, dataset)
    model = get_model(args, backbone, dataset.get_loss(), dataset.get_transform())
    model.reset_optimizers(dataset)

    # Set some arguments to default ones if still not set at this point
    if args.n_epochs is None and isinstance(dataset, ContinualDataset):
        args.n_epochs = dataset.get_epochs()
        assert args.n_epochs is not None, 'Could not get number of epochs'
    if args.batch_size is None:
        args.batch_size = dataset.get_batch_size()
        assert args.batch_size is not None, 'Could not get batch size'
    if hasattr(importlib.import_module('models.' + args.model), 'Buffer') and (not hasattr(args, "minibatch_size") or args.minibatch_size is None):
        args.minibatch_size = dataset.get_minibatch_size()
        assert args.minibatch_size is not None, 'Could not get minibatch size'

    # Re-create the dataset to reflect some argument changes and build dataloaders
    dataset = get_dataset(args)
    dataset.build_data_loaders()
    if args.cum_loaders:
        dataset.build_data_loaders_up_to()

    # Initialize logger and callbacks
    # Always using wandb for the logger
    logger = WandbLogger(args, dataset.SETTING, args.project)

    # build callbacks
    callbacks = []
    if args.save_weights:
        callbacks.append(CheckpointCallback(args, model, dataset))

    # Finetune callback is always used
    callbacks.append(FintuneCallback(args, model, dataset))

    if ckpt is not None:
        ckpt = torch.load(ckpt_path)

        if hasattr(model, "buffer"):
            # initialize the variables in buffer
            for attr_str in model.buffer.attributes:
                key = "buffer." + attr_str
                if key in ckpt['state_dict']:
                    model.buffer.register_buffer(attr_str, ckpt['state_dict'][key])

        if "old_net.classifier.weight" in ckpt['state_dict']:
            model.old_net = copy.deepcopy(model.net)

        # Load model
        model.load_state_dict(ckpt['state_dict'])
        model.opt.load_state_dict(ckpt['opt_state_dict'])
        if model.scheduler is not None:
            model.scheduler.load_state_dict(ckpt['scheduler_state_dict'])

        start_run = ckpt['run']
        start_task = ckpt['task']
        start_epoch = ckpt['epoch']
        wandb_id = ckpt['wandb_id']

        wandb.init(
            project=args.project,
            id=wandb_id,
            resume="must",
            dir=args.ckpt_folder,
            settings=wandb.Settings(start_method="fork")
        )
        print("Experiment resumed from", ckpt_path)
    else:
        wandb_id = wandb.util.generate_id()
        wandb.init(
            project=args.project,
            name=args.exp_name,
            id=wandb_id,
            config=args,
            dir=args.ckpt_folder,
            reinit=True,
            settings=wandb.Settings(start_method="fork")
        )
        start_run = 0
        start_task = 0
        start_epoch = 0

    return model, dataset, logger, callbacks, start_run, start_task, start_epoch, wandb_id

def save_training_state(args, model, dataset, run_id, task_id, epoch, wandb_id):
    temp_path = os.path.join(args.ckpt_folder, "temp.ckpt")
    ckpt_path = os.path.join(args.ckpt_folder, "latest.ckpt")

    state_dict = model.state_dict()

    ckpt = {
        'state_dict': state_dict,
        "opt_state_dict": model.opt.state_dict(),
        'run': run_id,
        'task': task_id,
        'epoch': epoch,
        'wandb_id': wandb_id,
        'args': args,
    }

    if model.scheduler is not None:
        ckpt["scheduler_state_dict"] = model.scheduler.state_dict()

    torch.save(ckpt, open(temp_path, 'wb'))

    os.replace(temp_path, ckpt_path)

def main(args):
    # whether to resume training or start a new one
    if args.preemptive:
        if args.resume_path is None:
            args.resume_path = os.path.join(args.ckpt_folder, "latest.ckpt")
        if not os.path.exists(args.resume_path):
            args.resume_path = None

    model, dataset, logger, callbacks, start_run, start_task, start_epoch, wandb_id = \
        create_or_restore_training_state(args, args.resume_path)

    print("Starting training from run", start_run, "task", start_task, "epoch", start_epoch)

    # If not running on a preemptive cluster, append the ckpt_folder with the experiment name
    if not args.preemptive:
        args.ckpt_folder = os.path.join(args.ckpt_folder, args.exp_name)

    if not os.path.exists(args.ckpt_folder):
        os.makedirs(args.ckpt_folder)

    train_loader_all = dataset.train_loader_all
    test_loader_all = dataset.test_loader_all

    for run_id in range(start_run, args.n_runs):
        set_random_seed(args.seed + run_id)
        if start_task == 0 and start_epoch == 0  and run_id > start_run:
            # Reset the state at the beginning of each run
            model, dataset, logger, callbacks, _, start_task, start_epoch, wandb_id = \
                create_or_restore_training_state(args, None)

        # Move the model to the proper device
        model.net.to(model.device)
        if hasattr(model, "old_net") and model.old_net is not None:
            model.old_net.to(model.device)

        for task_id in range(start_task, dataset.N_TASKS):
            model.net.train()
            if args.cum_loaders:
                train_loader, _ = dataset.get_data_loaders_up_to_task(task_id)
            else:
                train_loader, _ = dataset.get_data_loaders_by_task(task_id)
            model.begin_task(dataset, task_id, start_epoch)

            for epoch in range(start_epoch, model.args.n_epochs):
                # Save checkpoint at the beginning of each epoch
                if args.preemptive:
                    save_training_state(args, model, dataset, run_id, task_id, epoch, wandb_id)

                model.begin_epoch(dataset, task_id, epoch)

                run_epoch(model, train_loader, logger, callbacks, task_id, epoch)

                model.end_epoch(dataset, task_id, epoch)

                # callbacks for epoch end
                for callback in callbacks:
                    callback.on_train_epoch_end(
                        epoch=epoch,
                        model=model,
                        task_train_loader=train_loader,
                    )

                # Evaluate the model every a few epochs
                if epoch % 5 == 0:
                    accs, mean_acc = evaluate(model, dataset, task_id=task_id)
                    logger.log_accuracy(np.array(accs), mean_acc)

            # At the end of a task
            if hasattr(model, 'end_task'):
                model.end_task(dataset)

            accs, mean_acc = evaluate(model, dataset, task_id=task_id)
            print_mean_accuracy(mean_acc, task_id + 1, dataset.SETTING)
            logger.log_accuracy(np.array(accs), mean_acc, type="end_task")

            for callback in callbacks:
                callback.on_task_end(
                    task_id=task_id,
                    model=model,
                    task_train_loader=train_loader,
                )

            start_epoch = 0

        # At the end of the experiment
        # Log the final accuracy
        logger.log_accuracy(np.array(accs), mean_acc, type="final")

        for callback in callbacks:
            callback.on_train_end(
                model=model,
                train_loader_all=train_loader_all,
                test_loader_all=test_loader_all
            )

        logger.close()

        start_task = 0

if __name__ == '__main__':
    lecun_fix()
    args = parse_args()
    args = process_args(args)
    main(args)


"""
You can to create 2 instances of a `Price` class and to do operations between them:
        - add prices;
        - do a subtraction of prices.
"""

from dataclasses import dataclass
from decimal import Decimal

# Indices for conversion to dollars
convert_currencies: dict = {"USD": Decimal("1.00"), "EUR": Decimal("0.97"), "UAH": Decimal("0.027")}

# list of currencies available for calculation
currencies: list = [val for val in convert_currencies]

class PriceError(Exception):
    pass

@dataclass()
class Price:
    amount: Decimal
    currency: str  # currencies

    def __post_init__(self):
        if self.currency not in currencies:
            raise PriceError("❌ Price rejected. Currency is not supported.")

    def __str__(self) -> str:
        return f"The prise is {self.amount} {self.currency}"

    def __add__(self, other: "Price") -> "Price":
        self.comparison(other)
        print("⏳ Counting the total price...")
        return Price(amount=(self.amount + other.amount).quantize(Decimal("1.00")), currency=self.currency)

    def __sub__(self, other: "Price") -> "Price":
        self.comparison(other)
        if self.amount >= other.amount:
            print("⏳ Counting the difference...")
            return Price(amount=(self.amount - other.amount).quantize(Decimal("1.00")), currency=self.currency)
        else:
            raise PriceError("The negative price is not possible 😕")

    def comparison(self, other):
        """Currency comparison."""
        if self.currency != other.currency:
            self.convert()
            other.convert()

    def convert(self):
        """Performs currency conversion against the dollar"""
        for index in convert_currencies:
            if index == self.currency:
                self.amount *= convert_currencies[index]
                self.currency = "USD"

def create_price():
    """Creates an instances of a `Price` class"""
    user_input = input(f"Available currencies: {currencies}.   Enter the price in format:\nPRICE CURRENCY\n").split(" ")
    return Price(amount=Decimal(user_input[0]), currency=user_input[1].upper())

def handle_base_errors(func):
    def inner(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except PriceError as error:
            print(f"Error: {error}")
        except Exception as error:
            print(f"A certain error occurred: {error}")

    return inner

@handle_base_errors
def main():
    # Ask about prices
    price_a = create_price()
    price_b = create_price()

    price_c = price_a + price_b
    price_d = price_a - price_b

    print(price_c)
    print(price_d)

if __name__ == "__main__":
    main()