import os
import random
import socket
import struct
import time
import traceback

from itertools import count
from nfvbench.log import LOG
from nfvbench.traffic_server import TRexTrafficServer
from nfvbench.utils import cast_integer
from nfvbench.utils import timeout
from nfvbench.utils import TimeoutError
from traffic_base import AbstractTrafficGenerator
from traffic_base import TrafficGeneratorException
import traffic_utils as utils
from traffic_utils import IMIX_AVG_L2_FRAME_SIZE
from traffic_utils import IMIX_L2_SIZES
from traffic_utils import IMIX_RATIOS

# pylint: disable=import-error
from trex_stl_lib.api import CTRexVmInsFixHwCs
from trex_stl_lib.api import Dot1Q
from trex_stl_lib.api import Ether
from trex_stl_lib.api import IP
from trex_stl_lib.api import IPv6
from trex_stl_lib.api import STLClient
from trex_stl_lib.api import STLError
from trex_stl_lib.api import STLFlowLatencyStats
from trex_stl_lib.api import STLFlowStats
from trex_stl_lib.api import STLPktBuilder
from trex_stl_lib.api import STLScVmRaw
from trex_stl_lib.api import STLStream
from trex_stl_lib.api import STLTXCont
from trex_stl_lib.api import STLVmFixChecksumHw
from trex_stl_lib.api import STLVmFlowVar
from trex_stl_lib.api import STLVmFlowVarRepetableRandom
from trex_stl_lib.api import STLVmWrFlowVar
from trex_stl_lib.api import UDP
from trex_stl_lib.services.trex_stl_service_arp import STLServiceARP

# pylint: enable=import-error

class TRex(AbstractTrafficGenerator):
    """TRex traffic generator driver."""

    LATENCY_PPS = 1000
    CHAIN_PG_ID_MASK = 0x007F
    PORT_PG_ID_MASK = 0x0080
    LATENCY_PG_ID_MASK = 0x0100

    def __init__(self, traffic_client):
        """Trex driver."""
        AbstractTrafficGenerator.__init__(self, traffic_client)
        self.client = None
        self.id = count()
        self.port_handle = []
        self.chain_count = self.generator_config.service_chain_count
        self.rates = []
        self.capture_id = None
        self.packet_list = []

    def get_version(self):
        """Get the Trex version."""
        return self.client.get_server_version() if self.client else ''

    def get_pg_id(self, port, chain_id):
        """Calculate the packet group IDs to use for a given port/stream type/chain_id.

        port: 0 or 1
        chain_id: identifies to which chain the pg_id is associated (0 to 255)
        return: pg_id, lat_pg_id

        We use a bit mask to set up the 3 fields:
        0x007F: chain ID (8 bits for a max of 128 chains)
        0x0080: port bit
        0x0100: latency bit
        """
        pg_id = port * TRex.PORT_PG_ID_MASK | chain_id
        return pg_id, pg_id | TRex.LATENCY_PG_ID_MASK

    def extract_stats(self, in_stats):
        """Extract stats from dict returned by Trex API.

        :param in_stats: dict as returned by TRex api
        """
        utils.nan_replace(in_stats)
        # LOG.debug(in_stats)

        result = {}
        # port_handles should have only 2 elements: [0, 1]
        # so (1 - ph) will be the index for the far end port
        for ph in self.port_handle:
            stats = in_stats[ph]
            far_end_stats = in_stats[1 - ph]
            result[ph] = {
                'tx': {
                    'total_pkts': cast_integer(stats['opackets']),
                    'total_pkt_bytes': cast_integer(stats['obytes']),
                    'pkt_rate': cast_integer(stats['tx_pps']),
                    'pkt_bit_rate': cast_integer(stats['tx_bps'])
                },
                'rx': {
                    'total_pkts': cast_integer(stats['ipackets']),
                    'total_pkt_bytes': cast_integer(stats['ibytes']),
                    'pkt_rate': cast_integer(stats['rx_pps']),
                    'pkt_bit_rate': cast_integer(stats['rx_bps']),
                    # how many pkts were dropped in RX direction
                    # need to take the tx counter on the far end port
                    'dropped_pkts': cast_integer(
                        far_end_stats['opackets'] - stats['ipackets'])
                }
            }
            self.__combine_latencies(in_stats, result[ph]['rx'], ph)

        total_tx_pkts = result[0]['tx']['total_pkts'] + result[1]['tx']['total_pkts']
        result["total_tx_rate"] = cast_integer(total_tx_pkts / self.config.duration_sec)
        result["flow_stats"] = in_stats["flow_stats"]
        result["latency"] = in_stats["latency"]
        return result

    def get_stream_stats(self, trex_stats, if_stats, latencies, chain_idx):
        """Extract the aggregated stats for a given chain.

        trex_stats: stats as returned by get_stats()
        if_stats: a list of 2 interface stats to update (port 0 and 1)
        latencies: a list of 2 Latency instances to update for this chain (port 0 and 1)
                   latencies[p] is the latency for packets sent on port p
                   if there are no latency streams, the Latency instances are not modified
        chain_idx: chain index of the interface stats

        The packet counts include normal and latency streams.

        Trex returns flows stats as follows:

        'flow_stats': {0: {'rx_bps': {0: 0, 1: 0, 'total': 0},
                   'rx_bps_l1': {0: 0.0, 1: 0.0, 'total': 0.0},
                   'rx_bytes': {0: nan, 1: nan, 'total': nan},
                   'rx_pkts': {0: 0, 1: 15001, 'total': 15001},
                   'rx_pps': {0: 0, 1: 0, 'total': 0},
                   'tx_bps': {0: 0, 1: 0, 'total': 0},
                   'tx_bps_l1': {0: 0.0, 1: 0.0, 'total': 0.0},
                   'tx_bytes': {0: 1020068, 1: 0, 'total': 1020068},
                   'tx_pkts': {0: 15001, 1: 0, 'total': 15001},
                   'tx_pps': {0: 0, 1: 0, 'total': 0}},
               1: {'rx_bps': {0: 0, 1: 0, 'total': 0},
                   'rx_bps_l1': {0: 0.0, 1: 0.0, 'total': 0.0},
                   'rx_bytes': {0: nan, 1: nan, 'total': nan},
                   'rx_pkts': {0: 0, 1: 15001, 'total': 15001},
                   'rx_pps': {0: 0, 1: 0, 'total': 0},
                   'tx_bps': {0: 0, 1: 0, 'total': 0},
                   'tx_bps_l1': {0: 0.0, 1: 0.0, 'total': 0.0},
                   'tx_bytes': {0: 1020068, 1: 0, 'total': 1020068},
                   'tx_pkts': {0: 15001, 1: 0, 'total': 15001},
                   'tx_pps': {0: 0, 1: 0, 'total': 0}},
                128: {'rx_bps': {0: 0, 1: 0, 'total': 0},
                'rx_bps_l1': {0: 0.0, 1: 0.0, 'total': 0.0},
                'rx_bytes': {0: nan, 1: nan, 'total': nan},
                'rx_pkts': {0: 15001, 1: 0, 'total': 15001},
                'rx_pps': {0: 0, 1: 0, 'total': 0},
                'tx_bps': {0: 0, 1: 0, 'total': 0},
                'tx_bps_l1': {0: 0.0, 1: 0.0, 'total': 0.0},
                'tx_bytes': {0: 0, 1: 1020068, 'total': 1020068},
                'tx_pkts': {0: 0, 1: 15001, 'total': 15001},
                'tx_pps': {0: 0, 1: 0, 'total': 0}},etc...

        the pg_id (0, 1, 128,...) is the key of the dict and is obtained using the
        get_pg_id() method.
        packet counters for a given stream sent on port p are reported as:
        - tx_pkts[p] on port p
        - rx_pkts[1-p] on the far end port

        This is a tricky/critical counter transposition operation because
        the results are grouped by port (not by stream):
        tx_pkts_port(p=0) comes from pg_id(port=0, chain_idx)['tx_pkts'][0]
        rx_pkts_port(p=0) comes from pg_id(port=1, chain_idx)['rx_pkts'][0]
        tx_pkts_port(p=1) comes from pg_id(port=1, chain_idx)['tx_pkts'][1]
        rx_pkts_port(p=1) comes from pg_id(port=0, chain_idx)['rx_pkts'][1]

        or using a more generic formula:
        tx_pkts_port(p) comes from pg_id(port=p, chain_idx)['tx_pkts'][p]
        rx_pkts_port(p) comes from pg_id(port=1-p, chain_idx)['rx_pkts'][p]

        the second formula is equivalent to
        rx_pkts_port(1-p) comes from pg_id(port=p, chain_idx)['rx_pkts'][1-p]

        If there are latency streams, those same counters need to be added in the same way
        """
        def get_latency(lval):
            try:
                return int(round(lval))
            except ValueError:
                return 0

        for ifs in if_stats:
            ifs.tx = ifs.rx = 0
        for port in range(2):
            pg_id, lat_pg_id = self.get_pg_id(port, chain_idx)
            for pid in [pg_id, lat_pg_id]:
                try:
                    pg_stats = trex_stats['flow_stats'][pid]
                    if_stats[port].tx += pg_stats['tx_pkts'][port]
                    if_stats[1 - port].rx += pg_stats['rx_pkts'][1 - port]
                except KeyError:
                    pass
            try:
                lat = trex_stats['latency'][lat_pg_id]['latency']
                # dropped_pkts += lat['err_cntrs']['dropped']
                latencies[port].max_usec = get_latency(lat['total_max'])
                latencies[port].min_usec = get_latency(lat['total_min'])
                latencies[port].avg_usec = get_latency(lat['average'])
            except KeyError:
                pass

    def __combine_latencies(self, in_stats, results, port_handle):
        """Traverse TRex result dictionary and combines chosen latency stats."""
        total_max = 0
        average = 0
        total_min = float("inf")
        for chain_id in range(self.chain_count):
            try:
                _, lat_pg_id = self.get_pg_id(port_handle, chain_id)
                lat = in_stats['latency'][lat_pg_id]['latency']
                # dropped_pkts += lat['err_cntrs']['dropped']
                total_max = max(lat['total_max'], total_max)
                total_min = min(lat['total_min'], total_min)
                average += lat['average']
            except KeyError:
                pass
        if total_min == float("inf"):
            total_min = 0
        results['min_delay_usec'] = total_min
        results['max_delay_usec'] = total_max
        results['avg_delay_usec'] = int(average / self.chain_count)

    def get_start_end_ipv6(self, start_ip, end_ip):
        ip1 = socket.inet_pton(socket.AF_INET6, start_ip)
        ip2 = socket.inet_pton(socket.AF_INET6, end_ip)
        hi1, lo1 = struct.unpack('!QQ', ip1)
        hi2, lo2 = struct.unpack('!QQ', ip2)
        max_p1 = abs(int(lo1) - int(lo2))
        base_p1 = lo1
        return base_p1, max_p1 + base_p1

    def _create_pkt(self, stream_cfg, l2frame_size):
        """Create a packet of given size.

        l2frame_size: size of the L2 frame in bytes (including the 32-bit FCS)
        """
        # Trex will add the FCS field, so we need to remove 4 bytes from the l2 frame size
        frame_size = int(l2frame_size) - 4

        pkt_base = Ether(src=stream_cfg['mac_src'], dst=stream_cfg['mac_dst'])
        if stream_cfg['vlan_tag'] is not None:
            pkt_base /= Dot1Q(vlan=stream_cfg['vlan_tag'])

        udp_args = {}
        if stream_cfg['udp_src_port']:
            udp_args['sport'] = int(stream_cfg['udp_src_port'])
        if stream_cfg['udp_dst_port']:
            udp_args['dport'] = int(stream_cfg['udp_dst_port'])
        pkt_base /= IPv6(src=stream_cfg['ip_src_addr'], dst=stream_cfg['ip_dst_addr']) / UDP(**udp_args)

        if stream_cfg['ip_addrs_step'] == 'random':
            src_fv = STLVmFlowVarRepetableRandom(
                name="ip_src",
                min_value=stream_cfg['ip_src_addr'],
                max_value=stream_cfg['ip_src_addr_max'],
                size=4,
                seed=random.randint(0, 32767),
                limit=stream_cfg['ip_src_count'])
            dst_fv = STLVmFlowVarRepetableRandom(
                name="ip_dst",
                min_value=stream_cfg['ip_dst_addr'],
                max_value=stream_cfg['ip_dst_addr_max'],
                size=4,
                seed=random.randint(0, 32767),
                limit=stream_cfg['ip_dst_count'])
        else:
            min_val, max_val = self.get_start_end_ipv6(stream_cfg['ip_src_addr'], stream_cfg['ip_src_addr'])
            src_fv = STLVmFlowVar(
                name="ip_src",
                min_value=min_val,
                max_value=max_val,
                size=8,
                op="inc")
            min_val, max_val = self.get_start_end_ipv6(stream_cfg['ip_dst_addr'], stream_cfg['ip_dst_addr_max'])
            dst_fv = STLVmFlowVar(
                name="ip_dst",
                min_value=min_val,
                max_value=max_val,
                size=8,
                op="inc")

        vm_param = [
            src_fv,
            STLVmWrFlowVar(fv_name="ip_src", pkt_offset="IPv6.src", offset_fixup=8),
            dst_fv,
            STLVmWrFlowVar(fv_name="ip_dst", pkt_offset="IPv6.dst", offset_fixup=8),
            STLVmFixChecksumHw(l3_offset="IPv6",
                               l4_offset="UDP",
                               l4_type=CTRexVmInsFixHwCs.L4_TYPE_UDP)
        ]
        pad = max(0, frame_size - len(pkt_base)) * 'x'

        return STLPktBuilder(pkt=pkt_base / pad, vm=STLScVmRaw(vm_param))

    def generate_streams(self, port, chain_id, stream_cfg, l2frame, latency=True, e2e=False):
        """Create a list of streams corresponding to a given chain and stream config.

        port: port where the streams originate (0 or 1)
        chain_id: the chain to which the streams are associated to
        stream_cfg: stream configuration
        l2frame: L2 frame size (including 4-byte FCS) or 'IMIX'
        latency: if True also create a latency stream
        """
        streams = []
        pg_id, lat_pg_id = self.get_pg_id(port, chain_id)
        if l2frame == 'IMIX':
            for ratio, l2_frame_size in zip(IMIX_RATIOS, IMIX_L2_SIZES):
                pkt = self._create_pkt(stream_cfg, l2_frame_size)
                if e2e:
                    streams.append(STLStream(packet=pkt,
                                             mode=STLTXCont(pps=ratio)))
                else:
                    streams.append(STLStream(packet=pkt,
                                             flow_stats=STLFlowStats(pg_id=pg_id),
                                             mode=STLTXCont(pps=ratio)))

            if latency:
                # for IMIX, the latency packets have the average IMIX packet size
                pkt = self._create_pkt(stream_cfg, IMIX_AVG_L2_FRAME_SIZE)

        else:
            l2frame_size = int(l2frame)
            pkt = self._create_pkt(stream_cfg, l2frame_size)
            if e2e:
                streams.append(STLStream(packet=pkt,
                                         mode=STLTXCont()))
            else:
                streams.append(STLStream(packet=pkt,
                                         flow_stats=STLFlowStats(pg_id=pg_id),
                                         mode=STLTXCont()))
            # for the latency stream, the minimum payload is 16 bytes even in case of vlan tagging
            # without vlan, the min l2 frame size is 64
            # with vlan it is 68
            # This only applies to the latency stream
            if latency and stream_cfg['vlan_tag'] and l2frame_size < 68:
                pkt = self._create_pkt(stream_cfg, 68)

        if latency:
            streams.append(STLStream(packet=pkt,
                                     flow_stats=STLFlowLatencyStats(pg_id=lat_pg_id),
                                     mode=STLTXCont(pps=self.LATENCY_PPS)))
        return streams

    @timeout(5)
    def __connect(self, client):
        client.connect()

    def __connect_after_start(self):
        # after start, Trex may take a bit of time to initialize
        # so we need to retry a few times
        for it in xrange(self.config.generic_retry_count):
            try:
                time.sleep(1)
                self.client.connect()
                break
            except Exception as ex:
                if it == (self.config.generic_retry_count - 1):
                    raise
                LOG.info("Retrying connection to TRex (%s)...", ex.message)

    def connect(self):
        """Connect to the TRex server."""
        server_ip = self.generator_config.ip
        LOG.info("Connecting to TRex (%s)...", server_ip)

        # Connect to TRex server
        self.client = STLClient(server=server_ip)
        try:
            self.__connect(self.client)
        except (TimeoutError, STLError) as e:
            if server_ip == '127.0.0.1':
                try:
                    self.__start_server()
                    self.__connect_after_start()
                except (TimeoutError, STLError) as e:
                    LOG.error('Cannot connect to TRex')
                    LOG.error(traceback.format_exc())
                    logpath = '/tmp/trex.log'
                    if os.path.isfile(logpath):
                        # Wait for TRex to finish writing error message
                        last_size = 0
                        for _ in xrange(self.config.generic_retry_count):
                            size = os.path.getsize(logpath)
                            if size == last_size:
                                # probably not writing anymore
                                break
                            last_size = size
                            time.sleep(1)
                        with open(logpath, 'r') as f:
                            message = f.read()
                    else:
                        message = e.message
                    raise TrafficGeneratorException(message)
            else:
                raise TrafficGeneratorException(e.message)

        ports = list(self.generator_config.ports)
        self.port_handle = ports
        # Prepare the ports
        self.client.reset(ports)
        # Read HW information from each port
        # this returns an array of dict (1 per port)
        """
        Example of output for Intel XL710
        [{'arp': '-', 'src_ipv4': '-', u'supp_speeds': [40000], u'is_link_supported': True,
          'grat_arp': 'off', 'speed': 40, u'index': 0, 'link_change_supported': 'yes',
          u'rx': {u'counters': 127, u'caps': [u'flow_stats', u'latency']},
          u'is_virtual': 'no', 'prom': 'off', 'src_mac': u'3c:fd:fe:a8:24:48', 'status': 'IDLE',
          u'description': u'Ethernet Controller XL710 for 40GbE QSFP+',
          'dest': u'fa:16:3e:3c:63:04', u'is_fc_supported': False, 'vlan': '-',
          u'driver': u'net_i40e', 'led_change_supported': 'yes', 'rx_filter_mode': 'hardware match',
          'fc': 'none', 'link': 'UP', u'hw_mac': u'3c:fd:fe:a8:24:48', u'pci_addr': u'0000:5e:00.0',
          'mult': 'off', 'fc_supported': 'no', u'is_led_supported': True, 'rx_queue': 'off',
          'layer_mode': 'Ethernet', u'numa': 0}, ...]
        """
        self.port_info = self.client.get_port_info(ports)
        LOG.info('Connected to TRex')
        for id, port in enumerate(self.port_info):
            LOG.info('   Port %d: %s speed=%dGbps mac=%s pci=%s driver=%s',
                     id, port['description'], port['speed'], port['src_mac'],
                     port['pci_addr'], port['driver'])
        # Make sure the 2 ports have the same speed
        if self.port_info[0]['speed'] != self.port_info[1]['speed']:
            raise TrafficGeneratorException('Traffic generator ports speed mismatch: %d/%d Gbps' %
                                            (self.port_info[0]['speed'],
                                             self.port_info[1]['speed']))

    def __start_server(self):
        server = TRexTrafficServer()
        server.run_server(self.generator_config)

    def resolve_arp(self):
        """Resolve all configured remote IP addresses.

        return: None if ARP failed to resolve for all IP addresses
                else a dict of list of dest macs indexed by port#
                the dest macs in the list are indexed by the chain id
        """
        self.client.set_service_mode(ports=self.port_handle)
        LOG.info('Polling ARP until successful...')
        arp_dest_macs = {}
        for port, device in zip(self.port_handle, self.generator_config.devices):
            # there should be 1 stream config per chain
            stream_configs = device.get_stream_configs()
            chain_count = len(stream_configs)
            ctx = self.client.create_service_ctx(port=port)
            # all dest macs on this port indexed by chain ID
            dst_macs = [None] * chain_count
            dst_macs_count = 0
            # the index in the list is the chain id
            arps = [
                STLServiceARP(ctx,
                              src_ip=cfg['ip_src_tg_gw'],
                              dst_ip=cfg['mac_discovery_gw'],
                              # will be None if no vlan tagging
                              vlan=cfg['vlan_tag'])
                for cfg in stream_configs
            ]

            for attempt in range(self.config.generic_retry_count):
                try:
                    ctx.run(arps)
                except STLError:
                    LOG.error(traceback.format_exc())
                    continue

                unresolved = []
                for chain_id, mac in enumerate(dst_macs):
                    if not mac:
                        arp_record = arps[chain_id].get_record()
                        if arp_record.dst_mac:
                            dst_macs[chain_id] = arp_record.dst_mac
                            dst_macs_count += 1
                            LOG.info('   ARP: port=%d chain=%d src IP=%s dst IP=%s -> MAC=%s',
                                     port, chain_id,
                                     arp_record.src_ip,
                                     arp_record.dst_ip, arp_record.dst_mac)
                        else:
                            unresolved.append(arp_record.dst_ip)
                if dst_macs_count == chain_count:
                    arp_dest_macs[port] = dst_macs
                    LOG.info('ARP resolved successfully for port %s', port)
                    break
                else:
                    retry = attempt + 1
                    LOG.info('Retrying ARP for: %s (retry %d/%d)',
                             unresolved, retry, self.config.generic_retry_count)
                    if retry < self.config.generic_retry_count:
                        time.sleep(self.config.generic_poll_sec)
            else:
                LOG.error('ARP timed out for port %s (resolved %d out of %d)',
                          port,
                          dst_macs_count,
                          chain_count)
                break

        self.client.set_service_mode(ports=self.port_handle, enabled=False)
        if len(arp_dest_macs) == len(self.port_handle):
            return arp_dest_macs
        return None

    def __is_rate_enough(self, l2frame_size, rates, bidirectional, latency):
        """Check if rate provided by user is above requirements. Applies only if latency is True."""
        intf_speed = self.generator_config.intf_speed
        if latency:
            if bidirectional:
                mult = 2
                total_rate = 0
                for rate in rates:
                    r = utils.convert_rates(l2frame_size, rate, intf_speed)
                    total_rate += int(r['rate_pps'])
            else:
                mult = 1
                total_rate = utils.convert_rates(l2frame_size, rates[0], intf_speed)
            # rate must be enough for latency stream and at least 1 pps for base stream per chain
            required_rate = (self.LATENCY_PPS + 1) * self.config.service_chain_count * mult
            result = utils.convert_rates(l2frame_size,
                                         {'rate_pps': required_rate},
                                         intf_speed * mult)
            result['result'] = total_rate >= required_rate
            return result

        return {'result': True}

    def create_traffic(self, l2frame_size, rates, bidirectional, latency=True, e2e=False):
        """Program all the streams in Trex server.

        l2frame_size: L2 frame size or IMIX
        rates: a list of 2 rates to run each direction
               each rate is a dict like {'rate_pps': '10kpps'}
        bidirectional: True if bidirectional
        latency: True if latency measurement is needed
        """
        r = self.__is_rate_enough(l2frame_size, rates, bidirectional, latency)
        if not r['result']:
            raise TrafficGeneratorException(
                'Required rate in total is at least one of: \n{pps}pps \n{bps}bps \n{load}%.'
                .format(pps=r['rate_pps'],
                        bps=r['rate_bps'],
                        load=r['rate_percent']))
        # a dict of list of streams indexed by port#
        # in case of fixed size, has self.chain_count * 2 * 2 streams
        # (1 normal + 1 latency stream per direction per chain)
        # for IMIX, has self.chain_count * 2 * 4 streams
        # (3 normal + 1 latency stream per direction per chain)
        streamblock = {}
        for port in self.port_handle:
            streamblock[port] = []
        stream_cfgs = [d.get_stream_configs() for d in self.generator_config.devices]
        self.rates = [utils.to_rate_str(rate) for rate in rates]
        for chain_id, (fwd_stream_cfg, rev_stream_cfg) in enumerate(zip(*stream_cfgs)):
            streamblock[0].extend(self.generate_streams(self.port_handle[0],
                                                        chain_id,
                                                        fwd_stream_cfg,
                                                        l2frame_size,
                                                        latency=latency,
                                                        e2e=e2e))
            if len(self.rates) > 1:
                streamblock[1].extend(self.generate_streams(self.port_handle[1],
                                                            chain_id,
                                                            rev_stream_cfg,
                                                            l2frame_size,
                                                            latency=bidirectional and latency,
                                                            e2e=e2e))

        for port in self.port_handle:
            self.client.add_streams(streamblock[port], ports=port)
            LOG.info('Created %d traffic streams for port %s.', len(streamblock[port]), port)

    def clear_streamblock(self):
        """Clear all streams from TRex."""
        self.rates = []
        self.client.reset(self.port_handle)
        LOG.info('Cleared all existing streams')

    def get_stats(self):
        """Get stats from Trex."""
        stats = self.client.get_stats()
        return self.extract_stats(stats)

    def get_macs(self):
        """Return the Trex local port MAC addresses.

        return: a list of MAC addresses indexed by the port#
        """
        return [port['src_mac'] for port in self.port_info]

    def get_port_speed_gbps(self):
        """Return the Trex local port MAC addresses.

        return: a list of speed in Gbps indexed by the port#
        """
        return [port['speed'] for port in self.port_info]

    def clear_stats(self):
        """Clear all stats in the traffic gneerator."""
        if self.port_handle:
            self.client.clear_stats()

    def start_traffic(self):
        """Start generating traffic in all ports."""
        for port, rate in zip(self.port_handle, self.rates):
            self.client.start(ports=port, mult=rate, duration=self.config.duration_sec, force=True)

    def stop_traffic(self):
        """Stop generating traffic."""
        self.client.stop(ports=self.port_handle)

    def start_capture(self):
        """Capture all packets on both ports that are unicast to us."""
        if self.capture_id:
            self.stop_capture()
        # Need to filter out unwanted packets so we do not end up counting
        # src MACs of frames that are not unicast to us
        src_mac_list = self.get_macs()
        bpf_filter = "ether dst %s or ether dst %s" % (src_mac_list[0], src_mac_list[1])
        # ports must be set in service in order to enable capture
        self.client.set_service_mode(ports=self.port_handle)
        self.capture_id = self.client.start_capture(rx_ports=self.port_handle,
                                                    bpf_filter=bpf_filter)

    def fetch_capture_packets(self):
        """Fetch capture packets in capture mode."""
        if self.capture_id:
            self.packet_list = []
            self.client.fetch_capture_packets(capture_id=self.capture_id['id'],
                                              output=self.packet_list)

    def stop_capture(self):
        """Stop capturing packets."""
        if self.capture_id:
            self.client.stop_capture(capture_id=self.capture_id['id'])
            self.capture_id = None
            self.client.set_service_mode(ports=self.port_handle, enabled=False)

    def cleanup(self):
        """Cleanup Trex driver."""
        if self.client:
            try:
                self.client.reset(self.port_handle)
                self.client.disconnect()
            except STLError:
                # TRex does not like a reset while in disconnected state
                pass


def mergeTwoLists(list1, list2):
    if not list1:
        return list2
    if not list2:
        return list1

    lil, big = (list1, list2) if list1.val < list2.val else (list2, list1)

    lil.next = mergeTwoLists(lil.next, big)
    return lil


import logging
import pandas as pd
import numpy as np

import config

from sentence_transformers import SentenceTransformer
import gensim.downloader as api

logger = logging.getLogger(__name__)

class SentenceEmbeddings:
    def __init__(self, name: str) -> None:
        self.model_name = name

        logger.info(f'Initializing {self.model_name.upper()} for Sentence Embeddings')

        if 'mpnet' in self.model_name:
            logger.debug('Loading all-mpnet-base-v2 model')
            self.model = SentenceTransformer('all-mpnet-base-v2')
        elif 'distil-roberta' in self.model_name:
            logger.debug('Loading all-distilroberta-v1')
            self.model = SentenceTransformer('all-distilroberta-v1')

    def generate_embeddings(self, input_texts: pd.Series):
        logger.info(f'{self.model_name.upper()} - Generating sentence embeddings...')
        return self.model.encode(input_texts.to_list())

class WordEmbeddings:
    def __init__(self, name: str) -> None:
        self.model_name = name

        logger.info(f'Initializing {self.model_name.upper()} for Word Embeddings')

        if 'w2v-google' in self.model_name:
            logger.debug('Loading word2vec-google-news-300')
            self.model = api.load('word2vec-google-news-300')
        elif 'glove-twitter' in self.model_name:
            logger.debug('Loading glove-twitter-200')
            self.model = api.load('glove-twitter-200')
        elif 'glove-wiki' in self.model_name:
            logger.debug('Loading glove-wiki-gigaword-300')
            self.model = api.load('glove-wiki-gigaword-300')

    def generate_embeddings(self, input_texts: pd.Series) -> list:
        logger.info(f'{self.model_name.upper()} - Generating sentence embeddings...')
        # init embeddings list
        embeddings = []
        for tokens in input_texts:
            # init zero vector and vector list
            zero_vector = np.zeros(self.model.vector_size)
            vectors = []
            for token in tokens:
                if token in self.model:
                    try:
                        logger.debug(f'Checking {token} in vocabulary')
                        vectors.append(self.model[token])
                    except KeyError:
                        logger.warning(f'{token} not in vocabulary, skipping...')
                        continue
            if vectors:
                vectors = np.asarray(vectors)
                # compute average across 0 axis
                avg_vec = vectors.mean(axis=0)
                embeddings.append(avg_vec)
            else:
                embeddings.append(zero_vector)

        return embeddings


import socket, ssl, sys, argparse
'''
python2.7.13 ssl 库不再支持 sslv3
'''

class Responses:
    ACCEPT, REJECT, NOT_AVAILABLE = range(3)

def test_server(hostname, port, ssl_version, timeout):
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(timeout)
        ssl_sock = ssl.wrap_socket(sock, ssl_version=ssl_version)
        ssl_sock.connect((hostname, port))
        return Responses.ACCEPT
    except ssl.SSLError:
        return Responses.REJECT
    except socket.error:
        return Responses.NOT_AVAILABLE
    finally:
        ssl_sock.close()

def m_poodle_run(hostname, port):
    quiet = 1
    timeout = 6
    result = test_server(hostname, port, ssl.PROTOCOL_SSLv3, timeout)
    if result == Responses.ACCEPT:
        print(" - [LOG] SSLv3 CONNECTION ACCEPTED")
        return "0x01"
    elif result == Responses.REJECT:
        print(" - [LOG] SSLv3 Rejected")
        return "0x00"
    else:
        print(" - [LOG] SSLv3 No Answer")
        return "0x00"

# www.baidu.com
m_poodle_run('14.215.177.38', 443)


import pandas as pd
import os

breakout_path = "/Breakouts_LFCcorner/"
path = "/home/shreyas/Documents/Final_year/finalyear/datasets/All_data/"
month = "August"

df = pd.read_excel(path + month + ".xls" , sheet_name= 'breakouts')

#df_breakouts = pd.read_excel("data May 2010 - columns pruned and output added.xls" , sheet_name= 'breakouts')

#unwanted_cols_breakouts = ["date","time","type of break out"]

df = df[(df.breakout == "LFC corner") ]

unwanted_cols = ["date","time",'shift colour', 'LFC index',
       'water jacket ID north', 'water jacket ID south','type of SEN',
       'water jacket ID east', 'water jacket ID west','mould number', 'rest_standtijd_kms','steelgrade']

for name in unwanted_cols:
#print(name)
       df.pop(name)

#for name in unwanted_cols_breakouts:
#    df_breakouts.pop(name)

"""col = 'steelgrade'
df.loc[df[col] == 'FN80', col] = 1
df.loc[df[col] == 'F12L', col] = 2
df.loc[df[col] == 'FN81', col] = 3
df.loc[df[col] == 'FV83', col] = 4
df.loc[df[col] == 'UT12', col] = 5
df.loc[df[col] == 'FV85', col] = 6
df.loc[df[col] == 'UT23', col] = 7
df.loc[df[col] == 'LGAB', col] = 8"""

df.loc[df["powder consumption"] == "Under Range", "powder consumption"] = 0
df.loc[df["powder consumption"] == "Over Range", "powder consumption"] = 4.01440477371216*1.1

#df_breakouts.loc[df["powder consumption"] == "Under Range", "powder consumption"] = 0
#df_breakouts.loc[df["powder consumption"] == "Over Range", "powder consumption"] = 4.01440477371216*1.1

df.to_excel(path + breakout_path +  "Breakouts_" + month  + ".xls" , sheet_name = "breakouts", index=False)
#df_breakouts.to_excel("filtered_data_breakouts.xls" , sheet_name = "breakouts")


def extractCatharcityWordpressCom(item):
	'''
	Parser for 'catharcity.wordpress.com'
	'''

	vol, chp, frag, postfix = extractVolChapterFragmentPostfix(item['title'])
	if not (chp or vol) or "preview" in item['title'].lower():
		return False

	tagmap = [
		('Love in Another Life',                        'Love in Another Life: My Gentle Tyrant',                      'translated'),
		('Ballad of Ten Thousand Gu',                   'Ballad of Ten Thousand Gu',                                   'translated'),
		('One Night, One Day, One Year, One Lifetime',  'One Night, One Day, One Year, One Lifetime',                  'translated'),
	]

	for tagname, name, tl_type in tagmap:
		if tagname in item['tags']:
			return buildReleaseMessageWithType(item, name, vol, chp, frag=frag, postfix=postfix, tl_type=tl_type)

	return False


#! _*_coding=utf-8_*_
import pandas as pd
import json
import requests
import time
from base import *

def future_quote_sina(exchange='all', flag=1):
    '''获取新浪期货全部合约即时行情数据,默认取全部交易所主力合约，取特定交易所主力或全部合约，用参数来指定
    para:
        exchange:   all,shfe,dce,czce
        flag:       1（active contracts),0(non-active contracts),2(all contracts)
    result:
        dataframe
    '''
    r = requests.get(
        'http://money.finance.sina.com.cn/d/api/openapi_proxy.php/?__s=[[%22qhhq%22,%22qbhy%22,%22zdf%22,1000]]')
    data = r.text
    data = json.loads(data)
    d = data[0]
    df = pd.DataFrame(d['items'], columns=d['fields'])
    df = df.apply(lambda x: pd.to_numeric(x, errors='ignore'))  #
    df.index = df.name
    # 交易所主力合约：df[(df.market=='dce')& (df.is_hot=='1')]
    # 全部主力合约：df[(df.market=='dce')& (df.is_hot=='1')]
    # 交易所合约：df[(df.market=='dce')]
    if exchange == 'all':
        if flag == 0:
            # flag=0,返回四大交易所非主力合约
            return df[df.is_hot == flag].sort_values('volume', ascending=False)
        elif flag==1:
            #flag=1,返回四大交易所主力合约
            return df[df.is_hot >= flag].sort_values('volume', ascending=False)
        elif flag==-1:
            # flag=-1,返回四大交易所全部合约
            return df.sort_values('volume', ascending=False)
    else:
            # 指定交易所主力（非主力）合约
        if flag == 0:
            #返回指定交易所非主力合约
            return df[(df.market == exchange) & (df.is_hot == flag)].sort_values('volume', ascending=False)
        elif flag == 1:
            #返回指定交易所非主力合约
            return df[(df.market == exchange) & (df.is_hot >= flag)].sort_values('volume', ascending=False)
        else:
            # 指定交易所全部合约
            return df[df.market == exchange].sort_values('volume', ascending=False)

def hot():
    a=future_quote_sina()
    a['hot']=a.volume/a.position
    a['current_time']=timenow()
    return a.loc[:,['trade','zdf','volume','position','hot','current_time']].to_html('/root/yuangs/www/my_flask/static/hot.html')

def hpl20(flag=0):
    f=future_quote_sina()
    h20=f.h_20t
    l20=f.l_20t
    price=f.trade
    f['hl']=100*(h20/l20-1)
    f['pl']=100*(price/l20-1)
    f.loc[:,['trade','zdf','volume','position','pl','hl']].to_html('/root/yuangs/www/my_flask/static/hpl.html')

def timenow():
    return time.asctime( time.localtime(time.time()) )

if __name__=='__main__':
    timenow()
    ppi_data()
    hot()
    hpl20(0)
    hpl20(1)

#add this line by sftp at 21:33 saturday


#!/usr/bin/env python

"""
Translated from Seabird code for calculating pH from glider outputs by Liza Wright-Fairbanks (Matlab)
Translated to Python by: Lori Garzio on 3/3/2021
Last modified: 5/12/2023
"""
import numpy as np

def phcalc(vrs, press, temp, salt, k0, k2, pcoefs):
    """
    :param vrs: voltage between reference electrode and ISFET source
    :param press: pressure in decibars
    :param temp: temperature in degrees C
    :param salt: salinity (usually CTD salinity on the PSS)
    :param k0: sensor reference potential (intercept at Temp = 0 C)
    :param k2: linear temperature coefficient (slope), or list containing K2(P) 3rd order polynomial pressure offset
    coefficients: [K2f3, K2f2, K2f1, K2f0]
    :param pcoefs: sensor dependent pressure coefficients (polynomial calculation of f(P) coefficients)
    :return: phfree, phtot
    """
    # SET CONSTANTS
    # Universal gas constant, (R), http://physics.nist.gov/cgi-bin/cuu/Value?r
    R = 8.31446  # J/(mol K)
    F = 96485  # Faraday constant Coulomb / mol
    Tk = 273.15 + temp  # convert to degrees Kelvin
    ln10 = np.log(10)  # natural log of 10

    # CALCULATE PHYSICAL AND THERMODYNAMIC DATA
    # Dickson, A. G., Sabine, C. L., & Christian, J. R. (2007). Guide to best practices for ocean CO2 measurements.

    # IONIC STRENGTH OF SEAWATER (mol / kg H2O)
    # Verified units by comparing to Dickson et al. 2007: Chap 5, p10 Table 2
    # Dickson et al. 2007: Chap 5, p13 Eq 34
    IonS = 19.924 * salt / (1000 - 1.005 * salt)

    # MEAN SEAWATER SULFATE CONCENTRATION (mol / kg solution)
    # This wants to be mol/kg sw  as KHSO4 is on that scale
    # Dickson et al. 2007: Chap 5, p10 Table 2
    Stotal = (0.14 / 96.062) * (salt / 1.80655)

    # MEAN SEAWATER CHLORIDE CONCENTRATION  (mol / kg H20)
    # this wants to be mol/kg H2O as activity is on mol/kg H2O scale
    # Dickson et al. 2007: Chap 5, p10 Table 2
    Cltotal = 0.99889 / 35.453 * salt / 1.80655  # (mol / kg solution)
    Cltotal = Cltotal / (1 - 0.001005 * salt)  # (mol / kg H20)

    # BISULFIDE DISSCIATION CONSTANT AT T,S AND IONIC STRENGTH(mol/kg solution)
    # Dickson et al. 2007: Chap 5, p12 Eq 33
    Khso4 = np.exp(-4276.1 / Tk + 141.328 - 23.093 * np.log(Tk) + (-13856. / Tk + 324.57 - 47.986 * np.log(Tk))
                   * IonS**0.5 + (35474. / Tk - 771.54 + 114.723 * np.log(Tk)) * IonS - 2698 / Tk * IonS**1.5
                   + 1776 / Tk * IonS**2 + np.log(1 - 0.001005 * salt))

    # Millero 1983 Chemical Oceanography vol 8
    # partial molar volume and compressibility of HSO4 in seawater.   delta v is cm^3
    deltaVHSO4 = -18.03 + 0.0466 * temp + 0.000316 * temp**2
    KappaHSO4 = (-4.53 + 0.09 * temp) / 1000
    lnKhso4fac = (-deltaVHSO4 + 0.5 * KappaHSO4 * (press / 10)) * (press / 10) / (R * 10. * Tk)

    # bisulfate association constant at T, S, P
    Khso4TPS = Khso4 * np.exp(lnKhso4fac)

    # GAMMA +/- HCl, activity coefficient of HCl at T/S, P=1
    # ADH is the Debye Huckel constant, calcualted as a polynomial fit to data in Khoo et al. 1977, doi:10.1021/ac50009a016
    # See Martz et al. 2010, DOI 10.4319/lom.2010.8.172, p175
    # Typo in paper 2nd term should be e-4 not e-6
    ADH = (3.4286e-6 * temp**2 + 6.7524e-4 * temp + 0.49172143)
    log10gammaHCl = -ADH * np.sqrt(IonS) / (1 + 1.394 * np.sqrt(IonS)) + (0.08885 - 0.000111 * temp) * IonS

    # Millero 1983 partial molar volume of HCl in seawater. deltaV is cm^3
    deltaVHCl = 17.85 + 0.1044 * temp - 0.001316 * temp**2

    # make activity coefficient of HCl more accurate by including the effect of pressure on partial molar volume of HCl
    # last divide by 10 is for units in cm^3 vs m^3 and the Pascal vs bar units in mks constants. (Meter/kilo/second)
    log10gammaHCLtP = log10gammaHCl + deltaVHCl * (press / 10) / (R * Tk * ln10) / 2. / 10

    if isinstance(k2, list):
        # added by L. Garzio with input from Sea-Bird to incorporate k2(P) correction
        # K2P coefficients are used to correct the temperature offset over pressure
        # Eo(T) or temperature offset Johnson et al. Anal. Chem. 2016
        # Polynomial K2, ie K2(P). From MBARI processing code base 11042022
        EoT = temp * np.polyval(k2, press)

        phfree = (vrs - EoT - pcoefs - k0) / (R * Tk / F * ln10) + np.log(Cltotal) / ln10 + 2 * log10gammaHCLtP  # mol/kg-H2O scale
    else:
        # Sensor reference potential
        k0T = k0 + k2 * temp  # temp in deg C

        # CALCULATE PRESSURE CORRECTION (POLYNOMIAL FUNCTION OF PRESSURE)
        # ALL SENSORS HAVE A PRESSURE RESPONSE WHICH IS DETERMINED IN THE LAB
        # AND CONTAINED IN THE POLYNOMIAL Pcoefs
        # pc = [flipud(Pcoefs);0]; % Matlab wants descending powers & n+1 (add 0)
        # pcorr = polyval(pc,Press)
        k0TP = k0T + pcoefs

        # pH on free scale then corrected to get to pH total on mol/kg sw scale
        # pHinsituFree = (Vrs - temp offset - press offset) / (R * Tk / F * ln10) + log(Cltotal) / ln10 + 2 * log10gammaHCLtP
        # this will be mol kg H2O. need to convert to mol/kg sw
        phfree = (vrs - k0TP) / (R * Tk / F * ln10) + np.log(Cltotal) / ln10 + 2 * log10gammaHCLtP  # mol/kg-H2O scale

    # CONVERT TO mol/kg-sw scale - JP 2/4/16
    phfree = phfree - np.log10(1 - 0.001005 * salt)  # mol/kg-sw scale

    # convert to total proton scale
    phtot = phfree - np.log10(1 + Stotal / Khso4TPS)

    return phfree, phtot


class Solution(object):
    def combinationSum4(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        dp = [-1]*(target + 1)
        dp[0] = 1
        return self.helper(nums, target, dp)

    def helper(self, nums, target, dp):
        if dp[target] != -1:
            return dp[target]

        combs = 0
        for n in nums:
            if n <= target:
                combs += self.helper(nums, target - n, dp)
        # print("combs of {}: {}".format(target, combs))
        dp[target] = combs
        return combs


from django.shortcuts import render

# Create your views here.

from exam.models import *
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect
from django.urls import reverse
from exam.forms import *
import datetime
from django.contrib import messages
from django.contrib.auth.decorators import login_required

@login_required
def index(request):
    return redirect('exam:home')

@login_required
def home(request):
    import pdb
    # pdb.set_trace()
    print (request)
    name = "prashanth"
    date = datetime.datetime.now()

    # return HttpResponse("
Hello %s, Time is %s
" % (name, str(date)))
    return render(request, 'exam/home.html', {'name': name, 'date1': date})

@login_required
def contact(request):
    context = {'contact': 9959994410}
    return render(request, 'exam/contact.html', context)

@login_required
def about(request):
    context = {'info': 'This is the job providing website'}
    return render(request, 'exam/about.html', context)

@login_required
def questions_list(request):
    # import pdb; pdb.set_trace()
    if request.method == 'GET':
        questions = Question.objects.all()
        return render(request, 'exam/question-list.html',
                      {'questions': questions})
    return redirect('exam:home')

@login_required
def delete_question(request, id=None):
    if request.method == 'POST':
        question_obj = Question.objects.filter(id=id).first()
        if question_obj:
            # question_obj.delete()
            return JsonResponse({'success': True,
                                 "message": "Question deleted successufully."})
        return JsonResponse({'success': False,
                             "message": "Question Not Found."})
    return redirect('exam:home')

@login_required
def create_question(request):
    if request.method == 'GET':
        # import pdb; pdb.set_trace()
        question_create_form = QuestionForm()
        return render(request, 'exam/create_question.html',
                      {'question_create_form': question_create_form})

    elif request.method == 'POST':
        question_create_form = QuestionForm(request.POST)
        if question_create_form.is_valid():
            question_obj = question_create_form.save()
            messages.add_message(request, messages.SUCCESS,
                                 'Question Created Successfully!.')
            return redirect(reverse('exam:update_question', kwargs={'id': question_obj.id}))
        else:
            messages.add_message(request, messages.ERROR,
                                 'Something Went Wrong!.')
            return render(request, 'exam/create_question.html',
                          {'question_create_form': question_create_form})
        return redirect('exam:home')

@login_required
def update_question(request, id):
    question_obj = Question.objects.filter(id=id).first()
    if not question_obj:
        messages.add_message(request, messages.ERROR,
                             'Question not found!.')
        return redirect('exam:questions_list')
    if request.method == 'GET':
        question_update_form = QuestionForm(instance=question_obj)
        return render(request, 'exam/update_question.html',
                      {'question_update_form': question_update_form})
    elif request.method == 'POST':
        question_update_form = QuestionForm(
            request.POST, instance=question_obj)
        if question_update_form.is_valid():
            question_obj = question_update_form.save()
            messages.add_message(request, messages.SUCCESS,
                                 'Question Updated Successfully!.')
            return redirect(reverse('exam:update_question', kwargs={'id': question_obj.id}))
        else:
            messages.add_message(request, messages.ERROR,
                                 'Something Went Wrong!.')
            return render(request, 'exam/update_question.html',
                          {'question_update_form': question_update_form})
    return redirect('exam:questions_list')


import os
import torch

from skimage import io
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import transforms  # , utils

from PIL import Image
import glob

from data_loader import RescaleT
from data_loader import ToTensorLab
from data_loader import SalObjDataset

from model import U2NET  # full size version 173.6 MB

# normalize the predicted SOD probability map
def normPRED(d):
    ma = torch.max(d)
    mi = torch.min(d)

    dn = (d - mi) / (ma - mi)

    return dn

def save_output(image_name, pred, d_dir):

    predict = pred
    predict = predict.squeeze()
    predict_np = predict.cpu().data.numpy()

    im = Image.fromarray(predict_np * 255).convert("L")
    # print(list(im.getdata()))
    img_name = image_name.split(os.sep)[-1]
    image = io.imread(image_name)
    imo = im.resize((image.shape[1], image.shape[0]), resample=Image.BILINEAR)

    aaa = img_name.split(".")
    bbb = aaa[0:-1]
    imidx = bbb[0]
    for i in range(1, len(bbb)):
        imidx = imidx + "." + bbb[i]

    imo.save(d_dir + imidx + ".png")

def main():

    # --------- 1. get image path and name ---------
    image_dir = "/root/TrainingDataset/TrainingData/ImagesTest"
    prediction_dir = "./test_data/ImagesTest_Result/"
    model_dir = "./saved_models/u2net-trained.pth"

    img_name_list = glob.glob(image_dir + os.sep + "*")
    print(img_name_list)

    # --------- 2. dataloader ---------
    # 1. dataloader
    test_salobj_dataset = SalObjDataset(
        img_name_list=img_name_list,
        lbl_name_list=[],
        transform=transforms.Compose([RescaleT(320), ToTensorLab(flag=0)]),
    )
    test_salobj_dataloader = DataLoader(
        test_salobj_dataset, batch_size=1, shuffle=False, num_workers=1
    )

    # --------- 3. model define ---------
    net = U2NET(3, 1)
    net.load_state_dict(torch.load(model_dir))
    if torch.cuda.is_available():
        net.cuda()
    net.eval()

    # --------- 4. inference for each image ---------
    for i_test, data_test in enumerate(test_salobj_dataloader):

        print("inferencing:", img_name_list[i_test].split(os.sep)[-1])

        inputs_test = data_test["image"]
        inputs_test = inputs_test.type(torch.FloatTensor)

        if torch.cuda.is_available():
            inputs_test = Variable(inputs_test.cuda())
        else:
            inputs_test = Variable(inputs_test)

        with torch.no_grad():
            d1, d2, d3, d4, d5, d6, d7 = net(inputs_test)

        # normalization
        pred = d1[:, 0, :, :]
        pred = normPRED(pred)

        # save results to test_results folder
        if not os.path.exists(prediction_dir):
            os.makedirs(prediction_dir, exist_ok=True)
        save_output(img_name_list[i_test], pred, prediction_dir)

        del d1, d2, d3, d4, d5, d6, d7

if __name__ == "__main__":
    main()


from django.db.models import Q
from rest_framework.decorators import api_view, permission_classes
from rest_framework import permissions, status, viewsets
from rest_framework.response import Response
from longclaw.shipping import models, utils, serializers
from longclaw.configuration.models import Configuration
from longclaw.basket.utils import basket_id

from .models import ShippingRateProcessor
from .signals import address_modified

class AddressViewSet(viewsets.ModelViewSet):
    """
    Create, list and view Addresses
    """
    queryset = models.Address.objects.all()
    serializer_class = serializers.AddressSerializer

    def perform_create(self, serializer):
        output = super().perform_create(serializer)
        instance = serializer.instance
        address_modified.send(sender=models.Address, instance=instance)

    def perform_update(self, serializer):
        output = super().perform_update(serializer)
        instance = serializer.instance
        address_modified.send(sender=models.Address, instance=instance)

    def perform_destroy(self, instance):
        output = super().perform_destroy(instance)
        address_modified.send(sender=models.Address, instance=instance)

def get_shipping_cost_kwargs(request, country=None):
    country_code = request.query_params.get('country_code', None)
    if country:
        if country_code is not None:
            raise utils.InvalidShippingCountry("Cannot specify country and country_code")
        country_code = country

    destination = request.query_params.get('destination', None)
    if destination:
        try:
            destination = models.Address.objects.get(pk=destination)
        except models.Address.DoesNotExist:
            raise utils.InvalidShippingDestination("Address not found")
    elif not country_code:
        raise utils.InvalidShippingCountry("No country code supplied")

    if not country_code:
        country_code = destination.country.pk

    bid = basket_id(request)
    option = request.query_params.get('shipping_rate_name', 'standard')
    settings = Configuration.for_request(request)

    return dict(country_code=country_code, destination=destination, basket_id=bid, settings=settings, name=option)

@api_view(['GET'])
@permission_classes({permissions.AllowAny})
def shipping_cost(request):
    """ Returns the shipping cost for a given country
    If the shipping cost for the given country has not been set, it will
    fallback to the default shipping cost if it has been enabled in the app
    settings
    """
    status_code = status.HTTP_400_BAD_REQUEST
    try:
        kwargs = get_shipping_cost_kwargs(request)
    except (utils.InvalidShippingCountry, utils.InvalidShippingDestination) as e:
        data = {'message': e.message}
    else:
        try:
            data = utils.get_shipping_cost(**kwargs)
        except utils.InvalidShippingRate:
            data = {
                "message": "Shipping option {} is invalid".format(kwargs['name'])
            }
        except utils.InvalidShippingCountry:
            data = {
                "message": "Shipping to {} is not available".format(kwargs['country_code'])
            }
        else:
            status_code = status.HTTP_200_OK

    return Response(data=data, status=status_code)

@api_view(["GET"])
@permission_classes([permissions.AllowAny])
def shipping_countries(request):
    """ Get all shipping countries
    """
    queryset = models.Country.objects.exclude(shippingrate=None)
    serializer = serializers.CountrySerializer(queryset, many=True)
    return Response(data=serializer.data, status=status.HTTP_200_OK)

@api_view(["GET"])
@permission_classes([permissions.AllowAny])
def shipping_options(request, country=None):
    """
    Get the shipping options for a given country
    """
    try:
        kwargs = get_shipping_cost_kwargs(request, country=country)
    except (utils.InvalidShippingCountry, utils.InvalidShippingDestination) as e:
        return Response(data={'message': e.message}, status=status.HTTP_400_BAD_REQUEST)

    country_code = kwargs['country_code']
    settings = kwargs['settings']
    bid = kwargs['basket_id']
    destination = kwargs['destination']

    processors = ShippingRateProcessor.objects.filter(countries__in=[country_code])
    if processors:
        if not destination:
            return Response(
                data={
                    "message": "Destination address is required for rates to {}.".format(country_code)
                },
                status=status.HTTP_400_BAD_REQUEST
            )
        for processor in processors:
            processor.get_rates(settings=settings, basket_id=bid, destination=destination)

    q = Q(countries__in=[country_code]) | Q(basket_id=bid, destination=None)

    if destination:
        q.add(Q(destination=destination, basket_id=''), Q.OR)
        q.add(Q(destination=destination, basket_id=bid), Q.OR)

    qrs = models.ShippingRate.objects.filter(q)
    serializer = serializers.ShippingRateSerializer(qrs, many=True)
    return Response(
        data=serializer.data,
        status=status.HTTP_200_OK
    )


from gen_utils import run_with_singularity
from status_manager import StatusManager
from search_operations import SearchOperations
from ledger import Ledger
import glob
import os

import re
class RfiFinder(SearchOperations):

	def __init__(self, config, out_prefix):
		super().__init__(config, out_prefix)

	def do_accelsearch(self, input_file, beam_name):

		prepdata_outfile_prefix = "{}_{}_DM0.00".format(self.out_prefix, beam_name)

		prepdata_cmd = "prepdata -dm 0 -nobary -o {} {}".format(prepdata_outfile_prefix, input_file)

		run_with_singularity(self.config.presto_config.singularity_image,
						self.config.presto_config.singularity_flags, prepdata_cmd)

		realfft_cmd = "realfft {}.dat".format(prepdata_outfile_prefix)

		run_with_singularity(self.config.presto_config.singularity_image,
						self.config.presto_config.singularity_flags, realfft_cmd )

		accelsearch_command = "accelsearch {} -zmax 0 -numharm 8 {}.fft".format(self.config.presto_config.accelsearch_flags, prepdata_outfile_prefix)

		run_with_singularity(self.config.presto_config.singularity_image,
						self.config.presto_config.singularity_flags, accelsearch_command)

	def run_rfifind(self, input_file, beam_name):

		rfifind_cmd = "rfifind -o {}_{} {} {}".format(self.out_prefix, beam_name, self.config.presto_config.rfifind_flags, input_file)

		run_with_singularity(self.config.presto_config.singularity_image,
						self.config.presto_config.singularity_flags, rfifind_cmd)

	def run_filtool(self, input_file, beam_name):
		beam_num = int(re.findall('\\d+', beam_name)[0])
		filtools_cmd ="filtool -t 16  -z kadaneF 8 4 zdot -i {} -telescope Meerkat -o {}_{} -f {}".format(beam_num, self.out_prefix,beam_name, input_file)
		run_with_singularity(self.config.pulsarX_config.singularity_image,
	 					self.config.pulsarX_config.singularity_flags,filtools_cmd)

	def make_birds_file(self, ACCEL_0_filename, width_Hz, flag_grow=1, sigma_birdies_threshold=4):
		infile_nameonly = os.path.basename(ACCEL_0_filename)
		infile_basename = infile_nameonly.replace("_ACCEL_0", "")
		birds_filename = ACCEL_0_filename.replace("_ACCEL_0", ".birds")

		#Skip first three lines

		print ("make_birds_file:: Opening the candidates: %s") % (ACCEL_0_filename)
		candidate_birdies = sifting.candlist_from_candfile(ACCEL_0_filename)
		candidate_birdies.reject_threshold(sigma_birdies_threshold)

		#Write down candidates above a certain sigma threshold
		list_birdies = candidate_birdies.cands

		print ("make_birds_file:: Number of birdies = %d") % (len(list_birdies))
		file_birdies = open(birds_filename, "w")
		print ("make_birds_file:: File_birdies: %s") % (birds_filename)

		for cand in list_birdies:
		        file_birdies.write("%.3f     %.20f \n" % (cand.f, width_Hz)  )
		file_birdies.close()

		return birds_filename

	def find_rfi(self, beam_name):

		file_name = glob.glob(os.path.join(self.config.file_locations.processing_path, beam_name)+ "/*.fil")[0]
		self.run_filtool(file_name, beam_name)
		self.ledger.update_status(beam_name, self.status_manager.FILTOOLS)

		self.run_rfifind(file_name, beam_name)
		self.ledger.update_status(beam_name, self.status_manager.RFIFIND_MASK)

		self.do_accelsearch(file_name, beam_name)
		self.ledger.update_status(beam_name, self.status_manager.ZERO_DM_ACCELSEARCH)

	def run(self, beam_name, search_type):
	    self.find_rfi(self, beam_name)


import logging

from flask import Flask, render_template, abort, redirect

from seasons import CURRENT_SEASON, ALL_SEASONS

app = Flask(__name__)

@app.context_processor
def inject_season_list():
    return dict(seasons=sorted(ALL_SEASONS.keys(), reverse=True))

@app.route("/")
def home():
    return redirect(f"/{CURRENT_SEASON.year}")

@app.route("/<int:year>")
def standings(year: int):
    season = ALL_SEASONS.get(year)
    if season is None:
        abort(404)
    return render_template("home.html", season=season)

@app.route("/<int:year>/<manager>")
def team_stats(year: int, manager: str):
    season = ALL_SEASONS.get(year)
    if season is None:
        abort(404)
    team = season.teams.get(manager.lower())
    if team is None:
        abort(404)
    team.fetch_all_stats()
    return render_template("team.html", team=team)

@app.template_filter('pluralize')
def pluralize(number: int, singular='', plural='s') -> str:
    # Ref: https://stackoverflow.com/a/22336061/8534196
    return singular if number == 1 else plural

if __name__ == "__main__":
    logging.basicConfig(format="%(levelname)-7s %(message)s", level=logging.INFO)
    app.run()


import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

col_names=['Analyzer Similarity Pair', 'mAP', 'gm_mAP']
output_data = pd.read_csv('output.csv', header=None, names=col_names)

df = pd.DataFrame(output_data)
ind = np.arange(16)
labels = df.iloc[:, 0]
map = df.iloc[:, 1]

fig=plt.figure(figsize=(10,8))

ax = plt.subplot(111)
width = 0.35
ax.bar(ind, map, width, color='blue', label="mAP Score")
ax.legend(loc='upper right', bbox_to_anchor=(1.1,1.1))

plt.xticks(ind + width / 2, ('0', '1', '2', '3', '4', '5', '6','7', '8', '9','10', '11', '12', '13', '14', '15'))

#stack overflow reference - https://stackoverflow.com/questions/62941033/how-to-turn-x-axis-values-into-a-legend-for-matplotlib-bar-graph
x_legend = '\n\n'.join(f'{index} - {analyzer_similarity}' for index,analyzer_similarity in zip(ind,labels))
t = ax.text(.63,.25,x_legend,transform=ax.figure.transFigure, color='blue')
plt.subplots_adjust(right=.6)

plt.xlabel('Analyzer and Similarity Pairs')
plt.ylabel('trec_eval Score')
plt.title('Search Engine Evaluation')

plt.show()


from typing import Any, List, Optional, Sequence, Union

import torch

class EnsembleMLP(torch.nn.Module):
    def __init__(
        self,
        *,
        n_inputs: int,
        n_hidden_units: Optional[Union[int, Sequence[int]]] = None,
        n_outputs: Optional[int] = None,
        n_heads: int = 10,
        dropout_prop: Optional[float] = None,
        batch_norm: bool = False,
        manual_expand_input: bool = False,
        manual_collapse_output: bool = False,
        activation: Any = None,
    ) -> None:
        super().__init__()

        if isinstance(n_hidden_units, int):
            n_hidden_units = [n_hidden_units]

        if n_hidden_units is None:
            n_hidden_units = []
        n_hidden_units = list(n_hidden_units)

        sequence: List[torch.nn.Module] = []
        for i, (n_in, n_out) in enumerate(zip([n_inputs] + list(n_hidden_units[:-1]), n_hidden_units)):
            layer = []
            layer.append(torch.nn.Conv1d(in_channels=n_in * n_heads, out_channels=n_out * n_heads, kernel_size=1, groups=n_heads))

            if activation is None:
                layer.append(torch.nn.ReLU())
            else:
                layer.append(activation())

            if batch_norm:
                layer.append(torch.nn.BatchNorm1d(n_out * n_heads))
            if dropout_prop is not None:
                layer.append(torch.nn.Dropout(dropout_prop))

            sequence.append(torch.nn.Sequential(*layer))

        if n_outputs is not None:
            last_size = n_hidden_units[-1] if n_hidden_units else n_inputs
            sequence.append(
                torch.nn.Conv1d(in_channels=last_size * n_heads, out_channels=n_outputs * n_heads, kernel_size=1, groups=n_heads)
            )

        self.model = torch.nn.Sequential(*sequence)
        self.n_outputs = n_hidden_units[-1] if n_outputs is None else n_outputs
        self.n_heads = n_heads
        self.manual_expand_input = manual_expand_input
        self.manual_collapse_output = manual_collapse_output

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        batch_size = x.shape[0]
        if not self.manual_expand_input:
            x = self.expand(x.clone())

        x = self.model(x)

        if not self.manual_collapse_output:
            x = x.view(batch_size, self.n_heads, self.n_outputs)

        return x

    def expand(self, x: torch.Tensor):
        return x.repeat(1, self.n_heads).unsqueeze(-1)


#!/usr/bin/env python3

import struct
import rospy
from std_msgs.msg import Int8

file = open( "/dev/input/mice", "rb" );

def publish():
	data_pub = rospy.Publisher('Mouse_RawDATA', Int8, queue_size=10)
	rospy.init_node('Mouse_Data_Publisher')
	rate = rospy.Rate(10)
	while not rospy.is_shutdown():
		buf = file.read(3)
		#button = ord( buf[0] )
		button = buf[0]
		bLeft = button & 0x1
		bMiddle = ( button & 0x4 ) > 0
		bRight = ( button & 0x2 ) > 0
		x,y = struct.unpack( "bb", buf[1:] )
		print ("L:%d, M: %d, R: %d, x: %d, y: %d\n" % (bLeft,bMiddle,bRight, x, y) )
		data_var = bLeft+bRight*2
		data_pub.publish(data_var)
		rospy.loginfo(data_var)
		rate.sleep()

if __name__ == '__main__':
	try:
		publish()
	except rospy.ROSInterruptException:
		pass


import RPi.GPIO as GPIO
import time

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)

class MotionSensor:
    def __init__(self, sensor_pin, led_pin=None,
                 movement_min=5, read_delay=2.5):
        self.sensor_pin = sensor_pin
        self.led_pin = led_pin
        self.movement_min = movement_min
        self.read_delay = read_delay
        # Read output from PIR motion sensor
        GPIO.setup(self.sensor_pin, GPIO.IN)
        # LED output pin
        if(self.led_pin):
            GPIO.setup(self.led_pin, GPIO.OUT)

    def start(self, on_motion_detected):
        motion_count = 0
        while True:
            time.sleep(self.read_delay)
            i = GPIO.input(self.sensor_pin)
            # When output from motion sensor is LOW
            if i == 0:
                if self.led_pin:
                    # Turn OFF LED
                    GPIO.output(self.led_pin, 0)

                motion_count = 0
            elif i == 1:
                if self.led_pin:
                    # Turn ON LED
                    GPIO.output(self.led_pin, 1)

                if motion_count == self.movement_min:
                    on_motion_detected(time.time())
                    motion_count = 0
                else:
                    motion_count += 1

if __name__ == "__main__":
    sensor = MotionSensor(11, led_pin=12)
    sensor.start(on_motion_detected=lambda t: print(t))


import requests
from bs4 import BeautifulSoup

def extract_section(url, section):
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')

    # Find the section header
    header = soup.find(
        lambda tag: tag.name == 'p' and f'ITEM {section}' in tag.get_text(strip=True, separator=' ').upper())

    if not header:
        return None

    # Extract content until the next ITEM is found
    content = []
    sibling = header.find_next_sibling()

    while sibling and not sibling.get_text(strip=True, separator=' ').startswith('ITEM'):
        content.append(sibling)
        sibling = sibling.find_next_sibling()

    return content

url_10k = "https://www.sec.gov/Archives/edgar/data/1318605/000095017023001409/tsla-20221231.htm"
section_1A = extract_section(url_10k, "1A")

if section_1A:
    for tag in section_1A:
        print(tag.get_text(strip=True))
else:
    print("Section not found")


# APP1: dfs. each time pick one chandidate
# Time: O(n * (target // min(candidates))) space: O(n) stack

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        if not candidates:
            return []
        res = []
        self.dfs(candidates, 0, target, [], res)
        return res

    def dfs(self, candi, idx, target, seq, res):
        if idx == len(candi) and target == 0:
            res.append(copy.deepcopy(seq))
            return
        if target < 0 or idx >= len(candi):
            return
        limit = target // candi[idx]
        for i in range(limit + 1):
            seq.extend([candi[idx]] * i)
            self.dfs(candi, idx + 1, target - i * candi[idx], seq, res)
            for _ in range(i):
                seq.pop()

# APP2: dfs using for loop on index
class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        if not candidates:
            return []
        res = []
        self.dfs(candidates, target, 0, [], res)
        return res

    def dfs(self, nums, target, idx, path, res):
        if target == 0:
            res.append(copy.deepcopy(path))
            return
        if target < 0:
            return
        for i in range(idx, len(nums)):
            path.append(nums[i])
            self.dfs(nums, target - nums[i], i, path, res)
            path.pop()


#   날짜 : 1월 13일
#   작성자 : 윤찬우
#   프로그램 : 예제
'''
#   ex1) 딕셔너리에 과일 이름과 수량을 저장(3개)한다.
#   pickle 모듈을 사용해서 이진파일 객체를 쓰고 읽는 프로그램을 작성한다.
import pickle as p
fruits = {'수박' : 3, '딸기' : 5, '자몽' : 5}
file = open("fruits.b",'wb')
p.dump(fruits, file)
file.close()

file = open("fruits.b", "rb")
print(p.load(file))
file.close()

#   ex2) 학생 3명에 대한 딕셔너리 생성
#   key, value
#   이름, 학생 3명의 이름
#   학과, 학생 3명의 학과
#   학번, 학생 3명의 학번

stu = {'이름' : ['구민재', '김민재', '윤찬우'], '학과' : ['소프트웨어', '소프트웨어', '컴퓨터공학'], '학번' : [20150001, 20150002, 20150003]}
file = open("fruits.b",'wb')
p.dump(stu, file)
file.close()

file = open("stu.p", "rb")
print(p.load(file))
file.close()
'''
#   ex3) 문자열 암호화
text = "윤찬우" # 평문
encrypt = "" # 암호문
for i in text:
    x = ord(i) # 문자의 코드값을 구한다.
    x += 1 # 코드값 1증가
    c = chr(x) # 증가된 코드값에 해당하는 문자를 계산한다.
    encrypt += c # 암호문에 추가한다.
print(encrypt)

#   ex4) 문자열 복호화
text = ""
for i in encrypt:
    x = ord(i) - 1
    c = chr(x)
    text += c
print(text)

#   ex5) 이름을 입력하는 입력박스를 작성한다.
from tkinter import*
w = Tk()
name = Label(w, text = "이름")
name_input = Entry(w)
name.pack()
name_input.pack()


# 문자열 내 p와 y의 개수

def solution(s):
    answer = True

    # y의 개수와 p의 개수
    cntY = s.count('Y') + s.count('y')
    cntP = s.count('P') + s.count('p')

    if cntY != cntP:
        answer = False

    return answer

s = "pPoooyY"
solution(s)


from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core.paginator import Paginator
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse
from django.views import View
from django.views.generic import CreateView
# from comment.forms import CommentForm
# from comment.models import Comment
from comment.models import Comment
from .forms import ArticlePostForm
from .models import ArticlePost, ArticleColumn
from django.db.models import Q
import markdown

class ArticleCreateView(CreateView):
    """类视图新建文章"""
    model = ArticlePost

    fields = '__all__'
    template_name = 'article/create_by_class_view.html'

# 视图函数
def article_list(request):
    # 取出所有博客文章
    # 从url中提取查询参数
    search = request.GET.get('search')
    order = request.GET.get('order')
    column = request.GET.get('column')
    tag = request.GET.get('tag')

    # 初始化查询集
    article_list = ArticlePost.objects.all()

    # 搜索查询集
    if search:
        # 用Q对象进行联合搜索
        article_list = article_list.filter(
            Q(title__icontains=search) |
            Q(body__icontains=search)
        )
    else:
        search = ''

    # 栏目查询集
    if column is not None and column.isdigit():
        article_list = article_list.filter(column=column)

    # 标签查询集
    if tag and tag != 'None':
        article_list = article_list.filter(tags__name__in=[tag])

    # 查询集排序
    if order == 'total_views':
        article_list = article_list.order_by('-total_views')

    # 每页显示3篇文章
    paginator = Paginator(article_list, 3)
    # 获取url中的页码
    page = request.GET.get('page')
    # 将导航对象相应的页码内容返回给articles
    articles = paginator.get_page(page)

    # 需要传递给模板（templates）的对象
    context = {'articles': articles,
               'order': order,
               'search': search,
               'column': column,
               'tag': tag, }
    # render函数：载入模板，并返回contenxt对象
    return render(request, 'article/list.html', context)

# 文章详情
def article_detail(request, id):
    # 取出相应的文章
    article = get_object_or_404(ArticlePost, id=id)
    # 浏览量+1
    article.total_views += 1
    article.save(update_fields=['total_views'])

    # 修改markdown语法渲染
    md = markdown.Markdown(
        extensions=[
            # 包含缩写、表哥等常用扩展
            'markdown.extensions.extra',
            # 语法高亮扩展
            'markdown.extensions.codehilite',
            # 目录扩展
            'markdown.extensions.toc',
        ]
    )
    article.body = md.convert(article.body)
    # 取出文章评论
    comments = Comment.objects.filter(article=id)

    # 新增了md.toc对象
    context = {'article': article, 'toc': md.toc,'comments': comments }
    # 载入模板，并返回contenxt对象
    return render(request, 'article/detail.html', context)

# 写文章的视图
@login_required(login_url='/userprofile/login/')
def article_create(request):
    # 判断用户是否提交数据
    if request.method == "POST":
        # 将提交的数据赋值到表单实例中
        article_post_form = ArticlePostForm(request.POST, request.FILES)
        # 判断提交的数据是否满足模型的要求
        if article_post_form.is_valid():
            # 保存数据，但暂时不提交到数据库中
            new_article = article_post_form.save(commit=False)
            # 指定数据库中id=1的用户为作者
            # 如果你进行过删除数据表的操作，可能会找不到id=1的用户
            # 指定目前登录的用户为作者
            new_article.author = User.objects.get(id=request.user.id)
            if request.POST['column'] != 'none':
                new_article.column = ArticleColumn.objects.get(id=request.POST['column'])
            # 将新文章保存到数据库中
            new_article.save()
            # 新增代码，保存tags的多对多关系
            article_post_form.save_m2m()
            # 完成后返回到文章列表
            return redirect("article:article_list")
        # 如果数据不合法，返回错误信息
        else:
            return HttpResponse("表单内容有误，请重新填写。")
    # 如果用户请求获取数据
    else:
        # 创建表单类实例
        article_post_form = ArticlePostForm()
        # 新增栏目
        columns = ArticleColumn.objects.all()
        # 赋值上下文
        context = {'article_post_form': article_post_form, 'columns': columns}
        # 返回模板
        return render(request, 'article/create.html', context)

# 删文章
# def article_delete(request, id):
#     # 根据id获取需要删除的文章
#     article = ArticlePost.objects.get(id=id)
#     # 调用delete()方法删除文章
#     article.delete()
#     # 完成删除后返回文章列表
#     return redirect("article:article_list")

# 安全删除文章
@login_required(login_url='/userprofile/login/')
def article_safe_delete(request, id):
    if request.method == 'POST':
        article = ArticlePost.objects.get(id=id)
        # 过滤非作者的用户
        if request.user != article.author:
            return HttpResponse("抱歉，你无权删除这篇文章。")
        article.delete()
        return redirect("article:article_list")
    else:
        return HttpResponse("仅允许post请求")

# 更新文章
@login_required(login_url='/userprofile/login/')
def article_updatee(request, id):
    """
    更新文章的视图函数
    通过POST方法提交表单，更新titile、body字段
    GET方法进入初始表单页面
    id: 文章的id
    """
    # 获取需要修改的具体文章对象
    article = ArticlePost.objects.get(id=id)
    # 过滤非作者的用户
    if request.user != article.author:
        return HttpResponse("抱歉，你无权修改这篇文章。")
    # 判断用户是否为POST提交表单数据
    if request.method == "POST":
        # 将提交的数据赋值到表单实例中
        article_post_form = ArticlePostForm(data=request.POST)
        # 判断提交的数据是否满足模型的要求
        if article_post_form.is_valid():
            # 保存新写入的title、body数据并保存
            article.title = request.POST['title']
            article.body = request.POST['body']
            if request.FILES.get('avatar'):
                article.avatar = request.FILES.get('avatar')
            article.tags.set(*request.POST.get('tags').split(','), clear=True)

            # 新增的代码
            if request.POST['column'] != 'none':
                article.column = ArticleColumn.objects.get(id=request.POST['column'])
            else:
                article.column = None
            article.save()
            # 完成后返回到修改后的文章中。需传入文章的id值
            return redirect("article:article_detail", id=id)
        # 如果数据不合法，返回错误信息
        else:
            return HttpResponse("表单内容有误，请重新填写。")

    else:
        # 创建表单类实例
        article_post_form = ArticlePostForm()
        # 新增及修改的代码
        columns = ArticleColumn.objects.all
        # 赋值上下文，将article文章对象也传递进去，以便提取旧的内容
        context = {'article': article, 'article_post_form': article_post_form,
                   'columns': columns,
                   'tags': ','.join([x for x in article.tags.names()]), }
        # 将响应返回到模板中
        return render(request, 'article/updatee.html', context)

class IncreaseLikesView(View):
    """点赞数+1"""
    def post(self, request, *args, **kwargs):
        article = ArticlePost.objects.get(id=kwargs.get('id'))
        article.likes += 1
        article.save()
        return HttpResponse('success')


import numpy as np
"""
Contains the conjugate gradient helper function
"""
def helper_PCG_direct(A, b, tol=1e-10, max_iter=None, x0=None, M=None):
    """
    Solves a linear system of equations Ax = b using a preconditioned conjugate
    gradient method within a user-defined tolerance

    Parameters
    ----------
    A : LHS Matrix (2-dimensional numpy array)
    b : RHS vector (1-dimensional numpy array)
    tol : User-defined tolerance for residual convergence (Default = 1.e-10)
    max_iter : User-defined maximum number of iterations for convergence (Default = 2 * len(b))
    x0 : User-specified guess vector (Default = zero-array)
    M : Preconditioner Matrix (2-dimensional numpy array)  (Default = Identity Matrix)

    Returns
    -------
    x : solution vector of Ax = b

    Notes
    -----

    Examples
    --------

    x = helper_PCG_direct(A, b)
    ...

    """

    if max_iter is None:
        max_iter = 2*len(b)
    if x0 is None:
        x = np.zeros_like(b)
    else:
        x = x0
    if M is None:
        M = np.diag(A)

    r = b - np.dot(A,x)
    z = r/M
    n = len(b)
    p = z
    res_k_norm = np.dot(r, z)
    print("Starting Conjugate Gradient Iterations...\n")
    for iteration in range(2*n):
        Ap = np.dot(A, p)
        alpha = res_k_norm / np.dot(p, Ap)
        x += alpha * p
        r -= alpha * Ap
        z = r/M
        res_kplus1_norm = np.dot(r, z)
        beta = res_kplus1_norm / res_k_norm
        res_k_norm = res_kplus1_norm
        rms = np.sqrt(np.sum(r**2) / len(r))
        print('CG Iteration %3d: RMS = %3.8f' % (iteration, rms))
        if (res_kplus1_norm < tol) or (iteration > max_iter):
            print('\nConverged!!\n')
            break
        p = beta * p + z
    return x


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
from django.conf import settings

class Migration(migrations.Migration):

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
        ('kb', '0007_auto_20170107_1437'),
    ]

    operations = [
        migrations.CreateModel(
            name='Kb_Magazine',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
            ],
        ),
        migrations.CreateModel(
            name='Magazine',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('title', models.CharField(default=b'\xe7\xbe\x8e\xe9\xa3\x9f\xe6\x8e\xa8\xe8\x8d\x90', max_length=1000, verbose_name=b'\xe6\x9c\x9f\xe5\x88\x8a\xe5\x90\x8d\xe7\xa7\xb0')),
                ('date', models.DateTimeField(auto_now_add=True)),
                ('count_read', models.IntegerField(default=0, verbose_name='\u9605\u8bfb')),
                ('real_count_read', models.IntegerField(default=0, verbose_name='\u9605\u8bfb')),
                ('count_good', models.IntegerField(default=0, verbose_name='\u8d5e')),
                ('real_count_good', models.IntegerField(default=0, verbose_name='\u8d5e')),
                ('author', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'ordering': ['-id'],
            },
        ),
        migrations.AlterModelOptions(
            name='article',
            options={'ordering': ['-date'], 'permissions': (('cannot_publish_kb', '\u9ed1\u540d\u5355:\u4e0d\u80fd\u53d1\u5e16\uff0c\u4e0d\u80fd\u56de\u5e16'), ('cannot_modify_kb', '\u4fee\u6539\u5e16\u5b50\u6743\u9650:\u6ca1\u6709\u6743\u9650\u4fee\u6539\u5e16\u5b50'), ('can_modify_all_kb_top_pic', '\u53ef\u4ee5\u8bbe\u7f6e\u6240\u6709\u5e16\u5b50\u7684\u9876\u56fe'), ('can_modify_all_kb', '\u7ba1\u7406\u5458\u53ef\u4ee5\u4fee\u6539\u6240\u6709\u4eba\u7684\u8d34\u5b50'), ('can_del_all_kb', '\u7ba1\u7406\u5458\u53ef\u4ee5\u5220\u9664\u6240\u6709\u4eba\u7684\u8d34\u5b50'), ('manage_all_kb', '\u7ba1\u7406\u8d34\u5b50\uff1a\u5220\u9664\uff0c\u8bbe\u4e3a\u7cbe\u534e\uff0c\u8bbe\u7f6e\u8f6e\u64ad\u56fe.'), ('check_kb_autor', '\u6709\u67e5\u770b\u5e16\u5b50\u4f5c\u8005\u540d\u79f0.'))},
        ),
        migrations.AlterModelOptions(
            name='kb_recommend',
            options={'ordering': ['-id']},
        ),
        migrations.AddField(
            model_name='kb_magazine',
            name='kb',
            field=models.ForeignKey(to='kb.Article'),
        ),
    ]


from contextlib import contextmanager
from functools import wraps
import inspect
import os
import platform
from typing import Any, Callable, Dict, Union

import pandas as pd
from pandas.core.internals import BlockManager, make_block

from .config import qargs, qhome, qlic
from ._version import version as __version__
from .exceptions import PyKXException

__all__ = [
    'num_available_cores',
    'BlockManagerUnconsolidated',
    'ClassPropertyDescriptor',
    'classproperty',
    'attr_as',
    'cached_property',
    'debug_environment',
    'df_from_arrays',
    'get_default_args',
    'normalize_to_bytes',
    'normalize_to_str',
    'once',
    'slice_to_range',
    'subclasses',
]

def __dir__():
    return sorted(__all__)

def num_available_cores() -> int:
    if hasattr(os, 'sched_getaffinity'):
        return len(os.sched_getaffinity(0))
    elif platform.system() == 'Windows': # nocov
        import ctypes # nocov
        import ctypes.wintypes # nocov
        kernel32 = ctypes.WinDLL('kernel32') # nocov
        DWORD_PTR = ctypes.wintypes.WPARAM # nocov
        PDWORD_PTR = ctypes.POINTER(DWORD_PTR) # nocov
        GetCurrentProcess = kernel32.GetCurrentProcess # nocov
        GetCurrentProcess.restype = ctypes.wintypes.HANDLE # nocov
        GetProcessAffinityMask = kernel32.GetProcessAffinityMask # nocov
        GetProcessAffinityMask.argtypes = (ctypes.wintypes.HANDLE, PDWORD_PTR, PDWORD_PTR) # nocov
        mask = DWORD_PTR() # nocov
        if not GetProcessAffinityMask(GetCurrentProcess(), ctypes.byref(mask), ctypes.byref(DWORD_PTR())): # noqa nocov
            raise PyKXException("Call to 'GetProcessAffinityMask' failed") # nocov
        return bin(mask.value).count('1') # nocov
    # No way to determine the number of cores available in this case. The CPU count will work in
    # most scenarios, and for those in which it does not there is no known workaround.
    return os.cpu_count() # nocov

# TODO: Once Python 3.7 support is dropped, we can replace this with `functools.cached_property`
class cached_property:
    """Property-like descriptor which overwrites itself with the first obtained property value."""
    def __init__(self, func):
        self.func = func
        self.attrname = func.__name__
        self.__doc__ = func.__doc__

    def __get__(self, instance, owner=None):
        if instance is None:
            return self
        value = self.func(instance)
        instance.__dict__[self.attrname] = value
        return value

def slice_to_range(s: slice, n: int) -> range:
    """Converts a slice and collection size into a range whose indices match the slice.

    Parameters:
        s: The slice to be converted into a range of indices.
        n: The size of the container the slice was going to be applied to.

    Returns:
        A range whose indices match the slice
    """
    return range(
        s.start or 0,
        n if s.stop is None else min(s.stop, n),
        s.step or 1
    )

def subclasses(cls: type) -> set:
    """Given a class, returns the set of all subclasses of that class (including itself)."""
    def _subclasses(cls):
        yield cls
        for subclass in cls.__subclasses__():
            yield subclass
            yield from _subclasses(subclass)
    return set(_subclasses(cls))

def normalize_to_bytes(s: Union[str, bytes], name: str = 'Argument') -> bytes:
    """Given text as a `str` or `bytes` object, returns that text as a `bytes` object.

    Parameters:
        s: The text as a `str` or `bytes` object.
        name: An identifiable name for `s` for the purpose of producing clear error messages.

    Returns:
        The given text as a `bytes` object.
    """
    if isinstance(s, str):
        return s.encode()
    elif isinstance(s, bytes):
        return s
    raise TypeError(f"{name} must be of type 'str' or 'bytes'")

def normalize_to_str(s: Union[str, bytes], name: str = 'Argument') -> str:
    """Given text as a `str` or `bytes` object, returns that text as a `str` object.

    Parameters:
        s: The text as a `str` or `bytes` object.
        name: An identifiable name for `s` for the purpose of producing clear error messages.

    Returns:
        The given text as a `str` object.
    """
    if isinstance(s, str):
        return s
    elif isinstance(s, bytes):
        return s.decode()
    raise TypeError(f"{name} must be of type 'str' or 'bytes'")

@contextmanager
def attr_as(x, name: str, val) -> None:
    """Temporarily replaces attribute `name` of `x` with `val`."""
    already_exists = hasattr(x, name)
    if already_exists:
        prev_val = getattr(x, name)
    setattr(x, name, val)
    try:
        yield
    finally:
        if already_exists:
            setattr(x, name, prev_val)
        else:
            delattr(x, name)

def once(f):
    """Decorator that makes it so that a function can only be run once.

    The return value is cached permanently. Repeated calls return that cached value.
    """
    @wraps(f)
    def wrapper(*args, **kwargs):
        if not wrapper.was_run:
            wrapper.was_run = True
            wrapper.result = f(*args, **kwargs)
        return wrapper.result
    wrapper.was_run = False
    return wrapper

class ClassPropertyDescriptor(object):

    def __init__(self, fget, fset=None):
        self.fget = fget
        self.fset = fset

    def __get__(self, obj, klass=None):
        if klass is None:
            klass = type(obj)
        return self.fget.__get__(obj, klass)()

    def __set__(self, obj, value):
        if not self.fset:
            raise AttributeError("can't set attribute")
        type_ = type(obj)
        return self.fset.__get__(obj, type_)(value)

    def setter(self, func):
        if not isinstance(func, (classmethod, staticmethod)):
            func = classmethod(func)
        self.fset = func
        return self

def classproperty(func):
    if not isinstance(func, (classmethod, staticmethod)):
        func = classmethod(func)
    return ClassPropertyDescriptor(func)

class BlockManagerUnconsolidated(BlockManager):
    """BlockManager that does not consolidate blocks, thus avoiding copying."""

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._is_consolidated = False
        self._known_consolidated = False

    def __reduce__(self):
        # This works in CI but fails in some other esoteric situations
        # return (BlockManager, super().__reduce__()[1])
        # Manually reassigning the class attribute to the pandas BlockManager fixes this function
        # in those situations.
        c = self.copy()
        c.__class__ = BlockManager
        return c.__reduce__()

    def _consolidate_inplace(self): # nocov
        pass

    def _consolidate(self): # nocov
        return self.blocks

def df_from_arrays(columns, arrays, index):
    """Create a DataFrame from Numpy arrays without copying."""
    blocks = tuple(
        make_block(values=a.reshape((1, len(a))), placement=(i,))
        for i, a in enumerate(arrays)
    )
    return pd.DataFrame(
        BlockManagerUnconsolidated(axes=[columns, index], blocks=blocks),
        copy=False
    )

    # TODO: The following code probably ought to work, but some parts of Pandas still rely on the
    # assumption that a BlockManager is being used. Next time we update the minimum Pandas version
    # required by PyKX we should check if we can use an ArrayManager (KXI-9722).

    # return pd.DataFrame(
    #     ArrayManager(arrays=arrays, axes=[index, columns]),
    #     copy=False
    # )

def get_default_args(f: Callable) -> Dict[str, Any]:
    """Returns a dictionary mapping each parameter name to its default argument.

    Parameters:
        f: An function which can be inspected by `inspect.signature`.

    Returns:
        A dictionary mapping each parameter name to its default arguments. Parameters which do not
        have default arguments are not added to this dictionary.
    """
    return {
        k: v.default for k, v in inspect.signature(f).parameters.items()
        if v.default is not inspect.Parameter.empty
    }

def debug_environment(detailed=False, return_info=False):
    """Displays information about your environment to help debug issues."""
    debug_info = ""
    debug_info += pykx_information()
    debug_info += python_information()
    debug_info += platform_information()
    debug_info += env_information()
    debug_info += lic_information(detailed=detailed)
    debug_info += q_information()
    if return_info:
        return debug_info
    print(debug_info)
    return None

def pykx_information():
    pykx_info = "**** PyKX information ****\n"
    pykx_info += f"pykx.args: {qargs}\n"
    pykx_info += f"pykx.qhome: {qhome}\n"
    pykx_info += f"pykx.qlic: {qlic}\n"

    from .config import licensed
    pykx_info += f"pykx.licensed: {licensed}\n"
    pykx_info += f"pykx.__version__: {__version__}\n"
    pykx_info += f"pykx.file: {__file__}\n"
    return pykx_info

def python_information():
    py_info = '\n**** Python information ****\n'
    try:
        import sys
        py_info += f"sys.version: {sys.version}\n"

        import importlib.metadata
        py_info += f"pandas: {importlib.metadata.version('pandas')}\n"
        py_info += f"numpy: {importlib.metadata.version('numpy')}\n"
        py_info += f"pytz: {importlib.metadata.version('pytz')}\n"

        import shutil
        py_info += f"which python: {shutil.which('python')}\n"
        py_info += f"which python3: {shutil.which('python3')}\n"
    except Exception:
        pass
    try:
        import find_libpython
        py_info += f"find_libpython: {find_libpython.find_libpython()}\n"
    except BaseException:
        pass
    return py_info

def platform_information():
    platform_info = '\n**** Platform information ****\n'
    platform_info += f"platform.platform: {platform.platform()}\n"
    return platform_info

def env_information():
    env_info = '\n**** PyKX Environment Variables ****\n'

    envs = ['PYKX_IGNORE_QHOME', 'PYKX_KEEP_LOCAL_TIMES', 'PYKX_ALLOCATOR',
            'PYKX_GC', 'PYKX_LOAD_PYARROW_UNSAFE', 'PYKX_MAX_ERROR_LENGTH',
            'PYKX_NOQCE', 'PYKX_Q_LIB_LOCATION', 'PYKX_RELEASE_GIL', 'PYKX_Q_LOCK',
            'PYKX_DEFAULT_CONVERSION', 'PYKX_SKIP_UNDERQ', 'PYKX_UNSET_GLOBALS',
            'PYKX_DEBUG_INSIGHTS_LIBRARIES', 'PYKX_EXECUTABLE', 'PYKX_PYTHON_LIB_PATH',
            'PYKX_PYTHON_BASE_PATH', 'PYKX_PYTHON_HOME_PATH', 'PYKX_DIR',
            'PYKX_UNLICENSED', 'PYKX_LICENSED'
            ]

    for x in envs:
        env_info += f"{x}: {os.getenv(x, '')}\n"

    env_info += '\n**** PyKX Deprecated Environment Variables ****\n'
    deps = ['SKIP_UNDERQ', 'UNSET_PYKX_GLOBALS', 'KEEP_LOCAL_TIMES', 'IGNORE_QHOME']

    for x in deps:
        env_info += f"{x}: {os.getenv(x, '')}\n"

    env_info += '\n**** q Environment Variables ****\n'
    qenv = ['QARGS', 'QHOME', 'QLIC', 'QINIT']

    for x in qenv:
        env_info += f"{x}: {os.getenv(x, '')}\n"
    return env_info

def lic_information(detailed=False):
    lic_info = '\n**** License information ****\n'

    lic_info += f"pykx.qlic directory: {os.path.isdir(qlic)}\n"
    lic_info += f"pykx.qhome writable: {os.access(qhome, os.W_OK)}\n"

    if detailed:
        lic_info += f"pykx.qhome contents: {os.listdir(qhome)}\n"
        lic_info += f"pykx.lic contents: {os.listdir(qlic)}\n"

    try:
        import re
        klic = re.compile('k.\\.lic').match
        qhomelics = list(filter(klic, os.listdir(qhome)))
        lic_info += f"pykx.qhome lics: {qhomelics}\n"
        qliclics = list(filter(klic, os.listdir(qlic)))
        lic_info += f"pykx.qlic lics: {qliclics}\n"
    except Exception:
        pass
    return lic_info

def q_information():
    q_info = '\n**** q information ****\n'

    try:
        import shutil
        import subprocess
        whichq = shutil.which('q')
        q_info += f"which q: {whichq}\n"
        if whichq is not None:
            q_info += ('q info: \n')
            if platform.system() == 'Windows': # nocov:
                q_info += subprocess.check_output("powershell -NoProfile -ExecutionPolicy ByPass \"echo \\\"-1 .Q.s1 (.z.o;.z.K;.z.k);-1 .Q.s1 .z.l 4;\\\" | q -c 200 200\"", shell=True).decode(encoding='utf-8') # noqa: E501
            else: # nocov:
                q_info += subprocess.check_output("echo \"-1 .Q.s1 (.z.o;.z.K;.z.k);-1 .Q.s1 .z.l 4;\" | q -c 200 200", shell=True).decode(encoding='utf-8') # noqa: E501
    except Exception:
        pass
    return q_info