from functools import partial
from .utils import download, make_cache_path

def _zenodo_url(record, name):
	return f'https://zenodo.org/record/{record}/files/{name}'

class Zoo:
	_initialized = False

	_numberbatch_lang_codes = [
		'af', 'ang', 'ar', 'ast', 'az', 'be', 'bg', 'ca', 'cs', 'cy', 'da',
		'de', 'el', 'en', 'eo', 'es', 'et', 'eu', 'fa', 'fi', 'fil', 'fo',
		'fr', 'fro', 'ga', 'gd', 'gl', 'grc', 'gv', 'he', 'hi', 'hsb', 'hu',
		'hy', 'io', 'is', 'it', 'ja', 'ka', 'kk', 'ko', 'ku', 'la', 'lt', 'lv',
		'mg', 'mk', 'ms', 'mul', 'nl', 'no', 'non', 'nrf', 'nv', 'oc', 'pl',
		'pt', 'ro', 'ru', 'rup', 'sa', 'se', 'sh', 'sk', 'sl', 'sq', 'sv', 'sw',
		'ta', 'te', 'th', 'tr', 'uk', 'ur', 'vi', 'vo', 'xcl', 'zh'
	]

	_embeddings = {
	}

	@staticmethod
	def _init():
		if Zoo._initialized:
			return

		from fasttext.util.util import valid_lang_ids as ft_valid_lang_ids
		for lang in ft_valid_lang_ids:
			Zoo._embeddings[f'fasttext-{lang}'] = {
				'constructor': PretrainedFastText,
				'lang': lang
			}

			Zoo._embeddings[f'fasttext-{lang}-mini'] = {
				'constructor': CompressedFastTextVectors,
				'url': _zenodo_url(4905385, f'fasttext-{lang}-mini')
			}

		for lang in Zoo._numberbatch_lang_codes:
			Zoo._embeddings[f'numberbatch-19.08-{lang}'] = {
				'constructor': partial(Word2VecVectors, binary=True),
				'url': _zenodo_url(4911598, f'numberbatch-19.08-{lang}.zip'),
				'name': f'numberbatch-19.08-{lang}'
			}

		for d in [50, 100, 200, 300]:
			Zoo._embeddings[f'glove-6B-{d}'] = {
				'constructor': partial(Word2VecVectors, binary=True),
				'url': _zenodo_url(4925376, f'glove.6B.{d}d.zip'),
				'name': f'glove-6B-{d}'
			}

		for name, sizes in {
			'42B': [300],
			'840B': [300],
			'twitter.27B': [25, 50, 100, 200]}.items():

			for size in sizes:
				Zoo._embeddings[f'glove-{name}-{size}'] = {
					'constructor': PretrainedGloVe,
					'name': name,
					'ndims': size
				}

		Zoo._initialized = True

	@staticmethod
	def _download(url, force_download=False):
		cache_path = make_cache_path()

		download_path = cache_path / "models"
		download_path.mkdir(exist_ok=True, parents=True)

		return download(url, download_path, force_download=force_download)

	@staticmethod
	def list():
		Zoo._init()
		return tuple(sorted(Zoo._embeddings.keys()))

	@staticmethod
	def load(name, force_download=False):
		Zoo._init()
		spec = Zoo._embeddings.get(name)
		if spec is None:
			raise ValueError(f"unknown embedding name {name}")
		kwargs = dict((k, v) for k, v in spec.items() if k not in ("constructor", "url"))
		if "url" in spec:
			kwargs["path"] = Zoo._download(spec["url"], force_download)
		return spec["constructor"](**kwargs)


from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import os
import pickle
import datetime
import pytz
import AssistantSpeak as ASpeak

#Some Constant Variables
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']

MONTHS = ["january", "february", "march", "april", "may", "june","july", "august", "september","october","november", "december"]

DAYS = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]

DAY_EXTENTIONS = ["rd", "th", "st", "nd"]

# Authenticating google Calender with the key given in the credentials.json
def authenticate_google():
    """Shows basic usage of the Google Calendar API.
    Prints the start and name of the next 10 events on the user's calendar.
    """
    creds = None
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)

    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(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)

        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('calendar', 'v3', credentials=creds)

    return service

# Gets and checks for the event entry from the google Calender
def get_events(day, service):
    # Call the Calendar API
    date = datetime.datetime.combine(day, datetime.datetime.min.time())
    end_date = datetime.datetime.combine(day, datetime.datetime.max.time())
    utc = pytz.UTC
    date = date.astimezone(utc)
    end_date = end_date.astimezone(utc)

    events_result = service.events().list(calendarId='primary', timeMin=date.isoformat(), timeMax=end_date.isoformat(),
                                        singleEvents=True,
                                        orderBy='startTime').execute()
    events = events_result.get('items', [])

    if not events:
        ASpeak.speak('No upcoming events found.')
        print('No upcoming events found')
    else:
        ASpeak.speak(f"You have {len(events)} events on this day.")

        for event in events:
            start = event['start'].get('dateTime', event['start'].get('date'))
            startsplit = start.split("+",1)
            start = startsplit[0]
            #print(start.replace("T", " "), event['summary'])
            start_time = str(start.split("T")[1].split("-")[0])

            # integrating 'am' and 'pm'
            if int(start_time.split(":")[0]) < 12:
                start_time = startsplit[1] + " am"
            else:
                start_time = str(int(start_time.split(":")[0])-12) + start_time.split(":")[1]
                start_time = startsplit[1] + " pm"

            ASpeak.speak(event["summary"] + " at " + start_time)
            #start_time = start_time.replace("T", " ")
            #print(event["summary"] + " at " + start_time)

#Gets the date from the user [COMPLEX :( ]
def get_date(text):
    text = text.lower()
    today = datetime.date.today()

    if text.count("today") > 0:
        return today

    day = -1
    day_of_week = -1
    month = -1
    year = today.year

    for word in text.split():
        if word in MONTHS:
            month = MONTHS.index(word) + 1
        elif word in DAYS:
            day_of_week = DAYS.index(word)
        elif word.isdigit():
            day = int(word)
        else:
            for ext in DAY_EXTENTIONS:
                found = word.find(ext)
                if found > 0:
                    try:
                        day = int(word[:found])
                    except:
                        pass

    if month < today.month and month != -1:  # if the month mentioned is before the current month set the year to the next
        year = year+1

    if month == -1 and day != -1:  # if we didn't find a month, but we have a day
        if day < today.day:
            month = today.month + 1
        else:
            month = today.month

    # if we only found a dta of the week
    if month == -1 and day == -1 and day_of_week != -1:
        current_day_of_week = today.weekday()
        dif = day_of_week - current_day_of_week

        if dif < 0:
            dif += 7
            if text.count("next") >= 1:
                dif += 7

        return today + datetime.timedelta(dif)

    if day != -1:
        return datetime.date(month=month, day=day, year=year)


from __future__ import print_function, absolute_import

import os
import vtk
import platform
import numpy as np
from vtk.util import numpy_support

if platform.uname().system.lower() == 'windows':
    # VTK warnings crashes python on windows
    vtk.vtkObject.SetGlobalWarningDisplay(False)

def _indices(extent):
    """
        Indices to data in full volume
    """
    if len(extent) == 4:
        return np.meshgrid(np.arange(extent[2], extent[3] + 1),
                           np.arange(extent[0], extent[1] + 1))

    return np.meshgrid(np.arange(extent[2], extent[3] + 1),
                       np.arange(extent[0], extent[1] + 1),
                       np.arange(extent[4], extent[5] + 1))

def dtype(i):
    """
        Map VTK type i to numpy.dtype
    """
    if i == vtk.VTK_CHAR:
        return np.int8
    elif i == vtk.VTK_UNSIGNED_CHAR:
        return np.uint8
    elif i == vtk.VTK_SHORT:
        return np.int16
    elif i == vtk.VTK_UNSIGNED_SHORT:
        return np.uint16
    elif i == vtk.VTK_INT:
        return np.int32
    elif i == vtk.VTK_UNSIGNED_INT:
        return np.uint32
    elif i == vtk.VTK_LONG:
        return np.int64
    elif i == vtk.VTK_UNSIGNED_LONG:
        return np.uint64
    elif i == vtk.VTK_FLOAT:
        return np.float32
    elif i == vtk.VTK_DOUBLE:
        return np.float64
    elif i == vtk.VTK_LONG_LONG:
        return np.int128 if hasattr(np, 'int128') else np.int64
    elif hasattr(np, 'uint128') and i == vtk.VTK_UNSIGNED_LONG_LONG:
        return np.uint128
    else:
        raise ValueError('Cannot understand type {}'.format(i))

def vtk_type(i):
    """
        Map numpy.dtype i to VTK type
    """
    if i == np.int8:
        return vtk.VTK_CHAR
    elif i == np.uint8:
        return vtk.VTK_UNSIGNED_CHAR
    elif i == np.int16:
        return vtk.VTK_SHORT
    elif i == np.uint16:
        return vtk.VTK_UNSIGNED_SHORT
    elif i == np.int32:
        return vtk.VTK_INT
    elif i == np.uint32:
        return vtk.VTK_UNSIGNED_INT
    elif i == np.int64:
        return vtk.VTK_LONG
    elif i == np.uint64:
        return vtk.VTK_UNSIGNED_LONG
    elif i == np.float32:
        return vtk.VTK_FLOAT
    elif i == np.float64:
        return vtk.VTK_DOUBLE
    elif hasattr(np, 'int128') and i == np.int128:
        return vtk.VTK_LONG_LONG
    elif hasattr(np, 'uint128') and i == np.uint128:
        return vtk.VTK_UNSIGNED_LONG_LONG
    else:
        raise ValueError('Cannot understand dtype {}'.format(i))

def create(array):
    """
        Return numpy array 'arr' as VTKImage array
    """
    return array.view(VTKImage)

class VTKInformation(dict):
    """
        Holds image metadata

            * datatype, VTK datatype, int
            * bounds, bounds of the geometry, size 6
            * center, center of the geometry, size 3
            * dimensions, size of the geometry, size 6
            * extent, six integers - give the index of the first and last
                      point in each direction
            * origin,
            * spacing,

        :param path:
            Path to vtk image

        :param reader:
            Instance of a vtk image reader
    """
    def __init__(self, path=None, reader=None):
        self.path = path

        if self.path is None and reader is None:
            return

        _del_reader = False

        if reader is None:
            if not isinstance(path, str):
                raise ValueError('path has to be of type string, not {}'
                                 .format(type(path)))

            if not os.path.exists(self.path):
                raise IOError("No such file or directory: '{}'"
                              .format(self.path))

            reader = vtk.vtkXMLImageDataReader()
            reader.SetFileName(self.path)
            _del_reader = True
        elif isinstance(reader, vtk.vtkXMLImageDataReader):
            self.path = reader.GetFileName()

            if self.path is None or not os.path.exists(self.path):
                raise ValueError('vtkXMLImageDataReader improperly configured.'
                                 ' Image path is empty or does not exist')
        else:
            if not hasattr(reader, 'Update') and not hasattr(reader, 'GetOutput'):
                if hasattr(reader, 'GetClassName'):
                    name = reader.GetClassName()
                else:
                    name = type(reader)

                raise ValueError('Unsupported reader, {}'.format(name))

        reader.Update()
        output = reader.GetOutput()

        self.datatype = output.GetPointData().GetArray(0).GetDataType()
        self.bounds = output.GetBounds()
        self.center = output.GetCenter()
        self.dimensions = output.GetDimensions()
        self.extent = output.GetExtent()
        self.origin = output.GetOrigin()
        self.spacing = output.GetSpacing()

        if _del_reader:
            del reader
            del output

        super(VTKInformation, self).__init__(self, extent=self.extent,
                                             origin=self.origin,
                                             spacing=self.spacing)

    @property
    def dtype(self):
        return dtype(self.datatype)

    def __repr__(self):
        return str(dict(
            datatype=self.datatype,
            dtype=dtype(self.datatype),
            bounds=self.bounds,
            center=self.center,
            dimensions=self.dimensions,
            extent=self.extent,
            origin=self.origin,
            spacing=self.spacing,
        ))

class VTKImage(np.ndarray):
    """
        Numpy ndarray wrapper for VTK images. This class holds meta data
        about the image such that reading and writing to file will keep
        the correct attributes

        >>> import numpy as np
        >>> import dictlearn as dl
        >>> # volume is a numpy array
        >>> volume = VTKImage.read('path/to/volume.vti')
        >>> assert isinstance(volume, np.ndarray)
        >>> prod = np.dot(volume[:10, :10], np.random.rand(10, 5))
        >>> assert prod.shape == (10, 5)

        >>> patches = dl.Patches(volume)
        >>> patch_generator = patches.create_batch_and_reconstruct(10000):
        >>> for batch, reconstruct in patch_generator:
        >>>     # Handle batch
        >>>     reconstruct(batch)

        Write 'patches.reconstructed' to disk with the
        same attributes as 'path/to/volume.vti'

        >>> volume.write('path/to/volume_new.vti', patches.volume)
    """
    ORIGIN = np.array([0, 0, 0], np.float32)
    SPACING = np.array([1, 1, 1], np.float32)

    # todo pickle support for faster to/from python

    @property
    def dimensions(self):
        return (self.extent[1] - self.extent[0] + 1,
                self.extent[3] - self.extent[2] + 1,
                self.extent[5] - self.extent[4] + 1)

    def information(self):
        """
            Get image meta data. See VTKInformation
        """
        if not hasattr(self, '_info'):
            self._info = VTKInformation()
            self._info.datatype = self.datatype
            self._info.bounds = self.bounds
            self._info.center = self.center
            self._info.dimensions = self.dimensions
            self._info.extent = self.extent
            self._info.origin = self.origin
            self._info.spacing = self.spacing

        return self._info

    @property
    def info(self):
        return self.information()

    @staticmethod
    def from_array(array, info=None):
        """
            Create a VTKImage from a numpy array
        """

        if array.ndim != 3:
            raise ValueError('Need array.ndim == 3, not {}'.format(array.ndim))

        if not isinstance(array, np.ndarray):
            array = np.asarray(array)

        obj = array.view(VTKImage)

        if info is None:
            obj.origin = (0, 0, 0)
            obj.spacing = (1, 1, 1)
            x, y, z = array.shape
            obj.extent = (0, x - 1, 0, y - 1, 0, z - 1)
            obj.bounds = obj.extent
            obj.center = np.array(obj.extent)[1::2] / 2.0
            obj.datatype = vtk_type(array.dtype)
        else:
            obj.origin = info.origin
            obj.spacing = info.spacing
            obj.extent = info.extent
            obj.bounds = info.bounds
            obj.center = info.center
            obj.datatype = info.datatype

        return obj

    @staticmethod
    def from_image_data(image_data, name=None):
        """
            Crate VTKImage from vtkImageData

        :param image_data:
            vtk.vtkImageData instance

        :param name:
            Name of point array to extract. Defaults to array at
            index 0

        :return:
            VTKImage
        """

        if not isinstance(image_data, vtk.vtkImageData):
            raise ValueError("'image_data' is not vtk.vtkImageData, but {}"
                             .format(str(image_data)))

        bounds = image_data.GetBounds()
        center = image_data.GetCenter()
        dimensions = image_data.GetDimensions()
        extent = image_data.GetExtent()
        origin = image_data.GetOrigin()
        spacing = image_data.GetSpacing()

        array = image_data.GetPointData().GetArray(0 if name is None else name)
        datatype = array.GetDataType()

        array = numpy_support.vtk_to_numpy(array)
        array = array.reshape(*dimensions, order='F')
        obj = array.view(VTKImage)
        obj.bounds = bounds
        obj.center = center
        obj.extent = extent
        obj.origin = origin
        obj.spacing = spacing
        obj.datatype = datatype

        return obj

    @staticmethod
    def from_dicom(filename):
        raise NotImplementedError()

    @staticmethod
    def read(path, name=None):
        """
        Read a vti image.

        :param path:
            Path to file

        :param name:
            Name or index of array.
            If 'name' is None then array at index 0 is returned

        :return:
            VTKImage instance
        """
        if not os.path.exists(path):
            raise IOError("No such file or directory: '{}'"
                          .format(path))

        reader = vtk.vtkXMLImageDataReader()
        reader.SetFileName(path)
        reader.Update()

        output = reader.GetOutput()
        obj = VTKImage.from_image_data(output, name)
        obj.info.path = path
        del output
        del reader
        return obj

    def write(self, path, array=None):
        """
            Write data (array or self) to 'vti' file. This file is written with
            self.extent, self.origin, self.spacing and self.dtype.
            If the instance is created with VTKImage.read() these attributes
            are copied from the read file, otherwise the default values are used:

                * extent = [0, self.dimensions[0] - 1,
                            0, self.dimensions[1] - 1,
                            0, self.dimensions[2] - 1]

                * origin = [0, 0, 0]
                * spacing = [1, 1, 1]
                * dtype = np.float64

        :param path:
            Filename, where to save

        :param array:
            Optional, if array is None 'self' is written to file.
            If array is not None then array is written to file

        :return:
            True if writing successful
        """
        if array is not None:
            if array.shape != self.dimensions:
                raise ValueError(
                    'Incompatible dimensions read image {} and array {}'
                    .format(self.dimensions, array.shape)
                )

        image = self if array is None else array

        return VTKImage.write_vti(path, image, self.extent,
                                  self.origin, self.spacing)

    @staticmethod
    def write_vti(path, array, info=None, extent=None, origin=None,
                  spacing=None, use_array_type=True, name='ImageScalars'):
        """
            Write 'array' to 'path' as vti file

        :param path:
            Where to write

        :param array:
            Data to write, ndarray with array.ndim == 3

        :param info:
            Optional instance of VTKInformation, overwrites extent, origin
            and spacing.

        :param extent:
            Data extent, array like, len(extent) == 6. Default [0, array.shape[0] - 1,\
            0, array.shape[1] - 1, 0, array.shape[2] - 1]

        :param origin:
            Data origin, default [0, 0, 0]

        :param spacing:
            Spacing between voxels, default [1, 1, 1]

        :param use_array_type:
            Only used if info is not None. If this is False the image is
            saved with the data type given by info, otherwise
            array.dtype is used

        :param name:
            Name of scalar array

        :return:
            True if write successful
        """
        dimensions = array.shape
        datatype = vtk_type(array.dtype)

        if info is not None:
            extent = info.extent
            origin = info.origin
            spacing = info.spacing

            if not use_array_type:
                datatype = info.datatype
        else:
            if extent is None:
                extent = np.zeros(2 * array.ndim, np.int32)
                extent[1::2] = np.asarray(dimensions, np.int32) - 1

            if origin is None:
                origin = VTKImage.ORIGIN

            if spacing is None:
                spacing = VTKImage.SPACING

        importer = vtk.vtkImageImport()
        importer.SetDataScalarType(datatype)
        importer.SetNumberOfScalarComponents(1)
        importer.SetDataExtent(extent)
        importer.SetWholeExtent(extent)
        importer.SetDataOrigin(origin)
        importer.SetDataSpacing(spacing)
        importer.SetScalarArrayName(name)

        array = array.astype(dtype(datatype))
        size = len(array.flat)*array.dtype.itemsize
        array = array.flatten('F')
        vtk_array = numpy_support.numpy_to_vtk(array, 0, datatype)
        # Set pointer to image scalars
        importer.CopyImportVoidPointer(vtk_array.GetVoidPointer(0), size)
        importer.Update()
        data = importer.GetOutput()

        writer = vtk.vtkXMLImageDataWriter()
        writer.SetFileName(path)
        writer.SetInputData(data)
        return bool(writer.Write())

    def print(self):
        """
            Print image information
        """
        string = 'VTKImage:\n  dimensions {}\n'.format(self.dimensions)
        string += '  bounds {}\n'.format(self.bounds)
        string += '  center {}\n'.format(self.center)
        string += '  extent {}\n'.format(self.extent)
        string += '  origin {}\n'.format(self.origin)
        string += '  spacing {}\n'.format(self.spacing)
        print(string)

    def copy(self, order='C'):
        """
        Return a copy of the image

        :param order: {'C', 'F', 'A', 'K'}, optional
            Controls the memory layout of the copy. 'C' means C-order,
            'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous,
            'C' otherwise. 'K' means match the layout of `a` as closely
            as possible.
        """
        res = np.ndarray.copy(self, order)
        try:
            res.bounds = self.bounds
            res.center = self.center
            res.extent = self.extent
            res.origin = self.origin
            res.spacing = self.spacing
            res.datatype = self.datatype
        except AttributeError:
            # Trying to copy a slice of this array
            # Don't need to keep track of the stuff above.
            # Ex: self[12].copy()
            # Implement __getitem__ to fix
            pass

        return res

def vtp_to_vti(surface, information, invalue=1, outvalue=0, flip=None):
    """
    Convert a closed surface to ImageData using
    vtkPolyDataToImageStencil. All points on or inside
    the takes 'invalue' while all point outside the
    surface takes 'outvalue'

    :param surface:
        Path to surface file

    :param information:
        Information about the volume to create. Either an
        instance of VTKInformation or path to a vti file. If
        this is a path to an image, its attributes are copied
        to the converted image

    :param invalue:
        Value of points inside or of the surface

    :param outvalue:
        Value of points outside the surface.

    :param flip:
        Flip around an axis, options: 'x', 'y', 'z' or None to keep
        as is

    :return:
        An instance of VTKImage
    """

    if not isinstance(surface, str) or not os.path.isfile(surface):
        raise IOError("No such file or directory: '{}'".format(surface))

    if not isinstance(information, VTKInformation):
        if os.path.isfile(information):
            information = VTKInformation(information)
        else:
            raise IOError("No such file or directory: '{}'".format(surface))

    reader = vtk.vtkXMLPolyDataReader()
    reader.SetFileName(surface)
    reader.Update()
    polydata = reader.GetOutput()
    del reader

    # Foreground, takes value invalue on all point
    # inside or on the surface
    image_data = vtk.vtkImageData()
    image_data.SetSpacing(information.spacing)
    image_data.SetOrigin(information.origin)
    image_data.SetDimensions(information.dimensions)
    image_data.SetExtent(information.extent)
    image_data.AllocateScalars(information.datatype, 1)

    num_points = image_data.GetNumberOfPoints()

    for i in range(num_points):
        image_data.GetPointData().GetScalars().SetTuple1(i, invalue)

    # Surface stencil
    stencil = vtk.vtkPolyDataToImageStencil()
    stencil.SetInputData(polydata)
    stencil.SetOutputOrigin(information.origin)
    stencil.SetOutputSpacing(information.spacing)
    stencil.SetOutputWholeExtent(image_data.GetExtent())
    stencil.Update()

    # Image stencil. All points not in stencil
    # gets value outvalue
    img_stencil = vtk.vtkImageStencil()
    img_stencil.SetInputData(image_data)
    img_stencil.SetStencilConnection(stencil.GetOutputPort())
    img_stencil.ReverseStencilOff()
    img_stencil.SetBackgroundValue(outvalue)
    img_stencil.Update()

    image = img_stencil.GetOutput()

    if flip is not None:
        axes = {'x': 0, 'y': 1, 'z': 2}
        flipper = vtk.vtkImageFlip()
        flipper.SetFilteredAxis(axes[flip])
        flipper.SetInputData(image)
        flipper.Update()
        image = flipper.GetOutput()

    return VTKImage.from_image_data(image)

def as_image_data(volume, info=None):
    """
        Convert a numpy array 'volume' to vtk.vtkImageData
    """
    if info is None and not isinstance(volume, VTKImage):
        raise ValueError('Need info instance of VTKInformation or '
                         'volume instance of VTKImage')

    if info is None:
        info = volume.information()

    # TODO: Fix seg fault when extent is not (0, x, 0, y, 0, z)
    # it's an issue with python's gc. The allocated memory
    # for importer.GetOutput() is freed when vtk_array goes
    # out of scope
    importer = vtk.vtkImageImport()
    importer.SetDataScalarType(info.datatype)
    importer.SetNumberOfScalarComponents(1)
    importer.SetDataExtent(info.extent)
    importer.SetWholeExtent(info.extent)
    importer.SetDataOrigin(info.origin)
    importer.SetDataSpacing(info.spacing)

    size = len(volume.flat)*volume.dtype.itemsize
    array = volume.flatten('F')
    vtk_array = numpy_support.numpy_to_vtk(array, 1, info.datatype)
    # Set pointer to image scalars
    importer.CopyImportVoidPointer(vtk_array.GetVoidPointer(0), size)
    importer.Update()
    return vtk_array, importer.GetOutput()

def marching_cubes(image_data, contours, connectivity=False, path=None):
    """
    """
    if isinstance(image_data, VTKImage):
        info = image_data.information()
        importer = vtk.vtkImageImport()
        importer.SetDataScalarType(info.datatype)
        importer.SetNumberOfScalarComponents(1)
        importer.SetDataExtent(info.extent)
        importer.SetWholeExtent(info.extent)
        importer.SetDataOrigin(info.origin)
        importer.SetDataSpacing(info.spacing)

        size = len(image_data.flat) * image_data.dtype.itemsize
        array = image_data.flatten('F')
        vtk_array = numpy_support.numpy_to_vtk(array, 1, info.datatype)
        importer.CopyImportVoidPointer(vtk_array.GetVoidPointer(0), size)
        importer.Update()
        image_data = importer.GetOutput()

    if isinstance(contours, (int, float)):
        contours = (contours, )

    contour = vtk.vtkMarchingContourFilter()
    contour.SetInputData(image_data)

    for i, value in enumerate(contours):
        contour.SetValue(0, value)

    contour.Update()
    poly_data = contour.GetOutput()

    if connectivity:
        connectivity = vtk.vtkConnectivityFilter()
        connectivity.SetInputData(poly_data)
        connectivity.SetExtractionModeToLargestRegion()
        connectivity.Update()

        mapper = vtk.vtkGeometryFilter()
        mapper.SetInputData(connectivity.GetOutput())
        mapper.Update()
        poly_data = mapper.GetOutput()

    if isinstance(path, str):
        writer = vtk.vtkXMLPolyDataWriter()
        writer.SetFileName(path)
        writer.SetInputData(poly_data)
        writer.Write()

    return poly_data


import os
import sys
import json
import logging.config

# LOAD CONFIG FILE
with open('config.json') as config:
    json_data = json.load(config)

'''
------------------------------------------------
                CONFIG VARIABLES
------------------------------------------------
'''
bot = json_data["bot"]
event = json_data["eventsVars"]

# HiemSword: Yes, i know this loop is not the best method, but it works
for i in json_data["bot"]:
    bot_branch = i["branch"]
    bot_version = i["version"]
    bot_version_dev = i["dev"]
    bot_version_info = i["info"]
    bot_prefix = i["prefix"]
    bot_prefix_dev = i["prefix_dev"]

    extensionsEnabled = i["extensionsEnabled"]
    exts_dir = i["exts_dir"]

    bot_presence = i["playing_status"]

# ------------|  Join/Left event config variables  |-----

for i in json_data["eventsVars"]:
    for ii in i["join&leave"]:

        welcome_dm = ii["dm_msg"]

        welcome_ch_id = ii["ch_id"]
        welcome_ch_name = ii["ch_name"]

        join_msg = ii["hello_msg"]
        left_msg = ii["bye_msg"]
# ------------|  Extensions variables |-----

exts_list = [""] * 30 # please someone find a better way to do this

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

def return_json():
    return json_data


from django.conf import settings
from django.conf.urls.defaults import patterns, include, handler404
from django.views.generic.simple import direct_to_template, redirect_to

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('channelguide.guide.views',
    (r'^$', 'frontpage.index'),
    (r'^admin/(.*)$', admin.site.root),
    (r'^favicon.ico$', redirect_to, {'url': '/images/favicon.ico'}),
    (r'^frontpage$', 'frontpage.index'),
    (r'^frontpage/edit-header$', 'frontpage.edit_header'),
    (r'^audio/', include('channelguide.guide.audio_urlconf')),
    (r'^firsttime$', 'firsttime.index'),
    (r'^accounts/', include('channelguide.user_profile.urls')),
    (r'^accounts/', include('django.contrib.auth.urls')),
    (r'^languages/', include('channelguide.labels.languages.urls')),
    (r'^notes/', include('channelguide.notes.urls')),
    (r'^watch/', include('channelguide.cobranding.urls')),
    (r'^i18n/setlang/?', 'i18n.set_language'),
    (r'^api/', include('channelguide.api.urls')),
    (r'^recommend/', include('channelguide.recommendations.urls')),
    (r'^ping/', include('channelguide.watched.urls')),
    (r'^submit/?', include('channelguide.submit.urls')),
    (r'^share/', include('channelguide.sharing.urls')),
    (r'^genres/', include('channelguide.labels.categories.urls')),
    (r'^tags/', include('channelguide.labels.tags.urls')),
    (r'^dmca$', direct_to_template,
     {'template': 'guide/dmca.html'}))

urlpatterns += patterns('channelguide.moderate.views',
    (r'^moderate$', 'index'),
    (r'^how-to-moderate$', 'how_to_moderate'),
    (r'^moderate/', include('channelguide.moderate.urls')))

urlpatterns += patterns('channelguide.search.views',
    (r'^search$', 'search'),
    (r'^search-more-channels$', redirect_to, {'url': '/search'}),
    (r'^search-more-items$', redirect_to, {'url': '/search'}))

urlpatterns += patterns('channelguide.user_profile.views',
    (r'^user/(.*)$', 'for_user'))

# new channel pages
urlpatterns += patterns('channelguide.channels.views',
                        (r'^popular/?$', 'filtered_listing', {
                    'filter': 'name',
                    'default_sort': '-popular',
                    'title': 'Popular Shows'}),
                        (r'^toprated/?$', 'filtered_listing', {
                    'filter': 'name',
                    'default_sort': '-rating',
                    'title': 'Top-Rated Shows'}),
                        (r'^feeds/?$', 'filtered_listing', {
                    'filter': 'feed',
                    'value': True,
                    'title': 'Feeds'}),
                        (r'^sites/?$', 'filtered_listing', {
                     'filter': 'feed',
                     'value':  False,
                     'title': 'Sites'}),
                        (r'^new/?$', 'filtered_listing', {
                    'filter': 'name',
                    'default_sort': '-age',
                    'title': 'New Shows'}),
                        (r'^featured/?$', 'filtered_listing', {
                    'filter': 'featured',
                    'value': True,
                    'title': 'Featured Shows'}),
                        (r'^hd/?$', 'filtered_listing', {
                    'filter': 'hd',
                    'value': True,
                    'title': 'High-Definition Shows'}),
                        (r'^(feeds|sites)/', include('channelguide.channels.urls')),
                        )

urlpatterns += patterns('channelguide.channels.playback',
                        (r'^items/(\d+)/?$', 'item'))

# donation pages
def donate_render(request, template):
    context = {'request': request,
               'google_analytics_ua': settings.GOOGLE_ANALYTICS_UA,
               'BASE_URL': settings.BASE_URL,
               'BASE_URL_FULL': settings.BASE_URL_FULL,
               'PAYPAL_URL': 'https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=donate%40pculture%2eorg&item_name=Tax%20Deductible%20Donation%20to%20Miro&page_style=MiroStore&no_shipping=1&return=https%3a%2f%2fwww%2emiroguide%2ecom%2fdonate%2fthanks&no_note=1&tax=0&currency_code=USD&lc=US&bn=PP%2dDonationsBF&charset=UTF%2d8',
               'CC_URL': 'https://www.getmiro.com/about/donate/cc-guide.html',
              }
    return direct_to_template(request,
                              template=template,
                              extra_context = context)

def donate_thanks(request):
    response = donate_render(request, template='donate/thanks.html')
    if 'donate_donated' not in request.COOKIES:
        response.set_cookie('donate_donated', 'yes', max_age=60*60*24*30,
                            secure=settings.USE_SECURE_COOKIES or None)
    return response

urlpatterns += patterns('',
                        (r'^donate$', donate_render, {
    'template': 'donate/donate.html'}),
                        (r'^donate/special$', donate_render, {
    'template': 'donate/special.html'}),
                        (r'^donate/biz$', donate_render, {
    'template': 'donate/biz.html'}),
                        (r'^donate/thanks$', donate_thanks),
                        )

# RSS feeds
from channelguide.guide import feeds

urlpatterns += patterns('',
    (r'^rss/(?P<name>new|featured|popular|toprated)/?', redirect_to,
     {'url': 'http://feeds.feedburner.com/miroguide/%(name)s'}))

urlpatterns = urlpatterns + patterns('',
    (r'^(?:rss|feeds)(?:_real)?/(?P<url>.*)$', feeds.cached_feed,
        {'feed_dict':
            {   'new': feeds.NewChannelsFeed,
                'features': feeds.FeaturedChannelsFeed,
                'featured': feeds.FeaturedChannelsFeed,
                'popular': feeds.PopularChannelsFeed,
                'toprated': feeds.TopRatedChannelsFeed,
                'categories': feeds.CategoriesFeed,
                'tags': feeds.TagsFeed,
                'languages': feeds.LanguagesFeed,
                'search': feeds.SearchFeed,
                'recommend': feeds.RecommendationsFeed}
        }),
    # be backwards compatible even though we're using /feeds/* for something
    # else now
    (r'^feeds/(?P<name>(new|featured|popular|toprated|categories|tags|languages|search|recommend).*)$',
     redirect_to, {'url': '/rss/%(name)s'}),
    (r'^feeds/features/?$', redirect_to, {'url': '/rss/featured'}),
)

# backwards compatible URLs
urlpatterns += patterns('',
                        (r'^browse/$', redirect_to, {'url': None}),
                        (r'^category-peek-fragment$', redirect_to,
                         {'url': None}),
                        (r'^channels/', include('channelguide.channels.urls')),
                        (r'^categories/', include('channelguide.labels.categories.urls')),
                        (r'^cobranding/', include('channelguide.cobranding.urls')))

js_info_dict = {
    'packages': ('channelguide.guide',),
}

urlpatterns += patterns('',
    (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
)

handler500 = 'channelguide.guide.views.errors.error_500'

if settings.DEBUG:
    import os
    static_patterns = []
    for dir in ('css', 'images', 'js', 'movies', 'swf'):
        static_patterns.append((r'^%s/(?P<path>.*)$' % dir,
            'django.views.static.serve',
            {'document_root': os.path.join(settings.STATIC_DIR, dir)}))
    urlpatterns.extend(patterns ('', *static_patterns))
    urlpatterns += patterns('',
                            (r'^media/(?P<path>.*)$',
                             'django.views.static.serve',
                             {'document_root': settings.MEDIA_ROOT}))


"""This module implements a serial bus class which talks to bioloid
devices through a serial port.

"""

import serial
from bioloid.bus import Bus

class SerialPort(serial.Serial):
    """Encapsulates serial port communicatons."""

    def __init__(self, *args, **kwargs):
        # Ensure that a reasonable timeout is set
        timeout = kwargs.get('timeout', 0.1)
        if timeout < 0.05:
            timeout = 0.05
        kwargs['timeout'] = timeout
        print("Using timeout of ", timeout)
        kwargs['bytesize'] = serial.EIGHTBITS
        kwargs['parity'] = serial.PARITY_NONE
        kwargs['stopbits'] = serial.STOPBITS_ONE
        kwargs['xonxoff'] = False
        kwargs['rtscts'] = False
        kwargs['dsrdtr'] = False
        serial.Serial.__init__(self, *args, **kwargs)

class SerialBus(Bus):
    """Implements a BioloidBus which sends commands to a bioloid device
    via a BioloidSerialPort.

    """

    def __init__(self, serial_port, show_packets=False):
        Bus.__init__(self, show_packets)
        self.serial_port = serial_port

    def read_byte(self):
        """Reads a byte from the bus. This function will return None if
        no character was read within the designated timeout.

        The max Return Delay time is 254 x 2 usec = 508 usec (the
        default is 500 usec). This represents the minimum time between
        receiving a packet and sending a response.

        """
        data = self.serial_port.read()
        if data:
            return ord(data[0])
        return None

    def write_packet(self, packet_data):
        """Function implemented by a derived class which actually writes
        the data to a device.

        """
        self.serial_port.write(packet_data)


# script principal para iniciar la ejecución del programa genético
import argparse, sys, os

## Importar el módulo principal del Programa Genético.
import gprogram as gp
from MoeaRegresion import MoeaRegresion

## Este módulo es que debemos cambiar para cada problema nuevo.
from ProblemaRegresion import *

# Esta función lee los argumentos pasados desde la consola.
def readArgs():
    parser = argparse.ArgumentParser(description='Parámetros para ejecutar el PG')

    parser.add_argument('-p', '--psize', type=int, required=True,
                        help='Population size')
    parser.add_argument('-g', '--ngens', type=int, required=True,
                        help='Number of generations')
    parser.add_argument('-x', '--pxover', type=float, required=False, default=0.9,
                        help='Probability for crossover')
    parser.add_argument('-m', '--pmut', type=float, required=False, default=0.1,
                        help='Probability for mutation')
    parser.add_argument('-d', '--depth', type=int, required=False, default=5,
                        help="Trees' maximum depth")
    parser.add_argument('-f', '--dFile', type=str, required=False, default='puntos_01.txt',
                        help="Archivo de entrada para el problema de regresión")

    args = parser.parse_args()
    return args

# La función que crea un objeto PG y realiza la optimización configurada.
def main():
    ### 1. Leer argumentos de la consola.
    args = readArgs()

    ### 2. Crear el problema que se resolverá con el PG
    ### En este ejemplo se crea el problema que define 2 cosas:
    ###    i) Cómo representar los polinomios que deberán ajustarse a nuestros puntos.
    ###   ii) Cómo evaluar cada uno de los árboles (polinomios) según la desviación a los puntos.
    archivoEntrada = args.dFile
    problema = MoeaRegresion(archivoEntrada)

    ### 3. Crear el objeto GP y optimizar el problema.
    myGP = gp.GeneticProgram(problema, args.psize, args.ngens, args.pxover, args.pmut, args.depth)
    myGP.optimize()

    ### La salida quedará en 3 archivos:
    # 1. fitness_history.txt: la aptitud y evaluación del MEJOR individuo en cada generación.
    # 2. lastPopFiteness.txt: la aptitud y evaluación de los N individuos de la población final.
    # 3. lastPopTrees.txt   : la representación en árbol de los N individuos de la población final.
    print("\n\nLa salida está en 3 archivos: fitness_history.txt, lastPopFitness.txt y lastPopTrees.txt\n\n")

if __name__ == "__main__":
    main()


import streamlit as st
import openai

openai.api_key = st.secrets["OPENAI_TOKEN"]

def request_chat_completion(messages, stream=False):
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=messages,
        stream=stream
    )
    return response

st.title("Streamlit Chat💬")

# session state에 대화 내용 저장할 messages list 생성
if "messages" not in st.session_state:
    st.session_state.messages = []

# avatar
user_avatar = "🧑💻"
system_avatar = "./images/profile_robot.png"

with st.chat_message(name="system", avatar=system_avatar):
    st.markdown("반갑습니다 휴먼")
    with st.spinner():
        st.image("./images/dance_robot.gif")

# 이전에 나눴던 대화들 차례대로 출력
for message in st.session_state.messages:
    role = message["role"]
    content = message["content"]
    avatar = user_avatar if role == "user" else system_avatar
    with st.chat_message(role, avatar=avatar):
        st.markdown(content)

# 유저의 입력 받아서 UI에 추가
prompt = st.chat_input("입력")
if prompt:
    # UI에 그려주기
    with st.chat_message("user", avatar=user_avatar):
        st.markdown(prompt)
    # 히스토리에 추가
    st.session_state.messages.append(
        {"role": "user", "content": prompt}
    )

    with st.chat_message(name="system", avatar=system_avatar):
        is_stream = True

        with st.spinner("AI는 고민중..."):
            # time.sleep(1)
            # response = "못알아듣겠습니다 휴먼"

            # chatGPT API
            chatgpt_response = request_chat_completion(
                st.session_state.messages,
                stream=is_stream
            )

        message_placeholder = st.empty()
        if not is_stream:
            response = chatgpt_response["choices"][0]["message"]["content"]
        else:
            response = ""
            for chunk in chatgpt_response:
                delta = chunk.choices[0]["delta"]
                if "content" in delta:
                    response += delta["content"]
                    message_placeholder.markdown(response + "▌")
                else:
                    break
        message_placeholder.markdown(response)
    # 히스토리에 추가
    st.session_state.messages.append(
        {"role": "system", "content": response}
    )


#Imports
import re
import pandas as pd
import json
import multiprocessing
import string
from gensim.models import Word2Vec
from gensim.models.phrases import Phrases, Phraser
from time import time
from collections import defaultdict
import numpy as np
import pdb

#Import Scikit
from sklearn.neural_network import MLPRegressor
from sklearn.model_selection import train_test_split

#Import natural language toolkit
import nltk
nltk.download('punkt')

#Import spacy and load web model
import spacy
#Must download in terminal before loading it
spacy.load("en_core_web_sm")
from spacy.vocab import Vocab

#For timing processes
t = time()

#loading data
df = pd.read_csv("casual_data_windows.csv")
df = df.dropna().reset_index(drop=True)

#Loading spacy nlp
nlp = spacy.load("en_core_web_sm")

#Creating sentences to train w2v
sent = [row.split() for row in df['Person1']]
phrases = Phrases(sent, min_count=30, progress_per=10000)
bigram = Phraser(phrases)
sentences = bigram[sent]

biggestLen = 31
currentLen = 0
index = 0
vecsX = []
vecsY = []
sent = []

#Create X and y arrays
X = []
y = []

#Check num cores in computer for w2v model input
cores = multiprocessing.cpu_count()

#Create model
w2vModel = Word2Vec(min_count=20,
                  window=2,
                  size=300,
                  sample=6e-5,
                  alpha=0.03,
                  min_alpha=0.0007,
                  negative=20,
                  workers=cores-1)

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

#Build vocab in Word2Vec model
print("Starting to build vocab...")
w2vModel.build_vocab(sentences, progress_per=10000)
#Print time taken to build vocab
print('Time to build vocab: {} mins'.format(round((time() - t) / 60, 2)))

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

#Train Word2Vec Model
print("Starting to train Word2Vec...")
w2vModel.train(sentences, total_examples=w2vModel.corpus_count,
          epochs=20, report_delay=1)
print('Time to train the model: {} mins'.format(round((time() - t) / 60, 2)))

w2vModel.init_sims(replace=True)

print(len(df['Person1']))
print("Appending Data...")

#Append Vectorized data into X and y training sets
for x in range(0, int(len(df['Person1']) / 560)):
  for i in range(0, len(df['Person1'][x].split(" "))):
      if x < len(df['Person1']) - 1 and i < len(df['Person1'][x].split(" ")):
          vecsX.append(nlp(df['Person1'][x][i].lower()).vector_norm)
          print(x)

  for e in range(0, biggestLen - len(df['Person1'][x].split(" "))):
      vecsX.append(nlp("unnapliccable").vector_norm)

  X.append(vecsX)
  vecsX = []

  for l in range(0, len(df['Person1'][x].split(" "))):
      if x < len(df['Person1']) - 1 and l < len(df['Person1'][x].split(" ")):
          vecsY.append(nlp(df['Person1'][x][l].lower()).vector_norm)
          print(x)

  for r in range(0, biggestLen - len(df['Person1'][x].split(" "))):
      vecsY.append(nlp("unnapliccable").vector_norm)

  y.append(vecsY)
  vecsY = []

print('Time to append data: {} mins'.format(round((time() - t) / 60, 2)))
# sentend = np.ones

#Split train and test data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20)

#Create and fit model
clf = MLPRegressor().fit(X_train, y_train)

#User Input
inp = input("Say something:")

#Data cleaning
for k in range(0, len(inp.split(" "))):
  sent.append(nlp(inp[k].lower()).vector_norm)

for i in range(0, biggestLen - len(inp.split(" "))):
  sent.append(nlp("unnapliccable").vector_norm)

sent = [sent]

#Predicting
predictions = clf.predict(sent)
pdb.set_trace()
# outputlist = [w2vModel.wv.similar_by_vector([predictions[0][i], predictions[0][i]], topn=1)[0][0] for i in range(biggestLen)]
# output = ' '.join(outputlist)


from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals

import numpy as np
import os

from os import listdir
from os.path import isfile, join
import sklearn.cluster as sc
import pickle

from AGCN.utils.data_loader import PointcloudLoader
from AGCN.models import Graph

from AGCN.utils import provider as pd
from AGCN.utils.save import save_to_disk, load_from_disk

# ShapeNet Part Segmentation
BASE_DIR = os.path.join(os.environ["HOME"], 'AGCN/data/3Dmesh/part_seg_shapenet/hdf5_data')
TRAIN_FILES = pd.getDataFiles(os.path.join(BASE_DIR, 'train_hdf5_file_list.txt'))
TEST_FILES = pd.getDataFiles(os.path.join(BASE_DIR, 'test_hdf5_file_list.txt'))

NUM_CATEGORIES = 16
CLUSTER_NUM = 100

TRAIN_NUM = 6000
TEST_NUM = 512

class ShapeNetLoader(PointcloudLoader):
    """
    This class of loader is for Point Cloud data, which is usually lots of binary files stay in
    a folder. Each binary file is a point cloud object, reading it, you get a nddarray of 3D points, each rwo of which
    is a point in laser receivers.
    Input: folder directory
    Output: ConvMol instance for each point cloud object. Features is intensity, adjacency matrix, degree
    are manually learned and set by clustering.
    """

    def featurize(self, shard_size=1024):
        """
        Args:
            input_folder: folder name of binary files (graph object)
            data_dir: where to save generated data frame
            shard_size: number of graphs in one shard
        Returns: creatd Train and Test dataset
        """
        assert os.path.exists(self.processed_data_dir)
        assert os.path.exists(self.data_dir)

        train_dir = os.path.join(self.processed_data_dir, 'train')
        test_dir = os.path.join(self.processed_data_dir, 'test')
        if not os.path.exists(train_dir):
            os.makedirs(train_dir)
        if not os.path.exists(test_dir):
            os.makedirs(test_dir)

        metadata_rows = []
        all_X, all_y, all_seg, all_y_one_hot = [], [], [], []
        for shard_num, (shard, y, seg, y_1h) in enumerate(self.get_shards(TRAIN_FILES, shard_size)):
            """shard is ndarray of 3D mesh point 3-dimension, [pc_id, point_id, (x,y,z)]
                y is the class id for each sample (3D mesh), int type
            """
            print('Featurizing Training Data , Shard - %d' % shard_num)
            X, seg = self.featurize_shard(shard, seg)

            """ save shard (x,y,ids, w)"""
            basename = "shard-%d" % shard_num
            metadata_rows.append(self.write_data_to_disk(train_dir, basename, X, y, seg, y_1h))

            """ stack to list"""
            all_X.append(X)
            all_y.append(y)
            all_seg.append(seg)
            all_y_one_hot.append(y_1h)

        """ save the meta data of training dataset to local """
        meta_data1 = list()
        meta_data1.append(metadata_rows)
        with open(os.path.join(train_dir, 'meta.pkl'), 'wb') as f:
            pickle.dump(meta_data1, f)

        """ return a Dataset contains all X, y, w, ids"""
        all_X = np.concatenate(all_X)
        all_y = np.squeeze(np.concatenate(all_y))
        all_seg = np.squeeze(np.vstack(all_seg))
        all_y_one_hot = np.squeeze(np.vstack(all_y_one_hot))
        assert all_X.shape[0] == all_y.shape[0] == all_seg.shape[0] == all_y_one_hot.shape[0]

        train_dataset = dict()
        train_dataset['X'] = all_X
        train_dataset['y'] = all_y
        train_dataset['seg_mask'] = all_seg
        train_dataset['one_hot_y'] = all_y_one_hot

        metadata_rows = []
        all_X, all_y, all_seg, all_y_one_hot = [], [], [], []
        for shard_num, (shard, y, seg, y_1h) in enumerate(self.get_shards(TEST_FILES, shard_size)):
            """shard is ndarray of 3D mesh point 3-dimension, [pc_id, point_id, (x,y,z)]
                y is the class id for each sample (3D mesh), int type [pc_id, part_id of point]
            """

            print('Featurizing Testing Data , Shard - %d' % shard_num)
            X, seg = self.featurize_shard(shard, seg)

            """ save shard (x,y,ids, w)"""
            basename = "shard-%d" % shard_num
            metadata_rows.append(self.write_data_to_disk(test_dir, basename, X, y, seg, y_1h))

            """ stack to list"""
            all_X.append(X)
            all_y.append(y)
            all_seg.append(seg)
            all_y_one_hot.append(y_1h)

        """ save the meta data to local """
        meta_data2 = list()
        meta_data2.append(metadata_rows)
        with open(os.path.join(test_dir, 'meta.pkl'), 'wb') as f:
            pickle.dump(meta_data2, f)

        """ return a Dataset contains all X, y, w, ids"""
        all_X = np.concatenate(all_X)
        all_y = np.squeeze(np.concatenate(all_y))
        all_seg = np.squeeze(np.vstack(all_seg))
        all_y_one_hot = np.squeeze(np.vstack(all_y_one_hot))
        assert all_X.shape[0] == all_y.shape[0] == all_seg.shape[0] == all_y_one_hot.shape[0]

        test_dataset = dict()
        test_dataset['X'] = all_X
        test_dataset['y'] = all_y
        test_dataset['seg_mask'] = all_seg
        test_dataset['one_hot_y'] = all_y_one_hot

        return train_dataset, test_dataset

    def get_shards(self, file_list, shard_size):

        """ shuffle the data files"""
        file_idxs = np.arange(0, len(file_list))
        np.random.shuffle(file_idxs)  # randomly extract data from files

        """read all data"""
        all_data, all_label, all_seg, all_one_hot_label = [], [], [], []
        for fn in file_idxs:
            # load the point cloud from the file, current_data -> data from one file
            current_data, current_label, current_seg = pd.loadDataFile_with_seg(os.path.join(BASE_DIR, file_list[fn]))
            # remove redundant dimensions
            current_label = np.squeeze(current_label)
            current_seg = np.squeeze(current_seg)

            # shuffle data order
            cur_data, cur_labels, order = pd.shuffle_data(current_data, np.squeeze(current_label))
            current_seg = current_seg[order, ...]

            # create one-hot class label
            cur_labels_one_hot = self.convert_label_to_one_hot(current_label)
            cur_labels_one_hot = np.squeeze(cur_labels_one_hot)

            all_data.append(current_data)
            all_label.append(current_label)
            all_seg.append(current_seg)
            all_one_hot_label.append(cur_labels_one_hot)

        """ create numpy for all data and label"""
        all_data = np.squeeze(np.vstack(all_data))
        all_seg = np.squeeze(np.vstack(all_seg))
        all_one_hot_label = np.squeeze(np.vstack(all_one_hot_label))
        all_label = np.squeeze(np.hstack(all_label))
        assert all_label.shape[0] == all_data.shape[0] == all_seg.shape[0] == all_one_hot_label.shape[0]

        "generate shard data, label, seg_mask, one_hot labels"
        shard_num = 0

        start_idx = shard_num * shard_size
        end_idx = (shard_num + 1) * shard_size
        while end_idx < all_data.shape[0]:
            sel_data = all_data[start_idx:end_idx, :, :]  # ready data
            sel_labels = all_label[start_idx:end_idx]       # corresponding labels
            sel_seg = all_seg[start_idx:end_idx, :]
            sel_one_hot_labels = all_one_hot_label[start_idx:end_idx, :]
            shard_num += 1
            start_idx = shard_num * shard_size
            end_idx = (shard_num + 1) * shard_size
            yield sel_data, sel_labels, sel_seg, sel_one_hot_labels
        # end exceed the bound of pc_names, return all
        yield all_data[start_idx:, :, :], all_label[start_idx:], all_seg[start_idx:, :], all_one_hot_label[start_idx:, :]

    @staticmethod
    def write_data_to_disk(
                           data_dir,
                           basename,
                           X=None,
                           y=None,
                           seg=None,
                           y_1h=None):

        out_X = "%s-X.joblib" % basename
        save_to_disk(X, os.path.join(data_dir, out_X))

        out_y = "%s-y.joblib" % basename
        save_to_disk(y, os.path.join(data_dir, out_y))

        out_seg = "%s-seg.joblib" % basename
        save_to_disk(seg, os.path.join(data_dir, out_seg))

        out_y_1h = "%s-y1h.joblib" % basename
        save_to_disk(y_1h, os.path.join(data_dir, out_y_1h))

        # note that this corresponds to the _construct_metadata column order
        return {'basename': basename, 'X': out_X, 'y': out_y, 'seg_mask': out_seg, 'one_hot_y': out_y_1h}

    def convert_label_to_one_hot(self, labels):
        label_one_hot = np.zeros((labels.shape[0], self.n_classes))
        for idx in range(labels.shape[0]):
            label_one_hot[idx, labels[idx]] = 1
        return label_one_hot

    def featurize_shard(self, shard, seg_mask):

        """
        convert ndarray (n-sample, n_point of sample, 3-d)
        :param shard: ndarray, point cloud raw data
        :return: graph object for each sample
        """
        cluster_num = CLUSTER_NUM  # min_node in this folder is 13 precomputed
        clusterer = sc.AgglomerativeClustering(n_clusters=cluster_num)

        X = []  # to save the graph object
        S = []  # list of new mask
        n_samples = shard.shape[0]
        for pc_id in range(n_samples):
            # iterate each pc in shard
            P = np.squeeze(shard[pc_id, :, :])
            mask = np.squeeze(seg_mask[pc_id, :])
            if P.shape[0] > cluster_num:
                # clustering on original cloud
                cluster_indicators = clusterer.fit_predict(P)  # labels of original points
                new_points = []
                Point_mask = []
                for i in range(cluster_num):
                    """ each cluster center is the new point after clustering"""
                    idx = np.where(cluster_indicators == i)
                    coord = np.mean(P[idx], axis=0)
                    part_id = np.argmax(np.bincount(mask[idx])).astype(np.int32)
                    new_points.append(coord)
                    Point_mask.append(part_id)  # this point at coord belongs to part_id
                new_PC = np.asarray(new_points).astype(np.float32)
                new_mask = np.asarray(Point_mask).astype(np.int32)
                assert new_PC.shape[0] <= cluster_num and new_PC.shape[0] == new_mask.shape[0]
            else:
                # do not need a clustering, use original points
                new_PC = P
                new_mask = mask

            # create graph on point cloud
            adj_list, adj_matrix = self.get_adjacency(new_PC)
            X.append(Graph(new_PC, adj_list, max_deg=cluster_num, min_deg=0))
            S.append(new_mask)

        return np.asarray(X), np.asarray(S),

    @staticmethod
    def get_adjacency(points):
        n_p = points.shape[0]

        # pre-learn the distance matrix, use mean as threshold to generate adjacency matrix, i.e. who connect who
        sum_dist = []
        for i in range(n_p):
            for j in range(i + 1):
                sum_dist += [np.linalg.norm(points[i] - points[j])]
                # input points are new points after clustering
        d_lim = np.mean(sum_dist)

        adj_matrix = np.zeros((n_p, n_p))
        adj_list = [[] for _ in range(n_p)]
        for i in range(n_p):
            for j in range(i + 1, n_p):
                if np.linalg.norm(points[i] - points[j]) < d_lim:
                    adj_matrix[i][j] = True
                    # adjacency list has redundancy
                    adj_list[i].append(j)
                    adj_list[j].append(i)

        return adj_list, adj_matrix

    def load_back_from_disk(self, data_dir, istrain=True):
        """
        load data backas Train/test from disk
        :return: Train/Test STDiskDataset
        """
        """load back metadata_df"""
        meta_data = pickle.load(open(os.path.join(data_dir, 'meta.pkl'), 'rb'))
        metadata_rows = meta_data[0]

        """itershard by loading from disk"""
        all_X, all_y, all_seg, all_y_1h = [], [], [], []

        for _, row in enumerate(metadata_rows):
            # each row is a dict, contains file name for X, y, seg, y_one_hot
            X = np.array(load_from_disk(os.path.join(data_dir, row['X'])))
            y = np.array(load_from_disk(os.path.join(data_dir, row['y'])))
            seg = np.array(load_from_disk(os.path.join(data_dir, row['seg_mask'])))
            y_1h = np.array(load_from_disk(os.path.join(data_dir, row['one_hot_y'])))

            """ stack to list"""
            all_X.append(X)
            all_y.append(y)
            all_seg.append(seg)
            all_y_1h.append(y_1h)

        """ return a Dataset contains all X, y, w, ids"""
        if istrain:
            cut = TRAIN_NUM
        else:
            cut = TEST_NUM
        all_X = np.concatenate(all_X)
        all_y = np.squeeze(np.concatenate(all_y))
        all_seg = np.squeeze(np.vstack(all_seg))
        all_y_1h = np.squeeze(np.vstack(all_y_1h))
        assert all_X.shape[0] == all_y.shape[0] == all_seg.shape[0] == all_y_1h.shape[0]

        dataset = dict()
        dataset['X'] = all_X[cut:]
        dataset['y'] = all_y[cut:]
        dataset['seg_mask'] = all_seg[cut:]
        dataset['one_hot_y'] = all_y_1h[cut:]

        return dataset

    def load(self):
        """Load chemical datasets. Raw data is given as SMILES format."""

        meta_data = []
        if len(os.listdir(self.processed_data_dir)) != 0:

            print("Loading Saved Data from Disk.......")

            """ pre-defined location for saving the train and test data"""
            train_dir = os.path.join(self.processed_data_dir, 'train')
            test_dir = os.path.join(self.processed_data_dir, 'test')

            train = self.load_back_from_disk(data_dir=train_dir, istrain=True)
            test = self.load_back_from_disk(data_dir=test_dir, istrain=False)

            meta_data = pickle.load(open(os.path.join(self.processed_data_dir, 'meta.pkl'), 'rb'))
            max_atom = meta_data[0]

        else:
            print("Loading and Featurizing Data.......")
            # loader = dc.data.CSVLoader(
            #     tasks=self.tasks, smiles_field=self.smiles_field, featurizer=self.Featurizer)
            train, test = self.featurize(shard_size=256)

            """max_atom is the max atom of molecule in all_dataset """
            max_atom = CLUSTER_NUM  # because we do clustering, so it is the cluster center number
            meta_data.append(max_atom)
            with open(os.path.join(self.processed_data_dir, 'meta.pkl'), 'wb') as f:
                pickle.dump(meta_data, f)

        return train, test, max_atom


from glob import glob
from os.path import join
from collections import defaultdict
import matplotlib.pyplot as plt
import json
from settings import BRIEFS_JSON_DIR, IMAGES_DIR

def count_matching_words(datadict, pattern):
    x = 0
    for word, wordcount in datadict['word_counts'].items():
        if pattern in word:
            x += wordcount
    return x

tally = defaultdict(int)
filenames = glob(join(BRIEFS_JSON_DIR, '*.json'))
for fn in filenames:
    with open(fn, 'r') as rf:
        data = json.load(rf)
    yr = data['date'][0:4]
    tally[yr] += count_matching_words(data, 'terror')

sorted_tally = sorted(tally.items(), key=lambda x: x[0])

years = [p[0] for p in sorted_tally]
words = [p[1] for p in sorted_tally]

plt.bar(years, words)
plt.savefig(join(IMAGES_DIR, 'terror-year.png'))


import pymc as pm
import numpy as np
from pymc.sandbox import GibbsStepMethods
from pymc.sandbox.GibbsStepMethods import DirichletMultinomial
from numpy import *

__all__ = ['make_model', 'make_MCMC']

def find_age_bins(a, a_lo, a_hi):

    slices = []
    bin_ctrs = []

    for a_tup in zip(a_lo, a_hi):
        i_min = np.where(a<=a_tup[0])[0][-1]
        i_max = np.where(a>=a_tup[1])[0]
        if len(i_max)==0:
            i_max = len(a)-1
        else:
            i_max = i_max[0]
        slices.append(slice(i_min, i_max))

        local_a = a[i_min:i_max+1]
        bin_ctrs.append((a_tup[0] + a_tup[1])/2.)

    return slices, np.array(bin_ctrs)

def make_model(datasets, a):
    "Datasets should be a list of record arrays with columns [a_lo,a_hi,pos,neg]"

    age_bin_ctrs = {}
    age_slices = {}
    for place in datasets.iterkeys():
        age_slices[place], age_bin_ctrs[place] = find_age_bins(a, datasets[place].a_lo, datasets[place].a_hi)

    N_pops = len(datasets)
    S_guess = exp(-a/20.)
    S_guess /= sum(S_guess)

    # Model for central tendency of age distribution.
    alph_pri = 10.

    scg = []
    for i in xrange(len(a)):
        asg_now = pm.Lambda('asg_%i'%i, lambda alpha=alph_pri, S=S_guess, i=i : alpha*S[i])
        scg.append(pm.Gamma('scg_%i'%i, alpha=asg_now, beta=1., value=asg_now.value))
    sc = pm.Lambda('sc',lambda gams=scg: array(gams)/sum(gams))

    # Model for age distributions of individual populations
    # alph = pm.Gamma('alph',2.,2./1000.)
    alph = pm.OneOverX('alph', value=50.)

    asc = pm.Lambda('asc',lambda alph=alph,S=sc: alph*S)

    S = []
    S_steps = []
    data_list = []
    for name in datasets.iterkeys():

        this_dataset = datasets[name]

        @pm.deterministic(trace=False)
        def this_asc_slice(asc=asc, slices = age_slices[name], dataset=this_dataset):
            out = []
            for i in xrange(len(dataset)):
                out.append(sum(asc[slices[i]]))
            out = array(out)
            return out

        S.append(pm.Dirichlet(('S_%s'%name).replace('.','_'), this_asc_slice))
        N = this_dataset.pos+this_dataset.neg
        data_list.append(pm.Multinomial('data',n=sum(N),p=S[-1],value=N,observed=True))

    S_pred = pm.Dirichlet('S_pred',asc)

    return locals()

def make_MCMC(datasets, a, dbname):
    M = pm.MCMC(make_model(datasets,a), db='hdf5',dbcomplevel=1, dbcomplib='zlib', dbname=dbname)

    M.use_step_method(pm.Metropolis, M.alph, proposal_sd=.05)

    for i in xrange(len(datasets)):
        M.use_step_method(DirichletMultinomial, M.S[i])

    return M


from database.Disease import Disease as DiseaseDB
from models.Disease import Disease
from models.Plant import Plant
from repository.base import Base
from sqlalchemy import and_

class DiseaseRepository(Base):
    """
    Disease repository, dedicated to realize all functions related to diseases.
    """

    def __init__(self,
                 dbuser="",
                 dbpass="",
                 dbhost="",
                 port="",
                 dbname=""):
        super().__init__(dbuser, dbpass, dbhost, port, dbname)

    def create(self, disease=Disease()):
        """
        (Disease) -> (Disease)
        """
        diseaseDB = DiseaseDB(disease=disease)
        session = self.session_factory()
        session.add(diseaseDB)
        session.flush()
        session.refresh(diseaseDB)
        session.commit()
        return Disease(diseaseDB.id,
                       Plant(diseaseDB.plant.id,
                             diseaseDB.plant.scientificName,
                             diseaseDB.plant.commonName),
                       diseaseDB.scientificName,
                       diseaseDB.commonName)

    def update(self, disease=Disease()):
        """
        (Disease) -> (Disease)
        """
        session = self.session_factory()
        diseaseDB = session.query(DiseaseDB).filter_by(id=disease.id).first()
        dic = {}
        if (diseaseDB.plant.id != disease.plant.id):
            dic['idPlant'] = disease.plant.id
        if (diseaseDB.scientificName != disease.scientificName):
            dic['scientificName'] = disease.scientificName
        if (diseaseDB.commonName != disease.commonName):
            dic['commonName'] = disease.commonName
        if (dic != {}):
            session.query(DiseaseDB).filter_by(id=disease.id).update(dic)
            session.commit()
            session.flush()
            session.refresh(diseaseDB)
        return Disease(diseaseDB.id,
                       Plant(diseaseDB.plant.id,
                             diseaseDB.plant.scientificName,
                             diseaseDB.plant.commonName),
                       diseaseDB.scientificName,
                       diseaseDB.commonName)

    def delete(self, disease=Disease()):
        """
        (Plant) -> (Boolean)
        """
        status = False
        session = self.session_factory()
        diseaseDB = session.query(DiseaseDB).filter_by(id=disease.id).first()
        session.delete(diseaseDB)
        session.commit()
        session.flush()
        if (not session.query(DiseaseDB).filter_by(id=diseaseDB.id).count()):
            status = True
        session.close()
        return status

    def search(self, disease=Disease(), pageSize=10, offset=0):
        """
        (Disease, pageSize, offset) -> {'total': int, 'content':[Disease]}
        """
        session = self.session_factory()
        query = session.query(DiseaseDB).filter(and_(
                        DiseaseDB.scientificName.like(
                            '%'+disease.scientificName+'%'),
                        DiseaseDB.commonName.like('%'+disease.commonName+'%')))
        content = query.slice(offset, pageSize).all()
        total = query.count()
        diseases = []
        for diseaseDB in content:
            diseases.append(Disease(
                       diseaseDB.id,
                       Plant(diseaseDB.plant.id,
                             diseaseDB.plant.scientificName,
                             diseaseDB.plant.commonName),
                       diseaseDB.scientificName,
                       diseaseDB.commonName))
        dic = {'total': total, 'content': diseases}
        return dic

    def searchByID(self, id):
        """
        (Int) -> (Disease)
        """
        session = self.session_factory()
        diseaseDB = session.query(DiseaseDB).get(id)
        return Disease(diseaseDB.id,
                       Plant(diseaseDB.plant.id,
                             diseaseDB.plant.scientificName,
                             diseaseDB.plant.commonName),
                       diseaseDB.scientificName,
                       diseaseDB.commonName)


import os.path as op
import os
import numpy as np
from sklearn.model_selection import train_test_split
from functions import load_settings_params as lsp
from functions import model_fitting_and_evaluation as mfe
from functions import plot_results as pr
import sys
import pickle

# --------- Main script -----------
vector_type = 'hidden'
print('Vector type: ' + vector_type)
print('Load settings and parameters')
settings = lsp.settings()
params = lsp.params()
# os.chdir(settings.path2code)
# print(os.getcwd())

# Load LSTM data
print('Loading pre-trained LSTM data...')
# LSTM_data = np.load(op.join(settings.path2LSTMdata, settings.LSTM_file_name))
# print(LSTM_data.files)
# LSTM_data = LSTM_data['vectors']
# print(LSTM_data.shape)
#sys.exit('breaked by user in code')
with open(op.join(settings.path2LSTMdata, settings.LSTM_file_name), 'rb') as f:
	LSTM_data = pickle.load(f)

LSTM_data = np.asarray(LSTM_data[vector_type])

# Loop over channels and fit a regression model between LSTM units and MEG channel
if len(sys.argv) > 1:
    print('Channel ' + sys.argv[1])
    channel = int(sys.argv[1])
    if len(sys.argv) > 2:
        print('Time point ' + sys.argv[2])
        time_point = int(sys.argv[2])
else:
    channel = 1
    time_point = 1

# for channel in range(channel, channel+10, 1):
    # If using optimal bin so don't loop over each time point within SOA
step = 10
if settings.use_optimal_bin:
    time_points = [-1]
else:
    time_points = range(0, params.SOA+1, step)

for time_point in time_points:
	pkl_filename = 'Regression_models_' + settings.patient + '_channel_' + str(channel) + '_timepoint_' + str(time_point) + '_averaged_over_' + str(step) + '_' + settings.LSTM_file_name + '.pckl'
	if not op.exists(op.join(settings.path2output, pkl_filename)):
		# Load Data
		print('Loading MEG data for channel ' + str(channel) + ' time point ' + str(time_point) + '...')
		if settings.use_optimal_bin:
			MEG_file_name = 'MEG_data_sentences_averaged_over_optimal_bin_channel_' + str(channel) + '.npz'
			MEG_data = np.load(op.join(settings.path2output, MEG_file_name))
		else:
			if settings.use_sources_data:
				MEG_file_name = 'sources/sources_dat_' + settings.patient + '_vertex_' + str(channel) + '.pkl'
				with open(op.join(settings.path2MEGdata, MEG_file_name), 'rb') as f:
					MEG_data = pickle.load(f, encoding='latin1')
			else:
				MEG_file_name = 'patient_' + settings.patient +'_epochs_lock_to_beginning_of_sentence_anomaly_type_0.npy'
				MEG_data = np.load(op.join(settings.path2MEGdata, MEG_file_name))
			real_speed_sec = int(params.sfreq * params.real_speed / 1e3)
			st = int(params.sfreq * params.startTime / 1e3) + time_point
			ed = st + real_speed_sec*8 # the same time point at the 8^th words
			IX_timepoints = np.arange(st, ed, real_speed_sec)
			print('timepoints ' + str(IX_timepoints))
			if not settings.use_sources_data:
				MEG_data = MEG_data[:,channel-1, :]

		# Reshape data to num_trials X num_features
		print('Reshaping datasets')
		num_trials, num_hidden_units, num_timepoints = LSTM_data.shape
		X = np.empty([0, num_hidden_units]) # LSTM data
		y = np.empty([0]) # MEG data
		for word in range(8):
			X = np.vstack((X, LSTM_data[:,:, word]))
			if settings.use_optimal_bin:
				y = np.hstack((y, MEG_data['arr_0'][:, word]))
			else:
				st = IX_timepoints[word]
				ed = st + step - 1
				MEG_data_mean = np.mean(MEG_data[:, st:ed], axis=1)
				y = np.hstack((y, MEG_data_mean))

	    # ## Split data to train/test sets
		print('Splitting data to train/test sets')
		X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=1./params.CV_fold,
		                                                random_state=params.seed_split)

		models = {}
		# ############ Ridge Regression ############
		if settings.run_Ridge:
			print('Fitting a ridge model for channel ' + str(channel) + ' time point ' + str(time_point))
			settings.method = 'Ridge'
			# Train model
			model_ridge = mfe.train_model(X_train, y_train, settings, params)
			# Evaluate model on test set
			ridge_scores_test = mfe.evaluate_model(model_ridge, X_test, y_test, settings, params)
			# Generate and save figures
			plt = pr.regularization_path(model_ridge, settings, params)
			file_name = 'Ridge_coef_and_R_squared_vs_regularization_size_channel_' + \
						str(channel) + '.png'
			plt.savefig(op.join(settings.path2figures, file_name))
			plt.close()
			models['model_ridge'] = model_ridge
			models['ridge_scores_test'] = ridge_scores_test
		# ##########################################

	    # ############ Lasso Regression ############
		if settings.run_LASSO:
			print('Fitting a lasso model for channel ' + str(channel) + ' time point ' + str(time_point))
			settings.method = 'Lasso'
			# Train model
			model_lasso = mfe.train_model(X_train, y_train, settings, params)
			# Evaluate model on test set
			lasso_scores_test = mfe.evaluate_model(model_lasso, X_test, y_test, settings, params)
			# Generate and save figures
			plt = pr.regularization_path(model_lasso, settings, params)
			file_name = 'Lasso_coef_and_R_squared_vs_regularization_size_channel_' + \
						str(channel) + '_timepoint_' + str(time_point) + '.png'
			plt.savefig(op.join(settings.path2figures, file_name))
			plt.close()
			models['model_lasso'] = model_lasso
			models['lasso_scores_test'] = lasso_scores_test
			print('Done fitting')
	    # ##########################################

	    # ############ Elastic-net Regression #####
		if settings.run_ElasticNet:
			print('Fitting an elastic-net model for channel ' + str(channel))
			settings.method = 'Elastic_net'
			model_enet = mfe.train_model(X_train, y_train, settings, params)
			# Evaluate model on test set
			enet_scores_test = mfe.evaluate_model(model_enet, X_test, y_test, settings, params)
			# Generate and save figures
			plt = pr.regularization_path(model_enet, settings, params)
			file_name = 'Elastic_net_coef_and_R_squared_vs_regularization_size_channel_' + \
						str(channel) + '.png'
			plt.savefig(op.join(settings.path2figures, file_name))
			plt.close()
			models['model_enet'] = model_enet
			models['enet_scores_test'] = model_enet
	    # ##########################################

	    # ############# Save models and results #####
		import pickle
		with open(op.join(settings.path2output, pkl_filename), "wb") as f:
		    pickle.dump(models, f)
		    pickle.dump(settings, f)
		    pickle.dump(params, f)
		print('Models for channel ' + str(channel) + ' time point ' + str(time_point) + 'were saved to Output folder')


#!/usr/bin/python
# -*- coding: utf-8 -*-

import os
import sys
import json
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, QUrl
import requests
import threading
from .utils import registerContext, duration_to_string
from dwidgets import dthread
import copy
from log import logger

songlist = {
    u'新歌榜': 'http://music.haosou.com/data/top/top_new.json',
    u'热歌榜': 'http://music.haosou.com/data/top/top_hot.json',
    u'咪咕音乐榜': 'http://music.haosou.com/data/top/top_migu.json',
    u'网络流行榜': 'http://music.haosou.com/data/top/top_internet.json',
    u'中国歌曲排行榜': 'http://music.haosou.com/data/top/top_zggqphb.json',
    u'日本ORICON': 'http://music.haosou.com/data/top/top_gongxin.json',
    u'英国UK Official': 'http://music.haosou.com/data/top/top_uk.json',
    u'美国The Billboard': 'http://music.haosou.com/data/top/top_bill.json',
    u'Channel V': 'http://music.haosou.com/data/top/top_channelv.json',
    u'香港中文龙虎榜': 'http://music.haosou.com/data/top/top_zwlhb.json',
    u'经典老歌': 'http://music.haosou.com/data/top/top_classic.json'
}

class Web360ApiWorker(QObject):

    #py2py
    playMediaContent = pyqtSignal('QVariant')
    swicthMediaContent = pyqtSignal('QVariant')

    addMediaContents = pyqtSignal(list)
    addMediaContent = pyqtSignal('QVariant')
    addMediaContentToFavorite = pyqtSignal('QVariant')
    removeMediaContentFromFavorite = pyqtSignal('QString')

    downloadSongConetent = pyqtSignal(dict)
    resultsCollected = pyqtSignal(int, dict)

    # qml2py
    playMusicByIdSignal = pyqtSignal(int)
    playMusicByIdsSignal = pyqtSignal('QString')
    playSonglistByNameSignal = pyqtSignal('QString')
    playSonglistByIdSignal = pyqtSignal(int)
    playAlbumByIdSignal = pyqtSignal(int)
    addFavoriteSignal = pyqtSignal(int)
    removeFavoriteSignal = pyqtSignal(int)
    downloadSongSignal = pyqtSignal(int)
    downloadSongsSignal = pyqtSignal('QString')

    __contextName__ = 'Web360ApiWorker'

    @registerContext
    def __init__(self, parent=None):
        super(Web360ApiWorker, self).__init__(parent)
        self.playedMusics = {}
        self.recommendedMusics = {}
        self.recommendedmusicIds = {}
        self._results = {}
        self._musicIds = []
        self.initConnect()

    def initConnect(self):
        self.playMusicByIdSignal.connect(self.playMusicById)
        self.playMusicByIdsSignal.connect(self.playMusicByIds)
        self.playSonglistByNameSignal.connect(self.playMusicBySonglistName)
        self.playSonglistByIdSignal.connect(self.playMusicBySonglistId)
        self.playAlbumByIdSignal.connect(self.playMusicByAlbumId)

        self.addFavoriteSignal.connect(self.addMusicToFavorite)
        self.removeFavoriteSignal.connect(self.removeMusicFromFavorite)

        self.downloadSongSignal.connect(self.downloadSong)
        self.downloadSongsSignal.connect(self.downloadSongs)

        self.resultsCollected.connect(self.collectResult)

    @classmethod
    def md5(cls, musicId):
        import hashlib
        s = 'id=%s_projectName=linuxdeepin' % (musicId)
        md5Value = hashlib.md5(s)
        return md5Value.hexdigest()

    @classmethod
    def md5s(cls, musicIds):
        import hashlib
        s = 'ids=%s_projectName=linuxdeepin' % (musicIds)
        md5Value = hashlib.md5(s)
        return md5Value.hexdigest()

    @classmethod
    def getUrlByID(cls, musicId):
        sign = cls.md5(musicId)
        params = {
            'id': musicId,
            'src': 'linuxdeepin',
            'sign': sign
        }

        url = 'http://s.music.haosou.com/player/songForPartner?id=%s&src=%s&sign=%s'\
            %(params['id'], params['src'], params['sign'])
        return url

    @classmethod
    def getUrlByIDs(cls, musicIds):
        sign = cls.md5s(musicIds)
        params = {
            'ids': musicIds,
            'src': 'linuxdeepin',
            'sign': sign
        }

        url = 'http://s.music.haosou.com/player/songlistForPartner?ids=%s&src=%s&sign=%s'\
            %(params['ids'], params['src'], params['sign'])
        return url

    @classmethod
    def getDownloadUrl(self, musicId):
        url = "http://s.music.haosou.com/player/zdown?projectName=linuxdeepin&id=%s" % musicId
        return url

    @classmethod
    def request(cls, url, count=5):
        result = None
        ret = None
        i = 0
        while i < count:
            try:
                ret = requests.get(url)
                result = ret.json()
                if isinstance(result, dict):
                    break
                else:
                    i = i + 1
            except ValueError:
                result = ret.text
                break
            except:
                i = i + 1
        return result

    def getResultById(self, musicId):
        url = self.getUrlByID(musicId)
        result = self.getResultByUrl(url)

        return result

    @classmethod
    def getResultByUrl(cls, url):
        tags = cls.request(url)
        if isinstance(tags, list) and not tags:
            tags = None
        else:
            tags.update({'url': url})

        return tags

    @pyqtSlot(int)
    def playMusicById(self, musicId):
        self.playMediaById(musicId)

    @dthread
    @pyqtSlot('QString')
    def playMusicByIds(self, musicIds):
        print(threading.currentThread())
        url = self.getUrlByIDs(musicIds)
        songLists = self.request(url)

        results = []
        for song in songLists:
            url = self.getUrlByID(song['songId'])
            song.update({'url': url})
            results.append(song)

        if results:
            self.addMediaContents.emit(results)
            url = self.getUrlByID(songLists[0]['songId'])
            self.playMediaByUrl(url)

    @dthread
    @pyqtSlot(int)
    def playMediaById(self, musicId):
        result = self.getResultById(musicId)
        if result:
            self.addMediaContent.emit(result)
            self.playMediaContent.emit(result)

    @dthread
    @pyqtSlot('QString')
    def playMediaByUrl(self, url):
        result = self.getResultByUrl(url)
        if result:
            self.playMediaContent.emit(result)

    @dthread
    @pyqtSlot('QString')
    def switchMediaByUrl(self, url):
        result = self.getResultByUrl(url)
        if result:
            self.swicthMediaContent.emit(result)

    @classmethod
    def getSongList(self, ret):
        results = []
        if 'songList' in ret:
            for song in ret['songList']:
                url = self.getUrlByID(song['songId'])
                tags = song
                tags.update({'url': url})
                results.append(tags)
        return results

    @dthread
    @pyqtSlot('QString')
    def playMusicBySonglistName(self, songlistName):
        if songlistName in songlist:
            url = songlist[songlistName]
            result = self.request(url)
            if result:
                header = 'cb_' + url.split('/')[-1].split('.')[0]
                content = result[len(header) + 1: -1]
                ret = json.loads(content)
                results = self.getSongList(ret)
                self.addMediaContents.emit(results)
                url = self.getUrlByID(ret['songList'][0]['songId'])
                self.playMediaByUrl(url)

    @dthread
    @pyqtSlot(int)
    def playMusicBySonglistId(self, songlistId):
        url = "http://s.music.haosou.com/list/intfDetail?id=%d" % songlistId
        ret = self.request(url)
        if ret:
            results = self.getSongList(ret)
            self.addMediaContents.emit(results)
            url = self.getUrlByID(ret['songList'][0]['songId'])
            self.playMediaByUrl(url)

    @dthread
    @pyqtSlot(int)
    def playMusicByAlbumId(self, albumId):
        url = "http://s.music.haosou.com/album/intfDetail?id=%d" % albumId
        ret = self.request(url)
        if ret:
            results = self.getSongList(ret)
            if results:
                for result in results:
                    result.update({
                        'singerId': ret['singerId'],
                        'singerName': ret['singerName'],
                        'albumId': ret['albumId'],
                        'albumName': ret['albumName']
                    })
                self.addMediaContents.emit(results)
                url = self.getUrlByID(ret['songList'][0]['songId'])
                self.playMediaByUrl(url)

    @pyqtSlot(int)
    def addMusicToFavorite(self, musicId):
        url = self.getUrlByID(musicId)
        tags = self.request(url)
        tags.update({'url': url})
        self.addMediaContentToFavorite.emit(tags)

    @pyqtSlot(int)
    def removeMusicFromFavorite(self, musicId):
        url = self.getUrlByID(musicId)
        self.removeMediaContentFromFavorite.emit(url)

    @dthread
    @pyqtSlot(int)
    def downloadSong(self, musicId):
        url = self.getDownloadUrl(musicId)
        result = self.request(url)
        if 'data' in result:
            self.downloadSongConetent.emit(result['data'])

    @dthread
    @pyqtSlot(int)
    def requestSong(self, musicId):
        url = self.getDownloadUrl(musicId)
        result = self.request(url)
        if 'data' in result:
            self.resultsCollected.emit(musicId, result['data'])

    @pyqtSlot('QString')
    def downloadSongs(self, musicIds):
        _musicIds = musicIds.split('_')
        for musicId in _musicIds:
            if musicId not in self._musicIds:
                self._musicIds.append(int(musicId))
                self.requestSong(int(musicId))

    @pyqtSlot(int, dict)
    def collectResult(self, musicId, result):
        self._results[musicId] = result
        _rmusicIds = copy.deepcopy(self._results.keys())
        _rmusicIds.sort()
        _musicIds = copy.deepcopy(self._musicIds)
        _musicIds.sort()

        if _rmusicIds == _musicIds:
            for musicId in self._musicIds:
                result = self._results[musicId]
                self.downloadSongConetent.emit(result)

            self._results = {}
            self._musicIds = []


from flask import Flask, render_template, request, send_file, make_response
import pandas as pd
import os
import io
from deployment.SynthesisLib import *
import zipfile

app = Flask(__name__)

def generate_single_file_response(df):
    # Convert DataFrame to CSV string
    csv_data = df.to_csv(index=False)
    # Create a response with the CSV data
    response = make_response(csv_data)
    response.headers['Content-Disposition'] = 'attachment; filename=data.csv'
    response.headers['Content-type'] = 'text/csv'
    return response

def generate_zip_file_response(df1, df2):
    # Convert DataFrame to CSV string
    zip_buffer = io.BytesIO()
    with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
        zip_file.writestr('data_task.csv', df1.to_csv(index=False))
        zip_file.writestr('data_worker.csv', df2.to_csv(index=False))

    # Set the buffer's position to the start
    zip_buffer.seek(0)
    return send_file(zip_buffer, attachment_filename='data.zip', as_attachment=True)

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        # Retrieve the form input values
        # radio_value = request.form.get('radio')
        checkbox_values = request.form.getlist('checkbox')
        input_text_value = request.form.get('input_text')
        # 0 - worksers
        # 1 - jobs

        if 'checkbox1' in checkbox_values:
            index = 0
            df_worker = generate(index, int(input_text_value))
            synfile = generate_single_file_response(df_worker)

        elif 'checkbox2' in checkbox_values:
            index = 1
            df_task = generate(index, int(input_text_value))
            synfile = generate_single_file_response(df_task)

        elif 'checkbox3' in checkbox_values:
            df_worker = generate(0, int(input_text_value))
            df_task = generate(1, int(input_text_value))
            synfile = generate_zip_file_response(df_task, df_worker)

        else:
            return "Server Error"

        return synfile

    return render_template('index.html')

def convert_to_csv(fake_data):

   # Convert the DataFrame to CSV format
    csv_data = fake_data.to_csv(index=False)
    csv_stream = io.BytesIO()
    csv_stream.write(csv_data.encode())
    csv_stream.seek(0)
    return csv_stream

if __name__ == '__main__':
    app.run(port=5000, host="0.0.0.0")


import cv2
import numpy as np
import math
from tablero import Tablero

class Juego:

    def __init__ (self):
        self.tablero=Tablero(600, 600)
        self.jugador=0
        self.resultadosfinales=False
        self.partidaterminada=False

    def evento_raton(self, event, x, y, flags, param):

        if event == cv2.EVENT_LBUTTONDOWN:
            if(self.resultadosfinales==True):
                self.partidaterminada=True
            else:

                self.tablero.ponerficharaton(self.jugador,x,y)

                if self.jugador==0:
                    self.jugador=1
                else:
                    self.jugador=0

class qlearning3enraya():

    def __init__ (self, iteraciones):
        self.totalpartidas=iteraciones
        self.contjuego=0
        self.contj1=0
        self.contj2=0
        self.contemp=0

    def jugar(self):
        while (self.contjuego<self.totalpartidas):
            self.contjuego=self.contjuego+1

            juego=Juego()

            juego.tablero.imprimetablero(self.contjuego, self.contj1, self.contj2, self.contemp)
            jugador=juego.jugador

            #Loop mientras no termine la partida
            while (juego.partidaterminada is False):

                cv2.setMouseCallback('imagen', juego.evento_raton)

                finpartida, juggana, posicion =juego.tablero.estresenraya()

                if jugador != juego.jugador:
                    accion=''

                    #print('cambio de jugador')

                    jugador=juego.jugador

                    if (finpartida):
                        juego.resultadosfinales=True

                        if (juggana is None):
                            print('EMPATE')
                            accion='EMPATE'
                            self.contemp=self.contemp+1

                        else:
                            print(f'Fin de la partida!! Gana el jugador {juggana}. Tablero en posicion {posicion}')
                            accion='JUG-'+str(juggana+1)

                            if juggana==0:
                                self.contj1=self.contj1+1
                            else:
                                self.contj2=self.contj2+1

                    juego.tablero.imprimetablero(self.contjuego, self.contj1, self.contj2, self.contemp, accion)

                k = cv2.waitKey(20) & 0xFF

        cv2.destroyAllWindows()

tresenraya=qlearning3enraya(iteraciones=3)
tresenraya.jugar()


import pyautogui

w = pyautogui.getWindowsWithTitle('메모장')[0]
w.activate()

# 문자열
pyautogui.write('12345')
pyautogui.write('nadocoding', interval=0.25)
# 영문과 숫자만 가능

# 기타 키
pyautogui.write(['t', 'e', 's', 't', 'left', 'left', 'right', 'l', 'a', 'enter'], interval=0.25)
# https://automatetheboringstuff.com/2e/chapter20/
# keyboard attributes

# 특수문자
pyautogui.keyDown('shift')
pyautogui.press('4')
pyautogui.keyUp('shift')

# 조합키
pyautogui.hotkey('ctrl', 'a')

# 한글 처리
import pyperclip
pyperclip.copy('나도코딩') # 클립보드에 저장
pyautogui.hotkey('ctrl', 'v')


import numpy as np
import csv
import pandas as pd
import plotly.express as px

with open("sample_data/coffee.csv") as file:
    data = csv.DictReader(file)
    x = []
    y = []
    for i in data:
        x.append(float(i['Sleep']))
        y.append(float(i['Coffee']))

    c = np.corrcoef(x, y)
    print("Correlation between sleep and coffee taken: " + str(c[0, 1]))

    df = pd.read_csv("sample_data/coffee.csv")
    d = px.scatter(df, x="Sleep", y="Coffee", title="graph", color="Week", size="Coffee")
    d.show()

with open("sample_data/marks.csv") as file:
    data = csv.DictReader(file)
    x = []
    y = []
    for i in data:
        x.append(float(i['Days Present']))
        y.append(float(i['Marks']))

    c = np.corrcoef(x, y)
    print("Correlation between days present and marks: " + str(c[0, 1]))

    df = pd.read_csv("sample_data/marks.csv")
    d = px.scatter(df, x="Days Present", y="Marks", title="graph", color="Roll No", size="Marks")
    d.show()