import logging
import math
import os
import struct
from typing import Any, Dict, Generator, Iterable, List, Optional, Set, Tuple, Union

from volatility.framework import constants, exceptions, interfaces, layers
from volatility.framework.configuration import requirements
from volatility.framework.layers import intel, scanners
from volatility.framework.symbols import intermed, native

if __name__ == "__main__":
    import sys

    sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))

vollog = logging.getLogger(__name__)

ValidKernelsType = Dict[str, Tuple[int, Dict[str, Optional[Union[bytes, str, int]]]]]
KernelsType = Iterable[Dict[str, Any]]

class PdbSignatureScanner(interfaces.layers.ScannerInterface):
    """A :class:`~volatility.framework.interfaces.layers.ScannerInterface` based scanner use to identify Windows PDB records

    Args:
        pdb_names: A list of bytestrings, used to match pdb signatures against the pdb names within the records.

    .. note:: The pdb_names must be a list of byte strings, unicode strs will not match against the data scanned
    """
    overlap = 0x4000
    """The size of overlap needed for the signature to ensure data cannot hide between two scanned chunks"""
    thread_safe = True
    """Determines whether the scanner accesses global variables in a thread safe manner (for use with :mod:`multiprocessing`)"""

    _RSDS_format = struct.Struct("<16BI")

    def __init__(self, pdb_names: List[bytes]) -> None:
        super().__init__()
        self._pdb_names = pdb_names

    def __call__(self, data: bytes, data_offset: int) -> Generator[Tuple[str, Any, bytes, int], None, None]:
        sig = data.find(b"RSDS")
        while sig >= 0:
            null = data.find(b'\0', sig + 4 + self._RSDS_format.size)
            if null > -1:
                if (null - sig - self._RSDS_format.size) <= 100:
                    name_offset = sig + 4 + self._RSDS_format.size
                    pdb_name = data[name_offset:null]
                    if pdb_name in self._pdb_names:

                        ## this ordering is intentional due to mixed endianness in the GUID
                        (g3, g2, g1, g0, g5, g4, g7, g6, g8, g9, ga, gb, gc, gd, ge, gf, a) = \
                            self._RSDS_format.unpack(data[sig + 4:name_offset])

                        guid = (16 * '{:02X}').format(g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, ga, gb, gc, gd, ge, gf)
                        if sig < self.chunk_size:
                            yield (guid, a, pdb_name, data_offset + sig)
            sig = data.find(b"RSDS", sig + 1)

def scan(ctx: interfaces.context.ContextInterface,
         layer_name: str,
         page_size: int,
         progress_callback: constants.ProgressCallback = None,
         start: Optional[int] = None,
         end: Optional[int] = None) -> Generator[Dict[str, Optional[Union[bytes, str, int]]], None, None]:
    """Scans through `layer_name` at `ctx` looking for RSDS headers that indicate one of four common pdb kernel names
       (as listed in `self.pdb_names`) and returns the tuple (GUID, age, pdb_name, signature_offset, mz_offset)

       .. note:: This is automagical and therefore not guaranteed to provide correct results.

       The UI should always provide the user an opportunity to specify the
       appropriate types and PDB values themselves
    """
    min_pfn = 0
    pdb_names = [bytes(name + ".pdb", "utf-8") for name in constants.windows.KERNEL_MODULE_NAMES]

    if start is None:
        start = ctx.memory[layer_name].minimum_address
    if end is None:
        end = ctx.memory[layer_name].maximum_address

    for (GUID, age, pdb_name, signature_offset) in ctx.memory[layer_name].scan(
            ctx, PdbSignatureScanner(pdb_names), progress_callback = progress_callback, sections = [(start,
                                                                                end - start)]):
        mz_offset = None
        sig_pfn = signature_offset // page_size

        for i in range(sig_pfn, min_pfn, -1):
            if not ctx.memory[layer_name].is_valid(i * page_size, 2):
                break

            data = ctx.memory[layer_name].read(i * page_size, 2)
            if data == b'MZ':
                mz_offset = i * page_size
                break
        min_pfn = sig_pfn

        yield {
            'GUID': GUID,
            'age': age,
            'pdb_name': str(pdb_name, "utf-8"),
            'signature_offset': signature_offset,
            'mz_offset': mz_offset
        }

class KernelPDBScanner(interfaces.automagic.AutomagicInterface):
    """Windows symbol loader based on PDB signatures

    An Automagic object that looks for all Intel translation layers and scans each of them for a pdb signature.
    When found, a search for a corresponding Intermediate Format data file is carried out and if found an appropriate
    symbol space is automatically loaded.

    Once a specific kernel PDB signature has been found, a virtual address for the loaded kernel is determined
    by one of two methods.  The first method assumes a specific mapping from the kernel's physical address to its
    virtual address (typically the kernel is loaded at its physical location plus a specific offset).  The second method
    searches for a particular structure that lists the kernel module's virtual address, its size (not checked) and the
    module's name.  This value is then used if one was not found using the previous method.
    """
    priority = 30
    max_pdb_size = 0x400000

    def find_virtual_layers_from_req(self, context: interfaces.context.ContextInterface, config_path: str,
                                     requirement: interfaces.configuration.RequirementInterface) -> List[str]:
        """Traverses the requirement tree, rooted at `requirement` looking for virtual layers that might contain a windows PDB.

        Returns a list of possible layers

        Args:
            context: The context in which the `requirement` lives
            config_path: The path within the `context` for the `requirement`'s configuration variables
            requirement: The root of the requirement tree to search for :class:~`volatility.framework.interfaces.layers.TranslationLayerRequirement` objects to scan
            progress_callback: Means of providing the user with feedback during long processes

        Returns:
            A list of (layer_name, scan_results)
        """
        sub_config_path = interfaces.configuration.path_join(config_path, requirement.name)
        results = []  # type: List[str]
        if isinstance(requirement, requirements.TranslationLayerRequirement):
            # Check for symbols in this layer
            # FIXME: optionally allow a full (slow) scan
            # FIXME: Determine the physical layer no matter the virtual layer
            virtual_layer_name = context.config.get(sub_config_path, None)
            layer_name = context.config.get(interfaces.configuration.path_join(sub_config_path, "memory_layer"), None)
            if layer_name and virtual_layer_name:
                memlayer = context.memory[virtual_layer_name]
                if isinstance(memlayer, intel.Intel):
                    results = [virtual_layer_name]
        else:
            for subreq in requirement.requirements.values():
                results += self.find_virtual_layers_from_req(context, sub_config_path, subreq)
        return results

    def recurse_symbol_fulfiller(self, context: interfaces.context.ContextInterface,
                                 valid_kernels: ValidKernelsType) -> None:
        """Fulfills the SymbolTableRequirements in `self._symbol_requirements` found by the `recurse_symbol_requirements`.

        This pass will construct any requirements that may need it in the context it was passed

        Args:
            context: Context on which to operate
            valid_kernels: A list of offsets where valid kernels have been found
        """
        join = interfaces.configuration.path_join
        for sub_config_path, requirement in self._symbol_requirements:
            # TODO: Potentially think about multiple symbol requirements in both the same and different levels of the requirement tree
            # TODO: Consider whether a single found kernel can fulfill multiple requirements
            if valid_kernels:
                # TODO: Check that the symbols for this kernel will fulfill the requirement
                for virtual_layer in valid_kernels:
                    _kvo, kernel = valid_kernels[virtual_layer]
                    if not isinstance(kernel['pdb_name'], str) or not isinstance(kernel['GUID'], str):
                        raise TypeError("PDB name or GUID not a string value")
                    filter_string = os.path.join(kernel['pdb_name'], kernel['GUID'] + "-" + str(kernel['age']))
                    # Take the first result of search for the intermediate file
                    for value in intermed.IntermediateSymbolTable.file_symbol_url("windows", filter_string):
                        isf_path = value
                        break
                    else:
                        isf_path = ''
                    if isf_path:
                        vollog.debug("Using symbol library: {}".format(filter_string))
                        clazz = "volatility.framework.symbols.windows.WindowsKernelIntermedSymbols"
                        # Set the discovered options
                        context.config[join(sub_config_path, "class")] = clazz
                        context.config[join(sub_config_path, "isf_url")] = isf_path
                        # Construct the appropriate symbol table
                        config_path = interfaces.configuration.parent_path(sub_config_path)
                        if isinstance(requirement, interfaces.configuration.ConstructableRequirementInterface):
                            requirement.construct(context, config_path)
                        break
                    else:
                        vollog.debug("Required symbol library path not found: {}".format(filter_string))
                else:
                    vollog.debug("No suitable kernel pdb signature found")

    def set_kernel_virtual_offset(self, context: interfaces.context.ContextInterface,
                                  valid_kernels: ValidKernelsType) -> None:
        """Traverses the requirement tree, looking for kernel_virtual_offset values that may need setting and sets
        it based on the previously identified `valid_kernels`.

        Args:
            context: Context on which to operate and provide the kernel virtual offset
            valid_kernels: List of valid kernels and offsets
        """
        for virtual_layer in valid_kernels:
            # Set the virtual offset under the TranslationLayer it applies to
            kvo_path = interfaces.configuration.path_join(context.memory[virtual_layer].config_path,
                                                          'kernel_virtual_offset')
            kvo, kernel = valid_kernels[virtual_layer]
            context.config[kvo_path] = kvo
            vollog.debug("Setting kernel_virtual_offset to {}".format(hex(kvo)))

    def get_physical_layer_name(self, context, vlayer):
        return context.config.get(interfaces.configuration.path_join(vlayer.config_path, 'memory_layer'), None)

    def method_fixed_mapping(self,
                             context: interfaces.context.ContextInterface,
                             vlayer: layers.intel.Intel,
                             progress_callback: constants.ProgressCallback = None) -> ValidKernelsType:
        # TODO: Verify this is a windows image
        vollog.debug("Kernel base determination - testing fixed base address")
        valid_kernels = {}
        virtual_layer_name = vlayer.name
        physical_layer_name = self.get_physical_layer_name(context, vlayer)
        kvo_path = interfaces.configuration.path_join(vlayer.config_path, 'kernel_virtual_offset')

        kernels = scan(
            ctx = context,
            layer_name = physical_layer_name,
            page_size = vlayer.page_size,
            progress_callback = progress_callback)
        for kernel in kernels:
            # It seems the kernel is loaded at a fixed mapping (presumably because the memory manager hasn't started yet)
            if kernel['mz_offset'] is None or not isinstance(kernel['mz_offset'], int):
                # Rule out kernels that couldn't find a suitable MZ header
                continue
            if vlayer.bits_per_register == 64:
                kvo = kernel['mz_offset'] + (31 << int(math.ceil(math.log2(vlayer.maximum_address + 1)) - 5))
            else:
                kvo = kernel['mz_offset'] + (1 << (vlayer.bits_per_register - 1))
            try:
                kvp = vlayer.mapping(kvo, 0)
                if (any([(p == kernel['mz_offset'] and layer_name == physical_layer_name)
                         for (_, p, _, layer_name) in kvp])):
                    valid_kernels[virtual_layer_name] = (kvo, kernel)
                    # Sit the virtual offset under the TranslationLayer it applies to
                    context.config[kvo_path] = kvo
                    vollog.debug("Setting kernel_virtual_offset to {}".format(hex(kvo)))
                    break
                else:
                    vollog.debug("Potential kernel_virtual_offset did not map to expected location: {}".format(
                        hex(kvo)))
            except exceptions.InvalidAddressException:
                vollog.debug("Potential kernel_virtual_offset caused a page fault: {}".format(hex(kvo)))
        return valid_kernels

    def method_module_offset(self,
                             context: interfaces.context.ContextInterface,
                             vlayer: layers.intel.Intel,
                             progress_callback: constants.ProgressCallback = None) -> ValidKernelsType:
        """Method for finding a suitable kernel offset based on a module table"""
        vollog.debug("Kernel base determination - searching layer module list structure")
        valid_kernels = {}  # type: ValidKernelsType
        # If we're here, chances are high we're in a Win10 x64 image with kernel base randomization
        virtual_layer_name = vlayer.name
        physical_layer_name = self.get_physical_layer_name(context, vlayer)
        physical_layer = context.memory[physical_layer_name]
        # TODO:  On older windows, this might be \WINDOWS\system32\nt rather than \SystemRoot\system32\nt
        results = physical_layer.scan(
            context, scanners.BytesScanner(b"\\SystemRoot\\system32\\nt"), progress_callback = progress_callback)
        seen = set()  # type: Set[int]
        # Because this will launch a scan of the virtual layer, we want to be careful
        for result in results:
            # TODO: Identify the specific structure we're finding and document this a bit better
            pointer = context.object(
                "pdbscan!unsigned long long",
                offset = (result - 16 - int(vlayer.bits_per_register / 8)),
                layer_name = physical_layer_name)
            address = pointer & vlayer.address_mask
            if address in seen:
                continue
            seen.add(address)

            valid_kernels = self.check_kernel_offset(context, vlayer, address, progress_callback)

            if valid_kernels:
                break
        return valid_kernels

    def method_kdbg_offset(self,
                           context: interfaces.context.ContextInterface,
                           vlayer: layers.intel.Intel,
                           progress_callback: constants.ProgressCallback = None) -> ValidKernelsType:
        vollog.debug("Kernel base determination - using KDBG structure for kernel offset")
        valid_kernels = {}  # type: ValidKernelsType
        physical_layer_name = self.get_physical_layer_name(context, vlayer)
        physical_layer = context.memory[physical_layer_name]
        results = physical_layer.scan(context, scanners.BytesScanner(b"KDBG"), progress_callback = progress_callback)

        seen = set()  # type: Set[int]
        for result in results:
            # TODO: Identify the specific structure we're finding and document this a bit better
            pointer = context.object(
                "pdbscan!unsigned long long", offset = result + 8, layer_name = physical_layer_name)
            address = pointer & vlayer.address_mask
            if address in seen:
                continue
            seen.add(address)

            valid_kernels = self.check_kernel_offset(context, vlayer, address, progress_callback)

            if valid_kernels:
                break

        return valid_kernels

    def check_kernel_offset(self,
                            context: interfaces.context.ContextInterface,
                            vlayer: layers.intel.Intel,
                            address: int,
                            progress_callback: constants.ProgressCallback = None) -> ValidKernelsType:
        """Scans a virtual address """
        # Scan a few megs of the virtual space at the location to see if they're potential kernels

        valid_kernels = {}  # type: ValidKernelsType

        virtual_layer_name = vlayer.name
        try:
            if vlayer.read(address, 0x2) == b'MZ':
                res = list(
                    scan(
                        ctx = context,
                        layer_name = vlayer.name,
                        page_size = vlayer.page_size,
                        progress_callback = progress_callback,
                        start = address,
                        end = address + self.max_pdb_size))
                if res:
                    valid_kernels[virtual_layer_name] = (address, res[0])
        except exceptions.InvalidAddressException:
            pass
        return valid_kernels

    # List of methods to be run, in order, to determine the valid kernels
    methods = [method_kdbg_offset, method_module_offset, method_fixed_mapping]

    def determine_valid_kernels(self,
                                context: interfaces.context.ContextInterface,
                                potential_layers: List[str],
                                progress_callback: constants.ProgressCallback = None) -> ValidKernelsType:
        """Runs through the identified potential kernels and verifies their suitability

        This carries out a scan using the pdb_signature scanner on a physical layer.  It uses the
        results of the scan to determine the virtual offset of the kernel.  On early windows implementations
        there is a fixed mapping between the physical and virtual addresses of the kernel.  On more recent versions
        a search is conducted for a structure that will identify the kernel's virtual offset.

        Args:
            context: Context on which to operate
            potential_kernels: Dictionary containing `GUID`, `age`, `pdb_name` and `mz_offset` keys
            progress_callback: Function taking a percentage and optional description to be called during expensive computations to indicate progress

        Returns:
            A dictionary of valid kernels
        """
        valid_kernels = {}  # type: ValidKernelsType
        for virtual_layer_name in potential_layers:
            vlayer = context.memory.get(virtual_layer_name, None)
            if isinstance(vlayer, layers.intel.Intel):
                for method in self.methods:
                    valid_kernels = method(self, context, vlayer, progress_callback)
                    if valid_kernels:
                        break
        if not valid_kernels:
            vollog.info("No suitable kernels found during pdbscan")
        return valid_kernels

    def __call__(self,
                 context: interfaces.context.ContextInterface,
                 config_path: str,
                 requirement: interfaces.configuration.RequirementInterface,
                 progress_callback: constants.ProgressCallback = None) -> None:
        if requirement.unsatisfied(context, config_path):
            if "pdbscan" not in context.symbol_space:
                context.symbol_space.append(native.NativeTable("pdbscan", native.std_ctypes))
            # TODO: check if this is a windows symbol requirement, otherwise ignore it
            self._symbol_requirements = self.find_requirements(context, config_path, requirement,
                                                               requirements.SymbolTableRequirement)
            potential_layers = self.find_virtual_layers_from_req(
                context = context, config_path = config_path, requirement = requirement)
            for sub_config_path, symbol_req in self._symbol_requirements:
                parent_path = interfaces.configuration.parent_path(sub_config_path)
                if symbol_req.unsatisfied(context, parent_path):
                    valid_kernels = self.determine_valid_kernels(context, potential_layers, progress_callback)
                    if valid_kernels:
                        self.recurse_symbol_fulfiller(context, valid_kernels)
                        self.set_kernel_virtual_offset(context, valid_kernels)


# By Daniel J. Cohen (Zink)
# Farming Simulator

# IMPORTS
from crop import Crop
from merchant import Merchant
from farmer import Farmer

# TURNS
TURN_COUNTER = 0

def introduction():
    print("Welcome to Farming Simulator. Let's get started.")
    name = input("What's your name? ")
    farming_name = f"Farmer {name}"

    # Instantiating the player (Farmer)
    player = Farmer(farming_name)

    print(f"Nice to meetchya {player.name}.")

    print()

    print("This here lovely little plot of land is yours.")
    print("Your land has 8 plots and each thing you grow takes up 1 plot. So you dur the math.")

    player.show_info()

# GAME PLAY
introduction()
# player.turn(turn_counter=TURN_COUNTER)


#求交集
# linux = ['alex','jack','rain','sb']
# python = ['sb','alex','mack','rachel']
# result = []
# for i in python:
#     if i in linux:
#         result.append(i)
# print(result)
#求交集    END

linux = {'alex','jack','rain','sb','alex'}
python = {'sb','alex','mack','rachel'}
result = {}
a = {'sb'}
#集合天然去重
# print(linux)

#交集
#result = linux.intersection(python)#简写 print(linux & python)

#差集 linux有 但python没有
#result = linux.difference(python)  #简写 print(linux - python)

#并集
#result = linux.union(python)        #简写 print(linux | python)

#反向差集 互相没有的数据
#result =linux.symmetric_difference(python)  #简写print(linux ^ python)
print(result)

#集合合并
# linux.update(python)#相当把python直接合并linux中

# 判断python是否是linux子集
#print(linux.issubset(python))

#父集
#print(linux.issuperset(a))

#两个集合交集为空则返回真
#print(linux.isdisjoint(python))

#增加
#linux.add('a')

#取出差集再存入linux
#linux.difference_update(python)

#删除
#linux.discard('sb')

#删除,但元素不存在会报错
#linux.remove("dd")

#随机删除1个
#linux.pop()

print(linux)


import sys
import os
import untangle
import re
from os.path import expanduser

sys.path.append(os.path.expandvars('$ITV_PYTHON_CORE_MODULES'))
sys.path.append(os.path.expandvars('$ITV_PYTHON_MODULES'))

import itv_shell
import itv_argparser
import itv_filesystem

def run(command):
    itv_shell.run("transmission-remote --auth transmission:transmission -w /hdd/torrents/tv_shows %s" % (command))

class Torrent:
    name = None
    season_episode = None
    magnet_720 = None
    magnet_1080 = None

    @property
    def id(self):
        if self.season_episode is None:
            return self.name
        else:
            return self.name + "-" + self.season_episode

    def print_desc(self):
        print(self.name)
        print(self.season_episode)
        if self.magnet_720 is None:
            print("720: False")
        else:
            print("720: True")
        if self.magnet_1080 is None:
            print("1080: False")
        else:
            print("1080: True")

    def cache_name(self):
        if self.season_episode is None:
            return self.name + "\n"
        else:
            return self.name + " - " + self.season_episode + "\n"

### --- MAIN --- ###

parser = itv_argparser.parser(
    os.path.dirname(__file__),
    '''
    Checks for new episodes to all your shows
    '''
)
args = parser.parse_args(sys.argv[1:])

download_show_cache = "/hdd/torrents/.show_cache"
show_cache = []

if itv_filesystem.does_file_exist(download_show_cache):
    file = open(download_show_cache, "r")
    show_cache = file.readlines()
    # print(show_cache)

url = 'http://showrss.info/user/255222.rss?magnets=true&namespaces=true&name=null&quality=null&re=null'

o = untangle.parse(url)
torrents = {}
for item in o.rss.channel.item:
    title = item.title.cdata.lower().replace("'", "")
    link = item.link.cdata
    if link:
        torrent = Torrent()

        season_search = re.search("(s\d\de\d\d)", title)
        if season_search is not None:
            title_search = re.split("(s\d\de\d\d)", title)
            torrent.name = title_search[0].strip()
            torrent.season_episode = season_search.group()

        if "720p" in title:
            torrent.magnet_720 = link
            if season_search is None:
                title_search = title.split("720p")
        elif "1080p" in title:
            torrent.magnet_1080 = link
            if season_search is None:
                title_search = title.split("1080p")
        else:
            continue

        torrent.name = title_search[0].strip()

        if torrent.id in torrents:
            if torrent.magnet_1080 is None:
                torrents[torrent.id].magnet_720 = link
            else:
                torrents[torrent.id].magnet_1080 = link
        else:
            torrents[torrent.id] = torrent

new_shows = []
for key in torrents.keys():
    torrent = torrents[key]
    # torrent.print_desc()

    if torrent.cache_name() in show_cache:
        continue

    if torrent.magnet_1080 is None:
        print("Downloading 720p >> " + torrent.id)
        run("-a '%s'" % (torrent.magnet_720))
    else:
        print("Downloading 1080p >> " + torrent.id)
        run("-a '%s'" % (torrent.magnet_1080))

    new_shows.append(torrent.cache_name())

write_show_cache = "".join(new_shows)
itv_filesystem.write_text_to_file(write_show_cache, download_show_cache, "a+")


import os.path
import sys
import pickle
import googleapiclient.errors

from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from google.auth.transport.requests import Request
from difflib import SequenceMatcher
from textify import clean_string

class YouTube:

    # Disable OAuthlib's HTTPS verification when running locally.
    # *DO NOT* leave this option enabled in production.
    os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

    def __init__(self, playlist_name):
        client_secrets_file = "client_secret.json"
        scopes = ["https://www.googleapis.com/auth/youtube.force-ssl"]
        api_service_name = "youtube"
        api_version = "v3"

        self.playlist = []
        self.videos = []
        self.videos_added = 0
        self.videos_removed = 0

        # Get credentials and create an API client
        creds = None
        if os.path.exists('token.pickle'):
            with open('token.pickle', 'rb') as __token:
                creds = pickle.load(__token)
        # If there are no (valid) credentials available, let the user log in.
        if not creds or not creds.valid:
            if creds and creds.expired and creds.refresh_token:
                creds.refresh(Request())
            else:
                flow = InstalledAppFlow.from_client_secrets_file(
                    client_secrets_file, scopes)
                creds = flow.run_local_server()
            # Save the credentials for the next run
            with open('token.pickle', 'wb') as __token:
                pickle.dump(creds, __token)
        self.youtube = build(api_service_name, api_version, credentials=creds)

        self.get_playlist(playlist_name)
        if not self.playlist:
            # print("YouTube playlist does not exist")
            create_playlist =  self.ask_user()
            if not create_playlist:
                print("Sync cancelled")
                exit(0)
            else:
               self.new_playlist(playlist_name)
        self.get_playlist_videos()

    # Search for a video
    def find_video(self, search_term_list):
        search_term = ' '.join([str(elem) for elem in search_term_list])
        request = self.youtube.search().list(
            part="snippet",
            maxResults=1,
            q=search_term,
            type="video",
            fields="items(snippet(title),id(videoId))"
        )
        response = request.execute()

        return [response['items'][0]['snippet']['title'],response['items'][0]['id']['videoId']]

    # Get a playlist
    def get_playlist(self,playlist_name):

        playlists = []

        request = self.youtube.playlists().list(
            part="snippet",
            mine=True,
            fields="items(id,snippet(title)),nextPageToken",
            maxResults=50
        )

        response = request.execute()
        items = response['items']

        for item in items:
            playlists.append([item['id'],[item][0]['snippet']['title']])

        while 'nextPageToken' in response:
            request = self.youtube.playlists().list(
                part="snippet",
                mine=True,
                fields="items(id,snippet(title)),nextPageToken",
                maxResults=50,
                pageToken=response['nextPageToken']
            )
            response = request.execute()
            items = response['items']
            for item in items:
                playlists.append([item['id'],[item][0]['snippet']['title']])

        for title_id in playlists:
            if playlist_name in title_id:
                self.playlist = title_id

    # Get all the videos in a playlist
    # Grab the videoId, title and playlistVideoId
    def get_playlist_videos(self):
        request = self.youtube.playlistItems().list(
            part="snippet",
            fields="items(snippet(resourceId(videoId)),snippet(title),id),nextPageToken",
            playlistId=self.playlist[0],
            maxResults=50
        )
        response = request.execute()
        for item in response['items']:
            clean_video_title = clean_string(item['snippet']['title'])
            self.videos.append([item['snippet']['resourceId']['videoId'],clean_video_title,item['id']])

        while 'nextPageToken' in response:
            request = self.youtube.playlistItems().list(
                part="snippet",
                fields="items(snippet(resourceId(videoId)),snippet(title),id),nextPageToken",
                playlistId=self.playlist[0],
                pageToken=response['nextPageToken'],
                maxResults=50
            )

            response = request.execute()
            for item in response['items']:
                clean_video_title = clean_string(item['snippet']['title'])
                self.videos.append([item['snippet']['resourceId']['videoId'],clean_video_title,item['id']])

    def sync_playlist(self, spotify_tracks, youtube_playlist):

        in_video_playlist = False

        # Add new videos
        for track in spotify_tracks:
            spot_words = track[0] + track[1]

            # Check if the track's artist and title already exist in a video within the YouTube playlist
            for video in self.videos:

                in_video_playlist = False

                if all(word in video[1] for word in spot_words):
                    in_video_playlist = True
                    break

            # If artist and title can't be found in a video, search for YouTube for it
            if not in_video_playlist:
                print(f"Searching for: {spot_words}")
                found_video = self.find_video(spot_words)
                # Check if the found video's id already exists in a video within the YouTube playlist
                # i.e. don't add duplicates
                for video in self.videos:
                    if found_video[1] in video[0]:
                        in_video_playlist = True
                        print(f"Already in playlist: {spot_words}. Video: {video[1]}")
                        # Add the video id to the spotify track
                        track[2] = found_video[1]
                        break
            if not in_video_playlist:
                self.add_video(found_video[1])
                self.videos_added += 1
                print("Added: " + found_video[0])

        # Remove videos not in playlist
        for video in self.videos:
            in_spotify_playlist = False
            for track in spotify_tracks:
                rem_spot_words = track[0] + track[1]
                if all(word in video[1] for word in rem_spot_words):
                    in_spotify_playlist = True
                    break

            # make sure
            for track in spotify_tracks:
                if track[2] == video[0]:
                    in_spotify_playlist = True
                    print("Not removing: " + ' '.join([str(elem) for elem in video[1]]))
                    break

            if not in_spotify_playlist:
                self.find_video(rem_spot_words)
                print("Removed: " + ' '.join([str(elem) for elem in video[1]]))
                self.remove_video(video[2])
                self.videos_removed += 1

        print(f"Sync complete, {self.videos_added} video(s) added, {self.videos_removed} video(s) removed")

    def add_video(self,video_id):
        request = self.youtube.playlistItems().insert(
            part="snippet",
            body={
                'snippet': {
                    'playlistId': self.playlist[0],
                    'position': 1,
                    'resourceId': {
                        'kind': 'youtube#video',
                        'videoId': video_id
                    }
                }
            }
        )
        request.execute()

    def remove_video(self, video_playlist_id):
        request = self.youtube.playlistItems().delete(
                id=video_playlist_id
            ).execute()

    def ask_user(self):
        check = str(input("YouTube playlist does not exist. Would you like to create it? (Y/N): ")).lower().strip()
        try:
            if check[0] == 'y':
                return True
            elif check[0] == 'n':
                return False
            else:
                print('Please press Y or N')
                return self.ask_user()
        except Exception as error:
            print("Please enter valid inputs")
            print(error)
            return self.ask_user()
        return check

    def new_playlist(self,playlist_name):
        request = self.youtube.playlists().insert(
            part="snippet",
            body={
                "snippet": {
                "title": playlist_name
                }
            },
            fields="id"
        )
        response = request.execute()
        print(f"{playlist_name} playlist created")
        self.playlist = [response['id'],playlist_name]


from collections import namedtuple

from pybliometrics.scopus.classes import Search
from pybliometrics.scopus.utils import check_integrity, check_field_consistency

class AuthorSearch(Search):
    @property
    def authors(self):
        """A list of namedtuples storing author information,
        where each namedtuple corresponds to one author.
        The information in each namedtuple is (eid surname initials givenname
        documents affiliation affiliation_id city country areas).

        All entries are strings or None.  Areas combines abbreviated subject
        areas followed by the number of documents in this subject.

        Raises
        ------
        ValueError
            If the elements provided in integrity_fields do not match the
            actual field names (listed above).
        """
        # Initiate namedtuple with ordered list of fields
        fields = 'eid surname initials givenname affiliation documents '\
                 'affiliation_id city country areas'
        auth = namedtuple('Author', fields)
        check_field_consistency(self.integrity, fields)
        # Parse elements one-by-one
        out = []
        for item in self._json:
            name = item.get('preferred-name', {})
            aff = item.get('affiliation-current', {})
            fields = item.get('subject-area',
                              [{'@abbrev': '', '@frequency': ''}])
            if isinstance(fields, dict):
                fields = [fields]
            areas = ["{} ({})".format(d.get('@abbrev', ''),
                                      d.get('@frequency', ''))
                     for d in fields]
            new = auth(eid=item.get('eid'), initials=name.get('initials'),
                       surname=name.get('surname'), areas="; ".join(areas),
                       givenname=name.get('given-name'),
                       documents=item.get('document-count', '0'),
                       affiliation=aff.get('affiliation-name'),
                       affiliation_id=aff.get('affiliation-id'),
                       city=aff.get('affiliation-city'),
                       country=aff.get('affiliation-country'))
            out.append(new)
        # Finalize
        check_integrity(out, self.integrity, self.action)
        return out or None

    def __init__(self, query, refresh=False, count=200, download=True,
                 integrity_fields=None, integrity_action="raise",
                 verbose=False):
        """Class to search a query, and retrieve a list of author IDs as results.

        Parameters
        ----------
        query : str
            A string of the query, e.g. "authlast(Einstein) and
            authfirst(Albert)".

        refresh : bool (optional, default=False)
            Whether to refresh the cached file if it exists or not.

        count : int (optional, default=200)
            The number of entries to be displayed at once.  A smaller number
            means more queries with each query having less results.

        download : bool (optional, default=True)
            Whether to download results (if they have not been cached).

        integrity_fields : None or iterable (default=None)
            Iterable of field names whose completeness should be checked.
            ScopusSearch will perform the action specified in
            `integrity_action` if elements in these fields are missing.  This
            helps avoiding idiosynchratically missing elements that should
            always be present, such as the EID.

        integrity_action : str (optional, default="raise")
            What to do in case integrity of provided fields cannot be
            verified.  Possible actions:
            - "raise": Raise an AttributeError
            - "warn": Raise a UserWarning

        verbose : bool (optional, default=False)
            Whether to print a downloading progress bar to terminal. Has no effect for download=False.

        Raises
        ------
        ScopusQueryError
            If the number of search results exceeds 5000.

        ValueError
            If the integrity_action parameter is not one of the allowed ones.

        Notes
        -----
        Json results are cached in ~/.scopus/author_search/STANDARD/{fname},
        where fname is the md5-hashed version of query.
        """
        # Checks
        allowed_actions = ("warn", "raise")
        if integrity_action not in allowed_actions:
            msg = 'integrity_action parameter must be one of ' +\
                  ', '.join(allowed_actions)
            raise ValueError(msg)

        # Parameters
        view = "STANDARD"  # In case Scopus adds different views in future

        # Query
        self.query = query
        Search.__init__(self, query=query, refresh=refresh, view=view,
                        api='AuthorSearch', count=count, download=download,
                        verbose=verbose)
        self.integrity = integrity_fields or []
        self.action = integrity_action

    def __str__(self):
        s = """Search {} yielded {} author(s):\n    {}"""
        return s.format(self.query, len(self._json),
                        '\n    '.join([str(a) for a in self._json]))


key = input("KEY: ")
key = key.replace(" ", "")
key = key.upper()

# Menbuat fungsi matriks
def matrix(x,y,initial):
    return [[initial for i in range(x)] for j in range(y)]

result=list()
for c in key:
    # Membuat kondisi dimana hurur 'J' tidak digunakan sebagai key.
    if c not in result:
        if c=='J':
            result.append('I')
        else:
            result.append(c)
flag=0
for i in range(65,91):
    if chr(i) not in result:
        if i==73 and chr(74) not in result:
            result.append("I")
            flag=1
        elif flag==0 and i==73 or i==74:
            pass
        else:
            result.append(chr(i))
k=0
# Inisialisasi Matriks
tabel_matriks = matrix(5,5,0)
# Membuat Tael Matriks
for i in range(0,5):
    for j in range(0,5):
        tabel_matriks[i][j]=result[k]
        k+=1

# Untuk mendapatkan lokasi matruks
def locindex(c):
    loc=list()
    if c=='J':
        c='I'
    for i ,j in enumerate(tabel_matriks):
        for k,l in enumerate(j):
            if c==l:
                loc.append(i)
                loc.append(k)
                return loc

# Membuat fungsi enkripsi yang digunakan untuk meng enkripsi
def Enkripsi():
    msg = str(input("PLAINTEXT: "))
    msg = msg.upper()
    msg = msg.replace(" ", "")
    i=0
    for s in range(0, len(msg)+1,2):
        if s<len(msg)-1:
            if msg[s]==msg[s+1]:
                msg=msg[:s+1]+'X'+msg[s+1:]
    if len(msg)%2!=0:
        msg=msg[:]+'X'
    print("CIPHERTEXT: ", end=' ')
    while i < len(msg):
        loc=list()
        loc=locindex(msg[i])
        loc1=list()
        loc1=locindex(msg[i+1])
        if loc[1]==loc1[1]:
            print("{}{}".format(tabel_matriks[(loc[0]+1)%5][loc[1]], tabel_matriks[(loc1[0]+1)%5][loc1[1]]),end=' ')
        elif loc[0]==loc1[0]:
            print("{}{}".format(tabel_matriks[loc[0]][(loc[1]+1)%5], tabel_matriks[loc1[0]][(loc1[1]+1)%5]),end=' ')
        else:
            print("{}{}".format(tabel_matriks[loc[0]][loc1[1]], tabel_matriks[loc1[0]][loc[1]]),end=' ')
        i=i+2

# Membuat fungsi deskripsi yang digunakan untuk mendeskripsi cipherteks
def Deskripsi():
    msg=str(input("CIPHERTEXT: "))
    msg=msg.upper()
    msg=msg.replace(" ", "")
    print("PLAINTEXT: ", end=' ')
    i=0
    while i<len(msg):
        loc=list()
        loc=locindex(msg[i])
        loc1=list()
        loc1=locindex(msg[i+1])
        if loc[1]==loc1[1]:
            print("{}{}".format(tabel_matriks[(loc[0]-1)%5][loc[1]], tabel_matriks[(loc1[0]-1)%5][loc1[1]]),end=' ')
        elif loc[0]==loc1[0]:
            print("{}{}".format(tabel_matriks[loc[0]][(loc[1]-1)%5], tabel_matriks[loc1[0]][(loc1[1]-1)%5]),end=' ')
        else:
            print("{}{}".format(tabel_matriks[loc[0]][loc1[1]], tabel_matriks[loc1[0]][loc[1]]),end=' ')
        i=i+2

# Membuat Menu
while(1):
    pil = int(input("\n\n1.Enkripsi\n2.Deskripsi\n3.Exit\nMasukkan Pilihan: "))
    if pil == 1:
        Enkripsi()
    elif pil == 2:
        Deskripsi()
    elif pil == 3:
        exit()


import argparse
from gendiff import format

def formatter(name):
    if name == format.DEFAULT:
        return format.default
    elif name == format.PLAIN:
        return format.plain
    elif name == format.JSON:
        return format.json
    raise argparse.ArgumentTypeError(f'Unknown formatter: {name}')

def parse_args():
    parser = argparse.ArgumentParser(description='Generate diff')
    parser.add_argument('first_file')
    parser.add_argument('second_file')
    parser.add_argument(
        '-f', '--format',
        help='set format of output (default, plain, json)',
        default=format.DEFAULT,
        type=formatter,
    )
    args = parser.parse_args()
    return args


import os.path as path
import pickle
import logging

import math
from tqdm import tqdm

import torch
from torch_geometric.data import Data
from torch_geometric.loader import NeighborLoader

from splicing.utils.general_utils import SPLIT2DESC, IX2CHR, \
    compute_scores, compute_average_scores
from splicing.utils.graph_utils import process_graph
from splicing.utils.wandb_utils import report_wandb, analyze_gradients

def get_gpu_stats():
    t = torch.cuda.get_device_properties(0).total_memory
    r = torch.cuda.memory_reserved(0)
    a = torch.cuda.memory_allocated(0)
    f = r-a  # free inside reserved
    return a, f

def finetune(graph_model, full_model, chromosomes, criterion, optimizer,
             epoch, opt, split):

    if split == 'train':
        graph_model.train()
    else:
        graph_model.eval()

    total_loss = 0
    batch_count = 0

    scores = {}

    # bin dict has information for all chromosomes
    # that's why we can load it here before:
    # we need it also for the constant case, thus always has to be loaded
    bin_dict_file = path.join(
        opt.graph_data_root,
        f'{opt.window_size}_test_val_train_bin_dict_{opt.hicsize}_{opt.hicnorm}norm.pkl'
    )
    bin_dict = pickle.load(open(bin_dict_file, "rb"))

    # get the graph info
    if opt.adj_type in ['hic', 'both']:
        graph_file = path.join(
            opt.graph_data_root,
            f"{opt.window_size}_{split}_graphs_{opt.hicsize}_{opt.hicnorm}norm.pkl")
        split_adj_dict = pickle.load(open(graph_file, "rb"))
    else:
        split_adj_dict = None

    # loop over all the chromosomes
    for chromosome in chromosomes:

        # load the saved nucleotide representations
        chromosome_data = torch.load(
            path.join(
                opt.model_name.split('/finetune')[0],
                f'chrom_feature_dict_{split}_chr{chromosome}.pt'
            ), map_location=torch.device('cpu')
        )

        xs = chromosome_data['x']
        ys = chromosome_data['y']

        # combine the nucleotide representations in a matrix
        xs = torch.stack([(xs[loc][0]) for loc in xs])
        ys = torch.stack([(ys[loc][0]) for loc in ys])

        # init predictions stores
        d1, d2, d3 = ys.shape
        all_preds = torch.zeros((d1 - d1 % opt.graph_batch_size, d2, d3)).cpu()
        all_targets = torch.zeros((d1 - d1 % opt.graph_batch_size, d2, d3)).cpu()
        count_ys = 0

        # create the graph of the appropriate type
        graph = process_graph(
            opt.adj_type, split_adj_dict, len(xs),
            IX2CHR(chromosome), bin_dict, opt.window_size
        )
        # put everything into a Geometric data type
        graph_data = Data(
            x=xs,
            y=ys,
            edge_index=graph.coalesce().indices()
        )

        # for incremental loading of the graph
        graph_loader = NeighborLoader(
            graph_data,
            num_neighbors=[-1],
            batch_size=opt.graph_batch_size,
            drop_last=True,
            # shuffle=True
        )

        desc_i = f'({str.upper(SPLIT2DESC[split])} on chromosome {chromosome})'
        logging.info(f'{desc_i} - batch size {opt.graph_batch_size}, nbatches '
                    f' {len(graph_loader)}')

        # loop over the entire chromosome graph in batches
        for batch, graph_batch in tqdm(enumerate(graph_loader), leave=False,
                                    total=len(graph_loader), desc=desc_i):

            # get the batch data
            _x = graph_batch['x'].to('cuda')
            _y = graph_batch['y'][:opt.graph_batch_size].to('cuda')
            _edge_index = graph_batch['edge_index'].to('cuda')

            # a, f = get_gpu_stats()

            if opt.boost_period > 1:
                if batch_count % opt.boost_period != 0:
                    # only update the full model every boost_period epochs
                    for param in full_model.parameters():
                        param.requires_grad = False
                else:
                    for param in full_model.parameters():
                        param.requires_grad = True

            # get the node representations from the graph model
            node_representation = graph_model(_x, _edge_index, opt)

            # only consider the original batch of the nodes,
            # not their neighbors
            _x = _x[:opt.graph_batch_size]
            node_representation = node_representation[:opt.graph_batch_size]

            _x.requires_grad = opt.ingrad and split == 'train'

            # make the predictions
            _y_hat = full_model(_x, node_representation)

            loss = criterion(_y_hat, _y)

            if split == 'train':
                if opt.ingrad:
                    node_representation.retain_grad()
                loss.backward()
                optimizer.step()

                # log the gradient information to wandb
                if batch_count % opt.log_interval == 0 and opt.wandb:
                    analyze_gradients(
                        graph_model, full_model, _x, node_representation, opt
                    )

                optimizer.zero_grad()

            if split != 'train':
                total_loss += loss.sum().item()
                all_preds[count_ys:count_ys + opt.graph_batch_size] = _y_hat.cpu().data
                all_targets[count_ys:count_ys + opt.graph_batch_size] = _y.cpu().data
                count_ys += opt.graph_batch_size

            # wandb reporting
            if split == 'train' and batch_count % opt.log_interval == 0 and opt.wandb:
                report_wandb(_y_hat, _y, loss, opt, split, step=batch_count)
            elif split == 'valid' and batch_count % opt.validation_interval == 0 and opt.wandb:
                report_wandb(_y_hat, _y, loss, opt, split, step=batch_count)

            batch_count+=1

        # compute the full chromosome prediction metrics
        if split in ["valid", "test"]:
            scores[chromosome] = compute_scores(
                all_preds.numpy(),
                all_targets.numpy(),
                total_loss,
                opt.wandb,
                epoch,
                split,
                chromosome
            )

            all_preds = torch.Tensor().cpu()
            all_targets = torch.Tensor().cpu()
            total_loss = 0

    # average the scores across the chromosomes
    if split in ["valid", "test"]:
        combined_scores = compute_average_scores(
            scores, opt.wandb, split
        )
    else:
        combined_scores = {}

    return combined_scores


"""
File: selection_sort.py
Assignment: hw
Language: python3
Author: Faisal Alzahrany
Purpose: sorting any list by using selection sort
CSCI 141
"""

"""
1- when the list is already sorted the insertion sort performing is better than selection sort

2- selection sort performing in this case is worse because selection sort scan every element
while the insertion sort will not scan anything in that case because it's already sorted
"""

def readfile(filename):
    """
    this function read the text file and convert it to list
    :param filename: file name
    :return:
    """
    file=open(filename)
    new_list=[]
    for i in file:
        num=int(i)
        new_list+=[num]
    return new_list

def find_min_from(lst,mark):
    """
    this function find the minimum number inside a list with specific range
    :param lst: the list that is going to be searched in it
    :param mark:  a mark in which range in the list to search
    :return: the index of the minimum number
    """
    newlist=lst[mark:]
    min=newlist[0]
    index=0
    for i in range(0,len(newlist)):
        if newlist[i]<min:
            min=newlist[i]
            index=i
    return index+mark

def swap( lst, i, j ):
    """
    swap: List NatNum NatNum -> None
    swap the contents of list at pos i and j.
    Parameters:
        lst - the list of data
        i   - index of one datum
        j   - index of the other datum
    """
    temp = lst[i]
    lst[i] = lst[j]
    lst[j] = temp

def selection_sort(lst):
    """
    this function sort the list by finding the minimum number
    :param lst: the list that is going to be sorted
    :return: the sorted list
    """
    for mark in range(0,len(lst)):
        swap(lst,mark,find_min_from(lst,mark))
    return lst

def main():
    filename=input("Enter the file name: ")
    lst=readfile(filename)
    print(lst)
    selection_sort(lst)
    print(lst)

main()


from collections import Counter

class Solution:
    def beautifulSubarrays(self, nums: List[int]) -> int:
        p = [0] * 32
        ctr = Counter()
        ctr[tuple(p)] = 1
        res = 0
        for el in nums:
            for b in range(32):
                if el & (1 << b):
                    p[b] += 1
                    p[b] %= 2
            curr = tuple(p)
            res += ctr[curr]
            ctr[curr] += 1
        return res


#!/usr/bin/env python3

"""
Proteins
========

Extracts all the protein codes from a BLAST result XML file.

Usage:
    $ ./proteins resultsBlast.xml -o proteins.txt

"""

import argparse
import re
import sys
from Bio.Blast import NCBIXML

RESULT = 'data/resultsBlast.xml'

def get_proteins(blast):
    records = NCBIXML.parse(blast)
    proteins = []

    for r in records:
        alignments = sorted(r.alignments, key=lambda a: a.hsps[0].expect)[0:10]

        for a in alignments:
            title = re.search(r'^(.*?)\|(\d+)\|(.*?)\|(.*?)\|.*',
                              a.title).group(4)
            proteins.append(title)

    return proteins

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("result", type=argparse.FileType('r'),
                        default=RESULT, nargs='?',
                        help="XML blast result file")
    parser.add_argument("-o", "--outfile", type=argparse.FileType('w'),
                        default=sys.stdout,
                        help="output file to write the protein list")
    args = parser.parse_args()

    for protein in get_proteins(args.result):
        args.outfile.write(protein + "\n")

if __name__ == "__main__":
    main()


from typing import List

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        rtnList = [];
        for  i in range(len(nums)):
            # 두 수의 합
            for j in range(i, len(nums)):
                if i == j:
                    continue

                if nums[i] + nums[j] == target:
                    rtnList.append(i)
                    rtnList.append(j)
        return rtnList

print('hello world')


class_names = ['jack', 'bob', 'mary', 'jeff', 'ann', 'pierre', 'martha', 'clause', 'pablo', 'susan', 'gustav']

def create_dataset():
    import random
    num_entries = 10000000
    fp = open("data.txt", "w")
    for i in range(num_entries):
        current = random.choice(class_names)
        fp.write(current+"\n")

def read_dataset_list():
    class_counts = []
    for c in class_names:
        class_counts.append(0)
    with open("data.txt", "r") as fp:
        for line in fp:
            line = line.strip()
            if line != "":
                class_counts[class_names.index(line)] += 1
    print(class_counts)

def read_dataset_dict():
    class_counts = {}
    for c in class_names:
        class_counts[c] = 0
    with open("data.txt") as fp:
        for line in fp:
            line = line.strip()
            if line != "":
                class_counts[line] += 1
    print(class_counts)

import time

t0 = time.time()
create_dataset()
t1 = time.time()
print("Create %0.1f \n" % (t1-t0))

t0 = time.time()
read_dataset_list()
t1 = time.time()
print("list %0.1f \n" % (t1-t0))

t0 = time.time()
read_dataset_dict()
t1 = time.time()
print("dictionary %0.1f \n" % (t1-t0))


import logging
from time import mktime, strptime, strftime

class SyslogListener(object):
    def syslog_received(self, time, src, msg):
        raise NotImplementedError

class SyslogServer(object):
    def __init__(self, bind_addr='0.0.0.0', bind_port=514):
        self._bind = (bind_addr, bind_port)
        self._loop = None
        self._transport = None
        self._listeners = []
        self.log = logging.getLogger(self.__class__.__name__)

    def register_listener(self, listener):
        self._listeners.append(listener)

    def start(self, loop):
        self._loop = loop

        listen = self._loop.create_datagram_endpoint(lambda: self, local_addr=self._bind)
        self._loop.run_until_complete(listen)

    def connection_made(self, transport):
        self._transport = transport

    def datagram_received(self, data, addr):
        for log in data.split(b'\n'):
            try:
                if log:
                    self._handle_log(log)
            except:
                self.log.error('Unhandled exception handling log')

    def _handle_log(self, log):
        try:
            pri, time, src, msg = self._parse_log(log)
        except ValueError as err:
            self.log.error('Failed to parse msg: %r', msg)
            self.log.error('=> %s', str(err))
            return
        except Exception as err:
            self.log.exception(err)

        self._dispatch_event(time, src, msg)

    def _dispatch_event(self, time, src, msg):
        for listener in self._listeners:
            try:
                listener.syslog_received(time, src, msg)
            except Exception as err:
                self.log.error('Caught exception while dispatching event to %s', listener.__class__.__name__)
                self.log.exception(err)

    def _parse_log(self, log):
        pri, log = self._parse_pri(log)
        time, log = self._parse_timestamp(log)
        src, log = self._parse_src(log)

        return pri, time, src, log

    @staticmethod
    def _parse_pri(log):
        # The PRI part MUST have 3, 4, or 5 chars and will be bounded by angle
        # brackets.

        if log[0:1] != b'<':
            raise ValueError('Log does not start with <')
        else:
            lpos = 1

        rpos = log.find(b'>', 2, 5)
        if rpos == -1:
            raise ValueError('pri does not end with >')

        pri = log[lpos:rpos].decode('ascii')
        if not pri.isdigit():
            raise ValueError('PRI not digits')

        return int(pri), log[rpos+1:]

    @staticmethod
    def _parse_timestamp(log):
        year = strftime('%Y')
        time_str = log[:15].decode('ascii').replace('  ', ' 0') + ' ' + year
        s_time = strptime(time_str, '%b %d %H:%M:%S %Y')
        return s_time, log[16:]

    @staticmethod
    def _parse_src(log):
        rpos = log.index(b' ')
        return log[:rpos], log[rpos+1:]

    def __del__(self):
        if self._transport:
            self._transport.close()

if __name__ == '__main__':
    import sys, asyncio, logging
    from .cisco.client import CiscoSSHClient
    from .cisco.manager import CiscoFwManager

    logging.basicConfig(level=logging.DEBUG)

    loop = asyncio.get_event_loop()

    server = SyslogServer(bind_port=50514)
    server.start(loop)

    conn = CiscoSSHClient(sys.argv[1], sys.argv[2], sys.argv[3], loop)
    manager = CiscoFwManager(conn, loop, None)

    server.register_listener(manager)

    loop.run_forever()


'''
Write a script that takes a string of words and a letter from the user.
Find the index of first occurrence of the letter in the string. For example:

String input: hello world
Letter input: o
Result: 4

'''

strinput = input("Give me a sentence. ")
strinput = strinput.lower()
letter = input("Give me a letter in the sentence. ")
index = strinput[letter]
print(index)


from django.shortcuts import render,redirect
from .models import Students
from .form import StudentsForm
from django.contrib import messages

def list_notes(request):
    students=Students.objects.filter(name__contains=request.GET.get('search',"")).order_by('curse')
    context={"students":students}
    return render(request, "notes.html",context)

def view(request,id):
    student=Students.objects.get(id=id)
    context={"student":student}
    return render(request, "detail.html",context)

def edit(request,id):
    student=Students.objects.get(id=id)
    if (request.method=="GET"):
        form=StudentsForm(instance=student)
        context={"form":form,
        "id":id}
        return render(request, "edit.html",context)
    if (request.method=="POST"):
        form=StudentsForm(request.POST,instance=student)
        if form.is_valid():
            form.save()
        context={"form":form,
        "id":id}
        messages.success(request, 'Student updated.')
        return render(request, "edit.html",context)
def create(request):
    if request.method=="GET":
        form=StudentsForm()
        context={"form":form}
        return render(request,"create.html",context)
    if request.method=="POST":
        form=StudentsForm(request.POST)
        if form.is_valid():
            form.save()
        return redirect("notes")

def delete(request,id):
    student=Students.objects.get(id=id)
    student.delete()
    return redirect("notes")


#encoding:utf8
import os
import math
import numpy as np
import pandas as pd
import lightgbm as lgb
import pickle
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import StratifiedKFold
from gen_train_data import report,make_train_set
from sklearn.metrics import mean_squared_error,make_scorer
from gen_test_data import make_test_set
import time

# train
def lgb_model(df_train,df_test,params,feature_list,num):
    if os.path.exists('./model/lgb_model%s.pkl' % num):
        gbm = pickle.load(open('./model/lgb_model%s.pkl' % num,'rb'))
    else:
        lgb_train = lgb.Dataset(df_train[feature_list],label=df_train['label'],feature_name=feature_list)
        lgb_eval = lgb.Dataset(df_test[feature_list],label=df_test['label'],feature_name=feature_list, reference=lgb_train)
        gbm = lgb.train(params,
                        lgb_train,
                        num_boost_round=1500,
                        valid_sets=lgb_eval,
                        early_stopping_rounds=100)
        # gbm.save_model('model.txt')
        pickle.dump(gbm,open('./model/lgb_model77.pkl','wb'))
    y_pred = gbm.predict(df_test[feature_list], num_iteration=gbm.best_iteration)
    print('The rmse of prediction is:', mean_squared_error(df_test['label'], y_pred) ** 0.5)

    return y_pred

data_path = './data/training.pkl'
df = pickle.load(open(data_path,'rb'))
df = df.sample(frac=1)
# pickle.dump(df,open('./data/training.pkl','wb'))
# print(df[['order_cluster_label','loan_cluster_label','click_cluster_label','cluster_label']].describe())
feature_list = list(df.columns)
feature_list.remove('uid')
# [param_23,order_90,click_90,loan_90,plannum_mean,param_37,buy_sum,loan_sum,sex,plannum_min]
feature_list.remove('label')
# feature_list.remove('param_23')
# feature_list.remove('order_90')
# feature_list.remove('click_90')
# feature_list.remove('loan_90')
# feature_list.remove('plannum_mean')
# feature_list.remove('param_37')
# feature_list.remove('buy_sum')
# feature_list.remove('loan_sum')
# feature_list.remove('sex')
# feature_list.remove('plannum_min')

# feature_list.remove('label2')

test_num = int(len(df) * 0.2)
#############training data 1 ####################
params1 = {
    'task': 'train','boosting_type': 'gbdt','objective': 'regression',
    'metric': {'l2', 'rmse'},'max_depth':5,'num_leaves':21,
    'min_data_in_leaf':300,'learning_rate': 0.02,
    'feature_fraction': 0.75,'bagging_fraction': 0.8,'bagging_freq': 5,
    'verbose': -1}

df_train1 = df[:-test_num]
df_test1 = df[-test_num:]
#############training data 2 ####################
params2 = {
    'task': 'train','boosting_type': 'gbdt','objective': 'regression',
    'metric': {'l2', 'rmse'},'max_depth':5,'num_leaves':27,
    'min_data_in_leaf':350,'learning_rate': 0.02,
    'feature_fraction': 0.9,'bagging_fraction': 0.7,'bagging_freq': 5,
    'verbose': -1}

df_train2 = df[:test_num]
df_test2 = df[test_num:]
#############training data 3 ####################
params3 = {
    'task': 'train','boosting_type': 'gbdt','objective': 'regression',
    'metric': {'l2', 'rmse'},'max_depth':6,'num_leaves':27,
    'min_data_in_leaf':300,'learning_rate': 0.025,
    'feature_fraction': 0.8,'bagging_fraction': 0.8,'bagging_freq': 5,
    'verbose': -1}

df_train3 = df[:test_num].append(df[test_num *2:])
df_test3 = df[test_num:test_num *2]
#############training data 4 ####################
params4 = {
    'task': 'train','boosting_type': 'gbdt','objective': 'regression',
    'metric': {'l2', 'rmse'},'max_depth':6,'num_leaves':27,
    'min_data_in_leaf':300,'learning_rate': 0.02,
    'feature_fraction': 0.8,'bagging_fraction': 0.8,'bagging_freq': 5,
    'verbose': -1}

df_train4 = df[:test_num*2].append(df[test_num *3:])
df_test4 = df[test_num*2: test_num*3]

#############training data 5 ####################
params5 = {
    'task': 'train','boosting_type': 'gbdt','objective': 'regression',
    'metric': {'l2', 'rmse'},'max_dept':5,'num_leaves':21,
    'min_data_in_leaf':300,'learning_rate': 0.02,'num_iterations':3000,
    'feature_fraction': 0.9,'bagging_fraction': 0.9,'bagging_freq': 5,
    'verbose': -1}

df_train5 = df[:test_num*3].append(df[test_num *4:])
df_test5 = df[test_num*3: test_num*4]

############## predict #########################
start = time.time()
# pred1 = lgb_model(df_train1,df_test1,params1,feature_list,78)
# pred2 = lgb_model(df_train2,df_test2,params2,feature_list,9)
# pred3 = lgb_model(df_train3,df_test3,params3,feature_list,7)
# pred4 = lgb_model(df_train4,df_test4,params4,feature_list,7)
# pred5 = lgb_model(df_train5,df_test5,params5,feature_list,779)

# report(np.array(df_test1['label']), pred1)

# df_test['pred_loan'] = np.abs(y_pred)
# pickle.dump(df_test[['uid','label','pred_loan']],open('lgb7.pkl','wb'))

end = time.time()
print('train time:',(end-start)/60.)

##############submission#################
# X_test = make_test_set()
data_path = './data/test.pkl'
X_test = pickle.load(open(data_path,'rb'))
print(X_test.describe())
sub = X_test.copy()
# del X_test['uid']
X_test.columns = feature_list

gbm1 = pickle.load(open('./model/lgb_model773.pkl','rb'))
pred1 = gbm1.predict(X_test[feature_list], num_iteration=gbm1.best_iteration)
pred1 = np.where(pred1< 0. ,0,pred1)

# gbm2 = pickle.load(open('./model/lgb_model7895.pkl','rb'))
# pred2 = gbm2.predict(X_test[feature_list], num_iteration=gbm2.best_iteration)
# pred2 = np.where(pred2< 0. ,0,pred2)

gbm3 = pickle.load(open('./model/lgb_model778.pkl','rb'))
pred3 = gbm3.predict(X_test[feature_list], num_iteration=gbm3.best_iteration)
pred3 = np.where(pred3< 0. ,0,pred3)

# gbm4 = pickle.load(open('./model/lgb_model4.pkl','rb'))
# pred4 = gbm4.predict(X_test[feature_list], num_iteration=gbm4.best_iteration)

# gbm5 = pickle.load(open('./model/lgb_model5.pkl','rb'))
# pred5 = gbm5.predict(X_test[feature_list], num_iteration=gbm5.best_iteration)
# pred5 = np.where(pred5< 0. ,-pred5,pred5)

# # pred = np.array(pred)
# # pred = np.where(pred< 0. ,-pred,pred)

sub['pred1'] = pred1
# sub['pred2'] = pred2
sub['pred3'] = pred3
# sub['pred4'] = pred4
# sub['pred5'] = pred5

sub = sub[['uid','pred1','pred3']]
print(sub.describe())
sub['mean'] = sub[['pred1','pred3']].apply(lambda x : x.mean(),axis=1)

sub = sub[['uid','mean']]
sub.to_csv('./sub/sub13.csv',sep=',',header=None,index=False,encoding='utf8')
print(sub.describe())


import logging
import tornado.template
import os
from tornado.options import define, options

import environment

# Make filepaths relative to settings.
path = lambda root,*a: os.path.join(root, *a)
ROOT = os.path.dirname(os.path.abspath(__file__))

define("port", default=8888, help="run on the given port", type=int)
define("config", default=None, help="tornado config file")
define("debug", default=False, help="debug mode")
tornado.options.parse_command_line()

MEDIA_ROOT = path(ROOT, 'static')
TEMPLATE_ROOT = path(ROOT, 'templates')

settings = {}
settings['debug'] = options.debug
settings['static_path'] = MEDIA_ROOT
settings['template_loader'] = tornado.template.Loader(TEMPLATE_ROOT)
settings['cookie_secret'] = "your-cookie-secret"
settings['xsrf_cookies'] = True

if settings['debug']:
    LOG_LEVEL = logging.DEBUG
else:
    LOG_LEVEL = logging.INFO

# logger
logger = logging.getLogger("")
logger.setLevel(LOG_LEVEL)

app_log = logging.getLogger("tornado")
app_log_handler = logging.handlers.RotatingFileHandler(
                    path(os.path.abspath(os.path.dirname(os.path.dirname(__file__))), "logs", "app.log"),
                    maxBytes=50000000, backupCount=5)
app_log_handler.setLevel(LOG_LEVEL)
app_log_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
app_log.addHandler(app_log_handler)

if options.config:
    tornado.options.parse_config_file(options.config)


# from django.shortcuts import render
from django.http import JsonResponse

from anomaly.metrics.krum import Krum
from anomaly.metrics.zeno import Zeno
from anomaly.metrics.fools import Fools
from anomaly.metrics.auror import Auror
from anomaly.metrics.sniper import Sniper
from anomaly.metrics.pca import Pca
from backend.rfile import RFile

# from const import *
import const
import numpy as np

# Create your views here.

# def krum(request):
#
#     rfile = RFile(JSON_PATH)
#
#     k = int(request.GET.get('k', -1))
#     round = int(request.GET.get('round', -1))
#     layers = rfile.get_layer(request.GET.get('layers', -1))
#
#     result = rfile.get_grad(JSON_PATH, layers, round)
#     round = result['round']
#     gradients = result['data']
#     krum_obj = Krum(k)
#     return JsonResponse({'round': round, 'data': krum_obj.get_score(gradients)}, safe=False)

# def geo_med(request):
#
#     layers = get_layer(request.GET.get('layers', -1))
#
#     gradients = get_grad('/Users/zhangtianye/Documents/FD/Femnist/test/', layers)
#     med_obj = Med(gradients)
#     return JsonResponse(med_obj.gradients['0'],safe=False)

def fools(request):

    rfile = RFile(const.JSON_PATH)

    k = int(request.GET.get('k', -1))
    round = int(request.GET.get('round', -1))
    layers = rfile.get_layer(request.GET.get('layers', -1))

    result = rfile.get_grad(const.JSON_PATH, layers, round)
    round = result['round']
    gradients = result['data']
    data = rfile.reshape_grad(gradients)

    fools_obj = Fools(k)

    scores = []
    for i in range(len(data)):
        scores.append(fools_obj.score(data[i]))
    score = rfile.avg_score(scores)

    return JsonResponse({'round': round, 'data': score}, safe=False)

def zeno(request):

    rfile = RFile(const.JSON_PATH)

    # suggest p = 100
    p = float(request.GET.get('p', -1))
    round = int(request.GET.get('round', -1))
    layers = rfile.get_layer(request.GET.get('layers', -1))

    latest_result = rfile.get_perf(const.JSON_PATH, round, 'train')
    latest_round = latest_result['round']
    latest_perf = latest_result['data']
    former_perf = rfile.get_perf(const.JSON_PATH, latest_round - 1, 'train')['data']

    latest_grad = rfile.get_grad(const.JSON_PATH, layers, latest_round)['data']
    reshape_latest_grad = rfile.reshape_grad(latest_grad)
    former_grad = rfile.get_grad(const.JSON_PATH, layers, latest_round - 1)['data']
    reshape_former_grad = rfile.reshape_grad(former_grad)

    zeno_obj = Zeno(p)

    scores = []
    for i in range(len(reshape_latest_grad)):
        scores.append(zeno_obj.score(latest_perf, former_perf, reshape_latest_grad[i], reshape_former_grad[i]))
    score = rfile.avg_score(scores)

    return JsonResponse({'round': latest_round, 'data': score}, safe=False)

def auror(request):

    rfile = RFile(const.JSON_PATH)

    k = int(request.GET.get('k', -1))
    round = int(request.GET.get('round', -1))
    layers = rfile.get_layer(request.GET.get('layers', -1))

    result = rfile.get_grad(const.JSON_PATH, layers, round)
    round = result['round']
    gradients = result['data']
    data = rfile.reshape_grad(gradients)

    auror_obj = Auror(k)

    scores = []
    for i in range(len(data)):
        scores.append(auror_obj.score(data[i]))
    score = rfile.avg_score(scores)

    return JsonResponse({'round': round, 'data': score}, safe=False)

def sniper(request):

    rfile = RFile(const.JSON_PATH)

    p = float(request.GET.get('p', -1))
    round = int(request.GET.get('round', -1))
    layers = rfile.get_layer(request.GET.get('layers', -1))

    result = rfile.get_grad(const.JSON_PATH, layers, round)
    round = result['round']
    gradients = result['data']
    data = rfile.reshape_grad(gradients)

    sniper_obj = Sniper(p)

    scores = []
    for i in range(len(data)):
        scores.append(sniper_obj.score(data[i]))
    score = rfile.avg_score(scores)

    return JsonResponse({'round': round, 'data': score}, safe=False)

# def dagmm(request):
#
#     layers = get_layer(request.GET.get('layers', -1))
#     gradients = get_grad(JSON_PATH, layers, -1)
#
#     dagmm_obj = DAGMM(gradients)
#     dagmm_obj.score()
#     return JsonResponse(['test'], safe=False)

def pca(request):

    rfile = RFile(const.JSON_PATH)

    k = int(request.GET.get('k', -1))
    round = int(request.GET.get('round', -1))
    layers = rfile.get_layer(request.GET.get('layers', -1))

    result = rfile.get_grad(const.JSON_PATH, layers, round)
    round = result['round']
    gradients = result['data']
    data = rfile.reshape_grad(gradients)

    pca_ojb = Pca(k)

    scores = []
    for i in range(len(data)):
        scores.append(pca_ojb.score(data[i]))
    score = rfile.avg_score(scores)

    return JsonResponse({'round': round, 'data': score}, safe=False)


from random import randint
from random import choice

def play_verifier(play):
    """this function is so the player can enter more than one possible
    value, and the programmer can act like they only recieve the
    cleanest of data entries. Would you call this an elegant solution?
    For a noob, at least."""

    if play.lower()[0] == "r" or play[0] == 1:
        play = "Rock"
    elif play.lower()[0] == "p" or play[0] == 2:
        play = "Paper"
    elif play.lower()[0] == "s" or play[0] == 3:
        play = "Scissors"

    player = play
    return player

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

score = 0
hand = ["Rock", "Paper", "Scissors"]
comments = ["Interesting choice.",
            "Why would you do that?",
            "Do you like that move?",
            "Are you proud of that choice?"]
crowd = ["BOOOOOOOOO!",
         "Yeeeeaaaaahhhhhhhh",
         "Lukewarm"]

player = False

while player == False:
    computer = hand[randint(0,2)]
    player = input("Rock, Paper, Scissors? ")

    while player not in hand:
        player = play_verifier(player)
        while player not in hand:
            player = input("Don't mess with me. R, P, S? ")
            player = play_verifier(player)

    print("You chose: {}. {}".format(player.upper(), choice(comments)))
    print("Computer chose: {}.".format(computer.upper()))

    if player == computer:
        print("Curious. Why did you choose the same thing?".format(computer))

    elif player == "Rock":
        if computer == "Paper":
            print("You lose. Computer wraps you up tight.")
            score -= 1
            print("crowd response: ", crowd)
        else:
            print("You win! You smash computer. Ow.")
            score += 1
            print("crowd response: ", crowd)

    elif player == "Paper":
        if computer == "Scissors":
            print("You lose. Computer cuts you.")
            score -= 1
            print("crowd response: ", crowd)
        else:
            print("You win! You cover computer. Go work out.")
            score += 1
            print("crowd response: ", crowd)

    elif player == "Scissors":
        if computer == "Rock":
            print("You lose. Computer smashes you.")
            score -= 1
            print("crowd response: ", crowd)
        else:
            print("You win! You cut computer.")
            score += 1
            print("crowd response: ", crowd)

    print("SCORE: ", score)

    yallah_tani = input("Play again? y or n")

    if yallah_tani == "y":
        player = False

    else:
        print("Okay. See you again.")


class Vanisher:
    WAITINGTHRESHOLD=600

    @property
    def floor(self):
        return self.__floor

    @floor.setter
    def floor(self,floor):
        self.__floor=floor

    def tick(self,time,people):
        toRemove=set()
        for p in people:
            if time-p.creationTime>self.WAITINGTHRESHOLD:
                toRemove.add(p)
            if p.targetLocation==self.__floor:
                toRemove.append(p)
                global PEOPLESERVED
                PEOPLESERVED+=1
        return toRemove


import sys

def fillCake(R, C, cake):
  i = 0
  j = 0
  initial = '?'

  while i < R:
    if cake[i][0] == '?':
      j = 0
      while j < C:
        if cake[i][j] != '?':
          break
        j += 1
      if j!= C:
        oldJ = j
        initial = cake[i][j]
        while j > 0 :
          cake[i][j-1] = initial
          j = j - 1
        j = oldJ
        while j < C:
          if cake[i][j] == '?':
            initial = cake[i][j-1]
            cake[i][j] = initial
          j += 1
    else:
      j = 1
      while j < C:
        if cake[i][j] == '?':
          initial = cake[i][j-1]
          cake[i][j] = initial
        j += 1
    i += 1

  i = 0
  j = 0

  while cake[i][0] == '?':
    if i == R:
      break
    i += 1
  if i!=R:
    oldI = i
    initialRow = cake[i]
    while i > 0:
      cake[i-1] = initialRow
      i = i - 1
    i = oldI
    while i < R:
      if cake[i][0] == '?':
        initialRow = cake[i - 1]
        cake[i] = initialRow
      i += 1
  return cake

def main():

  file_name = "A-large-practice.in"
  txt_file = open(file_name, "r")
  numCase = int(txt_file.readline())
  counter = 1
  lineCoutner = 1
  new_file = open("output.txt","w")
  while counter <= numCase:
    line = txt_file.readline()
    if (line[0]).isdigit():
      cake = []
      rowCounter = 0
      line = line.strip('\n')
      dimensions = line.split(' ')
      row = int(dimensions[0])
      col = int(dimensions[1])
    else:
      line = line.strip('\n')
      cakeRow = list(line)
      cake.append(cakeRow)
      rowCounter += 1
    if rowCounter == row:
      newcake = fillCake(row,col,cake)
      new_file.write('Case #' + str(counter) + ':\n')
      i = 0
      while i < row:
        j = 0
        while j < col:
          new_file.write(str(newcake[i][j]))
          j += 1
        new_file.write('\n')
        i += 1
      counter += 1

if __name__ == "__main__":
	sys.exit(main())


"""
A simple wrapper around PiCamera that can randomly vary the exposure and
white balance during image capture as a form of data augmentation.
"""
from time import sleep
from random import choice, uniform

from picamera.array import PiRGBArray
from picamera import PiCamera

class Camera:
    """ A simple PiCamera wrapper. Setting training_mode will randomly vary
        exposure and white balance between captured images. The capture stream
        is truncated before capture to reduce recognition latency at the expense
        of frame rate. """
    def __init__(self, training_mode):
        self.training_mode = training_mode
        self.camera = PiCamera()
        self.camera.resolution = (128, 128)
        self.camera.framerate = 30
        self.capture = PiRGBArray(self.camera, size=self.camera.resolution)
        self.stream = self.camera.capture_continuous(self.capture,
                                                     format='rgb',
                                                     use_video_port=True)
        if training_mode:
            # We allow picamera's auto exposure settings to settle for 5 seconds then we
            # lock them so they don't change in response to actions as this can cause problems.
            # If waving your hands causes the camera to shift its exposure settings during training
            # as then the network will likely learn to detect the exposure setting not your hands!
            sleep(5)
            self.camera.shutter_speed = self.camera.exposure_speed
            self.camera.exposure_mode = 'off'
            self.base_awb = self.camera.awb_gains
            self.camera.awb_mode = 'off'

    def next_frame(self):
        """ Capture a frame from the camera. By truncating the frame buffer we
        exchange FPS for lower latency. When responding to gestures latency is
        more important to the user experience. """
        self.capture.truncate(0)
        if self.training_mode:
            self.camera.iso = choice([100, 200, 320, 400, 500, 640, 800])
            awb_r = max(0., uniform(-.5, .5) + self.base_awb[0])
            awb_b = max(0., uniform(-.5, .5) + self.base_awb[1])
            self.camera.awb_gains = (awb_r, awb_b)

        frame = self.stream.next().array
        return frame


# Target Sum
# DP 背包问题

# https://blog.csdn.net/fuxuemingzhu/article/details/80484450
# runtime: faster than 79.06%
class Solution:
    def findTargetSumWays(self, nums: List[int], S: int) -> int:
        dp = [ collections.defaultdict(int) for _ in range(len(nums)+1)]
        dp[0][0] = 1

        for k, v in enumerate(nums):
            for s,cnt in dp[k].items():
                dp[k+1][s+v] += cnt
                dp[k+1][s-v] += cnt

        return dp[len(nums)][S]

# DP 转化为背包问题
# https://labuladong.github.io/algo/di-er-zhan-a01c6/bei-bao-le-34bd4/dong-tai-g-35341/
class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        total = sum(nums)
        if total < abs(target) or (total + target) % 2 == 1:
            return 0

        # 计算 nums 中有几个子集的和为total
        total = (total + target) // 2
        n = len(nums)
        dp = [[0] * (total + 1) for _ in range(n+1)]
        dp[0][0] = 1

        for i in range(1, n+1):
            for j in range(total+1):
                if j >= nums[i-1]:
                    dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i-1]]
                else:
                    dp[i][j] = dp[i-1][j]
        return dp[-1][-1]

# backtrack
# TLE
class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        res = 0

        def backtrack(nums, i, remain):
            nonlocal res
            if i == len(nums):
                if remain == 0:
                    res += 1
                return

            # "-" for nums[i]
            remain += nums[i]
            backtrack(nums, i+1, remain)
            remain -= nums[i]

            # "+" for nums[i]
            remain -= nums[i]
            backtrack(nums, i+1, remain)
            remain -= nums[i]

        backtrack(nums, 0, target)
        return res


import numpy as np

from mygrad.nnet.initializers.uniform import uniform

def glorot_uniform(*shape, gain=1, dtype=np.float32, constant=None):
    r"""Initialize a :class:`mygrad.Tensor` according to the uniform initialization procedure
    described by Glorot and Bengio.

    Parameters
    ----------
    shape : Sequence[int]
        The shape of the output Tensor. Note that ``shape`` must be at least two-dimensional.

    gain : Real, optional (default=1)
        The gain (scaling factor) to apply.

    dtype : data-type, optional (default=float32)
        The data type of the output tensor; must be a floating-point type.

    constant : bool, optional (default=False)
        If ``True``, the returned tensor is a constant (it
            does not back-propagate a gradient).

    Returns
    -------
    mygrad.Tensor, shape=``shape``
        A Tensor, with values initialized according to the glorot uniform initialization.

    Notes
    -----
    Glorot and Bengio put forward this initialization in the paper
        "Understanding the Difficulty of Training Deep Feedforward Neural Networks"
    http://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf

    A Tensor :math:`W` initialized in this way should be drawn from a distribution about

    .. math::
        U[-\frac{\sqrt{6}}{\sqrt{n_j+n_{j+1}}}, \frac{\sqrt{6}}{\sqrt{n_j+n_{j+1}}}]
    """
    if len(shape) == 1:
        shape = shape[0]
    if len(shape) < 2:
        raise ValueError(
            "Glorot Uniform initialization requires at least two dimensions"
        )

    fan_in = shape[1] * (np.prod(shape[2:]) if len(shape) > 2 else 1)
    fan_out = shape[0] * (np.prod(shape[2:]) if len(shape) > 2 else 1)
    bound = gain * np.sqrt(6 / (fan_in + fan_out))
    return uniform(
        shape, lower_bound=-bound, upper_bound=bound, dtype=dtype, constant=constant
    )


import time
from threading import Lock, Thread
import numpy as np

from constants import tick_time
from google_ads import GoogleAds
from market import Market
from twitter import Twitter
#import sheet_api

class Seller(object):

    def __init__(self, name, products_list, wallet):
        """
        A class to represent the seller
        :param name: seller name string, eg. apple
        :param products_list: list of products sold by the seller
        :param wallet: total money owned by the seller
        """
        self.name = name
        # Each seller can sell multiple products in products_list
        self.products_list = products_list
        # self.product = product
        self.wallet = wallet

        # register the seller with each product it owns in market
        if products_list is not None:
            for product in products_list:
                Market.register_seller(self, product)

        # metrics tracker:
        # item_sold is total number of items of each product sold by seller.
        # A dictionary with each product as key and value is no. of items sold.eg.{iphone: 0, airpods: 0}
        self.item_sold = {key: 0 for key in products_list}

        # inventory is a list of dictionary with product as key and inventory number as value for each quarter
        # assume initial inventory is 1000 items for each product. Eg.{iphone: 1000, airpods: 1000}
        self.inventory = {key: 1000 for key in products_list}

        # sales, revenue, profit, expense and sentiment history start with zero for each product
        # Eg.[{iphone: 0, airpods: 0}] {key: 0 for key in products_list}
        self.sales_history = []
        self.revenue_history = []
        self.profit_history = []
        self.expense_history = [{key: 0 for key in products_list}]
        self.sentiment_history = []
        # advert_type and scale store data of advertisement strategy and users viewing ads for each product
        self.advert_history = [{key: (GoogleAds.ADVERT_BASIC, 1) for key in products_list}]
        self.promo_history = []
        self.buyer_history = []
        self.total_revenue = []
        self.total_expense = []
        self.total_profit = []
        self.budget = [wallet]

        # Flag for thread
        self.STOP = False

        self.lock = Lock()

        # start this seller in separate thread
        self.thread = Thread(name=name, target=self.loop)
        self.thread.start()

    def loop(self):
        """
        tick time for seller, one tick represent one quarter
        :return: none
        """
        while not self.STOP:
            self.tick()
            time.sleep(tick_time)

    def sold(self, product):
        """
        Add to the database when an item is sold
        :param product: product sold by the seller
        :return: available or not
        """
        if self.inventory[product] <= 0:
            return False
        else:
            self.lock.acquire()
            self.item_sold[product] += 1
            self.inventory[product] -= 1
            self.lock.release()

        return True

    def tick(self):
        """
        Actions to do in one time step in the simulation world:
        1. record sales history of number of items sold for each product
        2. calculate the metrics for previous tick and add to tracker, like revenue, expense, profit, user sentiment
        3. adjust price based on sales and inventory
        4. decide advertising type by CEO
        :return: none
        """
        # lock time to avoid shared variable being changed by other threads
        self.lock.acquire()

        # record sales history
        self.sales_history.append(self.item_sold)
        # reset the sales counter
        self.item_sold = self.item_sold.fromkeys(self.item_sold, 0)

        # release lock
        self.lock.release()

        # record metrics of revenue, profit
        self.record_metric()

#        printing results for debugging
#        print('\n\nSeller: ', self.name)
#        print('Revenue in previous quarter:', self.my_revenue())
#        print('Expenses in previous quarter:', self.my_expenses())
#        print('Profit in previous quarter:', self.my_profit())

        # add the profit to seller's wallet
        self.wallet += self.new_profit()

        # record current money in wallet as budget for next cycle
        self.budget.append(self.wallet)

        # adjust price for next time step
        self.adjust_price()

        # choose advertisement strategy for next time step
        self.CEO()

        # printing results for debugging
        #print('\nStrategy for next quarter \nProduct: {}, Advert Type: {}, scale: {}\n\n'.format(product.name, advert_type[product], scale[product]) for product in self.products_list)
        return

    def record_metric(self):
        """
        calculate the metrics (revenue, profit, user_sentiment, promotion effectiveness and number of buyers) for previous tick and add to tracker
            revenue = sales * price
            profit = revenue - expense
            user_sentiment is obtained from function "self.user_sentiment()"
            prmotion effectiveness = sales/ads scale
            number of buyers is obtained from GoogleAds purchase history
        :return: none
        """
        revenue = {k: v * (k.price) for k, v in self.sales_history[-1].items()}
        expense = self.expense_history[-1]
        profit = {k: v - expense[k] for k, v in revenue.items() if k in expense}
        ads_scale = self.advert_history[-1]
        promo_effect = {k: float(v/ads_scale[k][1]) for k, v in self.sales_history[-1].items() if k in ads_scale}

        num_buyer = {k: len(set(GoogleAds.purchase_history[k])) for k in self.products_list}

        # append revenue and profit record to the history in a list
        # Eg.[{iphone: 1, airpods: 2}, {iphone: 2, airpods: 3}]
        self.revenue_history.append(revenue)
        self.profit_history.append(profit)
        self.sentiment_history.append(self.user_sentiment())
        self.promo_history.append(promo_effect)
        self.buyer_history.append(num_buyer)

        return

    def my_revenue(self):
        """
        sum total revenue for all products in each time tick
        :return: list of revenue
        """
        return [sum(revenue.values()) for revenue in self.revenue_history]

    def my_expense(self):
        """
        sum total expense for all products in each time tick
        :return: list of expense
        """
        return [sum(expense.values()) for expense in self.expense_history]

    def my_profit(self):
        """
        sum total profit for all products in each time tick
        :return: list of profit
        """
        return [sum(profit.values()) for profit in self.profit_history]

    def new_profit(self):
        """
        calculate the latest total profit
        :return: total profit earned from all products sold (float)
        """
        return sum(self.profit_history[-1].values())

#    another method to get latest revenue (not used here in model)
#    def my_revenue(self, latest_only=False):
#        """
#        calculate the total revenue
#        :param latest_only: give the revenue in last tick if latest_only = True, else give the total revenue
#        :return: total revenue for all products sold (float)
#        """
#        if latest_only:
#            revenue = self.revenue_history[-1]
#            sum_revenue = sum(revenue.values())
#        else:
#            sum_revenue = sum(sum(revenue.values()) for revenue in self.revenue_history)
#
#        return sum_revenue

    def user_sentiment(self):
        """
        calculates the user sentiment from tweets.
        :return: a dictionary of sentiment value for each product as key
        """
        # initialize sentiment list with 1 for all products representing positive user_sentiment at first
#        sentiment_list = {key: 1 for key in self.products_list}
        sentiment_list = {}
        # get the latest tweets and calculate the percentage of positive tweets as user_sentiment
        for product in self.products_list:
            tweets = np.asarray(Twitter.get_latest_tweets(product, 10))
            sentiment = 1 if len(tweets) == 0 else (tweets == 'POSITIVE').mean()
            sentiment_list.update({product: sentiment})

        return sentiment_list

    def kill(self):
        """
        to stop the seller thread
        """
        self.STOP = True
        self.thread.join()

    def __str__(self):
        return self.name

    # Cognition system that decides what to do next.
    def CEO(self):
        """
        Choose advertisement types and scales for each product based on revenue and user_coverage.
        If user_coverage is less than target, choose basic ads, otherwise choose targeted ads.

        Set total advertisement budget less than a percentage of revenue or wallet money, to avoid bankrupt
        Scale (number of ads to put) equals to budget divided by advert price.

        :return: none
        """
        # initilize empty variable
        advert_type = {}
        expense = {}
        ads_type = GoogleAds.ADVERT_BASIC

        # set advertising budget as a percentage of total revenue or total money in wallet
        ads_percent = 0.5
        max_budget = self.wallet * 0.2

        # decide individual advertising strategy for each product
        for product in self.products_list:

            # get the latest revenue to decide ads budget
            revenue = self.revenue_history[-1][product]

            #avoid bankrupt by setting advertisment budget
            ads_budget = max(ads_percent * revenue, max_budget)
            coverage = GoogleAds.user_coverage(product)

            # check if user_coverage is more than half of GoogleAds users
            if coverage > 0.5:
                ads_type = GoogleAds.ADVERT_TARGETED

            scale = min(int(ads_budget / GoogleAds.advert_price[ads_type]), 500)

            # perform the actions and view the expense
            advert_type.update({product: (ads_type, scale)})

            # obtain expense from GoogleAds
            expense.update({product: GoogleAds.post_advertisement(self, product, ads_type, scale)})

        # store advertisement types and scales, and expense history
        self.advert_history.append(advert_type)
        self.expense_history.append(expense)

        return

    def adjust_price(self):
        """
        This function is for seller to increase or reduce price based on historical data:
        1. increase price when average sales is above target
        2. reduce price when inventory is more than benchmark
        or average sales volume is lower than benchmark
        :return: none
        """
        invent_bench = 200
        invent_min = 10
        sales_target = 200
        sales_bench = 2

        for product in self.products_list:

            total_sales = self.sales_history[-1][product]
            qtrs = len(self.sales_history)
            avg_sales = total_sales / qtrs
            price_delta = 0

            # adjust price 2 qtrs after market start
            if qtrs > 2:
                # 30% price increase for more profit
                if avg_sales > sales_target or self.inventory[product] < invent_min:
                    price_delta = 0.3

                # 90% discount promotion to improve sales
                elif avg_sales < sales_bench:
                    price_delta = -0.1

                # 80% discount to clear inventory
                elif self.inventory[product] > invent_bench:
                    price_delta = -0.2

            # calculate new price after adjustment
            product.price = int(product.price * (1 + price_delta))

        return


# 12. 整数转罗马数字
# 罗马数字包含以下七种字符： I， V， X， L，C，D 和 M。
# 整形转罗马数字
class Solution(object):
    def intToRoman(self, num):
        """
        :type num: int
        :rtype: str
        """
        nums = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
        romans = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"]
        index = 0
        res = ''
        while index < 13:
            # 注意：这里是等于号
            while num >= nums[index]:
                res += romans[index]
                num -= nums[index]
            index += 1
        return res

if __name__ == '__main__':
    s = Solution()
    num = 3
    result = s.intToRoman(num)
    print(result)