from pyDiameter.pyDiaAVPTools import address_to_bytes
from pyDiameter.pyDiaMessage import DiaMessage

import helpers.debug_functions as df
from avp.BaseGenerator import BaseGenerator
from config.global_temp_config import *

class CCR_gx_generator(BaseGenerator):
    def __init__(self, request, msisdn, imsi, test_called_station='internet.youroperator.ru'):
        super().__init__(request, msisdn, imsi, test_called_station)
        self.generator_name = 'gx'

    def test_message(self, terminate=False, crr=False):
        msg_bytes = 'if u wanna use it, capture a real packet of your mobile operator with wireshark'
        msg = DiaMessage()
        msg.decode(bytes.fromhex(msg_bytes))

        msg.setFlags(0)
        msg.setRequestFlag()
        msg.setProxyableFlag()
        msg.generateHBHID()
        msg.generateE2EID()

        df.set_avp_value(msg, 'Session-Id', self.session_id)
        df.set_avp_value(msg, 'Origin-Host', test_origin_host_gx.encode('utf-8'))
        df.set_avp_value(msg, 'Origin-Realm', test_origin_realm_gx.encode('utf-8'))
        df.set_avp_value(msg, 'Destination-Host', test_destination_host_gx.encode('utf-8'))
        df.set_avp_value(msg, 'Destination-Realm', test_destination_realm_gx.encode('utf-8'))
        df.set_avp_value(msg, 'Called-Station-Id', self.test_called_station.encode('utf-8'))

        next_cc = self.get_next_cc()
        if next_cc == 0:
            df.set_avp_value(msg, 'CC-Request-Type', 1)
        elif not terminate:
            df.set_avp_value(msg, 'CC-Request-Type', 2)
        else:
            df.set_avp_value(msg, 'CC-Request-Type', 3)

        df.set_avp_value(msg, 'CC-Request-Number', next_cc)
        self.set_subscription_data(msg)

        return msg

    @staticmethod
    def set_charging_rule_report(msg, error_value, injector):
        df.set_avp_value(msg, 'Charging-Rule-Name', injector)
        df.set_avp_value(msg, 'Rule-Failure-Code', error_value)

    @staticmethod
    def set_3gpp_location(msg, location):
        location = bytes.fromhex(location)
        df.set_avp_value(msg, '3GPP-User-Location-Info', location)

    @staticmethod
    def set_imei(msg, imei):
        df.set_avp_value(msg, 'User-Equipment-Info-Value', imei.encode('utf-8'))

    @staticmethod
    def set_3gpp_sgsn_mcc_mnc(msg, location):
        location = bytes(location, 'utf-8')
        df.set_avp_value(msg, '3GPP-SGSN-MCC-MNC', location)

    @staticmethod
    def set_charging_an_gw_address(msg, address):
        df.set_avp_value(msg, 'AN-GW-Address', address_to_bytes(('ipv4', address)))

    @staticmethod
    def set_rat_type(msg, rat_type):
        df.set_avp_value(msg, 'RAT-Type', rat_type)

    @staticmethod
    def set_mnr(msg, mnr):
        CCR_gx_generator.set_3gpp_sgsn_mcc_mnc(msg, mnr.value['3GPP-SGSN-MCC-MNC'])
        CCR_gx_generator.set_charging_an_gw_address(msg, mnr.value['SGSN-Address'])
        CCR_gx_generator.set_3gpp_location(msg, mnr.value['3GPP-User-Location-Info'])

    @staticmethod
    def add_5g_avps_in_qos_information(msg, type_extend, value):
        if type_extend == 'Extended-APN-AMBR':
            dl = df.construct_avp('uint', 2848, value, 192, 10415)
            ul = df.construct_avp('uint', 2849, value, 192, 10415)
        elif type_extend == 'Extended-Max-Requested-BW':
            dl = df.construct_avp('uint', 554, value, 192, 10415)
            ul = df.construct_avp('uint', 555, value, 192, 10415)
        elif type_extend == 'Extended-GBR':
            dl = df.construct_avp('uint', 2850, value, 192, 10415)
            ul = df.construct_avp('uint', 2851, value, 192, 10415)
        else:
            raise AssertionError("Выберите правильный type_extend")
        qos_information = df.find_avp_by_name(msg, 'QoS-Information')

        if qos_information:
            qos_information.addAVP(dl)
            qos_information.addAVP(ul)

    @staticmethod
    def add_5g_avps_supported_features(msg):
        vendor_id = df.construct_avp('int', 266, 10415, 64)
        feature_list_id = df.construct_avp('uint', 629, 2, 128, 10415)
        feature_list = df.construct_avp('uint', 630, 128, 128, 10415)
        sf = df.construct_avp('group', 628, [vendor_id, feature_list_id, feature_list], 192, 10415)
        msg.getAVPs().append(sf)

    @staticmethod
    def add_event_trigger(msg, trigger_value):
        et = df.construct_avp('uint', 1006, trigger_value, 192, 10415)
        msg.getAVPs().append(et)


import pandas as pd
from sklearn.preprocessing import LabelEncoder

# Read the data
df = pd.read_csv("/kaggle/input/credit-score-classification-dataset/Credit Score Classification Dataset.csv")

# Simplify education categories
df["Education"] = df["Education"].replace({"High School Diploma": "Undergraduate", "Associate's Degree": "Undergraduate",
                                           "Bachelor's Degree": "Graduate", "Master's Degree": "Postgraduate",
                                           "Doctorate": "Postgraduate"})

# Encode categorical features
label_encoder = LabelEncoder()
categorical_cols = df.select_dtypes(include='object').columns
for col in categorical_cols:
    df[col] = label_encoder.fit_transform(df[col])

# Perform any additional preprocessing steps based on the findings

# Drop unnecessary columns
df.drop(['ID'], axis=1, inplace=True)

# Scale numerical features if necessary

# Split the data into features and target
X = df.drop('Credit Score', axis=1)
y = df['Credit Score']


from Models.DDPGModel import DDPGModel
from Buffers.ReplayBuffer import ReplayBuffer
from Agents.BasicAgent import BasicOffPolicyAgent

class DDPGAgent(BasicOffPolicyAgent):

    def __init__(self, action_space, gamma, tau, buffer_size, noise_std):
        self.model = DDPGModel(action_space, gamma, tau, noise_std)
        self.buffer = ReplayBuffer(buffer_size)
        self.last_actions = None

    def create_models(self, save_models_path, state_space, action_space, learning_rate, gradient_clipping, **ignored):
        self.model.create_models(state_space, action_space, learning_rate, gradient_clipping, save_models_path)

    def step(self, states):
        self.last_actions = self.model.forward(states)
        return self.last_actions

    def store_transitions(self, states, rewards, terminals, next_states):
        self.buffer.store_transitions(states, self.last_actions, rewards, terminals, next_states)

    def train(self, batch_size):
        losses = {}

        if self.buffer.is_sampling_possible(batch_size):
            states, actions, rewards, terminals, next_states, = self.buffer.get_transitions(batch_size)

            loss_actor = self.model.update_actor(states)
            loss_critic = self.model.update_critic(states, actions, rewards, terminals, next_states)
            self.model.update_actor_target()
            self.model.update_critic_target()

            losses = {'Actor Loss' : loss_actor, 'Critic Loss' : loss_critic}

        return losses


from collections import defaultdict
from dnutils import logs, ProgressBar
from .fastconj import FastConjunctionGrounding
from mln.util import dict_union
from mln.constants import HARD
from logic.elements import Logic
from utils.multicore import with_tracing, check_mem
import multiprocessing
from multiprocessing import Value

import pdb

import types
from multiprocessing.pool import Pool

# this readonly global is for multiprocessing to exploit copy-on-write
# on linux systems
global_bpll_grounding = None

logger = logs.getlogger(__name__)

# multiprocessing function

def create_formula_groundings(formula, unsatfailure=True):
    check_mem()
    results = []

    if global_bpll_grounding.mrf.mln.logic.is_literal_conj(formula):
        for res in global_bpll_grounding.iter_groundings_fast(formula):
            check_mem()
            results.append(res)
    else:
        for gf in formula.iter_groundings(global_bpll_grounding.mrf, simplify=False):
            check_mem()
            stat = []
            for ground_atom in gf.ground_atoms():
                world = list(global_bpll_grounding.mrf.evidence)
                var = global_bpll_grounding.mrf.variable(ground_atom)
                for val_index, value in var.iter_values():
                    var.setval(value, world)
                    truth = gf(world)
                    if truth != 0:
                        stat.append((var.index, val_index, truth))
                    elif unsatfailure and gf.weight == HARD and gf(global_bpll_grounding.mrf.evidence) != 1:
                        print()
                        gf.print_structure(global_bpll_grounding.mrf.evidence)
            results.append((gf.index, stat))
    return results

class BPLLGroundingFactory(FastConjunctionGrounding):
    """
    Grounding factory for efficient grounding of conjunctions for
    pseudo-likelihood learning.
    """

    def __init__(self, mrf, formulas=None, cache=None, **params):
        FastConjunctionGrounding.__init__(self, mrf, simplify=False, unsatfailure=False, formulas=formulas, cache=cache, **params)
        self._stat = {}
        self._var_index2f_index = defaultdict(set)

    def iter_groundings_fast(self, formula):
        """
        Recursively generate the groundings of a conjunction. Prunes the
        generated grounding tree in case that a formula cannot be rendered
        true by subsequent literals.
        """
        # make a copy of the formula to avoid side effects
        formula = formula.ground(self.mrf, {}, partial=True)
        children = [formula] if not hasattr(formula, 'children') else formula.children
        # make equality constraints access their variable domains
        # this is a _really_ dirty hack but it does the job ;-)
        var_doms = formula.var_doms()

        def eqvar_doms(self, v=None, c=None):
            if v is None:
                v = defaultdict(set)
            for a in self.args:
                if self.mln.logic.isvar(a):
                    v[a] = var_doms[a]
            return v

        for child in children:
            if isinstance(child, Logic.Equality):
                setattr(child, 'var_doms', types.MethodType(eqvar_doms, child))
        lits = sorted(children, key=self._conjsort)
        for gf in self._iter_groundings_fast(formula, lits, 0, assignment={}, variables=[]):
            yield gf

    def _iter_groundings_fast(self, formula, constituents, c_index, assignment, variables, false_var=None, level=0):
        if c_index == len(constituents):
            # no remaining literals to ground. return the ground formula
            # and statistics
            stat = [(var_index, val_index, count) for (var_index, val_index, count) in variables]
            yield formula.index, stat
            return
        c = constituents[c_index]
        # go through all remaining groundings of the current constituent
        for varass in c.iter_var_groundings(self.mrf, partial=assignment):
            gnd = c.ground(self.mrf, dict_union(varass, assignment))
            # check if it violates a hard constraint
            if formula.weight == HARD and gnd(self.mrf.evidence) < 1:
                raise Exception('MLN is unsatisfiable by evidence due to hard constraint violation {} (see above)'.
                                format(global_bpll_grounding.mrf.formulas[formula.index]))
            if isinstance(gnd, Logic.Equality):
                # if an equality grounding is false in a conjunction, we can
                # stop since the  conjunction cannot be rendered true in any
                # grounding that follows
                if gnd.truth(None) == 0:
                    continue
                for gf in self._iter_groundings_fast(formula, constituents, c_index + 1, dict_union(assignment, varass),
                                                     variables, false_var, level + 1):
                    yield gf
            else:
                var = self.mrf.variable(gnd.ground_atom)
                world_ = list(self.mrf.evidence)
                stat = []
                skip = False
                false_var_ = false_var
                vars_ = list(variables)
                for val_index, value in var.iter_values():
                    var.setval(value, world_)
                    truth = gnd(world_)
                    if truth == 0 and value == var.evidence_value():
                        # if the evidence value renders the current
                        # constituent false and there was already a false
                        # literal in the grounding path, we can prune the
                        # tree since no grounding will be true
                        if false_var is not None and false_var != var.index:
                            skip = True
                            break
                        else:
                            # if there was no literal false so far, we collect statistics only for the current literal
                            # and only if all future literals will be true by evidence
                            vars_ = []
                            false_var_ = var.index
                    if truth > 0 and false_var is None:
                        stat.append((var.index, val_index, truth))
                if false_var is not None and false_var == var.index:
                    # in case of non-mutual exclusive values take only the values that render all literals true
                    # example: soft-functional constraint with !foo(?x) ^ foo(?y), x={X,Y,Z} where the evidence
                    # foo(Z) is true, here the grounding !foo(X) ^ foo(Y) is false:
                    # !foo(X) is true for foo(Z) and foo(Y) and
                    # (!foo(Z) ^ !foox(X) ^ !foo(Y)), foo(Y) is true for foo(Y), both are only true for foo(Y)
                    stat = set(variables).intersection(stat)
                    skip = not bool(stat)  # skip if no values remain
                if skip:
                    continue
                for gf in self._iter_groundings_fast(formula, constituents, c_index + 1, dict_union(assignment, varass),
                                                     vars_ + stat, false_var=false_var_, level=level + 1):
                    yield gf

    def _iter_groundings(self, simplify=False, unsatfailure=False):
        global global_bpll_grounding
        global_bpll_grounding = self
        # pdb.set_trace()
        if self.multicore:
            pool = Pool(maxtasksperchild=1)
            i = 0
            try:
                for ground_result in pool.imap(with_tracing(create_formula_groundings), self.formulas):
                    if self.verbose:
                        bar = ProgressBar(color='green')
                        bar.update(float(i + 1) / float(len(self.formulas)))
                        i += 1

                    for f_index, stat in ground_result:
                        for (var_index, val_index, val) in stat:
                            self._var_index2f_index[var_index].add(f_index)
                            self._addstat(f_index, var_index, val_index, val)
                        check_mem()
                    yield None
            except Exception as e:
                logger.error('Error in child process. Terminating pool...')
                pool.close()
                raise e
            finally:
                pool.terminate()
                pool.join()
        else:
            for ground_result in map(create_formula_groundings, self.formulas):
                for f_index, stat in ground_result:
                    for (var_index, val_index, val) in stat:
                        self._var_index2f_index[var_index].add(f_index)
                        self._addstat(f_index, var_index, val_index, val)
                yield None

    def _addstat(self, f_index, var_index, val_index, inc=1):
        if f_index not in self._stat:
            self._stat[f_index] = {}
        d = self._stat[f_index]
        if var_index not in d:
            d[var_index] = [0] * self.mrf.variable(var_index).value_count()
        d[var_index][val_index] += inc


# -*- coding: utf-8 -*-
####事件处理####
##窗口关闭事件
import sys
from PySide.QtCore import Qt
from PySide.QtGui import QApplication, QWidget, QTextEdit,QPushButton,\
                        QVBoxLayout,QHBoxLayout,QMessageBox

class Demo(QWidget):
    """docstring for Demo"""
    def __init__(self):
        super(Demo, self).__init__()

        self.is_save = True
        # is_saved变量用于记录用户是否已经进行保存；

        self.textedit = QTextEdit(self)
        self.textedit.textChanged.connect(self.on_textchanged_func)
        #实例化一个QTextEdit控件用于文本编辑，将其textChanged信号和自定义的槽函数连接起来

        self.button = QPushButton(self)
        self.button.clicked.connect(self.on_clicked_func)
        #实例化一个按钮用于保存操作，将clicked信号与自定义的槽函数进行连接

        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.textedit)
        self.v_layout.addWidget(self.button)
        self.setLayout(self.v_layout)

    def on_textchanged_func(self):
        if self.textedit.toPlainText():
            self.is_save = False
        else:
            self.is_save = True

    def on_clicked_func(self):
        self.save_func(self.textedit.toPlainText())
        self.is_save = True

    def save_func(self,text):
        with open('save.txt','w')as f:
            f.write(text)

    def closeEvent(self,QcloseEvent):
        if not self.is_save:
            choice = QMessageBox.question(self,'','Do yout want to save the text?',
                                            QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel)
            if choice == QMessageBox.Yes:
                self.save_func(self.textedit.toPlainText())
                QcloseEvent.accept()
            elif choice == QMessageBox.No:
                QcloseEvent.accept()
            else:
                QcloseEvent.ignore()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())


class Tank:
    def __init__(self,name, range, speed, caliber, weight, year, country):
        self.name = name
        self.range = range
        self.speed = speed
        self.caliber = caliber
        self.weight = weight
        self.year = year
        self.country = country
    def print_info(self):
        print('name: ' + self.name + '  range: ' + self.range + '  max speed: ' + self.speed +
              '  caliber: ' + self.caliber + '  weight ' + self.weight + '  year ' +
              self.year + '  country ' + self.country)
    def return_weight(self):
            return self.weight


from os import listdir
import json, os
import numpy as np
from torch.utils.data import Dataset
from sklearn.model_selection import train_test_split

# 12: TB > RL > Tigga > P > LD
# 16: TB > RL > P > LD > Tigga
# 24: TB > P > LD > RL > Tigga
# 32: TB > LD > P > RL > Tigga

#TEAM = ['Toad Brigade', 'RL is all you need', 'Love Deluxe', 'Tigga', 'perspective']
#TEAM = ['Toad Brigade', 'RL is all you need']
#TEAM = ['Toad Brigade']
#TEAM = ['RL is all you need']
def to_label(action):
    strs = action.split(' ')
    unit_id = strs[1]
    if strs[0] == 'm':
        label = {'c': None, 'n': 0, 's': 1, 'w': 2, 'e': 3}[strs[2]]
        unit_id = strs[1]
    elif strs[0] == 'bcity':
        label = 4
        unit_id = strs[1]
    else:
        label = None
    return unit_id, label

def depleted_resources(obs):
    for u in obs['updates']:
        if u.split(' ')[0] == 'r':
            return False
    return True

def create_dataset(obses_list, map_size=24):
    obses = {}
    samples = []

    for data in obses_list:

        eps_id = data['EpisodeId']
        #if data['info']['TeamNames'][index] not in TEAM or \

        for i in range(len(data['steps'])-1):
            #if data['steps'][i][index]['status'] == 'ACTIVE':
            if True:
                actions = data['steps'][i+1]['action']
                obs = data['steps'][i]['observation']

                if not actions:
                    continue

                if depleted_resources(obs): # if no resources left, dump rest steps
                    break

                obs['player'] = 0
                obs = dict([
                    (k,v) for k,v in obs.items()
                    if k in ['step', 'updates', 'player', 'width', 'height']
                ])
                obs_id = f'{eps_id}_{i}'
                obses[obs_id] = obs

                for action in actions:
                    unit_id, label = action
                    if label is not None:
                        samples.append((obs_id, unit_id, label))

    return obses, samples

def make_input(obs, unit_id):

    width, height = obs['width'], obs['height']
    #x_shift = (24 - width) // 2
    #y_shift = (24 - height) // 2
    cities = {}

    b = np.zeros((21, width, width), dtype=np.float32)
    pos_x, pos_y = 0, 0
    count_u, count_ct = 0, 0

    for update in obs['updates']:
        strs = update.split(' ')
        input_identifier = strs[0]

        # example: 'u 0 0 u_11 2 26 0 100 0 0'
        # identifier unit_type team unit_id pos_x pos_y cooldown wood coal uranium
        if input_identifier == 'u':
            #count_u += 1
            x = int(strs[4]) #+ x_shift
            y = int(strs[5]) #+ y_shift
            wood = int(strs[7])
            coal = int(strs[8])
            uranium = int(strs[9])

            if unit_id == strs[3]:
                pos_x, pos_y = x, y
                # Position and Cargo
                b[:2, x, y] = (1, (wood + coal + uranium) / 100)
            #else:
                # Units
            team = int(strs[2])
            cooldown = float(strs[6])

            # idx 0:3 own resources
            # idx 3:6 adversary's resources
            #idx = (team - obs['player']) % 2 * 3
            idx = 2 + (team - obs['player']) % 2 * 3
            b[idx:idx + 3, x, y] = (1, cooldown / 6, (wood + coal + uranium) / 100)

        elif input_identifier == 'ct':
            # CityTiles
            #count_ct += 1
            team = int(strs[1])
            city_id = strs[2]
            x = int(strs[3]) #+ x_shift
            y = int(strs[4]) #+ y_shift
            cooldown = float(strs[5])

            if unit_id == strs[3]+strs[4]:
                pos_x, pos_y = x, y
            # idx 6:9 own citytiles
            # idx 9:12 adversary citytiles
            #idx = 6 or 8 (cooldown) + (team - obs['player']) % 2 * 3
            idx = 8 + (team - obs['player']) % 2 * 3
            b[idx:idx + 3, x, y] =  (1, cities[city_id], cooldown / 6)
            #b[idx:idx + 2, x, y] =  (1, cities[city_id])

        elif input_identifier == 'r':
            # Resources
            r_type = strs[1]
            x = int(strs[2]) #+ x_shift
            y = int(strs[3]) #+ y_shift
            amt = int(float(strs[4]))
            #b[{'wood': 12, 'coal': 13, 'uranium': 14}[r_type], x, y] = amt / 800
            b[{'wood': 14, 'coal': 15, 'uranium': 16}[r_type], x, y] = amt / 800

        elif input_identifier == 'rp':
            # Research Points
            team = int(strs[1])
            rp = int(strs[2])
            #b[15 + (team - obs['player']) % 2, :] = min(rp, 200) / 200
            b[17 + (team - obs['player']) % 2, :] = min(rp, 200) / 200

        elif input_identifier == 'c':
            # Cities
            city_id = strs[2]
            fuel = float(strs[3])
            lightupkeep = float(strs[4])
            cities[city_id] = min(fuel / lightupkeep, 10) / 10

        #elif input_identifier == 'ccd':
            # Road
        #    x =
    # #unity, #citytile
    #b[17, :] = count_u / 100
    #b[18, :] = count_ct / 100

    # Day/Night Cycle
    b[19, :] = obs['step'] % 40 / 40
    # Turns
    b[20, :] = obs['step'] / 360

    # Map Size
    #b[19, x_shift:32 - x_shift, y_shift:32 - y_shift] = 1

    #distance_mask = np.zeros((32,32))
    #for i in range(len(distance_mask)):
    #    for j in range(len(distance_mask)):
    #        distance_mask[i, j] = 1 - ((i - pos_y)**2 + (j - pos_x)**2) / 2048
    #map_mask = np.zeros((32,32))
    #map_mask[x_shift:32 - x_shift, y_shift:32 - y_shift] = 1
    #b[22, :] = distance_mask
    #b[21, :] = map_mask

    return b

class LuxDataset(Dataset):
    def __init__(self, states, actions):
        self.states = states
        self.actions = actions

    def __len__(self):
        return len(self.states)

    def __getitem__(self, idx):
        return states[idx], actions[idx]


"""Base model framework."""
import math
import random
import pickle
import argparse
import datetime
from datetime import timedelta
from timeit import default_timer as timer
import numpy as np
from mindspore import context, save_checkpoint, load_checkpoint, load_param_into_net
import mindspore.nn as nn

from utils.mindspore_helper import GradWrap
from utils.logger import Logger
from utils.data import LabeledDocuments
from utils.evaluation import compute_retrieval_precision
from utils.mindspore_helper import gen_checkpoints_list

context.set_context(mode=context.PYNATIVE_MODE, device_target="CPU")

class BaseModel(nn.Cell):
    """Base model"""
    def __init__(self, hparams):
        super().__init__()
        self.hparams = hparams
        self.load_data()

    def load_data(self):
        self.data = LabeledDocuments(self.hparams.data_path, self.hparams.num_neighbors)

    def run_training_sessions(self):
        """run outer training session"""
        logger = Logger(self.hparams.model_path + '.log', on=True)
        val_perfs = []
        best_val_perf = float('-inf')
        start = timer()
        random.seed(self.hparams.seed)  # For reproducible random runs

        for run_num in range(1, self.hparams.num_runs + 1):
            state_dict, val_perf = self.run_training_session(run_num, logger)
            val_perfs.append(val_perf)

            if val_perf > best_val_perf:
                best_val_perf = val_perf
                logger.log('----New best {:8.2f}, saving'.format(val_perf))
                save_checkpoint(gen_checkpoints_list(state_dict), self.hparams.model_path+'.ckpt')
                pickle.dump(self.hparams, open(self.hparams.model_path+'.hpar', 'wb'))

        logger.log('Time: %s' % str(timedelta(seconds=round(timer() - start))))
        self.load()
        if self.hparams.num_runs > 1:
            logger.log_perfs(val_perfs)
            logger.log('best hparams: ' + self.flag_hparams())

        val_perf, test_perf = self.run_test()
        logger.log('Val:  {:8.2f}'.format(val_perf))
        logger.log('Test: {:8.2f}'.format(test_perf))

    def run_training_session(self, run_num, logger):
        """run inner training session"""
        if self.hparams.num_runs > 1:
            logger.log('RANDOM RUN: %d/%d' % (run_num, self.hparams.num_runs))
            for hparam, values in self.get_hparams_grid().items():
                assert hasattr(self.hparams, hparam)
                self.hparams.__dict__[hparam] = random.choice(values)

        np.random.seed(self.hparams.seed)
        random.seed(self.hparams.seed)

        train_loader, database_loader, val_loader, _ = self.data.get_loaders(
            self.hparams.num_trees, self.hparams.alpha, self.hparams.batch_size, self.hparams.num_workers,
            shuffle_train=True, get_test=False)
        self.define_parameters(self.data.num_nodes, self.data.num_edges)
        opt = nn.Adam(params=self.trainable_params(), learning_rate=self.hparams.lr)
        train_network = GradWrap(self)
        train_network.set_train()
        best_val_perf = float('-inf')
        loss_sum = 0
        num_steps = 0
        bad_epochs = 0

        times = []
        try:
            for epoch in range(1, self.hparams.epochs + 1):
                starttime = datetime.datetime.now()
                for _, batch in enumerate(train_loader):
                    x, label, edge1, edge2, weight = batch[0], batch[1], batch[2], batch[3], batch[4]
                    grads = train_network(x, label, edge1, edge2, weight)
                    opt(grads)

                    loss = self.construct(x, edge1, edge2, weight)
                    loss_sum += loss.asnumpy()
                    num_steps += 1

                endtime = datetime.datetime.now()
                times.append(endtime - starttime)

                if math.isnan(loss_sum):
                    logger.log('Stopping epoch because loss is NaN')
                    break

                val_perf = self.evaluate(database_loader, val_loader)
                logger.log('End of epoch {:3d}'.format(epoch), False)
                logger.log(' Loss: {:8.2f} | val perf {:8.2f}'.format(loss_sum / num_steps, val_perf), False)

                if val_perf > best_val_perf:
                    best_val_perf = val_perf
                    bad_epochs = 0
                    logger.log('\t\t*Best model so far, deep copying*')
                    state_dict = self.parameters_and_names()
                else:
                    bad_epochs += 1
                    logger.log('\t\tBad epoch %d' % bad_epochs)

                if bad_epochs > self.hparams.num_bad_epochs:
                    break
        except KeyboardInterrupt:
            logger.log('-' * 89)
            logger.log('Exiting from training early')

        logger.log("time per training epoch: " + str(np.mean(times)))
        return state_dict, best_val_perf

    def evaluate(self, database_loader, eval_loader):
        perf = compute_retrieval_precision(database_loader, eval_loader, self.encode_discrete,\
            self.hparams.distance_metric, self.hparams.num_retrieve, self.hparams.num_features)
        return perf

    def load(self):
        checkpoint = load_checkpoint(self.hparams.model_path+'.ckpt')
        hparams = pickle.load(open(self.hparams.model_path+'.hpar', 'rb'))
        self.hparams = hparams
        self.define_parameters(self.data.num_nodes, self.data.num_edges)
        load_param_into_net(self, checkpoint, strict_load=True)

    def run_test(self):
        _, database_loader, val_loader, test_loader = self.data.get_loaders(
            self.hparams.num_trees, self.hparams.alpha, self.hparams.batch_size, self.hparams.num_workers,
            shuffle_train=False, get_test=True)
        val_perf = self.evaluate(database_loader, val_loader)
        test_perf = self.evaluate(database_loader, test_loader)
        return val_perf, test_perf

    def flag_hparams(self):
        """flag hyperparameters"""
        flags = '%s %s' % (self.hparams.model_path, self.hparams.data_path)
        for hparam in vars(self.hparams):
            val = getattr(self.hparams, hparam)
            if str(val) == 'False':
                continue
            elif str(val) == 'True':
                flags += ' --%s' % (hparam)
            elif str(hparam) in {'model_path', 'data_path', 'num_runs',
                                 'num_workers'}:
                continue
            else:
                flags += ' --%s %s' % (hparam, val)
        return flags

    @staticmethod
    def get_general_argparser():
        """command parser"""
        parser = argparse.ArgumentParser()

        parser.add_argument('model_path', type=str)
        parser.add_argument('data_path', type=str)
        parser.add_argument('--train', action='store_true',
                            help='train a model?')

        parser.add_argument('--num_features', type=int, default=64,
                            help='num discrete features [%(default)d]')
        parser.add_argument('--dim_hidden', type=int, default=500,
                            help='dimension of hidden state [%(default)d]')
        parser.add_argument('--num_layers', type=int, default=0,
                            help='num layers [%(default)d]')
        parser.add_argument('--num_neighbors', type=int, default=10,
                            help='num neighbors [%(default)d]')

        parser.add_argument('--batch_size', type=int, default=128,
                            help='batch size [%(default)d]')
        parser.add_argument('--lr', type=float, default=0.001,
                            help='initial learning rate [%(default)g]')
        parser.add_argument('--init', type=float, default=0.05,
                            help='unif init range (default if 0) [%(default)g]')
        parser.add_argument('--clip', type=float, default=10,
                            help='gradient clipping [%(default)g]')
        parser.add_argument('--epochs', type=int, default=100,
                            help='max number of epochs [%(default)d]')
        parser.add_argument('--num_runs', type=int, default=1,
                            help='num random runs (not random if 1) '
                            '[%(default)d]')

        parser.add_argument('--num_retrieve', type=int, default=100,
                            help='num neighbors to retrieve [%(default)d]')
        parser.add_argument('--num_bad_epochs', type=int, default=6,
                            help='num indulged bad epochs [%(default)d]')
        parser.add_argument('--num_workers', type=int, default=0,
                            help='num dataloader workers [%(default)d]')
        parser.add_argument('--distance_metric', default='hamming',
                            choices=['hamming', 'cosine'])
        parser.add_argument('--no_tfidf', action='store_true',
                            help='raw bag-of-words as input instead of tf-idf?')
        parser.add_argument('--seed', type=int, default=50971,
                            help='random seed [%(default)d]')
        parser.add_argument('--cuda', action='store_true',
                            help='use CUDA?')

        return parser


# -*- coding: utf-8 -*-
"""some functions for plots."""

import numpy as np
import matplotlib.pyplot as plt
import pickle

def plot_weight_distribution(weights):
	ax = plt.figure().gca()
	weights.hist(ax=ax, bins=30, log=True)
	ax.set_title('Weigths Distribution')
	ax.set_xlabel('weigth')

def plot_statistics_on_user(users, drop=False):
	if drop:
		users_to_drop = set()

	_, [ax1,ax2,ax3] = plt.subplots(3,1, figsize=(20,10))

	# Plot max
	data = users.max()
	data.hist(ax=ax1, column='weight', bins=30, log=True)
	ax1.set_title('Max weigth distribution over users')
	ax1.set_xlabel('weigth');
	if drop:
		# Select users to drop based on the plotted histogram
		users_to_drop.update(data[data.weight > 200000].index)

	# Plot mean
	data = users.mean()
	data.hist(ax=ax2, column='weight', bins=30, log=True)
	ax2.set_title('Mean Weigth distribution over users')
	ax2.set_xlabel('weigth')
	if drop:
		# Select users to drop based on the plotted histogram
		users_to_drop.update(data[data.weight > 15000].index)

	# Plot number of different artists users listened to
	data = users.nunique().artistID
	data.hist(ax=ax3, bins=30, log=True);
	ax3.set_title('Different artists distribution over users')
	ax3.set_xlabel('Number of different artists')
	if drop:
		# Select users to drop based on the plotted histogram
		users_to_drop.update(data[data<10].index)

	if drop:
		print(len(users_to_drop), ' users to drop')
		return users_to_drop

def user_weight_distribution(normalized, seed=1):
	np.random.seed(seed)
	user = np.random.choice(normalized.userID)
	y = normalized[normalized.userID == user].weight
	plt.bar(np.arange(len(y)), y);
	plt.title('Distribution of weights for a random user');
	plt.xlabel('user');
	plt.ylabel('weight');

def degree_distribution(degree):
	degree_dict = dict(degree)
	data = list(degree_dict.values())

	plt.figure(figsize=(20,10))
	plt.hist(data,bins=120)

	plt.xticks(range(0, 120, 2))
	plt.title('Users\' degree distribution');
	plt.xlabel('degree');
	plt.ylabel('# users')
	plt.show()

def plot_tags_statistics(group):
	_, [ax1,ax2] = plt.subplots(1,2, figsize=(20,10))

	group.plot(use_index=False, ax=ax1, title='Tag distribution');
	ax1.set_xlabel('artistID')
	ax1.set_xlabel('# tags')

	# Tags distribution
	group.hist(ax=ax2, bins=50, log=True);
	ax2.set_xlabel('# tags');
	ax2.set_title('Tags Distribution');

def plot_separate_small_artist(small, big):
	_, [ax1,ax2] = plt.subplots(1, 2, figsize=(20,10));

	small.hist(ax=ax1, bins=30);
	ax1.set_xlabel('# tags');
	ax1.set_title('Histogram of artists with low tag frequency');

	big.hist(ax=ax2, bins=30, xlabelsize=8);
	ax2.set_xticks(np.round(np.linspace(min(big),max(big),10)))
	ax2.set_xlabel('# tags');
	ax2.set_title('Histogram of artists with high tag frequency');

def plot_unique_tags(group):
	group.plot(use_index=False);
	plt.title('Unique tags');
	plt.xlabel('artist ID');
	plt.ylabel('# tags')

def plot_listenig_count_frequency(max_user_weight):

	plt.figure(num=None, figsize=(12, 6), dpi=80, facecolor='w', edgecolor='k')
	max_user_weight['weight'].plot.hist(bins=30)
	plt.xlabel('Listening count');
def plot_artist_per_user(number_user_artist):

	plt.figure(num=None, figsize=(12, 6), dpi=80, facecolor='w', edgecolor='k')
	number_user_artist['artistID'].plot.hist(bins=10)

def plot_rmse():
    fp = open('./data/RMSE_plots.pickle', 'rb')
    art_net, friend_net, no_net = pickle.load(fp)
    fp.close()

    _, ax = plt.subplots(1,3, figsize=(16,8))
    ax[0].semilogx(*art_net)
    ax[0].set_title('artist smooth')
    ax[0].set_xlabel('alpha')
    ax[0].set_ylabel('RMSE')
    ax[0].grid()
    ax[1].semilogx(*friend_net)
    ax[1].set_title('user smooth')
    ax[1].set_xlabel('alpha')
    ax[1].set_ylabel('RMSE')
    ax[1].grid()
    ax[2].semilogx(*no_net)
    ax[2].set_title('no smooth')
    ax[2].set_xlabel('alpha')
    ax[2].set_ylabel('RMSE')
    ax[2].grid()

    print('RMSE on smooth MF over artists: ', 0.9067)
    print('RMSE on smooth MF over users: ', 0.9074)
    print('RMSE on classic SVD: ', 0.9068)
    print('RMSE on global mean estimator: ', 1.0721)


# -*- coding: utf-8 -*-
# @Time   : 2021/5/14 01:51
# @Author : beyoung
# @Email  : linbeyoung@stu.pku.edu.cn
# @File   : word_count.py

from collections import Counter

input_path = 'multi_lines.txt'
with open(input_path, 'r') as f:
    lines = f.readlines()

new_lines = []

for line in lines:
    line = line.replace('/disks/sdd/beyoung/Fakepages/chinese_fonts/', '').replace('\n', '').replace(' ', '')
    new_lines.append(line)

dict2 = Counter(new_lines)
sorted_x = sorted(dict2.items(), key=lambda x: x[1], reverse=True)
# print(sorted_x)

for i in sorted_x:
    print(i)
# for key, value in dict2.items():
#     print('{key}:{value}'.format(key=key, value=value))
'''

b=set(new_lines)
c=[]
for i in b:
    c.append([i,new_lines.count(i)])
c.sort(key = lambda x:(x[1], x[0]),reverse = True)
print(c)
'''

'''
#  字典统计
dict = {}
for key in new_lines:
    dict[key] = dict.get(key, 0) + 1
print(dict)
'''


import asyncio
import json
import websockets
import database_setup
from google.protobuf.json_format import ParseDict
import api_methods
from MarketDataFeed_pb2 import FeedResponse  # Import the generated protobuf classes
import multiprocessing
import time
import argparse
import sys

def subscribe_to_stock(subscribed_stock):

    async def main():

        print('Market Opened starting sync operation')
        websocket_url = api_methods.get_config().get('INDEX', 'websocket_url')
        ACCESS_TOKEN = api_methods.get_access_token()
        timeout_seconds = 60

        async with websockets.connect(websocket_url, ping_interval=timeout_seconds, extra_headers={
            "Api-Version": "2.0",
            "Authorization": "Bearer " + ACCESS_TOKEN,
        }) as ws:
            print("connected")

            await asyncio.sleep(1)  # Sleep for 1 second

            data = {
                "guid": "someguid",
                "method": "sub",
                "data": {
                    "mode": "full",
                    "instrumentKeys": [subscribed_stock]
                }
            }
            await ws.send(json.dumps(data).encode())

            async for message in ws:
                feed_response = FeedResponse()
                feed_response.ParseFromString(message)
                if subscribed_stock.startswith('NSE_INDEX'):
                    current_price = feed_response.feeds[subscribed_stock].ff.indexFF.ltpc.ltp
                    current_year, current_month, current_day, current_hour, current_minute, current_second,current_millisecond = database_setup.get_current_time_asia_kolkata()

                elif subscribed_stock.startswith('NSE_FO'):
                    current_price = feed_response.feeds[subscribed_stock].ff.marketFF.ltpc.ltp
                    current_year, current_month, current_day, current_hour, current_minute, current_second,current_millisecond = database_setup.get_current_time_asia_kolkata()

                data_dict = {
                    'symbol': subscribed_stock,
                    'year': current_year,
                    'month': current_month,
                    'day': current_day,
                    'hour': current_hour,
                    'minute': current_minute,
                    'second': current_second,
                    'millisecond': current_millisecond,
                    'price': current_price
                }
                # print(data_dict)
                database_setup.insert_into_table(subscribed_stock.replace('|','').replace(' ', ''), data_dict)

            print("disconnected")

    if __name__ == "__main__":
        loop = asyncio.get_event_loop()
        loop.run_until_complete(main())

def start_sync(stock):
    print(f'Websocket Sync for {stock} waiting for market to open...')

    while True:
        while not database_setup.market_opened():
            time.sleep(1)

        print(f'Websocket Sync for {stock} started')
        p = multiprocessing.Process(target=subscribe_to_stock, args=(stock,))
        p.start()

        while database_setup.market_opened():
            time.sleep(1)

        print(f'Websocket Sync for {stock} stopping...')
        p.terminate()
        p.join()

if __name__ == "__main__":

    parser = argparse.ArgumentParser(description="WebSocket synchronization for stock symbols")
    parser.add_argument("symbols", nargs='+', help="List of stock symbols to sync (up to 3)")

    args = parser.parse_args()

    if len(args.symbols) > 3:
        print("Error: You can specify up to 3 stock symbols.")
        parser.print_help()
        sys.exit(1)

    SUBSCRIBED_STOCKS = args.symbols
    # How to use
    # SUBSCRIBED_STOCKS = ['NSE_INDEX|Nifty 50', 'NSE_INDEX|Nifty Bank', 'NSE_INDEX|Nifty Fin Service']
    # python market_socket.py 'NSE_INDEX|Nifty 50' 'NSE_INDEX|Nifty Bank' 'NSE_INDEX|Nifty Fin Service'
    # SUBSCRIBED_STOCKS = ['NSE_FO|54643', 'NSE_FO|54644']

    processes = []
    for stock in SUBSCRIBED_STOCKS:
        process = multiprocessing.Process(target=start_sync, args=(stock,))
        process.start()
        processes.append(process)

    for process in processes:
        process.join()


# Python
from icalendar import Calendar, Event

# Django
from django.shortcuts import get_object_or_404, render_to_response
from django.http import HttpResponse, HttpResponseForbidden, HttpResponseRedirect
from django.template.context import RequestContext
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.core.cache import cache
from django.template import loader
from django.utils.translation import ugettext_lazy as _

# A+
from course.models import Course, CourseInstance
from course.context import CourseContext
from course.results import ResultTable
from course.forms import CourseModuleForm
from exercise.exercise_summary import CourseSummary
from exercise.submission_models import Submission
from exercise.exercise_models import CourseModule

def _get_course_instance(course_url, instance_url):
    '''
    Returns a CourseInstance or raises an HttpResponse with code 404 (not found) based on the
    given course URL and instance URL.

    @param course_url: the URL attribute of a course
    @param instance_url: the URL attribute of an instance belonging to the course
    @return: a CourseInstance model matching the attributes
    '''
    return get_object_or_404(CourseInstance, url=instance_url, course__url=course_url)

def course_archive(request):
    """
    Displays a course archive of all courses in the system.
    """

    context = CourseContext(request)
    return render_to_response("course/archive.html", context)

@login_required
def view_course(request, course_url):
    """
    Displays a page for the given course. The page consists of a list of
    course instances for the course.

    @param request: the Django HttpRequest object
    @param course_url: the url value of a Course object
    """

    course  = get_object_or_404(Course, url=course_url)
    context = CourseContext(request, course=course)
    return render_to_response("course/view.html", context)

@login_required
def view_instance(request, course_url, instance_url):
    """ Renders a dashboard page for a course instance. A dashboard has a list
        of exercise rounds and exercises and plugins that may have been
        installed on the course. Students also see a summary of their progress
        on the course dashboard.

        @param request: the Django HttpRequest object
        @param course_url: the url value of a Course object
        @param instance_url: the url value of a CourseInstance object """

    course_instance = _get_course_instance(course_url, instance_url)
    course_summary  = CourseSummary(course_instance, request.user)
    course_instance.plugins.all()

    return render_to_response("course/view_instance.html",
                              CourseContext(request,
                                            course_instance=course_instance,
                                            course_summary=course_summary
                                            ))

@login_required
def view_my_page(request, course_url, instance_url):
    """
    Renders a personalized page for a student on the course. The page is intended to show
    how well the student is doing on the course and shortcuts to the latest submissions.

    @param request: the Django HttpRequest object
    @param course_url: the url value of a Course object
    @param instance_url: the url value of a CourseInstance object
    """

    course_instance = _get_course_instance(course_url, instance_url)
    course_summary  = CourseSummary(course_instance, request.user)
    submissions     = request.user.get_profile().submissions.filter(exercise__course_module__course_instance=course_instance).order_by("-id")

    return render_to_response("course/view_my_page.html",
                              CourseContext(request,
                                            course_instance=course_instance,
                                            course_summary=course_summary,
                                            submissions=submissions
                                            ))

def view_instance_calendar(request, course_url, instance_url):
    """
    Renders a iCalendar feed for a CourseInstance. Unlike most other views in this module, this
    view does not require the user to be logged in.

    @param request: the Django HttpRequest object
    @param course_url: the url value of a Course object
    @param instance_url: the url value of a CourseInstance object
    """

    course_instance = _get_course_instance(course_url, instance_url)

    cal = Calendar()

    cal.add('prodid', '-// A+ calendar //')
    cal.add('version', '2.0')

    for course_module in course_instance.course_modules.all():
        event = Event()
        event.add('summary', course_module.name)

        # FIXME: Currently all times added are the closing time.
        # The event will need to be longer than 0 seconds in order
        # to be displayed clearly on calendar applications.
        event.add('dtstart', course_module.closing_time)
        event.add('dtend', course_module.closing_time)
        event.add('dtstamp', course_module.closing_time)

        event['uid'] = "module/" + str(course_module.id) + "/A+"

        cal.add_component(event)

    response = HttpResponse(cal.as_string(), content_type="text/calendar; charset=utf-8")
    return response

@login_required
def view_instance_results(request, course_url, instance_url):
    """
    Renders a results page for a course instance. The results contain individual
    scores for each student on each exercise.

    @param request: the Django HttpRequest object
    @param course_url: the url value of a Course object
    @param instance_url: the url value of a CourseInstance object
    """

    course_instance = _get_course_instance(course_url, instance_url)
    table           = ResultTable(course_instance)

    table_html = loader.render_to_string("course/_results_table.html", {"result_table": table})

    return render_to_response("course/view_results.html",
                              CourseContext(request, course_instance=course_instance,
                                                     result_table=table,
                                                     table_html=table_html
                                             ))

@login_required
def teachers_view(request, course_url, instance_url):
    """
    This is the special page for teachers of the course instance.

    @param request: the Django HttpRequest object
    @param course_url: the url value of a Course object
    @param instance_url: the url value of a CourseInstance object
    """
    course_instance = _get_course_instance(course_url, instance_url)
    has_permission  = course_instance.is_teacher(request.user.get_profile())

    if not has_permission:
        return HttpResponseForbidden("You are not allowed to access this view.")

    return render_to_response("course/teachers_view.html",
                              CourseContext(request, course_instance=course_instance)
                              )

@login_required
def assistants_view(request, course_url, instance_url):
    """
    This is the special page for the assistants on the given course instance.

    @param request: the Django HttpRequest object
    @param course_url: the url value of a Course object
    @param instance_url: the url value of a CourseInstance object
    """
    course_instance = _get_course_instance(course_url, instance_url)

    has_permission  = course_instance.is_staff(request.user.get_profile())
    if not has_permission:
        return HttpResponseForbidden(_("You are not allowed to access this view."))

    return render_to_response("course/assistants_view.html",
                              CourseContext(request, course_instance=course_instance)
                              )

@login_required
def add_or_edit_module(request, course_url, instance_url, module_id=None):
    """
    This page can be used by teachers to add new modules and edit existing ones.

    @param request: the Django HttpRequest object
    @param course_url: the url value of a Course object
    @param instance_url: the url value of a CourseInstance object
    @param module_id: The id of the module to edit. If not given, a new module is created.
    """
    course_instance = _get_course_instance(course_url, instance_url)
    has_permission  = course_instance.is_teacher(request.user.get_profile())

    if not has_permission:
        return HttpResponseForbidden("You are not allowed to access this view.")

    if module_id != None:
        module = get_object_or_404(CourseModule, id=module_id, course_instance=course_instance)
    else:
        module = CourseModule(course_instance=course_instance)

    if request.method == "POST":
        form = CourseModuleForm(request.POST, instance=module)
        if form.is_valid():
            module = form.save()
            messages.success(request, _('The course module was saved successfully.'))
            next_url = "/course/%s/%s/teachers/" % (course_instance.course.url, course_instance.url)
            return HttpResponseRedirect(next_url)
    else:
        form = CourseModuleForm(instance=module)

    return render_to_response("course/edit_module.html",
                              CourseContext(request, course_instance=course_instance,
                                                     module=module,
                                                     form=form
                                             ))