from PyQt5 import QtGui, QtCore, QtWidgets
from appGUI.GUIElements import FCTable, FCEntry, FCButton, FCFileSaveDialog

import sys
import webbrowser

from copy import deepcopy
from datetime import datetime
import gettext
import appTranslation as fcTranslate
import builtins

fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
    _ = gettext.gettext

class BookmarkManager(QtWidgets.QWidget):

    # mark_rows = QtCore.pyqtSignal()

    def __init__(self, app, storage, parent=None):
        super(BookmarkManager, self).__init__(parent)

        self.app = app

        assert isinstance(storage, dict), "Storage argument is not a dictionary"

        self.bm_dict = deepcopy(storage)

        # Icon and title
        # self.setWindowIcon(parent.app_icon)
        # self.setWindowTitle(_("Bookmark Manager"))
        # self.resize(600, 400)

        # title = QtWidgets.QLabel(
        #     "FlatCAM
"
        # )
        # title.setOpenExternalLinks(True)

        # layouts
        layout = QtWidgets.QVBoxLayout()
        self.setLayout(layout)

        table_hlay = QtWidgets.QHBoxLayout()
        layout.addLayout(table_hlay)

        self.table_widget = FCTable(drag_drop=True, protected_rows=[0, 1])
        self.table_widget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        table_hlay.addWidget(self.table_widget)

        self.table_widget.setColumnCount(3)
        self.table_widget.setColumnWidth(0, 20)
        self.table_widget.setHorizontalHeaderLabels(
            [
                '#',
                _('Title'),
                _('Web Link')
            ]
        )
        self.table_widget.horizontalHeaderItem(0).setToolTip(
            _("Index.\n"
              "The rows in gray color will populate the Bookmarks menu.\n"
              "The number of gray colored rows is set in Preferences."))
        self.table_widget.horizontalHeaderItem(1).setToolTip(
            _("Description of the link that is set as an menu action.\n"
              "Try to keep it short because it is installed as a menu item."))
        self.table_widget.horizontalHeaderItem(2).setToolTip(
            _("Web Link. E.g: https://your_website.org "))

        # pal = QtGui.QPalette()
        # pal.setColor(QtGui.QPalette.Background, Qt.white)

        # New Bookmark
        new_vlay = QtWidgets.QVBoxLayout()
        layout.addLayout(new_vlay)

        new_title_lbl = QtWidgets.QLabel('%s' % _("New Bookmark"))
        new_vlay.addWidget(new_title_lbl)

        form0 = QtWidgets.QFormLayout()
        new_vlay.addLayout(form0)

        title_lbl = QtWidgets.QLabel('%s:' % _("Title"))
        self.title_entry = FCEntry()
        form0.addRow(title_lbl, self.title_entry)

        link_lbl = QtWidgets.QLabel('%s:' % _("Web Link"))
        self.link_entry = FCEntry()
        self.link_entry.set_value('http://')
        form0.addRow(link_lbl, self.link_entry)

        # Buttons Layout
        button_hlay = QtWidgets.QHBoxLayout()
        layout.addLayout(button_hlay)

        add_entry_btn = FCButton(_("Add Entry"))
        remove_entry_btn = FCButton(_("Remove Entry"))
        export_list_btn = FCButton(_("Export List"))
        import_list_btn = FCButton(_("Import List"))
        # closebtn = QtWidgets.QPushButton(_("Close"))

        # button_hlay.addStretch()
        button_hlay.addWidget(add_entry_btn)
        button_hlay.addWidget(remove_entry_btn)

        button_hlay.addWidget(export_list_btn)
        button_hlay.addWidget(import_list_btn)
        # button_hlay.addWidget(closebtn)
        # ##############################################################################
        # ######################## SIGNALS #############################################
        # ##############################################################################

        add_entry_btn.clicked.connect(self.on_add_entry)
        remove_entry_btn.clicked.connect(self.on_remove_entry)
        export_list_btn.clicked.connect(self.on_export_bookmarks)
        import_list_btn.clicked.connect(self.on_import_bookmarks)
        self.title_entry.returnPressed.connect(self.on_add_entry)
        self.link_entry.returnPressed.connect(self.on_add_entry)
        # closebtn.clicked.connect(self.accept)

        self.ui_connect()
        self.build_bm_ui()

    def ui_connect(self):
        self.table_widget.drag_drop_sig.connect(self.mark_table_rows_for_actions)

    def ui_disconnect(self):
        try:
            self.table_widget.drag_drop_sig.connect(self.mark_table_rows_for_actions)
        except (TypeError, AttributeError):
            pass

    def build_bm_ui(self):

        self.table_widget.setRowCount(len(self.bm_dict))

        nr_crt = 0
        sorted_bookmarks = sorted(list(self.bm_dict.items()), key=lambda x: int(x[0]))
        for entry, bookmark in sorted_bookmarks:
            row = nr_crt
            nr_crt += 1

            title = bookmark[0]
            weblink = bookmark[1]

            id_item = QtWidgets.QTableWidgetItem('%d' % int(nr_crt))
            # id.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.table_widget.setItem(row, 0, id_item)  # Tool name/id

            title_item = QtWidgets.QTableWidgetItem(title)
            self.table_widget.setItem(row, 1, title_item)

            weblink_txt = QtWidgets.QTextBrowser()
            weblink_txt.setOpenExternalLinks(True)
            weblink_txt.setFrameStyle(QtWidgets.QFrame.NoFrame)
            weblink_txt.document().setDefaultStyleSheet("a{ text-decoration: none; }")

            weblink_txt.setHtml('%s' % (weblink, weblink))

            self.table_widget.setCellWidget(row, 2, weblink_txt)

            vertical_header = self.table_widget.verticalHeader()
            vertical_header.hide()

            horizontal_header = self.table_widget.horizontalHeader()
            horizontal_header.setMinimumSectionSize(10)
            horizontal_header.setDefaultSectionSize(70)
            horizontal_header.setSectionResizeMode(0, QtWidgets.QHeaderView.Fixed)
            horizontal_header.resizeSection(0, 20)
            horizontal_header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
            horizontal_header.setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)

        self.mark_table_rows_for_actions()

        self.app.defaults["global_bookmarks"].clear()
        for key, val in self.bm_dict.items():
            self.app.defaults["global_bookmarks"][key] = deepcopy(val)

    def on_add_entry(self, **kwargs):
        """
        Add a entry in the Bookmark Table and in the menu actions
        :return: None
        """
        if 'title' in kwargs:
            title = kwargs['title']
        else:
            title = self.title_entry.get_value()
        if title == '':
            self.app.inform.emit('[ERROR_NOTCL] %s' % _("Title entry is empty."))
            return 'fail'

        if 'link' in kwargs:
            link = kwargs['link']
        else:
            link = self.link_entry.get_value()

        if link == 'http://':
            self.app.inform.emit('[ERROR_NOTCL] %s' % _("Web link entry is empty."))
            return 'fail'

        # if 'http' not in link or 'https' not in link:
        #     link = 'http://' + link

        for bookmark in self.bm_dict.values():
            if title == bookmark[0] or link == bookmark[1]:
                self.app.inform.emit('[ERROR_NOTCL] %s' % _("Either the Title or the Weblink already in the table."))
                return 'fail'

        # for some reason if the last char in the weblink is a slash it does not make the link clickable
        # so I remove it
        if link[-1] == '/':
            link = link[:-1]
        # add the new entry to storage
        new_entry = len(self.bm_dict) + 1
        self.bm_dict[str(new_entry)] = [title, link]

        # add the link to the menu but only if it is within the set limit
        bm_limit = int(self.app.defaults["global_bookmarks_limit"])
        if len(self.bm_dict) < bm_limit:
            act = QtWidgets.QAction(parent=self.app.ui.menuhelp_bookmarks)
            act.setText(title)
            act.setIcon(QtGui.QIcon(self.app.resource_location + '/link16.png'))
            act.triggered.connect(lambda: webbrowser.open(link))
            self.app.ui.menuhelp_bookmarks.insertAction(self.app.ui.menuhelp_bookmarks_manager, act)

        self.app.inform.emit('[success] %s' % _("Bookmark added."))

        # add the new entry to the bookmark manager table
        self.build_bm_ui()

    def on_remove_entry(self):
        """
        Remove an Entry in the Bookmark table and from the menu actions
        :return:
        """
        index_list = []
        for model_index in self.table_widget.selectionModel().selectedRows():
            index = QtCore.QPersistentModelIndex(model_index)
            index_list.append(index)
            title_to_remove = self.table_widget.item(model_index.row(), 1).text()

            if title_to_remove == 'FlatCAM' or title_to_remove == _('Backup Site'):
                self.app.inform.emit('[WARNING_NOTCL] %s.' % _("This bookmark can not be removed"))
                self.build_bm_ui()
                return
            else:
                for k, bookmark in list(self.bm_dict.items()):
                    if title_to_remove == bookmark[0]:
                        # remove from the storage
                        self.bm_dict.pop(k, None)

                        for act in self.app.ui.menuhelp_bookmarks.actions():
                            if act.text() == title_to_remove:
                                # disconnect the signal
                                try:
                                    act.triggered.disconnect()
                                except TypeError:
                                    pass
                                # remove the action from the menu
                                self.app.ui.menuhelp_bookmarks.removeAction(act)

        # house keeping: it pays to have keys increased by one
        new_key = 0
        new_dict = {}
        for k, v in self.bm_dict.items():
            # we start with key 1 so we can use the len(self.bm_dict)
            # when adding bookmarks (keys in bm_dict)
            new_key += 1
            new_dict[str(new_key)] = v

        self.bm_dict = deepcopy(new_dict)
        new_dict.clear()

        self.app.inform.emit('[success] %s' % _("Bookmark removed."))

        # for index in index_list:
        #     self.table_widget.model().removeRow(index.row())
        self.build_bm_ui()

    def on_export_bookmarks(self):
        self.app.defaults.report_usage("on_export_bookmarks")
        self.app.log.debug("on_export_bookmarks()")

        date = str(datetime.today()).rpartition('.')[0]
        date = ''.join(c for c in date if c not in ':-')
        date = date.replace(' ', '_')

        filter__ = "Text File (*.TXT);;All Files (*.*)"
        filename, _f = FCFileSaveDialog.get_saved_filename(
            caption=_("Export Bookmarks"),
            directory='{l_save}/{n}_{date}'.format(l_save=str(self.app.get_last_save_folder()),
                                                   n=_("Bookmarks"),
                                                   date=date),
            ext_filter=filter__)

        filename = str(filename)

        if filename == "":
            self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled."))
            return
        else:
            try:
                f = open(filename, 'w')
                f.close()
            except PermissionError:
                self.app.inform.emit('[WARNING] %s' %
                                     _("Permission denied, saving not possible.\n"
                                       "Most likely another app is holding the file open and not accessible."))
                return
            except IOError:
                self.app.log.debug('Creating a new bookmarks file ...')
                f = open(filename, 'w')
                f.close()
            except Exception:
                e = sys.exc_info()[0]
                self.app.log.error("Could not load the file.")
                self.app.log.error(str(e))
                self.app.inform.emit('[ERROR_NOTCL] %s' % _("Could not load the file."))
                return

            # Save Bookmarks to a file
            try:
                with open(filename, "w") as f:
                    for title, link in self.bm_dict.items():
                        line2write = str(title) + ':' + str(link) + '\n'
                        f.write(line2write)
            except Exception:
                self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed to write bookmarks to file."))
                return
        self.app.inform.emit('[success] %s: %s' % (_("Exported bookmarks to"), filename))

    def on_import_bookmarks(self):
        self.app.log.debug("on_import_bookmarks()")

        filter_ = "Text File (*.txt);;All Files (*.*)"
        filename, _f = QtWidgets.QFileDialog.getOpenFileName(caption=_("Import Bookmarks"), filter=filter_)

        filename = str(filename)

        if filename == "":
            self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled."))
        else:
            try:
                with open(filename) as f:
                    bookmarks = f.readlines()
            except IOError:
                self.app.log.error("Could not load bookmarks file.")
                self.app.inform.emit('[ERROR_NOTCL] %s' % _("Could not load the file."))
                return

            for line in bookmarks:
                proc_line = line.replace(' ', '').partition(':')
                self.on_add_entry(title=proc_line[0], link=proc_line[2])

            self.app.inform.emit('[success] %s: %s' % (_("Imported Bookmarks from"), filename))

    def mark_table_rows_for_actions(self):
        for row in range(self.table_widget.rowCount()):
            item_to_paint = self.table_widget.item(row, 0)
            if row < self.app.defaults["global_bookmarks_limit"]:
                item_to_paint.setBackground(QtGui.QColor('gray'))
                # item_to_paint.setForeground(QtGui.QColor('black'))
            else:
                item_to_paint.setBackground(QtGui.QColor('white'))
                # item_to_paint.setForeground(QtGui.QColor('black'))

    def rebuild_actions(self):
        # rebuild the storage to reflect the order of the lines
        self.bm_dict.clear()
        for row in range(self.table_widget.rowCount()):
            title = self.table_widget.item(row, 1).text()
            wlink = self.table_widget.cellWidget(row, 2).toPlainText()

            entry = int(row) + 1
            self.bm_dict.update(
                {
                    str(entry): [title, wlink]
                }
            )

        self.app.install_bookmarks(book_dict=self.bm_dict)

    # def accept(self):
    #     self.rebuild_actions()
    #     super().accept()

    def closeEvent(self, QCloseEvent):
        self.rebuild_actions()
        self.ui_disconnect()
        super().closeEvent(QCloseEvent)


from warnings import filterwarnings
filterwarnings('ignore')

import pandas as pd
import numpy as np

from sklearn.metrics import roc_auc_score
from sklearn.metrics import roc_curve
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report

from load_data import sc1_phenotype, sc1_outcome, sc1_rna_data

def sc1_model(rna_data):
    """We collected 20 gene features based on literature of related research,
    and divided into two groups by their biological function.

    ['PLAT', 'DUSP5', 'VHL', 'DUSP10', 'COL5A1', 'IL13RA2',
     'CCR4', 'XCL1', 'STAT4', 'MMP9', 'JUN', 'BRCA2', 'MET'] is adverse to patient's
    survival if gene has high expression

    ['SHC2', 'CREBBP', 'FGF22', 'EP300', 'ZNF346', 'FOXO4',
    'AMH', 'FGF20', 'PTEN', 'CDKN2B', 'CDKN2A', 'CCL19', 'PTCH1'] is adverse to patient's
    survival if gene has low expression
    Parameters
    ----------
    rna_data:
        pandas DataFrame, Gene expression profiles.
    Returns
    -------
    score:
        pandas DataFrame, survival score.
    """
    pos_pair = ['PLAT', 'DUSP5', 'VHL', 'DUSP10', 'COL5A1',
                'IL13RA2', 'CCR4', 'XCL1', 'STAT4', 'MMP9',
                'JUN', 'BRCA2', 'MET']
    neg_pair =['SHC2', 'CREBBP', 'FGF22', 'EP300', 'ZNF346',
                'FOXO4', 'AMH', 'FGF20', 'PTEN', 'CDKN2B',
                'CDKN2A', 'CCL19', 'PTCH1']

    rna_data['score'] = rna_data[pos_pair].mean(axis=1)-rna_data[neg_pair].mean(axis=1)
    return rna_data[['score']]

def cutoff_youdens_j(data):
    """Calculate Youden's J statistic for selecting the optimum cut-off point of score in
    train dataset.
        J = sensitivity + specificity -1
    Parameters
    ----------
    data:
        pandas DataFrame, score and SURVIVAL_STATUS must in columns.
    Returns
    -------
    j_ordered:
        pandas DataFrame, Youden's J statistic.
    """

    assert 'score' in data.columns
    assert 'SURVIVAL_STATUS' in data.columns
    score = data[['SURVIVAL_STATUS','score']].copy()
    fpr, tpr, threshold = roc_curve(score['SURVIVAL_STATUS'].values.astype(int), score['score'].values)
    j_scores = tpr-fpr
    j_ordered = sorted(zip(j_scores,threshold))
    j_ordered = pd.DataFrame(columns=['youden_j','threshold'],data=j_ordered)
    return j_ordered.sort_values('youden_j',ascending=False)

if __name__ == '__main__':

    survival_score = sc1_model(sc1_rna_data)
    result = pd.merge(sc1_outcome,survival_score,left_index=True,right_index=True)
    threshold = cutoff_youdens_j(result)['threshold'].values[0]
    result['predict_label'] = result['score'].apply(lambda x:1 if x>threshold else 0)

    # Model Performance
    [[tn,fp],[fn,tp]] = confusion_matrix(result['SURVIVAL_STATUS'].values,
                                         result['predict_label'].values)
    #print confusion matrix
    print('T\\P\tAlive\tDied\tSum\nAlive\t{}\t{}\t{}\nDied\t{}\t{}\t{}\nSum\t{}\t{}\t{}\n'.format(tn,fp,tn+fp,
                                                                                fn,tp,fn+tp,
                                                                                tn+fn,fp+tp,tn+fp+fn+tp))
    print(classification_report(result['SURVIVAL_STATUS'].values, result['predict_label'].values))
    print('AUC score:',roc_auc_score(result['SURVIVAL_STATUS'].values,result['score'].values))
    print('Overall accuracy:',accuracy_score(result['SURVIVAL_STATUS'].values,
                                             result['predict_label'].values,
                                             normalize=True))


import sys
import os
from itertools import islice

def less(args):
    if len(args) == 1:
        print("needs more arguments!")
    elif len(args) == 2:
        page_lines = 20
        with open(args[1], 'r') as input_file:
            while input_file:
                lines_cache = islice(input_file, page_lines)
                for lines in lines_cache:
                    print(lines)

            # count += 1
            # if count == 20:
            #     input("Hit enter to go to next page ")
            #     os.system('clear')


from typing import Callable

from catalyst.callbacks.metric import BatchMetricCallback
from catalyst.metrics._functional_metric import BatchFunctionalMetric

class FunctionalMetricCallback(BatchMetricCallback):
    """Custom metric in functional way.
    Note: the loader metrics calculated as average over all examples.

    Args:
        input_key: input key, specifies our `predictions`
        target_key: output key, specifies our `y_pred`
        metric_function: metric function, that get outputs, targets and return score as
        torch.Tensor
        metric_name: key for the metric's name
        log_on_batch: boolean flag to log computed metrics every batch
    """

    def __init__(
        self,
        input_key: str,
        target_key: str,
        metric_function: Callable,
        metric_name: str,
        log_on_batch: bool = True,
    ):
        """Init."""
        super().__init__(
            metric=BatchFunctionalMetric(metric_fn=metric_function, metric_name=metric_name),
            input_key=input_key,
            target_key=target_key,
            log_on_batch=log_on_batch,
        )

__all__ = ["FunctionalMetricCallback"]


import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import r2_score

df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.data', header=None, sep='\s+')
df.columns = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']

X = df[['LSTAT']].values
y = df['MEDV'].values

regr = LinearRegression()

#create polynomial features
quadratic = PolynomialFeatures(degree=2)
cubic = PolynomialFeatures(degree=3)
X_quad = quadratic.fit_transform(X)
X_cubic = cubic.fit_transform(X)

#linear fit
X_fit = np.arange(X.min(), X.max(), 1)[:, np.newaxis]
regr = regr.fit(X, y)
y_lin_fit = regr.predict(X_fit)
linear_r2 = r2_score(y, regr.predict(X))

#quadratic fit
regr = regr.fit(X_quad, y)
y_quad_fit = regr.predict(quadratic.fit_transform(X_fit))
quadratic_r2 = r2_score(y, regr.predict(X_quad))

#cubic fit
regr = regr.fit(X_cubic, y)
y_cubic_fit = regr.predict(cubic.fit_transform(X_fit))
cubic_r2 = r2_score(y, regr.predict(X_cubic))

#plot results
plt.scatter(X, y, label='training points', color='lightgray')
plt.plot(X_fit, y_lin_fit, label=f'linear (d=1), $Rˆ2={linear_r2:.2f}', color='blue', lw=2, linestyle=':')
plt.plot(X_fit, y_quad_fit, label=f'linear (d=2), $Rˆ2={quadratic_r2:.2f}', color='red', lw=2, linestyle='-')
plt.plot(X_fit, y_cubic_fit, label=f'linear (d=3), $Rˆ2={cubic_r2:.2f}', color='green', lw=2, linestyle='--')
plt.xlabel('% lower status of the population [LSTAT]')
plt.ylabel('Price in $1000\'s [MEDV]')
plt.legend(loc='upper right')
plt.show()


import json

from django.http import JsonResponse

#from manpower.utils.constants import ERROR_DICT

__author__ = 'senthamilarasu'

from rest_framework.response import Response
from rest_framework import status

from street.code_msg import *

# Rest Response for Success
def success_response(code=3000, message='', data={}, status=status.HTTP_200_OK):
    if message == '':
        message = codes_msg[code]

    meta = {
        'status':'success',
        'message': message,
        'code': status
    }
    return Response({'meta':meta, 'data':data}, status=status)

# Rest Response for Fail
def fail_response(error_code, message='', data={}, status=status.HTTP_400_BAD_REQUEST):
    if message == '':
        message = codes_msg[error_code]

    meta = {
        'status':'fail',
        'message': message,
        'code': error_code
    }
    return Response({'meta':meta, 'data':data}, status=status)

def generate_failed_json(error_code, message, status=200, data={}):
    """
    Generates a failure response json message

    :param message:     The message to return as reason for failure
                        :type <type, 'str'>
    :param error_code:  The magical internal error code used by magical to identify and track common
                        known and uncommon unknown errors and or exceptions
                        :type <type, 'str'>
    :param status :     The status code that holds the http status code
    :return:            The collection object that holds the formatted key value collections
                        :type <type, 'dict'>
    """
    failed_json_data = load_failed_json_payload(data, error_code, message)
    failed_json_object = dict()

    failed_json_object['status'] = "fail"
    failed_json_object['message']=message
    failed_json_object['code']=error_code
    #failed_json_object['data']=dict()
    #failed_json_object['data'] = failed_json_data
    return JsonResponse({"meta":failed_json_object})

    #return JsonResponse({"meta":success_json,"data":data},status=status,  safe=False)

def generate_success_message(message,data, status=200):
    """
    Generates successful operation ,json message from the valid json resolvable :param `data`

    This :param `data` is what ends up as the value of the data key of all successful json responses
    this in line with the json schema chosen to represent all magical json responses
    :see http:\\www.jsonapi.com/schema for more information.

    :param data:            The data to be appended as the value of the json response key of the same
                            name i.e. `data`
                            :type <type, 'object'> limited to [str, int, list, None]
    :param code:
    :param message:
    :param status:
    :return success_json:   The fully parsed json response dict, might require additional wrapping by flask
                            json generating header function
                            :type <type, 'collections.OrderedDict'>
    """

    success_json = dict()

    success_json['status'] ='success'
    success_json['message']=message
    success_json['code']=200
    #success_json['data'] = data

    return JsonResponse({"meta":success_json,"data":data},status=status,  safe=False)

def load_failed_json_payload(data={}, error_code="", message=""):
    """
    Generates a failure response json dictionary

    :param message:     The message to return as reason for failure
                        :type <type, 'str'>
    :param error_code:  The magical internal error code used by magical to identify and track common
                        known and uncommon unknown errors and or exceptions
                        :type <type, 'str'>
    :return:            The collection object that holds the formatted key value collections
                        :type <type, 'dict'>
    """
    failed_json_info = dict()
    #failed_json_info['info'] = data
    failed_json_info['code'] = error_code
    failed_json_info['message'] = message
    return failed_json_info

def load_success_json_payload(data ="", code="", message=""):
    """
    Generates a failure response json dictionary

    :param message:     The message to return as reason for failure
                        :type <type, 'str'>
    :param code:  The magical internal code used by magical to identify and track common
                        known and uncommon unknown errors and or exceptions
                        :type <type, 'str'>
    :return:            The collection object that holds the formatted key value collections
                        :type <type, 'dict'>
    """
    success_json_info = dict()
    success_json_info['info'] = data
    success_json_info['code'] = code
    success_json_info['message'] = message
    return success_json_info


from glados.api.shared.dynamic_downloads import jobs
from glados.es.es_properties_configuration import configuration_manager
from glados.api.shared.dynamic_downloads.models import DownloadJobManager
from glados.api.shared.dynamic_downloads.models import DownloadJob
from glados.usage_statistics import glados_server_statistics
import json
import os
from datetime import timezone
import logging
from django.conf import settings

logger = logging.getLogger('django')

def queue_download_job(index_name, raw_query, desired_format, context_id, columns_group='download'):

    columns_to_download = configuration_manager.get_config_for_group(index_name, columns_group)['properties']['default']
    raw_columns_to_download = json.dumps(columns_to_download)
    id_property = configuration_manager.get_id_property_for_index(index_name)

    try:
        download_job = jobs.queue_new_job(
            index_name=index_name,
            raw_columns_to_download=raw_columns_to_download,
            raw_query=raw_query,
            parsed_desired_format=desired_format.upper(),
            context_id=context_id,
            id_property=id_property
        )
    except DownloadJobManager.DownloadJobAlreadyExistsError:
        download_job_manager = DownloadJobManager()
        job_id = download_job_manager.get_download_id(index_name, raw_query, desired_format, context_id)
        download_job = DownloadJob.objects.get(job_id=job_id)

        if download_job.status == DownloadJob.ERROR:
            # if it was in error state, requeue it
            jobs.requeue_job(job_id, 'Job was in error state, queuing again.')

        elif download_job.status == DownloadJob.FINISHED:
            # verify that the job exists and save statistics
            try:
                file_size = os.path.getsize(download_job.file_path)
                glados_server_statistics.record_download(
                    download_id=job_id,
                    time_taken=0,
                    is_new=False,
                    file_size=file_size,
                    es_index=index_name,
                    es_query=raw_query,
                    desired_format=desired_format,
                    total_items=download_job.total_items
                )

            except FileNotFoundError:
                # if for some reason the file is not found. requeue que job
                jobs.requeue_job(job_id, 'File not found, queuing again.')

        elif download_job.status == DownloadJob.DELETING:
            # someone is deleting the job, I just need to wait until it is deleted and then re queue it
            logger.info('job is being deleted! We need to wait until the process finishes')
            if settings.SPAWN_JOBS:
                jobs.wait_until_job_is_deleted_and_requeue.delay(job_id)
            else:
                jobs.wait_until_job_is_deleted_and_requeue(job_id)

    return download_job.job_id

def get_download_status(download_id):

    download_job = DownloadJob.objects.get(job_id=download_id)
    status = download_job.status

    response = {
        'percentage': download_job.progress,
        'status': status
    }

    if status == DownloadJob.FINISHED:
        if download_job.expires is not None:
            expiration_time_str = download_job.expires.replace(tzinfo=timezone.utc).isoformat()
            response['expires'] = expiration_time_str

    return response


import csv, sys, os
import pandas as pd

project_dir = "/Users/colton_proctor/Desktop/seniorProject/mySite"

sys.path.append(project_dir)

os.environ['DJANGO_SETTINGS_MODULE']='mySite'

import django
django.setup()

from main.models import Property

data = pd.read_csv('/Users/colton_proctor/Desktop/seniorProject/mySite/db.csv') #,delimiter="|")
#data = csv.reader(open('/Users/cohen/my-python-project/venv/ofac/ofac_project/ofac_sdn/sdn2.csv'), dialect='excel-tab')
for index, row in data.iterrows():
        property = Property()
        property.state = row[0]
        property.recorded = row[1]
        property.date = row[2]
        property.grantor = row[3]
        property.address = row[4]
        property.city = row[5]
        property.grantee = row[6]
        property.price = row[7]
        property.propType = row[8]
        property.built = row[9]
        property.acreage = row[10]
        property.impsq = row[11]
        property.units = row[12]
        property.landsq = row[13]
        property.sfimp = row[14]
        property.unitimp = row[15]
        property.sfland = row[16]
        property.garage = row[17]
        property.caprate = row[18]
        property.noi = row[19]
        property.exp = row[20]
        property.egi = row[21]
        property.occup = row[22]
        property.corner = row[23]
        property.regshape = row[24]
        property.utilities = row[25]
        property.location = row[26]
        property.quality = row[27]
        property.condition = row[28]
        property.description = row[29]
        property.comments = row[30]
        property.save()


import re
import pymorphy2
from bs4 import BeautifulSoup as bs

morph = pymorphy2.MorphAnalyzer()

def get_sample():
    with open('sample.xml', 'r', encoding='utf8') as inf:
        return bs(inf.read(), 'html.parser')

def lemmatize_texts(text):
    global morph
    texts = []
    for sentence in text:
        s = []
        word_list = re.sub('[».,«:;"%—!?)(]|\W-\W', '', sentence.strip().lower()).split()
        for word in word_list:
            p = morph.parse(word)[0]
            try:
                s.append(p.normal_form + '_' + p.tag.POS)
            except TypeError:
                s.append(word)
        texts.append(' '.join(s))
    return texts

def splitter(doc):
    return doc.split()


import numpy as np
# -------------------------------
class Course:
    def __init__(self, rubric, number):
     self.rubric = rubric
     self.number = number
    def __str__(self):
     return self.rubric + " " + str(self.number)

class Course_Schedule:
    def __init__(self,course):
        self.array = np.array(["         ","       ","        "])

    def add(self,course):
        status = False
        i = 0
        while status == False:
            if self.array[i].strip() == "":
                self.array[i] = course
                status = True
            i += 1
    def __str__(self):
        return ("My Schedule\n" + "---------\n" + self.array[0] +"\n" + self.array[1]
                + "\n" + self.array[2])

# -------------------------------
def main():
    my_courses = Course_Schedule(3)
    course_1 = Course("CSCI", 127)
    my_courses.add(course_1)
    course_2 = Course("M", 171)
    my_courses.add(course_2)
    course_3 = Course("WRIT", 101)
    my_courses.add(course_3)
    print(my_courses)
# -------------------------------
main()

Exam/Practicum 3 - Final Exam review/Problem2.py


import random
import string
import serial
import time

'''SET UP'''
#PORTS
#port = '/dev/tty.usbserial-A1014XTT' #NANO
#port = '/dev/tty.usbserial-AM01VG4I'
#port = '/dev/cu.usbmodem1421'

port = '/dev/tty.usbserial-AL00U150' #USB
#port = '/dev/tty.hapticJacket3-DevB'#BT
#port = '/dev/tty.BlueSmirf1-RNI-SPP' #BT BlueSmirf

#BAUD
baud = 57600

#Serial
ser = serial.Serial(port, baud)

if ser.isOpen():
    ser.close()

print("Connecting to jacket at port %s (baud: %d)" %(port,baud))
ser.open()
print("Serial established")

print('FROM CONNECTION:')
print(ser.inWaiting())
print(ser.read(ser.inWaiting()))

#print(b)

'''FUNCTIONS'''

# def frombits(bits):
#     chars = []
#     for b in range(len(bits) / 8):
#         byte = bits[b*8:(b+1)*8]
#         chars.append(chr(int(''.join([str(bit) for bit in byte]), 2)))
#     return ''.join(chars)
# s = frombits(b)

'''Packets'''
packets = []
for i in xrange(48):
    packets += ['#%d %d$' %(i, 100)]
    # packets += ['#%d %d$' %(i, 500)]
    # packets += ['#%d %d$' %(i, 1000)]

freq = 1

'''LOOP'''
while(True):
	for packet in packets:
		ser.write(packet)
		print(ser.read())
		time.sleep(1.0/freq)

	# ser.close()


# from selenium import webdriver
# import time
#
# browser = webdriver.Chrome()
# browser.implicitly_wait(5)
# browser.get("http://suninjuly.github.io/wait1.html")
#
#
# button = browser.find_element_by_id("verify")
# button.click()
# message = browser.find_element_by_id("verify_message")
#
# assert "successful" in message.text

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver

import math

def calc(x):
    return str(math.log(abs(12*math.sin(int(x)))))

link = "http://suninjuly.github.io/explicit_wait2.html"
browser = webdriver.Chrome()
browser.get(link)

button = WebDriverWait(browser, 12).until(
        EC.text_to_be_present_in_element((By.ID, "price"), "$100")
    )
button = browser.find_element_by_class_name("btn-primary")
button.click()

x_element = browser.find_element_by_id("input_value")
x = x_element.text
y = calc(x)

input1 = browser.find_element_by_id("answer")
input1.send_keys(y)

btn = browser.find_element_by_id("solve")
btn.click()

browser.quit()


"""Indiana double deck bid euchre"""
from random import shuffle
from itertools import cycle
from collections import deque

import config

SUITS = ["Spades", "Clubs", "Hearts", "Diamonds"]
VALUES = ["9", "10", "Jack", "Queen", "King", "Ace"]
PLAYER_NAMES = ["Me", "P1", "Partner", "P2"]
WINNING_SCORE = 52

class Card:
    """
    Cards have suit and value
    """

    def __init__(self, value: str, suit: str):
        self.value = value
        self.suit = suit

    def __str__(self) -> str:
        return f"{self.value} of {self.suit}"

    def __gt__(self, other) -> bool:
        # left bower trickery
        if config.trump == "Hearts":
            left = "Diamonds"
        elif config.trump == "Diamonds":
            left = "Hearts"
        elif config.trump == "Spades":
            left = "Clubs"
        elif config.trump == "Clubs":
            left = "Spades"
        else:
            left = None

        if self.suit == left and self.value == "Jack":
            self.suit = config.trump
            self.value = "Left"
        if other.suit == left and self.value == "Jack":
            other.suit = config.trump
            other.value = "Left"

        # high and low config.trump
        if self.suit == config.first_suit and other.suit == config.first_suit:
            if config.trump == "Low":
                values = ["Ace", "King", "Queen", "Jack", "10", "9"]
                return values.index(self.value) > values.index(other.value)
            if config.trump == "High":
                values = ["9", "10", "Jack", "Queen", "King", "Ace"]
                return values.index(self.value) > values.index(other.value)
        elif self.suit != config.first_suit and other.suit != config.first_suit:
            return False
        elif self.suit == config.first_suit and other.suit != config.first_suit:
            return True
        elif self.suit != config.first_suit and other.suit == config.first_suit:
            return False

        # if both suits are not config.trump
        if self.suit != config.trump and other.suit != config.trump:
            if self.suit == config.first_suit and other.suit == config.first_suit:
                pass
            elif self.suit != config.first_suit and other.suit != config.first_suit:
                return False

            elif self.suit == config.first_suit and other.suit != config.first_suit:
                return True
            elif self.suit != config.first_suit and other.suit == config.first_suit:
                return False
            values = ["9", "10", "Jack", "Queen", "King", "Ace"]
            return values.index(self.value) > values.index(other.value)
        # if both suits are config.trump
        elif self.suit == config.trump and other.suit == config.trump:
            values = ["9", "10", "Queen", "King", "Ace", "Left", "Jack"]
            return values.index(self.value) > values.index(other.value)
        # if played card is config.trump and other is not
        elif self.suit == config.trump and other.suit != config.trump:
            return True
        # if other card is config.trump and played card is not
        elif self.suit != config.trump and other.suit == config.trump:
            return False

    def get_suit(self) -> str:
        """ Card suit """
        # left bower trickery
        if config.trump == "Hearts":
            left = "Diamonds"
        elif config.trump == "Diamonds":
            left = "Hearts"
        elif config.trump == "Spades":
            left = "Clubs"
        elif config.trump == "Clubs":
            left = "Spades"
        else:
            left = None

        if self.suit == left and self.value == "Jack":
            return config.trump
        return self.suit

    def get_value(self) -> str:
        """ Card value """
        return self.value

class Deck:
    """
    All cards in 48-card double euchre deck
    """

    def __init__(self):
        self.cards = []
        for _ in range(2):
            for suit in SUITS:
                for value in VALUES:
                    self.cards.append(Card(value, suit))

    def __len__(self) -> int:
        return len(self.cards)

    def __str__(self) -> str:
        out = ""
        for card in self.cards:
            out += str(card) + "\n"
        return out

    def shuffle(self) -> None:
        """
        Shuffle the deck of cards
        """
        shuffle(self.cards)

    def deal_hand(self, count: int = 12) -> list:
        """
        Get list of cards from the deck
        """
        dealt_cards = []
        for _i in range(count):
            dealt_cards.append(self.cards.pop())
        return dealt_cards

class Player:
    """
    Player has a hand of cards
    """

    def __init__(self, name: str, cards: list, is_dealer: bool):
        self.name = name
        self.cards = cards
        self.is_dealer = is_dealer

    def get_name(self) -> str:
        """ Player name """
        return self.name

    def get_card(self, index: int, remove_card: bool = True) -> Card:
        """
        Remove chosen card from hand
        """
        chosen_card = self.cards[index]
        if remove_card:
            del self.cards[index]
        return chosen_card

    def set_card(self, card: Card) -> None:
        """
        Add card to hand
        """
        self.cards.append(card)

    def set_cards(self, cards: list) -> None:
        """ Add multiple cards to hand """
        self.cards = cards

    def sort_cards(self) -> None:
        """
        Sort cards according to suit
        """
        # left bower trickery
        if config.trump == "Hearts":
            left = "Diamonds"
        elif config.trump == "Diamonds":
            left = "Hearts"
        elif config.trump == "Spades":
            left = "Clubs"
        elif config.trump == "Clubs":
            left = "Spades"
        else:
            left = None
        for card in self.cards:
            if card.suit == left and card.value == "Jack":
                card.suit = config.trump
                card.value = "Left"

        def sort_order(card: Card) -> int:
            if card.suit == config.trump:
                values = ["9", "10", "Queen", "King", "Ace", "Left", "Jack"]
            else:
                values = ["9", "10", "Jack", "Queen", "King", "Ace"]

            return values.index(card.value)

        self.cards = sorted(
            self.cards, key=lambda card: (str(card).split("of")[1], sort_order(card))
        )

        # change left name back
        for card in self.cards:
            if card.value == "Left":
                card.suit = left
                card.value = "Jack"

    def __str__(self) -> str:
        self.sort_cards()
        out = self.name + "->\t"
        for i, card in enumerate(self.cards):
            out += str(i + 1) + ": " + str(card) + "\t"
        return out

    def __len__(self) -> int:
        return len(self.cards)

def get_bid() -> dict:
    """
    Get bid from player
    """
    bid = {}

    def check_input(input_string: str):
        # cast value to int
        if input_string.isnumeric():
            input_string = int(input_string)

        return input_string

    bid["value"] = None
    while bid["value"] is None:
        bid["value"] = input(
            "Select bid value (1-12) or type 'pass' to pass or 'alone' to go alone: "
        )
        bid["value"] = check_input(bid["value"])

    # if bid was not passed then get suit
    if bid["value"] != "pass":
        bid["trump"] = input(
            f"Select config.trump suit: high, low, {', '.join(SUITS)}: "
        )
    else:
        bid["trump"] = "pass"

    return bid

def highest_bidder_drops_3_cards(player: Player):
    """
    When going alone the bidder must discard three cards
    """

    def check_inputs(input_string: str) -> list:
        removed_cards = [int(x) for x in input_string.split(",")]
        removed_cards = [x - i - 1 for i, x in enumerate(removed_cards)]
        return removed_cards

    removed_cards = None
    while removed_cards is None:
        removed_cards = input(
            "Type numbers of 3 cards to get rid of separated by commas: "
        )
        removed_cards = check_inputs(removed_cards)

    for removed in removed_cards:
        player.get_card(removed)
    print(player)

def partner_provides_3_cards(partner: Player, bidder: Player):
    """
    When going alone the partern must provide three cards to the bidder
    """

    def check_inputs(input_string: str) -> list:
        removed_cards = [int(x) for x in input_string.split(",")]
        removed_cards = [x - i - 1 for i, x in enumerate(removed_cards)]
        return removed_cards

    removed_cards = None
    while removed_cards is None:
        removed_cards = input(
            "Type numbers of 3 cards to get rid of separated by commas: "
        )
        removed_cards = check_inputs(removed_cards)

    for removed in removed_cards:
        c = partner.get_card(removed)
        bidder.set_card(c)

def play_trick(players, first_player: Player) -> dict:
    """
    Play through one trick
    """
    trick_results = {"Trick Winner": None, "Winning card": None}
    trick_players = players
    trick_players.rotate(trick_players.index(first_player))
    for player in trick_players:
        print(player)
        played = len(player) + 1
        while played > len(player):
            played = input("Type # of card to play: ")
            # handle non-numeric responses
            if not played.isnumeric():
                played = len(player) + 1
            elif int(played) < 1:
                played = len(player) + 1
            else:
                played = int(played)
        played_card = player.get_card(int(played) - 1)
        if (
            trick_results["Winning card"] is None
            or played_card > trick_results["Winning card"]
        ):
            trick_results["Trick Winner"] = player
            trick_results["Winning card"] = played_card

    return trick_results

def update_hand_results(trick_results: dict, hand_results: dict = None) -> dict:
    """
    Track scores after each trick is played
    """
    if hand_results is None:
        hand_results = {}
    hand_results.setdefault("Bidding Team Score", 0)
    hand_results.setdefault("Opposing Team Score", 0)

    if trick_results["Trick Winner"] in config.teams[config.bidding_team]:
        hand_results["Bidding Team Score"] = hand_results["Bidding Team Score"] + 1
    else:
        hand_results["Opposing Team Score"] = hand_results["Opposing Team Score"] + 1
    return hand_results

def play_game():
    """
    Play game
    """
    # setup game
    # build list of players

    players = []
    for player_name in PLAYER_NAMES:
        players.append(Player(player_name, [], False))
    players = deque(players)

    # establish config.teams
    config.teams[1].append(players[0])
    config.teams[1].append(players[2])
    config.teams[2].append(players[1])
    config.teams[2].append(players[3])

    # set team scores to 0
    score = {1: 0, 2: 0}

    # set initial dealer
    players[3].is_dealer = True

    hand_number = 0

    while score[1] < WINNING_SCORE and score[2] < WINNING_SCORE:
        # reshuffle deck
        deck = Deck()
        deck.shuffle()

        # deal hand to each player
        for player in players:
            player.set_cards(deck.deal_hand(12))

        # set dealer to next player in the rotation
        if hand_number > 0:
            players.rotate(1)
            for i in range(3):
                players[i].is_dealer = False
            players[3].is_dealer = True

        # bidding continues until no players wish to make a higher bid
        print("START BIDDING")

        highest_bid = 0
        highest_bid_trump = None
        highest_bidder = None
        pass_count = 0
        alone = False
        for player in cycle(players):
            print(player)
            bid = get_bid()

            # player is not bidding higher
            if bid["value"] == "pass":
                pass_count = pass_count + 1
            # player wishes to shoot the moon/go alone
            elif bid["value"] == "alone":
                highest_bid = 12
                highest_bid_trump = bid["trump"]
                highest_bidder = player
                alone = True
                break
            # new highest bid
            elif bid["value"] > highest_bid:
                highest_bid = bid["value"]
                highest_bid_trump = bid["trump"]
                highest_bidder = player
                pass_count = 0

            # no player wishes to exceed current highest bid, end bidding
            if pass_count == 3:
                break

        # handle card exchange during alone scenario
        if alone:
            partner = players[(players.index(highest_bidder) + 2) % 4]
            highest_bidder_drops_3_cards(highest_bidder)
            partner_provides_3_cards(partner, highest_bidder)

        # track team that made winning bid
        if highest_bidder in config.teams[1]:
            config.bidding_team = 1
            opposing_team = 2
        else:
            config.bidding_team = 2
            opposing_team = 1

        # track winning config.trump
        config.trump = highest_bid_trump
        print(
            f"BIDDING OVER. {highest_bid} {highest_bid_trump} made by {highest_bidder.name}"
        )

        # trick play
        for i in range(12):
            if i == 0:
                trick_results = play_trick(players, highest_bidder)
            else:
                trick_results = play_trick(players, trick_winner)

            trick_winner = trick_results["Trick Winner"]

            # track results of all tricks played so far
            if hand_number > 0:
                hand_results = update_hand_results(trick_results, hand_results)
            else:
                hand_results = update_hand_results(trick_results)

        # update scores
        # bidding team euchred
        if hand_results["Bidding Team Score"] < highest_bid:
            if alone:
                score[config.bidding_team] = score[config.bidding_team] - 24
            else:
                score[config.bidding_team] = score[config.bidding_team] - highest_bid
        # bidding team successful
        else:
            if alone:
                score[config.bidding_team] = score[config.bidding_team] + 24
            else:
                score[config.bidding_team] = (
                    score[config.bidding_team] + hand_results["Bidding Team Score"]
                )
        score[opposing_team] = (
            score[opposing_team] + hand_results["Opposing Team Score"]
        )

        print(score)

        hand_number = hand_number + 1

    print(score)

if __name__ == "__main__":
    play_game()


import random

class Card:

    rank_dict = {"A": 1, "J": 11, "Q": 12, "K": 13}
    rank_dict2 = {1: "A", 11: "J", 12: "Q", 13: "K"}

    def __init__(self, rank = 0, suit = ""):
        if type(rank) == str:
            try:
                self.rank = Card.rank_dict[rank]
            except:
                self.rank = 0
        elif rank in range(1,14):
            self.rank = rank
        else:
            self.rank = 0
        if str(suit).lower() in {"h", "s", "d", "c"}:
            self.suit = suit.upper()
        else:
            self.suit = ""

    def __str__(self):
        if self.is_blank():
            return "blk"
        elif self.rank in Card.rank_dict2:
            return "{:>3}".format(Card.rank_dict2[self.rank] + self.suit)
        else:
            return "{:>3}".format(str(self.rank) + self.suit)

    def is_blank(self):
        if self.rank == 0 and self.suit == "":
            return True
        return False

class Deck:

    def __init__(self):
        deck = []
        suits = ("S", "H", "D", "C")
        for i in range(1,14):
            for a_suit in suits:
                a_card = Card(i,a_suit)
                deck.append(a_card.__str__())
        self.deck = deck

    def __str__(self):
        deck_string = ""
        for k in range(4):
            for i in range(13):
                try:
                    deck_string  += self.deck[k*13+i] + " "
                except:
                    pass
            if deck_string != "":
                deck_string += "\n"
        return deck_string

    def shuffle(self):
        random.shuffle(self.deck)

    def deal(self):
        return self.deck.pop(0)

class PlayingHand:

    NUMBER_CARDS = 13

    def __init__(self):
        self.hand = ["blk" for i in range(1,14)]

    def __str__(self):
        hand_string = ""
        for item in self.hand:
            hand_string += "{:>4}".format(item)
        return hand_string

    def add_card(self, card):
        for index,value in enumerate(self.hand):
            if value == "blk":
                self.hand[index] = card
                break

def test_cards():
    card1 = Card()
    print(card1)
    card2 = Card(5,'s')
    print(card2)
    card3 = Card('Q','D')
    print(card3)
    card4 = Card('x', 7)
    print(card4)
def print_4_hands(hand1, hand2, hand3, hand4):
    ''' Prints the 4 hands '''
    print(hand1)
    print(hand2)
    print(hand3)
    print(hand4)
def deal_4_hands(deck, hand1, hand2, hand3, hand4):
    ''' Deals cards for 4 hands '''
    for i in range(PlayingHand.NUMBER_CARDS):
        hand1.add_card(deck.deal())
        hand2.add_card(deck.deal())
        hand3.add_card(deck.deal())
        hand4.add_card(deck.deal())
def test_hands(deck):
    hand1 = PlayingHand()
    hand2 = PlayingHand()
    hand3 = PlayingHand()
    hand4 = PlayingHand()
    print("The 4 hands:")
    print_4_hands(hand1, hand2, hand3, hand4)
    deal_4_hands(deck, hand1, hand2, hand3, hand4)
    print("The 4 hands after dealing:")
    print_4_hands(hand1, hand2, hand3, hand4)

#The main program starts here
random.seed(10)
test_cards()
deck = Deck()
deck.shuffle()
print("The deck:")
print(deck)
test_hands(deck)
print("The deck after dealing:")
print(deck)


# 先寫網路模型
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear

# 寫完網絡的時候建議檢查網絡中的參數是否正確，因為網絡中key錯參數並不會特別報錯
from torch.utils.tensorboard import SummaryWriter

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        # 如何計算 padding, stride 可參考官方文件中的公式

        ''' 不用 nn.Sequential 的作法，比較囉唆
        self.conv1 = Conv2d(3, 32, 5, padding=2)
        ## Max-pooling kernel size 為 2
        self.maxpool1 = MaxPool2d(2)
        self.conv2 = Conv2d(32, 32, 5, padding=2)
        self.maxpool2 = MaxPool2d(2)
        self.conv3 = Conv2d(32, 64, 5, padding=2)
        self.maxpool3 = MaxPool2d(2)
        self.flatten = Flatten()
        self.linear1 = Linear(1024, 64)
        self.linear2 = Linear(64, 10)
        '''

        self.model1 = nn.Sequential(
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )
    ''' 不用 Sequential 的 forward，真的很囉唆
    def forward(self, x):
        x = self.conv1(x)
        x = self.maxpool1(x)
        x = self.conv2(x)
        x = self.maxpool2(x)
        x = self.conv3(x)
        x = self.maxpool3(x)
        x = self.flatten(x)
        x = self.linear1(x)
        x = self.linear2(x)
        return x
    '''

    def forward(self,x):
        x = self.model1(x)
        return x

# 驗證網絡正確性
tudui = Tudui()
print(tudui)

input = torch.ones((64, 3, 32, 32))
output = tudui(input)
print(output.shape)

# 使用 tensorboard 做 visualization
writer = SummaryWriter("../logs_seq")
writer.add_graph(tudui, input)
writer.close()


#!/usr/bin/env python3
import os
import re
import subprocess
import sys
import xml.etree.ElementTree as ET

def int16_as_bytes(value):
    value = value & 0xFFFF
    return [value & 0xFF, (value >> 8) & 0xFF]

def int32_as_bytes(value):
    value = value & 0xFFFFFFFF
    return [value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF, (value >> 24) & 0xFF]

def pc_to_snes(value):
    return ((value<<1) & 0x7F0000)|(value & 0x7FFF)|0x8000

def snes_to_pc(value):
    return ((value & 0x7F0000)>>1)|(value & 0x7FFF)

def parse_player_names(names, players, teams):
    names = [n for n in re.split(r'[, ]', names) if n]
    ret = []
    while names or len(ret) < teams:
        team = [n[:16] for n in names[:players]]
        while len(team) != players:
            team.append(f"Player {len(team) + 1}")
        ret.append(team)

        names = names[players:]
    return ret

def is_bundled():
    return getattr(sys, 'frozen', False)

def local_path(path):
    return path

    if local_path.cached_path is not None:
        return os.path.join(local_path.cached_path, path)

    if is_bundled():
        # we are running in a bundle
        local_path.cached_path = sys._MEIPASS # pylint: disable=protected-access,no-member
    else:
        # we are running in a normal Python environment
        local_path.cached_path = os.path.dirname(os.path.abspath(__file__))

    return os.path.join(local_path.cached_path, path)

local_path.cached_path = None

def output_path(path):
    if output_path.cached_path is not None:
        return os.path.join(output_path.cached_path, path)

    if not is_bundled():
        output_path.cached_path = '.'
        return os.path.join(output_path.cached_path, path)
    else:
        # has been packaged, so cannot use CWD for output.
        if sys.platform == 'win32':
            #windows
            import ctypes.wintypes
            CSIDL_PERSONAL = 5       # My Documents
            SHGFP_TYPE_CURRENT = 0   # Get current, not default value

            buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH)
            ctypes.windll.shell32.SHGetFolderPathW(None, CSIDL_PERSONAL, None, SHGFP_TYPE_CURRENT, buf)

            documents = buf.value

        elif sys.platform == 'darwin':
            from AppKit import NSSearchPathForDirectoriesInDomains # pylint: disable=import-error
            # http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSearchPathForDirectoriesInDomains
            NSDocumentDirectory = 9
            NSUserDomainMask = 1
            # True for expanding the tilde into a fully qualified path
            documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, True)[0]
        else:
            raise NotImplementedError('Not supported yet')

        output_path.cached_path = os.path.join(documents, 'ALttPEntranceRandomizer')
        if not os.path.exists(output_path.cached_path):
            os.mkdir(output_path.cached_path)
        return os.path.join(output_path.cached_path, path)

output_path.cached_path = None

def open_file(filename):
    if sys.platform == 'win32':
        os.startfile(filename)
    else:
        open_command = 'open' if sys.platform == 'darwin' else 'xdg-open'
        subprocess.call([open_command, filename])

def close_console():
    if sys.platform == 'win32':
        #windows
        import ctypes.wintypes
        try:
            ctypes.windll.kernel32.FreeConsole()
        except Exception:
            pass

def make_new_base2current(old_rom='Zelda no Densetsu - Kamigami no Triforce (Japan).sfc', new_rom='working.sfc'):
    from collections import OrderedDict
    import json
    import hashlib
    with open(old_rom, 'rb') as stream:
        old_rom_data = bytearray(stream.read())
    with open(new_rom, 'rb') as stream:
        new_rom_data = bytearray(stream.read())
    # extend to 2 mb
    old_rom_data.extend(bytearray([0x00] * (2097152 - len(old_rom_data))))

    out_data = OrderedDict()
    for idx, old in enumerate(old_rom_data):
        new = new_rom_data[idx]
        if old != new:
            out_data[idx] = [int(new)]
    for offset in reversed(list(out_data.keys())):
        if offset - 1 in out_data:
            out_data[offset-1].extend(out_data.pop(offset))
    with open('data/base2current.json', 'wt') as outfile:
        json.dump([{key:value} for key, value in out_data.items()], outfile, separators=(",", ":"))

    basemd5 = hashlib.md5()
    basemd5.update(new_rom_data)
    return "New Rom Hash: " + basemd5.hexdigest()

entrance_offsets = {
    'Sanctuary': 0x2,
    'HC West': 0x3,
    'HC South': 0x4,
    'HC East': 0x5,
    'Eastern': 0x8,
    'Desert West': 0x9,
    'Desert South': 0xa,
    'Desert East': 0xb,
    'Desert Back': 0xc,
    'TR Lazy Eyes': 0x15,
    'TR Eye Bridge': 0x18,
    'TR Chest': 0x19,
    'Aga Tower': 0x24,
    'Swamp': 0x25,
    'Palace of Darkness': 0x26,
    'Mire': 0x27,
    'Skull 2 West': 0x28,
    'Skull 2 East': 0x29,
    'Skull 1': 0x2a,
    'Skull 3': 0x2b,
    'Ice': 0x2d,
    'Hera': 0x33,
    'Thieves': 0x34,
    'TR Main': 0x35,
    'GT': 0x37,
    'Skull Pots': 0x76,
    'Skull Left Drop': 0x77,
    'Skull Pinball': 0x78,
    'Skull Back Drop': 0x79,
    'Sewer Drop': 0x81
}

entrance_data = {
    'Room Ids': (0x14577, 2),
    'Relative coords': (0x14681, 8),
    'ScrollX': (0x14AA9, 2),
    'ScrollY': (0x14BB3, 2),
    'LinkX': (0x14CBD, 2),
    'LinkY': (0x14DC7, 2),
    'CameraX': (0x14ED1, 2),
    'CameraY': (0x14FDB, 2),
    'Blockset': (0x150e5, 1),
    'FloorValues': (0x1516A, 1),
    'Dungeon Value': (0x151EF, 1),
    'Frame on Exit': (0x15274, 1),
    'BG Setting': (0x152F9, 1),
    'HV Scroll': (0x1537E, 1),
    'Scroll Quad': (0x15403, 1),
    'Exit Door': (0x15488, 2),
    'Music': (0x15592, 1)
}

def read_entrance_data(old_rom='Zelda no Densetsu - Kamigami no Triforce (Japan).sfc'):
    with open(old_rom, 'rb') as stream:
        old_rom_data = bytearray(stream.read())

    for ent, offset in entrance_offsets.items():
        # print(ent)
        string = ent
        for dp, data in entrance_data.items():
            byte_array = []
            address, size = data
            for i in range(0, size):
                byte_array.append(old_rom_data[address+(offset*size)+i])
            some_bytes = ', '.join('0x{:02x}'.format(x) for x in byte_array)
            string += '\t'+some_bytes
            # print("%s: %s" % (dp, bytes))
        print(string)

def print_wiki_doors(d_regions, world, player):

    for d, region_list in d_regions.items():
        tile_map = {}
        for region in region_list:
            tile = None
            r = world.get_region(region, player)
            for ext in r.exits:
                door = world.check_for_door(ext.name, player)
                if door is not None and door.roomIndex != -1:
                    tile = door.roomIndex
                    break
            if tile is not None:
                if tile not in tile_map:
                    tile_map[tile] = []
                tile_map[tile].append(r)
        print(d)
        print('{| class="wikitable"')
        print('|-')
        print('! Room')
        print('! Supertile')
        print('! Doors')
        for tile, region_list in tile_map.items():
            tile_done = False
            for region in region_list:
                print('|-')
                print('| '+region.name)
                if not tile_done:
                    listlen = len(region_list)
                    link = '| {{UnderworldMapLink|'+str(tile)+'}}'
                    print(link if listlen < 2 else '| rowspan = '+str(listlen)+' '+link)
                    tile_done = True
                strs_to_print = []
                for ext in region.exits:
                    strs_to_print.append(ext.name)
                print('| '+' <br /> '.join(strs_to_print))
        print('|}')

def print_xml_doors(d_regions, world, player):
    root = ET.Element('root')
    for d, region_list in d_regions.items():
        tile_map = {}
        for region in region_list:
            tile = None
            r = world.get_region(region, player)
            for ext in r.exits:
                door = world.check_for_door(ext.name, player)
                if door is not None and door.roomIndex != -1:
                    tile = door.roomIndex
                    break
            if tile is not None:
                if tile not in tile_map:
                    tile_map[tile] = []
                tile_map[tile].append(r)
        dungeon = ET.SubElement(root, 'dungeon', {'name': d})
        for tile, r_list in tile_map.items():
            supertile = ET.SubElement(dungeon, 'supertile', {'id': str(tile)})
            for region in r_list:
                room = ET.SubElement(supertile, 'room', {'name': region.name})
                for ext in region.exits:
                    ET.SubElement(room, 'door', {'name': ext.name})
    ET.dump(root)

def print_graph(world):
    root = ET.Element('root')
    for region in world.regions:
        r = ET.SubElement(root, 'region', {'name': region.name})
        for ext in region.exits:
            attribs = {'name': ext.name}
            if ext.connected_region:
                attribs['connected_region'] = ext.connected_region.name
            if ext.door and ext.door.dest:
                attribs['dest'] = ext.door.dest.name
            ET.SubElement(r, 'exit', attribs)
    ET.dump(root)

if __name__ == '__main__':
    pass
    # make_new_base2current()
    read_entrance_data(old_rom='C:\\Users\\Randall\\Documents\\kwyn\\orig\\z3.sfc')


def parse_ingredient(ingredient: str):
    try:
        ingredient_name, quantity, measure = ingredient.split('|')
        return {
            'ingredient_name': ingredient_name.strip(),
            'quantity': int(quantity.strip()),
            'measure': measure.strip()
        }
    except ValueError:
        print('В файле ошибка')

def get_cook_book_from_file():
    cook_book = {}
    with open('recipes.txt') as file:
        while True:
            dishes_name = file.readline().strip()
            ingredient_count = int(file.readline())
            ingredient_list = [parse_ingredient(file.readline()) for _ in range(ingredient_count)]
            cook_book[dishes_name] = ingredient_list
            if not file.readline():
                break
    return cook_book

def get_shop_list_by_dishes(dishes: list, person_count: int):
    cook_book = get_cook_book_from_file()
    shop_list = {}
    for dishe in dishes:
        if dishe not in cook_book.keys():
            print(f'Блюда {dishe} нет в рецептах, оно будет пропущено')
            continue
        for ingredient in cook_book.get(dishe):
            ingredient_name = ingredient.get('ingredient_name')
            if ingredient_name not in shop_list:
                shop_list[ingredient_name] = {
                    'measure': ingredient.get('measure'),
                    'quantity': ingredient.get('quantity') * person_count
                }
            else:
                shop_list[ingredient_name]['quantity'] += ingredient.get('quantity') * person_count
    return shop_list

if __name__ == '__main__':
    shop_list = get_shop_list_by_dishes(['Фахитос', 'Омлет'], 1)
    print(shop_list)


#!/usr/bin/python
# -*- coding: utf-8 -*-
import xbmc, xbmcgui, xbmcaddon, xbmcplugin, os

addon = xbmcaddon.Addon()
addon_path = addon.getAddonInfo('path').decode('utf-8')

name = "I Love Electronic"
url = "https://bit.ly/35hm7IZ"
iconimage = os.path.join(addon_path,"icon.png")

liz=xbmcgui.ListItem(name, iconImage=iconimage,thumbnailImage=iconimage); liz.setInfo( type="audio", infoLabels={ "Title": name } )
xbmc.Player ().play(url, liz, True)


from django.contrib import admin

from django_ymap.admin import YmapAdmin
from team.models import SEO
from .models import EventLocation, Event

class SEO(admin.StackedInline):
    model = SEO
    extra = 0
    fields = (
        'seo_description',
        'key_words',
    )
    show_change_link = True

class EventAdmin(admin.ModelAdmin):
    model = Event
    inlines = (SEO,)
    prepopulated_fields = {'slug': ('title',)}
    fieldsets = (
        ('Основное', {'fields': (
            'title', 'sub_title', 'slug', 'start', 'end', 'tags', 'type', 'featured_image', 'profile_image',
            'location')}),
        ('Описание', {'fields': ('allow_comments', 'description')}),
        ('Дополнительная информация', {'fields': ('internet_available', 'take_computer', 'site', 'value')}),
    )

    class Media:
        js = ['js/FB_CKEditor.js',
              'js/ckeditor.js']

    def save_model(self, request, obj, form, change):
        obj.author = request.user
        obj.save()

admin.site.register(Event, EventAdmin)

class RecordAdmin(YmapAdmin, admin.ModelAdmin):
    pass

admin.site.register(EventLocation, RecordAdmin)


# -*- coding: utf-8 -*-

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Copyright (c) 2018, Eurecat / UPF
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the <organization> nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
#   @file   SOFASimpleFreeFieldHRIR.py
#   @author Andrés Pérez-López
#   @date   29/08/2018
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

import warnings

from pysofaconventions import SOFAFile, SOFAWarning

class SOFASimpleFreeFieldHRIR(SOFAFile):
    conventionVersionMajor = 1
    conventionVersionMinor = 0

    def isValid(self):
        """
        Check for GeneralFIR convention consistency
        It ensures general file consistency, and also specifics for this convention.
        - 'DataType' == 'FIR'
        - 'SOFAConventions' == 'SimpleFreeFieldHRIR'
        - 'RoomType' == 'free field'
        - Mandatory attribute 'ListenerShortName'
        - Mandatory attribute 'DatabaseName'
        - E == 1 (single emitter)
        - R == 2 (two ears)

        :return:    Boolean
        :raises:    SOFAWarning with error description, in case
        """

        # Check general file validity
        if not SOFAFile.isValid(self):
            return False

        # Ensure specifics of this convention

        # # Attributes
        if not self.isFIRDataType():
            warnings.warn('DataType is not "FIR", got: "{}"'.format(
                self.getGlobalAttributeValue('DataType')), SOFAWarning)
            return False

        if not self.getGlobalAttributeValue('SOFAConventions') == 'SimpleFreeFieldHRIR':
            warnings.warn('SOFAConventions is not "SimpleFreeFieldHRIR", got: "{}"'.format(
                self.getGlobalAttributeValue('SOFAConventions')), SOFAWarning)
            return False

        if not self.getGlobalAttributeValue('RoomType') == 'free field':
            warnings.warn('RoomType is not "free field", got: "{}"'.format(self.getGlobalAttributeValue('RoomType')),
                          SOFAWarning)
            return False

        if not self.hasGlobalAttribute('ListenerShortName'):
            warnings.warn('Missing required Global Attribute "ListenerShortName"', SOFAWarning)
            return False

        if not self.hasGlobalAttribute('DatabaseName'):
            warnings.warn('Missing required Global Attribute "DatabaseName"', SOFAWarning)
            return False

        # # Dimensions
        if not self.getDimensionSize('E') == 1:
            warnings.warn('Number of emitters (E) is not "1", got "{}"'.format(self.getDimensionSize('E')),
                          SOFAWarning)
            return False

        if not self.getDimensionSize('R') == 2:
            warnings.warn('Number of receivers (R) is not "2", got "{}"'.format(self.getDimensionSize('R')),
                          SOFAWarning)
            return False

        return True


import os
import gspread
import requests
from .util import full_path, assign_code, search_records
import yaml
from ast import literal_eval
import weakref

class Importer():

    def __init__(self, items_dict, app):
        """
        Main Importing object, contains methods for fetching, importing,
        processing, and exporting data

        Parameters:
            files_dict: dict of files to be recognized by importer. This comes
                        from main.yaml
            app: weakref to main app for accessing higher resources

        Attributes:
            app: weakref to main app for accessing higher resources
            files: dict of files recognized by importer
                Each file has two states: loaded and not loaded. Loaded is when
                a GET request has been made, not loaded is before any request
                has been made
            empty_records: any records deemed "empty" during processing
        """
        self.app = app
        self.items = {}
        self.empty_records = []
        self.temp = {}

        #This loop builds up the dictionary of recognized items
        for key, value in items_dict.items():
            if value['type'] == 'sheets':
                #File is a spreadsheet
                self.items[key] = Spreadsheet(_type=value['type'],
                                              _id=value['id'],
                                              contents=None,
                                              loaded=False,
                                              ingested=False,
                                              app=self.app)

            elif value['type'] == 'folder':
                #Item is a folder
                self.items[key] = Directory(_type=value['type'],
                                       _id=value['id'],
                                       contents=None,
                                       loaded=False,
                                       ingested=False,
                                       app=self.app)

            elif value['type'] == 'file':
                #File is any other file
                self.items[key] = File(_type=value['type'],
                                       _id=value['id'],
                                       contents=None,
                                       loaded=False,
                                       ingested=False,
                                       app=self.app)

            elif value['type'] == 'file':
                #File is any other file
                self.items[key] = File(_type=value['type'],
                                       _id=value['id'],
                                       contents=None,
                                       loaded=False,
                                       ingested=False,
                                       app=self.app)

    def load_directories(self, recursive=True, exclusions=[]):
        """
        Makes initial GET requests for all recognized directories in main.yaml

        Parameters:
            exclusions: list of directories to ignore during loading. Exclusions are
            referenced by key (that is, their name in main.yaml)
        """
        #Loop through all recognized files
        for key, _directory in self.items.items():
            #Check if file is loaded and not in exclusions
            if not _directory.loaded and key not in exclusions:
                app = self.app() #Loads app from weakref
                #Requests are stored in the main app
                request = app.requests.requests[key]
                print(request)
                #Load file contents
                contents = app.auth.make_get_request(request=request)
                _directory.contents = contents
                _directory.loaded = True

    def ingest_spreadsheets(self, exclusions=[]):
        """
        Ingests all spreadsheets present in the dict of recognized files
        """
        #Get the file containing all metadata flags
        self.get_flag_file()
        for key, _file in self.files.items():
            #Check if the filetype is sheets, not excluded, and not ingested
            if _file._type == 'sheets' and key not in exclusions and not _file.ingested:
                #Set 'current' attributes
                self.current_filename = key
                self.current_file_id = _file._id
                #Ingest sheet
                self.ingest_single_spreadsheet()
                _file.ingested = True
        #Clean up 'current' attributes
        self.current_filename = None
        self.current_file_id = None

    def ingest_single_spreadsheet(self):
        """
        Sets current spreadsheet and runs ingestion
        """
        #Get current spreadsheet using gspread
        self.current_spreadsheet = self.spreadsheet_manager.open_by_key(
                                        self.current_file_id)
        if self.current_spreadsheet.title == 'AppointmentData':
            self.assigning = True
        else:
            self.assigning = False
        for j in self.current_spreadsheet.worksheets():
            self.current_worksheet = j
            for i in self.flags:
                self.set_current_sheet_flags(i)
                for flag_name, flag_content in self.current_sheet_flags.items():
                    self.set_current_sheet_flags(i)
                    if flag_name == 'model':
                        self.temp[flag_name] = flag_content
                    elif flag_name != 'records':
                        self.temp[flag_name] = self.run_flag(flag_name,
                                                             flag_content)
                    else:
                        self.temp['records'] = self.run_flag_records(flag_content,
                                                        self.current_worksheet.title)
                print('Set flag data for ' + j.title)
                self.sheets[j.title] = self.temp
                self.temp = {}
        #Clean up Attributes for next iteration
        self.current_spreadsheet = None
        self.current_worksheet = None
        self.temp = {}

    def set_current_sheet_flags(self, i):
        """
        Get the appropriate flags for current sheet (passed in as i)

        Parameters:
            i: dict representation of loaded flagfile
        """
        try:
            self.current_sheet_flags = i[self.current_filename]
        except KeyError:
            print('No flags found for ' + self.current_filename)
            self.current_sheet_flags = {}

    def get_flag_file(self):
        """
        Retrieve all flagfiles.
        """
        flag_file_path = full_path('src/config/flagfiles/')
        flags = []
        for i in os.listdir(flag_file_path):
            with open(flag_file_path + i) as f:
                print(f)
                flags.append(yaml.load(f))
        self.flags = flags

    def run_flag_records(self, flag_dict, sheet_title):
        """
        Gets header row for the sheet's records
        """
        cell = self.current_worksheet.find(flag_dict['flag_string'])
        row = cell.row
        records = self.current_worksheet.get_all_records(head=row)
        deletions = []
        k = 1
        for (i, record) in enumerate(records):
            if self.check_record_empty(record):
                deletions.append(i)
            #CAREFUL, THIS NEXT LINE IS HARDCODED AND CAN CAUSE ISSUES
            elif self.assigning==True:
                record['code'] = assign_code(record, k, self.temp['location'],
                                         sheet_title)
                k += 1
        for j in sorted(deletions, reverse=True):
            print('Deleting ' + str(j))
            del records[j]
        return records

    def check_record_empty(self, record):
        """
        Checks all fields in the current record. If more than 50% are blank,
        registers the record as empty

        Parameters:
            record: Dictionary representation of current record to be tested

        Returns:
            boolean: if record is deemed to be empty
        """
        counter = 0.0
        length = len(record.items())
        for key, value in record.items():
            if not value:
                counter += 1.0
        if counter / length >= 0.5:
            self.empty_records.append(record)
            return True
        else:
            return False

    def run_flag(self, flag_name, flag_dict):
        """
        For a given flag, extracts the vector for identifying data and
        retrieves that value
        """
        cell = self.current_worksheet.find(flag_dict['flag_string'])
        vector = (int(flag_dict['flag_data_row']),
                  int(flag_dict['flag_data_column']))
        (row, col) = cell.row, cell.col
        (data_row, data_col) = (row + vector[0], col + vector[1])
        data_cell = self.current_worksheet.cell(data_row, data_col)
        flag_cell = self.current_worksheet.cell(row, col)
        return data_cell.value

####CODE BELOW THIS LINE SHOULD BE REFACTORED
class File(object):
    __slots__ = '_type', '_id', 'contents', 'loaded', 'ingested', 'app'
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

class Directory(object):
    __slots__ = '_type', '_id', 'contents', 'loaded', 'ingested', 'app'
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

class Spreadsheet(File):
    __slots__ = 'sheet_names', 'values'
    def __init__(self, **kwargs):
        super(Spreadsheet, self).__init__()
        for key, value in kwargs.items():
            setattr(self, key, value)
        self.values = {}

    def set_sheet_names(self, names):
        self.sheet_names = names

    def get_values(self, name=None, _range=None):
        if _range == None:
            #Return the entire sheet
            request=self.app().requests.base(_type='sheets',
                                  _id = self._id,
                                  suffix='/values/' + name)
        elif name == None:
            request=self.app().requests.base(_type='sheets',
                                  _id = self._id,
                                  suffix='/values/' + _range)
        else:
            raise ValueError('Need a range for the sheets request!')
        return request

    def parse_sheet(self, field):
        """
        Parses an individual sheet in spreadsheet object until the requested
        field is found. CASE SENSITIVE
        """


import networkx as nx
import random

def sample(elements, num_samples, with_replacement=True):
    print("Taking a sample of size %d from %d. Replacement=%s" % \
        (num_samples, len(elements), with_replacement))
    if not with_replacement:
        return random.sample(elements, num_samples)
    samples = []
    for i in range(0, num_samples):
        samples.append(random.choice(elements))
    return samples

# Returns a list of `num_samples` edges not in the graph's edge set.
def non_edges_sample(nodes, edges, directed, num_samples, with_replacement=True):
    num_nodes = len(nodes)
    num_edges = len(edges)
    nodes_list = list(nodes)
    nodes_list.sort()

    edges_set = edges
    if not (type(edges_set) is set):
        edges_set = set(edges_set)

    edges_list = list(edges)
    if len(edges_list[0]) == 3:
        edges_list = [(a, b) for (a, b, t) in edges]

    num_non_edges = int((num_nodes * (num_nodes - 1)) / \
        (2 - int(directed))) - num_edges

    print("Taking a non-edges sample of size %d from %d. Replacement=%s" % \
        (num_samples, num_non_edges, with_replacement))

    # If sufficiently large sample size,
    #   just enumerate all possible edges and sample.

    # Enumerate all possible non-edges only if sample size is a large fraction
    #   of non-edges.
    if num_samples > (num_non_edges * 0.75):
        possible_edges = set()
        if directed:
            for i in range(0, num_nodes):
                for j in range(0, num_nodes):
                    if j == i:
                        continue
                    possible_edges.add((nodes[i], nodes[j]))
        else:
            for i in range(0, num_nodes):
                for j in range(i + 1, num_nodes):
                    possible_edges.add((nodes[i], nodes[j]))
        non_edges = list(possible_edges - edges_set)
        if not with_replacement:
            return random.sample(non_edges, num_samples)
        result = []
        for i in range(0, num_samples):
            result.append(random.choice(non_edges))
        return result

    """ Skip the fancy stuff for now. It's SLOW and maybe wrong.
    if directed:
        num_possible_targets = {n: num_nodes - 1 for n in nodes_list}
    else:
        # If undirected, only consider one way of generating the edges
        #   (a, b) and (b, a): (min(a, b), max(a, b))
        num_possible_targets = {nodes_list[i]: (num_nodes - 1) - i \
            for i in range(0, num_nodes)}

    relevant_neighbors = {n: set() for n in nodes}

    for (a, b) in edges_list:
        if directed:
            num_possible_targets[a] -= 1
            relevant_neighbors[a].add(b)
        else:
            s = min(a, b)
            t = max(a, b)
            num_possible_targets[s] -= 1
            relevant_neighbors[s].add(t)

    total_non_edges = \
        float(sum([poss for n, poss in num_possible_targets.items()]))
    source_probs = [num_possible_targets[n] / total_non_edges for n in nodes_list]
    source_probs_cumulative = [source_probs[0]]
    s = source_probs[0]
    for i in range(1, num_nodes):
        s += source_probs[i]
        source_probs_cumulative.append(s)
    """

    if with_replacement:
        non_edges = []
    else:
        non_edges = set()

    while True:
        """ Skip the fancy stuff for now. It's SLOW and maybe wrong.
        source_idx = __cumulative_idx_select__(source_probs_cumulative)
        source = nodes[source_idx]
        if directed:
            valid_targets = []
            for n in nodes:
                if n not in relevant_neighbors[source]:
                    valid_targets.append(n)
        else:
            valid_targets = []
            for i in range(source_idx + 1, num_nodes):
                n = nodes[i]
                if n not in relevant_neighbors[source]:
                    valid_targets.append(n)

        target = valid_targets[random.randint(0, len(valid_targets) - 1)]
        """
        # Simple version. Way faster.
        source = random.choice(nodes_list)
        target = random.choice(nodes_list)
        if source == target or (source, target) in edges_set or \
                ((not directed) and (target, source) in edges_set):
            continue

        if not with_replacement and (source, target) in non_edges:
            continue

        if with_replacement:
            non_edges.append[(source, target)]
        else:
            non_edges.add((source, target))

        if len(non_edges) == num_samples:
            return list(non_edges)

# A binary search for the idx such that:
#
#   cp[idx - 1] < val <= cp[idx]
#   note the _strictly_ less than.
def __cumulative_idx_select__(cumulative_prob_list):
    val = random.random()
    num_options = len(cumulative_prob_list)
    upper = num_options  # exclusive
    lower = 0  # inclusive
    idx = int(upper / 2)
    while True:
        if lower + 1 == upper:
            return idx

        cp = cumulative_prob_list[idx]

        if val <= cp:
            if cumulative_prob_list[idx - 1] < val:
                return idx
            # otherwise, cumulative_prob_list[idx - 1] == val:
            upper = idx
        else:
            lower = idx + 1
        # i.e. overflow-safe idx = int((upper + lower) / 2)
        idx = lower + int((upper - lower) / 2)

def all_disconnected_node_pairs_within_k(graph, k):
    nodes = list(graph.nodes())
    nodes.sort()
    pairs = set()

    nx_graph = nx.Graph()
    for node in nodes:
        nx_graph.add_node(node)
    for (a, b) in graph.edges():
        nx_graph.add_edge(a, b)

    for node in nodes:
        bfs_edges = nx.bfs_edges(nx_graph, node, depth_limit=k)
        bfs_nodes = set([v for (u, v) in bfs_edges])
        if graph.is_directed():
            for bfs_n in bfs_nodes:
                if not graph.has_edge(node, bfs_n):
                    pairs.add((node, bfs_n))
        else:
            bfs_nodes = bfs_nodes - set(graph.neighbors(node))
            for bfs_n in bfs_nodes:
                if bfs_n > node:
                    pairs.add((node, bfs_n))
    return pairs

def all_connected_node_pairs_that_would_be_within_k_if_disconnected(graph, k):
    nodes = list(graph.nodes())
    nodes.sort()
    pairs = set()

    nx_graph = nx.Graph()
    for node in nodes:
        nx_graph.add_node(node)
    for (a, b) in graph.edges():
        nx_graph.add_edge(a, b)

    for node in nodes:
        neighbors = list(nx_graph.neighbors(node))
        for neighbor in neighbors:
            if neighbor > node:
                continue

            nx_graph.remove_edge(node, neighbor)

            k_half_a = int(k / 2)
            k_half_b = k - k_half_a
            bfs_edges_a = nx.bfs_edges(nx_graph, node, depth_limit=k_half_a)
            bfs_nodes_a = set([v for (u, v) in bfs_edges_a])
            bfs_edges_b = nx.bfs_edges(nx_graph, neighbor, depth_limit=k_half_b)
            bfs_nodes_b = set([v for (u, v) in bfs_edges_b])

            if len(bfs_nodes_a & bfs_nodes_b) > 0:
                if graph.is_directed():
                    if graph.has_edge(node, neighbor):
                        pairs.add((node, neighbor))
                    if graph.has_edge(neighbor, node):
                        pairs.add((neighbor, node))
                else:
                    pairs.add((node, neighbor))

            nx_graph.add_edge(node, neighbor)

    return pairs


import sqlite3
import csv

con = sqlite3.connect("measurements.sqlite")

cur = con.cursor()
cur.execute("SELECT * FROM reports WHERE sessionid=2")
data = cur.fetchall()
print(len(data[0]))

with open('measurements.csv', 'w') as f:
    writer = csv.writer(f, lineterminator='\n')
    writer.writerow(["_id", "sessionid", "report", "systime", "simstate", "netopname", "netopcode", "roaming",
                     "nettype", "callstate", "datastate", "dataact", "datarx", "datatx", "nstartid", "nstopid",
                     "ngsm", "numts", "nlte", "nrssi", "nregcells", "tech", "mcc", "mnc",
                     "lactac", "nodeid", "cid", "pscpci", "rssi", "rsrq", "rssnr", "slev",
                     "gps", "accur", "lat", "long", "clat", "clong", "band", "arfcn"])
    for tup in data:
        writer.writerow(tup)


import sys
import pandas as pd
import numpy as np
import json
from datetime import datetime, timedelta

from flask import Flask, render_template, request, redirect, url_for
from flask import jsonify, Response

import pymongo
from pymongo import MongoClient

from utils_message import get_unlabeled, get_labeled
from config import DB_MONGO

from bson.json_util import dumps

sys.path.append("/home/xiaomu/xiaomu")

import logging

log = logging.getLogger(__name__)
log.setLevel(logging.INFO)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter(
    "%(asctime)s - %(name)s - %(levelname)s - %(message)s")
ch.setFormatter(formatter)
log.addHandler(ch)

client = MongoClient(DB_MONGO)
xiaomu = client.xiaomu
xiaomu_random_question = client.xiaomu_random_question

app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False

course_ids = xiaomu.message.distinct("course_id")

course_info = pd.read_csv(
    './data/course_info.csv', index_col='tw_ms_courseinfo_d.id')

from collections import defaultdict
c2course = defaultdict(list)
id2name = {}

def get_cnt_unlabeled(course_id, labeled_questions):
    message_set = xiaomu.message.find(
        {'course_id': course_id, 'type': 'question', 'flag': {"$in": [None, 'more']}, 'question_source': {"$nin": ['wobudong', 'active_question']}})
    message_set = list(message_set)
    items = xiaomu.message.find(
        {'course_id': course_id, 'type': 'answer', 'flag': {"$in": [None, 'more', ""]}})
    items = list(filter(lambda x: 'message' in x or 'answers' in x, items))

    origin_question_ids = set()
    for item in items:
        if 'origin_question' in item:
            origin_question_ids.add(item['origin_question'])
    unlabeled = list(filter(lambda x: x['message'] not in labeled_questions and '[    ]' not in x['message']
                            and x['_id'] in origin_question_ids, message_set))
    return len(set([x['message'] for x in unlabeled])), max([x['time'] for x in unlabeled]) if unlabeled else ''

log.info(len(course_info))

for index, row in course_info.iterrows():
    if row['tw_ms_courseinfo_d.course_id'] not in course_ids:
        continue
    try:
        category = json.loads(row['tw_ms_courseinfo_d.category'])
    except:
        category = {}
    course_id = row['tw_ms_courseinfo_d.course_id']

    id2name[row['tw_ms_courseinfo_d.course_id']
            ] = row['tw_ms_courseinfo_d.name']
    c2course['-'.join(tuple(category.values()))].append([row['tw_ms_courseinfo_d.' + x] if type(row['tw_ms_courseinfo_d.' + x]) != float else ''
                                                         for x in ['course_id', 'name']])
for k in c2course:
    c2course[k].sort()

@app.route('/unlabeled/<path:course_id>/')
def message(course_id):
    qids, answers, questions, times, tags, cnt_left = get_unlabeled(course_id)
    return render_template('message.html', q_a=zip(qids, questions, answers, times), course_id=course_id, name=id2name[course_id], cnt_left=cnt_left)

@app.route('/')
def main():
    return render_template("main.html", m=c2course)

tags = {
    0: "平台使用相关",
    1: "课程信息相关",
    2: "简单知识点解释",
    3: "复杂知识点讨论",
    4: "共性的反馈及建议",
    5: "聊天及其他",
    6: "个人相关的请求",
    7: "无意义或不适宜的内容",
    8: "预置的服务请求"
}

@app.route('/record')
def record():
    items = xiaomu.qa_annotation.find()
    from collections import Counter
    log.info('>>> record')
    c = Counter([str(x['created'].date()) for x in items if 'created' in x])
    return render_template('record.html', m=[(a, c[a]) for a in sorted(c.keys(), reverse=True)])

@app.route('/record_date/<date>')
def record_date(date):
    date = datetime.strptime(date, '%Y-%m-%d')
    items = xiaomu.qa_annotation.find(
        {'created': {"$gte": date, "$lt": date+timedelta(1)}}).sort("created", pymongo.DESCENDING)
    return jsonify([x['question'] for x in items])

@app.route('/statistics')
def statistics():
    log.info('>>> statistics')
    concepts = set([x['concept'] for x in xiaomu.kp.find()])
    log.info('concepts: %d' % len(concepts))
    active_questions = set([x["content"] if x["question_type"] != 'keyword' else "什么是%s？" % (
        x['content']) for x in xiaomu_random_question.ques.find()])
    log.info('active_questions: %d' % len(active_questions))
    labeled_questions = set(
        [x['question'] for x in xiaomu.qa_annotation.find()])
    log.info('labeled_questions: %d' % len(labeled_questions))

    labeled_questions = labeled_questions.union(
        active_questions).union(concepts)
    log.info('labeled_questions: %d' % len(labeled_questions))

    question_all = list(xiaomu.message.find({'type': 'question', 'flag': {"$in": [
                        None, 'more']}, 'question_source': {"$nin": ['wobudong', 'active_question']}}))
    log.info('question_all: %d' % len(question_all))
    answer_all = list(xiaomu.message.find(
        {'type': 'answer', 'flag': {"$in": [None, 'more', ""]}}))
    answer_all = list([x for x in answer_all if 'message' in x and x['message'] or 'answers' in x])
    log.info('answer_all: %d' % len(answer_all))
    labeled_all = list(xiaomu.qa_annotation.find())
    log.info('labeled_all: %d' % len(labeled_all))

    log.info('id2name: %d' % len(id2name))
    l = []
    for course_id, course_name in id2name.items():
        log.info(course_id)
        message_set = [x for x in question_all if x['course_id'] == course_id]

        items = [x for x in answer_all if x['course_id'] == course_id]

        origin_question_ids = set([x['origin_question']
                                   for x in items if 'origin_question' in x])
        unlabeled = list(filter(lambda x: x['message'] not in labeled_questions and '[    ]' not in x['message']
                                and x['_id'] in origin_question_ids, message_set))
        cnt_unlabeled = len(set([x['message'] for x in unlabeled]))
        latest = max([x['time'] for x in unlabeled]) if unlabeled else ''

        cnt_labeled = len([x for x in labeled_all if x['course_id'] == course_id])

        tags_distribution = []

        for i in range(9):
            cnt = len([x for x in labeled_all if x['course_id'] ==
                       course_id and x.get('category', "") == str(i)])
            tags_distribution.append(cnt)

        if not cnt_unlabeled:
            continue
        l.append([latest, cnt_unlabeled, course_id,
                  course_name, cnt_labeled, tags_distribution])
    l.sort(reverse=True)
    return render_template('statistics.html', l=l)

@app.route('/labeled/<course_id>/')
def labeled(course_id):
    qids, answers, questions, times, tags, cnt_left = get_labeled(course_id)
    return render_template('message.html', q_a=zip(qids, questions, answers, times), course_id=course_id, name=id2name[course_id], cnt_left=cnt_left)

@app.route('/gen_qa_pair', methods=['POST'])
def add_pre():
    # we store the annotated pair into mongo datebase
    course_id = request.form["course_id"]
    item = {k: v for k, v in request.form.items()}
    item.update({'created': datetime.now()})
    xiaomu.qa_annotation.insert(item)
    return json.dumps({'success': True})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=9005, threaded=True, debug=True)