from pig_tv_csts import *
from utils import *
import json_loader as json_loader
import universe
import button
from importlib import reload
from entity import Entity, CircleEntity

# Classe d'agent racine
class Agent(CircleEntity):

    reload(json_loader)

    cost_of_reproduction = json_loader.json_data["cost_of_reproduction"]

    required_energy_to_reproduce = json_loader.json_data["required_energy_to_reproduce"]

    prob_of_mutation = json_loader.json_data["prob_of_mutation"]

    def __init__(self, screen, pos=None, type_agent : TypeAgent =None, radius=None, energy=None, color=None, draw_energy=True):

        # type_agent
        if type_agent != None:

            self.type_agent = type_agent

        else:

            self.type_agent = TypeAgent.BASIC

        if self.type_agent == TypeAgent.BASIC:
            self.type_agent_int =0
        elif self.type_agent == TypeAgent.ALTRUIST:
            self.type_agent_int =1
        elif self.type_agent == TypeAgent.PROFITEER:
            self.type_agent_int =2

        CircleEntity.__init__(self, screen, pos, color, radius)

        #energy
        if energy != None:
            self.energy = energy
        else:
            self.energy = json_loader.json_data["agent_initial_energy"]
        ##

        self.vector = Arr([10, 0])  # Arr.get_nul([2])

        self.speed_norm = json_loader.json_data["agent_speed_norm"]

        self.delta_t = random.random()

        self.mode_transitoire = 0

        self.age = 0

        self.is_eating = False

        self.on_food = False

        self.can_make_pheromone = True

        self.has_reproduced_this_cycle = False

        self.new_born = True

        self.proba_of_gene_proba_change_max = json_loader.json_data["proba_of_gene_proba_change_max"]

        self.draw_energy = draw_energy

        self.square = None

    def get_color():
        return self.color

    def get_energy(self):

        return self.energy

    def get_vector(self):

        return self.vector

    def get_y(self):

        return self.y

    def get_x(self):

        return self.x

    def add_to_energy(self,loss):
        self.energy += loss

    def aging(self): #changes the value of the agent based on its age
        age = self.age

        def loss_function(x):

            return log(log(x+1)+1)/2  # the "+1" value is due to the fact that log must always be positive

        Agent.add_to_energy(self, -loss_function(age))

    def reproduce_alone(self,object_type,genome,gene_prob):
        child = object_type(self.screen, self.pos, gene_type=genome, gene_proba=gene_prob)

        #child.gene_type =
        #child.gene_proba = gene_prob

        # change = gene + random.randrange(-self.proba_of_gene_proba_change_max*100,self.proba_of_gene_proba_change_max*100,1)/10000
        # if change < 0:
        #     child.gene_proba = 0
        # elif change > 1:
        #     child.gene_proba = 1
        # else :
        #     child.gene_proba = change

        return child

    def eat(self): # Simulate eating on the food spot

        list_of_foods = self.square.foods

        agent_has_eaten = False

        for food in list_of_foods: #checks if the agent is on a food spot

            if food.ressource > 0:

                if (self.pos-food.pos).norme_eucli() < 10:  # close enough

                    self.on_food = True #the agent is on a food
                    self.is_eating = True #the agent is no longer moving

                    energy = food.getting_eaten() #updates the amount of food remaining in the box
                    Agent.add_to_energy(self, energy) #updates the energy of the agent
                    agent_has_eaten =True

        if (agent_has_eaten == False) and (self.on_food == True): #if another agent has eaten the last bit of food of the food before this agent, it still needs to be able to move again or it will be stuck on the food
            self.is_eating = False
            self.can_make_pheromone = True

    def update(self, draw=True ):  # , list_of_foods, list_of_pheromones

        agent_state = Agent.update_energy(self, draw)

        # updates vector then moves
        Agent.random_walk(self)
        Agent.move(self)

        # eats
        Agent.eat(self)  # returns in case a pheromone has been created

        return agent_state

    def update_energy(self, draw): #Changing energy (decreasing when aging and increasing when eating)

        if self.new_born == False:

            self.age += 1

            # decreases energy
            Agent.aging(self)

            if self.energy > 0:

                if draw:

                    Agent.draw(self)

            else:
                return "dead"  # If it has no more energy then it's dead

        else :
            self.new_born = False
        return

    def find_closest_pheromone(self):
        # this class is for the the basic agents that don't sense pheormones
        return None

    def draw(self):

        #CircleEntity.draw(self)

        if self.vector == Arr.get_nul([2]):

            vertical = Arr([1, 0])

        else:

            vertical = self.vector

        vertical.normalize(self.radius)

        horizontal = vertical.get_orth()

        horizontal.normalize(self.radius/2)

        pt_list = (self.pos-vertical-horizontal, self.pos-vertical+horizontal, self.pos+vertical)

        pygame.draw.polygon(self.screen, self.color, pt_list)

        if self.draw_energy:

            aff_txt(str(round(self.energy)), self.x, self.y, window=self.screen)

    def move(self):

        self.pos += self.vector
        Agent.update_pos(self)

    def normalize_vect(self):

        self.vector.normalize(self.speed_norm)

    def random_walk(self) :

          # if he s eating we don't change position
          if self.is_eating :

              vect2 = Arr.get_nul([2])

          else:

              vect = self.get_vector()

              #module = sqrt((vect[0]**2 + vect[1]**2))

              if (self.get_y() <= 0) or (self.get_y() >= screen_height) or (self.get_x() <= 0) or (self.get_x() >= screen_width):  # out screen

                self.mode_transitoire = 10

                vect2 = Arr(screen_center)-self.pos  # Arr([-sin(pi*j*1/6),-cos(pi*j*1/6)])

                self.delta_t = random.random()

              else:

                  # back into screen
                  if self.mode_transitoire > 0 :
                       vect2 = vect
                       self.mode_transitoire -= 1

                  #randomized movement
                  else :
                      frequency = 10000
                      #t=0.01
                      amp = 5

                      perturbation = Arr([sin(2*pi*self.delta_t*frequency),cos(2*pi*self.delta_t*frequency)]) # The movement is sinusoidal and it's random

                      perturbation.normalize(self.speed_norm/10)

                      vect2 = perturbation+vect

          self.vector = vect2

          Agent.normalize_vect(self)


# 팽창연산
# 영상 속 사물의 주변을 덧붙여 영역을 확장
# 해당 예시는 사각형 3x3 픽셀 영역 기준으로 모자란 부분에 팽창하여
# 하얀색 글자 내의 작은 점들이 덮어짐, 전체적으로 굵어짐

import cv2
import numpy as np

img = cv2.imread("./img/morph_hole.png")

k = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))

# cv2.dilate(입력영상, 구조화 요소 커널 객체)
dst = cv2.dilate(img, k)

merged = np.hstack((img, dst))
cv2.imshow("Dilation", merged)
cv2.waitKey(0)
cv2.destroyAllWindows()


from Equipos_abs import Equipo
import numpy as np
import pandas as pd
import abc
from numpy_financial import pmt, ipmt, ppmt, npv, irr
class Procesos():
    def __init__(self, _name, _equipos, _salaries,_waters, _years, _sales):
        self.name = _name
        self.equipos = _equipos
        self.salaries = _salaries
        self.waters = _waters
        self.years = _years
        self.sales = _sales

    def capex(self):
        sum = 0
        for equipo in self.equipos:
            sum += equipo.lang()

        return sum

    def loan(self,prestamo, interest, years):
        """Compute annual payment of a loan. Inputs:
        quantity [monetary units] == investment which will be funded
        interest [as fraction of unity] == annual interest
        years == number of yeras to return the loan."""
        quantity = prestamo * self.capex()
        assert quantity > 0
        assert interest >= 0 and interest <= 1
        assert years > 1

        loan_payment   = pmt(interest, years, quantity)
        loan_interest  = ipmt(interest, np.arange(years) + 1, years, quantity)
        loan_principal = ppmt(interest, np.arange(years) + 1, years, quantity)

        return loan_payment, loan_interest, loan_principal

    def depreciation(self,annual_percent, residual_value=0):
        """Compute annual depreciation of investment. Inputs:
        annual_percent [as fraction of unity] == annual percent of depreciation.
        capex [monetary units] == capital expenditure
        residual_value[monetary units] == plant value at the end of its life."""

        assert annual_percent >= 0 and annual_percent <= 1

        annual_depreciation = []
        prev = 1

        while True:
            if prev < annual_percent:
                annual_depreciation.append(prev)
                break
            annual_depreciation.append(annual_percent)
            prev = prev - annual_percent

        depreciation_array = -1 * np.array(annual_depreciation) * (self.capex() - residual_value)

        return depreciation_array

    def financial_model(self,interest, principal, dep_array):
        capex = self.capex()
        investment    = np.array([-capex*0.4] + [0 for i in range(self.years-1)])
        depreciation  = np.hstack(([0], dep_array, [0 for i in range(self.years-1-len(dep_array))]))
        loan_prin     = np.hstack(([0], principal, [0 for i in range(self.years-1-len(principal))]))
        loan_int      = np.hstack(([0], interest, [0 for i in range(self.years-1-len(interest))]))

        sales_array    = np.zeros(self.years)
        water_array    = np.zeros(self.years)
        salaries_array = np.zeros(self.years)

        for i in range(self.years):
            if i == 0:
                sales_array[i]    = 0
                water_array[i]    = 0
                salaries_array[i] = 0
            elif i == 1:
                sales_array[i]    = self.sales
                water_array[i]    = -1*self.waters
                salaries_array[i] = -1*self.salaries
            else:
                sales_array[i]    = sales_array[i-1]*1.03
                water_array[i]    = water_array[i-1]*1.03
                salaries_array[i] = salaries_array[i-1]*1.02

        ebt   = np.vstack((investment, depreciation, loan_int, sales_array, water_array, salaries_array)).sum(axis=0)
        taxes = ebt * -0.3
        for i in range(len(taxes)):
            if taxes[i] > 0:
                taxes[i] = 0
        eat = ebt - taxes
        cash_flow = eat - depreciation + loan_prin
        cumulative_cash_flow = np.cumsum(cash_flow)

        data = np.vstack((investment, sales_array, depreciation, loan_prin, loan_int, salaries_array, water_array, ebt,
                        taxes, eat, cash_flow, cumulative_cash_flow))
        self.df   = pd.DataFrame(data,
                            index=['Investment', 'Sales', 'Depreciation', 'Loan principal', 'Loan interest', 'Salaries',
                                'Water', 'EBT', 'Taxes', 'EAT', 'Cash Flow', 'Cumulative Cash Flow'],
                            columns=[i for i in range(self.years)])

    def financial_metrics(self,discount_rate):
        return irr(self.df.loc['Cash Flow']),npv(discount_rate, self.df.loc['Cash Flow'])

    def results(self,discount_rate):
        irr,npv = self.financial_metrics(discount_rate)
        print(self.df)
        print(f"The project has a net present value of {'{:,.2f}'.format(npv)}€ and an internal rate of return of {round(irr*100, 2)}%")

    def payback(self):
        new_df = self.df.loc['Cumulative Cash Flow']
        r_init = new_df[0]
        i = 2
        sum = new_df[1]
        acumulado = sum + r_init

        while acumulado < 0 and i < self.years:
            print("HOLAAAAAAA",new_df[i])
            print("acumuladooo", acumulado)
            sum += new_df[i]
            i += 1
            acumulado = sum + r_init
        if i >= self.years:
            return "No hay periodo de recuperacion suficiente"
        anio = i - 2#anio anterior al que se sobrepasa la deuda
        acumulado_anio_anterior= np.sum(self.df.loc['Cumulative Cash Flow'][1:anio+1])
        falta = -(acumulado_anio_anterior + r_init)
        decimales = falta / self.df.loc['Cumulative Cash Flow'][anio+1]
        #divisor = acumulado + r_init

        return anio + decimales


from rest_framework import serializers
from .models import *

class DepartmentSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField(max_length=10, min_length=2, error_messages={
        "max_length": "最多10个字",
        "min_length": "最少2个字"
    })

    def create(self, validated_data):
        instance = Department.objects.create(**validated_data)
        return instance

    def update(self, instance, validated_data):
        instance.name = validated_data.get("name", instance.name)
        instance.save()
        return instance

class EmployeeSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField(max_length=10, min_length=2, error_messages={
        "max_length": "最多10个字",
        "min_length": "最少2个字"
    })
    gender = serializers.CharField(max_length=10)
    age = serializers.CharField(max_length=10)
    position = serializers.CharField(max_length=20, min_length=2, error_messages={
        "max_length": "最多20个字",
        "min_length": "最少2个字"
    })
    salary = serializers.IntegerField()
    department = serializers.CharField(source='department.name', read_only=True)

    def create(self, validated_data):
        instance = Employee.objects.create(**validated_data)
        return instance

    def update(self, instance, validated_data):
        instance.name = validated_data.get("name", instance.name)
        instance.gender = validated_data.get("gender", instance.gender)
        instance.age = validated_data.get("age", instance.age)
        instance.position = validated_data.get("position", instance.position)
        instance.salary = validated_data.get("salary", instance.salary)
        instance.save()
        return instance


from __future__ import print_function

import os.path

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

SCOPES = ['https://www.googleapis.com/auth/spreadsheets']

with open('PlanilhaGoogle\\id_da_planilha.txt', 'r') as arquivo:
    id_da_planilha = arquivo.read()

def autenticar_acesso():
    # ETAPA DE AUTENTICAÇÃO COM O GOOGLE:
    creds = None

    if os.path.exists('PlanilhaGoogle\\token.json'):
        creds = Credentials.from_authorized_user_file('PlanilhaGoogle\\token.json', SCOPES)
    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(
                'PlanilhaGoogle\\client_secret.json', SCOPES)
            creds = flow.run_local_server(port=0)
        with open('PlanilhaGoogle\\token.json', 'w') as token:
            token.write(creds.to_json())

    return creds

def pegar_arquivo(creds):
    try:
        service = build('sheets', 'v4', credentials=creds)

        sheet = service.spreadsheets()  # -> Pega tod0 o arquivo.

        return sheet

    except HttpError as err:
        print(err)

def pegar_dados_planilha(intervalo: str = 'Página1!A:Z') -> list:
    creds = autenticar_acesso()

    # LER OS DADOS DA PLANILHA: (GET)
    try:
        sheet = pegar_arquivo(creds)

        result = sheet.values().get(spreadsheetId=id_da_planilha,
                                    range=intervalo).execute()  # -> Leio o arquivo, passando as informações.

        valores = result.get('values', [])  # -> Obtendo os dados da planilha que foi pega anteriormente.

        return valores

    except HttpError as err:
        print(err)

def atualizar_dados_intervalo_planilha(valores_adicionar: list, intervalo: str):
    creds = autenticar_acesso()

    # ADICIONAR/EDITAR DADOS NA PLANILHA: (UPDATE)
    try:
        sheet = pegar_arquivo(creds)

        sheet.values().update(spreadsheetId=id_da_planilha,  # -> Atualizo o arquivo, passando as informações
                              range=intervalo, valueInputOption='USER_ENTERED',
                              body={'values': valores_adicionar}).execute()

    except HttpError as err:
        print(err)

def adicionar_dados_fim_planilha(valores_adicionar: list, intervalo: str = 'Página1!A:A') -> None:
    """
    Adiciona os valores na primeira linha disponível da coluna informada.
    :param valores_adicionar: Valores a serem adicionados.
    :param intervalo: Intervalo onde será adicionado os valores.
    :return: None
    """
    creds = autenticar_acesso()

    # ETAPA DE MANIPULAÇÃO DA PLANILHA:
    try:
        sheet = pegar_arquivo(creds)

        sheet.values().append(spreadsheetId=id_da_planilha, range=intervalo,
                              valueInputOption='USER_ENTERED', body={'values': valores_adicionar}).execute()

    except HttpError as err:
        print(err)

def adicionar_dados_intervalo_planilha(valores_adicionar: list, intervalo: str):
    creds = autenticar_acesso()

    # ETAPA DE MANIPULAÇÃO DA PLANILHA:
    try:
        sheet = pegar_arquivo(creds)

        sheet.values().append(spreadsheetId=id_da_planilha, range=intervalo,
                              valueInputOption='USER_ENTERED', body={'values': valores_adicionar}).execute()

    except HttpError as err:
        print(err)

def remover_dados_planilha(intervalo: str = 'Página1!A1:Z99'):
    creds = autenticar_acesso()

    # ETAPA DE MANIPULAÇÃO DA PLANILHA:
    try:
        sheet = pegar_arquivo(creds)

        sheet.values().clear(spreadsheetId=id_da_planilha, range=intervalo, body={}).execute()

    except HttpError as err:
        print(err)

def atualizar_formatacao_planilha(base: bool = True, request: bool = False):
    """
    formatacao=False -> Se a formatação for False, cell_format e request NÃO devem ser informados,
    pois os dados padrão da função SERÃO usados.
    formatacao=True -> Se a formatação for True, cell_format e request DEVEM ser informados,
    pois os dados padrão da função NÃO serão usados.
    """
    creds = autenticar_acesso()

    if base:
        cell_format = {
            'horizontalAlignment': 'LEFT',
            'backgroundColor': {
                'red': 1,
                'green': 1,
                'blue': 1
            }
        }

        request = {
            'repeatCell': {
                'range': {
                    'sheetId': 0,
                    'startRowIndex': 0,
                    'endRowIndex': 99,
                    'startColumnIndex': 0,
                    'endColumnIndex': 99
                },
                'cell': {
                    'userEnteredFormat': cell_format
                },
                'fields': 'userEnteredFormat.horizontalAlignment,userEnteredFormat.backgroundColor'
            }
        }

    # ETAPA DE MANIPULAÇÃO DA PLANILHA:
    try:
        sheet = pegar_arquivo(creds)

        sheet.batchUpdate(spreadsheetId=id_da_planilha, body={'requests': [request]}).execute()

    except HttpError as err:
        print(err)

if __name__ == '__main__':
    pass


import logging
import json

from flask import request, jsonify;

from cfg import app;

logger = logging.getLogger(__name__)

@app.route('/salad-spree', methods=['POST'])
def evaluate_salad():
    data = request.get_json()
    logging.info("data sent for evaluation {}".format(data))
    result = salad_spree(data.get("number_of_salads"), data.get("salad_prices_street_map"))
    logging.info("result : {}".format(result))

    return json.dumps({'result': int(result)})

def salad_spree(num, list_array):
    index = 0
    min_value = 0
    temp_value = 0
    for array in list_array:
        for elements in range(len(array)-num+1):
            index = 0
            temp_value = 0
            for loop in range(num):
                if array[elements+loop] != "X":
                    temp_value += int(array[elements+loop])
                else:
                    break
                index += 1

            if index == num and (min_value == 0 or min_value > temp_value):
                min_value = temp_value

    return min_value


"""
Setups the environment for tests.
Import this module to have the side effect
that the project root dir will be added to ``sys.path``,
i.e. ``import preloaded`` works afterwards.
In the test code, you would have this::

    import _setup_test_env  # noqa

The ``# noqa`` is to ignore the warning that this module is not used.
See :func:`setup` below for details.
"""

def setup():
    """
    Calls necessary setups.
    """
    import logging
    import os
    import sys

    my_dir = os.path.dirname(os.path.realpath(os.path.abspath(__file__)))
    root_dir = os.path.dirname(my_dir)
    sys.path.insert(0, root_dir)

    # Enable all logging, up to debug level.
    logging.basicConfig(level=logging.DEBUG, format='%(message)s')

    try:
        # noinspection PyUnresolvedReferences
        import better_exchook
        better_exchook.install()
        better_exchook.replace_traceback_format_tb()
    except ImportError:
        print("no better_exchook")

    import preloaded
    assert preloaded.__file__.startswith(root_dir)

    try:
        # noinspection PyUnresolvedReferences
        import faulthandler
        # Enable after libSigSegfault, so that we have both,
        # because faulthandler will also call the original sig handler.
        faulthandler.enable()
    except ImportError:
        print("no faulthandler")

    _try_hook_into_tests()

def _try_hook_into_tests():
    """
    Hook into nosetests or other unittest based frameworks.

    The hook will throw exceptions such that a debugger like PyCharm can inspect them easily.
    This will only be done if there is just a single test case.

    This code might be a bit experimental.
    It should work though. But if it does not, we can also skip this.
    Currently any exception here would be fatal though, as we expect this to work.

    Also see: https://youtrack.jetbrains.com/issue/PY-9848
    """
    import sys
    get_trace = getattr(sys, "gettrace", None)
    in_debugger = False
    if get_trace and get_trace() is not None:
        in_debugger = True

    # get TestProgram instance from stack...
    from unittest import TestProgram
    # noinspection PyProtectedMember,PyUnresolvedReferences
    top_frame = sys._getframe(1)
    if not top_frame:
        # This will not always work. Just silently accept this. This should be rare.
        return

    test_program = None
    frame = top_frame
    while frame:
        local_self = frame.f_locals.get("self")
        if isinstance(local_self, TestProgram):
            test_program = local_self
            break
        frame = frame.f_back

    test_names = None
    if test_program:  # nosetest, unittest
        test_names = getattr(test_program, "testNames")

    test_session = None
    try:
        # noinspection PyPackageRequirements,PyUnresolvedReferences
        import pytest
    except ImportError:
        pass
    else:
        frame = top_frame
        while frame:
            local_self = frame.f_locals.get("self")
            if isinstance(local_self, pytest.Session):
                test_session = local_self
                break
            frame = frame.f_back
        if test_session and not test_names:
            test_names = test_session.config.args

    if not test_names:
        # Unexpected, but just silently ignore.
        return
    if len(test_names) >= 2 or ":" not in test_names[0]:
        # Multiple tests are being run. Do not hook into this.
        # We only want to install the hook if there is only a single test case.
        return

    # Skip this if we are not in a debugger.
    if test_program and in_debugger:  # nosetest, unittest

        # Ok, try to install our plugin.
        class _ReraiseExceptionTestHookPlugin:
            @staticmethod
            def _reraise_exception(test, err):
                exc_class, exc, tb = err
                print("Test %s, exception %s %s, reraise now." % (test, exc_class.__name__, exc))
                raise exc

            handleFailure = _reraise_exception
            handleError = _reraise_exception

        config = getattr(test_program, "config")
        config.plugins.addPlugin(_ReraiseExceptionTestHookPlugin())

setup()


import copy
from pubsub import pub
import wx
import wx.grid
from wx.lib.agw.customtreectrl import EVT_TREE_ITEM_CHECKED

from _ids import ID_POLYGON
import _icons as ico
from frames.frame_design import ObjectFrame, GAP
from frames.property_panels import SelectionTree

class CorrelationSelectionTree(SelectionTree):
    def __init__(self, parent, object_menu_page):
        super().__init__(parent, object_menu_page)

    def GetIndices(self):
        items = self.GetCheckedItems()
        indices = []
        for i, item in enumerate(items):
            if item.IsChecked() and not item.HasChildren():
                indices.append(i)

        return indices

    def CheckAllItems(self, parent=None):
        if parent is None:
            parent = self.tree.GetRootItem()

        child, cookie = self.tree.GetFirstChild(parent)

        while child:
            self.tree.CheckItem2(child, checked=True, torefresh=True)

            self.CheckAllItems(child)
            child, cookie = self.tree.GetNextChild(parent, cookie)

class CorrelationFrame(ObjectFrame):
    def __init__(self, parent, title, mgr, object_menu_page, items, types):
        super().__init__(parent=parent, title=title)

        self._items = items
        self._types = types

        self._mgr = mgr
        self._object_menu_page = object_menu_page
        self._correlation, self._labels = mgr.GetCorrelationMatrix()

        self.splitter = wx.SplitterWindow(self.custom, wx.ID_ANY, style=wx.SP_THIN_SASH | wx.SP_LIVE_UPDATE)
        self.selection = CorrelationSelectionTree(self.splitter, self._object_menu_page)
        self.properties = wx.Panel(self.splitter)
        self.splitter.SplitVertically(self.selection, self.properties, 200)
        self.grid = wx.grid.Grid(self.properties)

        self.custom_sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.InitUI()
        self.Load()
        self.Center()

        # events -------------------------------------------------------------------------------------------------------
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.Bind(EVT_TREE_ITEM_CHECKED, self.OnTreeItemChecked, self.selection.tree)
        self.apply_button.Bind(wx.EVT_BUTTON, self.OnApplyButton)
        self.ok_button.Bind(wx.EVT_BUTTON, self.OnOKButton)

    def InitUI(self):
        self.SetIcon(ico.correlation_16x16.GetIcon())

        # selection tree -----------------------------------------------------------------------------------------------
        self.selection.Populate(self._items, self._types)
        self.selection.CheckAllItems()

        n = len(self._correlation)
        self.grid.CreateGrid(n, n)
        self.grid.SetColLabelTextOrientation(wx.VERTICAL)

        # disable lower half of the correlation matrix (including diagonal)
        n = len(self._correlation)
        for j in range(0, n):
            for i in range(j, n):
                self.grid.SetReadOnly(i, j, True)
                self.grid.SetCellBackgroundColour(i, j, wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE))

        # change row and column options
        for i in range(0, n):
            # labels
            self.grid.SetColLabelValue(i, self._labels[i])
            self.grid.SetRowLabelValue(i, self._labels[i])

            # sizes
            self.grid.SetColSize(i, 30)
            self.grid.SetRowSize(i, 30)

        self.grid.SetColLabelSize(wx.grid.GRID_AUTOSIZE)

        # sizing -------------------------------------------------------------------------------------------------------
        self.custom_sizer.Add(self.splitter, 1, wx.EXPAND | wx.ALL, GAP)
        self.custom.SetSizer(self.custom_sizer)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.grid, 1, wx.EXPAND)
        self.properties.SetSizer(sizer)
        self.custom_sizer.Fit(self.custom)

        self.Realize()

    def OnClose(self, event):
        pass

    def OnTreeItemChecked(self, event):
        indices = self.selection.GetIndices()
        n = len(self._correlation)
        for i in range(0, n):
            if i in indices:
                self.grid.ShowCol(i)
                self.grid.ShowRow(i)
            else:
                self.grid.HideCol(i)
                self.grid.HideRow(i)

    def OnApplyButton(self, event):
        return self.Save()

    def OnOKButton(self, event):
        saved = self.OnApplyButton(None)
        if saved:
            self.Close(True)

    def Load(self):
        # load upper half of the correlation matrix
        n = len(self._correlation)
        for j in range(0, n):
            for i in range(0, j):
                self.grid.SetCellValue(i, j, str(self._correlation[i][j]))

                # set alignment
                self.grid.SetCellAlignment(i, j, wx.ALIGN_CENTER, wx.ALIGN_CENTER)

            # Fill diagonal with ones
            self.grid.SetCellValue(j, j, str(1))
            self.grid.SetCellAlignment(j, j, wx.ALIGN_CENTER, wx.ALIGN_CENTER)

    def Save(self):
        # Save upper half of the grid to the upper and lower half of the correlation matrix
        correlation = copy.deepcopy(self._correlation)
        n = len(correlation)
        for j in range(1, n):
            for i in range(0, j):
                try:
                    value = float(self.grid.GetCellValue(i, j))
                    if -1. <= value <= 1.:
                        correlation[i][j] = value
                        correlation[j][i] = value
                    else:
                        msg = 'coefficient ({},{}) must be in the range -1 to 1'.format(i, j)
                        box = wx.MessageDialog(self, msg, caption='Value Error')
                        box.ShowModal()
                        box.Destroy()
                        return False

                except ValueError:
                    msg = 'coefficient ({},{}) must be a number'.format(i, j)
                    box = wx.MessageDialog(self, msg, caption='Type Error')
                    box.ShowModal()
                    box.Destroy()
                    return False

        self._mgr.SetCorrelationMatrix(correlation)
        return True

class EntityCorrelationFrame(CorrelationFrame):
    def __init__(self, parent, mgr, object_menu_page):

        items = (object_menu_page.subsurface,)
        types = (ID_POLYGON,)

        super().__init__(parent, 'Correlated polygons', mgr, object_menu_page, items, types)

    def OnClose(self, event):
        pub.sendMessage('entity_correlation_closed')

        event.Skip()

class VariableCorrelationFrame(CorrelationFrame):
    def __init__(self, parent, mgr, object_menu_page):

        items = (object_menu_page.statics, object_menu_page.scalers)
        types = ('scalers', 'statics')

        super().__init__(parent, 'Correlated variables', mgr, object_menu_page, items, types)

    def OnClose(self, event):
        pub.sendMessage('variable_correlation_closed')

        event.Skip()


import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision

class AE(nn.Module):
    def __init__(self, in_channels = 1, hidden_dims=[128, 256, 512], z_dim=128):
        super(AE, self).__init__()
        self.fc1 = nn.Linear(12800, z_dim) # 均值 向量mu
        self.fc2 = nn.Linear(z_dim, 12800) #decoder_input
        self.conv1 = nn.Sequential(
                    nn.Conv2d(in_channels, out_channels=hidden_dims[0],kernel_size= 3, stride= 2, padding  = 1),
                    nn.BatchNorm2d(hidden_dims[0]),
                    nn.LeakyReLU(),
                    nn.MaxPool2d(kernel_size = 2, return_indices=True))
        self.conv2 = nn.Sequential(
                    nn.Conv2d(hidden_dims[0], out_channels=hidden_dims[1],kernel_size= 3, stride= 2, padding  = 1),
                    nn.BatchNorm2d(hidden_dims[1]),
                    nn.LeakyReLU(),
                    nn.MaxPool2d(kernel_size = 2, return_indices=True))
        self.conv3 = nn.Sequential(
                    nn.Conv2d(hidden_dims[1], out_channels=hidden_dims[2],kernel_size= 3, padding  = 1),
                    nn.BatchNorm2d(hidden_dims[2]),
                    nn.LeakyReLU(),
                    nn.MaxPool2d(kernel_size = 2, return_indices=True))
        self.upsample = nn.MaxUnpool2d(2)
        #ConvTranspose2d 逆卷積

        self.trans1 = nn.Sequential(
                    nn.ConvTranspose2d(hidden_dims[2],
                                       hidden_dims[1],
                                       kernel_size = 3,
                                       stride = 1,
                                       padding = 1,
                                       output_padding = 0),
                    nn.BatchNorm2d(hidden_dims[1]),
                    nn.LeakyReLU())
        self.trans2 = nn.Sequential(
                    nn.ConvTranspose2d(hidden_dims[1],
                                       hidden_dims[0],
                                       kernel_size = 3,
                                       stride = 2,
                                       padding = 1,
                                       output_padding = 1),
                    nn.BatchNorm2d(hidden_dims[0]),
                    nn.LeakyReLU())
        self.trans3 = nn.Sequential(
                            nn.ConvTranspose2d(hidden_dims[0],
                                               hidden_dims[0],
                                               kernel_size = 3,
                                               stride = 2,
                                               padding = 1,
                                               output_padding = 1),
                            nn.BatchNorm2d(hidden_dims[0]),
                            nn.LeakyReLU(),
                            nn.Conv2d(hidden_dims[0], out_channels = 1,
                                      kernel_size = 3, padding = 1),
                            nn.Tanh())

    def latent_code(self,x):
        result = torch.flatten(x, start_dim=1)
        return self.fc1(result)

    def forward(self, x):
        #print(x.size())
        x, indice1 = self.conv1(x)
        #print(x.size())
        x, indice2 = self.conv2(x)
        #print(x.size())
        x, indice3 = self.conv3(x)
        #print(x.size())
        x = self.upsample(x,indice3)
        #print(x.size())
        x = self.trans1(x)
        #print(x.size())
        x = self.upsample(x,indice2)
        x = self.trans2(x)
        x = self.upsample(x,indice1)
        x = self.trans3(x)
        return x

#%%
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
import torchvision
from torchvision import transforms
from torchvision.utils import save_image
from torchvision import datasets
from torch.utils.data import DataLoader
from IPython.display import Image
from IPython.core.display import Image, display
from dae import AE

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
learning_rate = 1e-3
batch_size = 32
num_epoch = 150
transform =  transforms.Compose([
        transforms.Grayscale(),
        transforms.RandomHorizontalFlip(),
        transforms.RandomVerticalFlip(),
        transforms.Resize((160, 160)),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.5],std=[0.5])
        ])
data = datasets.ImageFolder('./normal',transform = transform)
dataloader = DataLoader(data, batch_size = batch_size, shuffle = True)
len(data.imgs), len(dataloader)
model = AE().to(device)
model
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate, weight_decay = 0.0001)
criterion = nn.MSELoss(reduction='sum')
Loss = []
for epoch in range(num_epoch):
    num_data = 0
    total_loss = 0
    for i, (images, _) in enumerate(dataloader):
        images = images.to(device)
        #print(images.size())
        batch_num = len(images)
        num_data += batch_num
        recon_images = model(images)
        loss = criterion(recon_images, images)
        total_loss += loss
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    Loss.append(total_loss)
    if (epoch+1) % 10 == 0:
        print('Train epoch: {}/{} Training Loss: {}'.format(epoch+1, num_epoch, total_loss/num_data))
invTrans = transforms.Compose([
    transforms.Normalize(mean = [0.],std = [ 1/0.5]),
    transforms.Normalize(mean = [ -0.5],std = [ 1.]),
    ])
torch.save(model.state_dict(), 'params130.pkl')
pretrained_dict = torch.load('params130.pkl')
model_dict = model.state_dict()

#%%
from PIL import Image as pic
test_image = pic.open('./normal/normal/Defect_P0000_P0135_000_000.jpg')
test_image
fixed_x = transform(test_image)
model.load_state_dict(torch.load('params130.pkl', map_location=torch.device('cpu')))
model.eval()
save_image(invTrans(fixed_x).data, 'sample_image.png')
display(Image('sample_image.png', width=160, unconfined=True))
fixed_x = fixed_x.to(device)
recon_x= model(fixed_x.view(-1,1,160,160))
recon_x = invTrans(recon_x.view(1,160,160))
save_image(recon_x.data, 'recon_image.png')
display(Image('recon_image.png', width=160, unconfined=True))

#https://arxiv.org/pdf/2008.12589.pdf


'''
Created on Apr 1, 2014

@author: irwink
'''

from django.shortcuts import render, redirect

from Instructors.models import TemplateDynamicQuestions, Challenges, ChallengesQuestions, TemplateTextParts, LuaLibrary, QuestionLibrary, QuestionProgrammingFiles
from Instructors.lupaQuestion import CodeSegment
from django.http import HttpResponse
from Instructors.views.utils import (addSkillsToQuestion, extractTags,
                                     getCourseSkills, getSkillsForQuestion,
                                     initialContextDict, saveTags,
                                     update_or_create_challenge_questions)
from Instructors.constants import unassigned_problems_challenge_name, unlimited_constant

from Badges.enums import ObjectTypes
from Instructors.questionTypes import QuestionTypes

import re
from django.contrib.auth.decorators import login_required, user_passes_test
from decimal import Decimal
from oneUp.decorators import instructorsCheck
from oneUp.ckeditorUtil import config_ck_editor
import os.path
import zipfile
from oneUp.settings import BASE_DIR
from shutil import copyfile

@login_required
@user_passes_test(instructorsCheck, login_url='/oneUp/students/StudentHome', redirect_field_name='')
def templateDynamicQuestionForm(request):
    context_dict, currentCourse = initialContextDict(request)

    # In this view, these are the names of the attributes which are just passed through with no processing.
    # We put them in an array so that we can copy them from one item to
    # another programmatically instead of listing them out.
    passthrough_attributes = ['preview', 'difficulty',
                              'instructorNotes', 'setupCode', 'numParts', 'author', 'submissionsAllowed', 'resubmissionPenalty']

    context_dict['skills'] = getCourseSkills(currentCourse)
    context_dict['tags'] = []
    if request.POST:
        # If there's an existing question, we wish to edit it.  If new question,
        # create a new Question object.
        if 'questionId' in request.POST:
            question = TemplateDynamicQuestions.objects.get(
                pk=int(request.POST['questionId']))
            isModifying = True
        else:
            question = TemplateDynamicQuestions()
            isModifying = False

        # Copy all strings from POST to database object.
        for attr in passthrough_attributes:
            setattr(question, attr, request.POST[attr])

        # used to fill in info for question text
        question.questonText = ''

        # if user did not specify author of the question, the author will be the user
        if question.author == '':
            question.author = request.user.username

        question.save()  # Writes to database.

        if request.FILES:
            print('we got files')
            files = request.FILES.getlist('testFile')
            saveFiles(currentCourse, question, files,
                      request.user, isModifying)

        # loops through and adds the multiple parts(the actual text) into to the template array
        templateArray = []
        partPointsArray = []
        numTemplateParts = int(request.POST['numParts'])
        # the 1 is the start of the range and we need to go all the way to the numparts (inclusive)
        for i in range(1, numTemplateParts+1):
            templateArray.append(request.POST['templateTextVisible'+str(i)])
            partPointsArray.append(int(request.POST['partpoints'+str(i)]))

        def combineCodeSegments(codeSegments):
            output = ""
            for codeSegment in codeSegments:
                output += codeSegment['code']
                output += "\n"
            return output

        # Add the path of the question files directory to the programinterface.program_checker
        '''LUA_PROBLEMS_ROOT = os.path.join(
            BASE_DIR, 'lua/problems/')  # This is for lua problems

        setupCode = re.sub("programinterface.program_checker\s*\(",
                           "programinterface.program_checker("+LUA_PROBLEMS_ROOT+",", question.setupCode)
        print("Replaced setupCode")
        print(setupCode)'''

        # Takes the array and converts the parts into lua code
        question.code = combineCodeSegments(
            templateToCodeSegments(question.setupCode, templateArray))

        # Fix the question type
        question.type = QuestionTypes.templatedynamic
        question.save()  # Writes to database.

        # Query that gets all objects that are in foreign key relation to the question and deletes them all
        TemplateTextParts.objects.filter(dynamicQuestion=question).delete()

        # Used for the number of parts in the array
        count = int(1)

        # make a new object that is a part and add all the fields it needs
        for text, partpoints in zip(templateArray, partPointsArray):
            textPart = TemplateTextParts()
            textPart.partNumber = count
            textPart.dynamicQuestion = question
            textPart.templateText = text
            textPart.pointsInPart = partpoints
            textPart.save()
            count += 1

        # Processing and saving tags in DB
        saveTags(request.POST['tags'], question, ObjectTypes.question)

        if 'challengeID' in request.POST:
            # save in ChallengesQuestions if not already saved
            update_or_create_challenge_questions(request,question)

            # Processing and saving skills for the question in DB
            addSkillsToQuestion(currentCourse, question, request.POST.getlist(
                'skills[]'), request.POST.getlist('skillPoints[]'))

            makeDependentLibraries(
                question, request.POST.getlist('dependentLuaLibraries[]'))

            redirectVar = redirect(
                '/oneUp/instructors/challengeQuestionsList', context_dict)
            redirectVar['Location'] += '?challengeID=' + \
                request.POST['challengeID']
            return redirectVar

        # Question is unassigned so create unassigned challenge object
        challenge = Challenges()
        challenge.challengeName = unassigned_problems_challenge_name
        challenge.courseID = currentCourse
        challenge.numberAttempts = unlimited_constant
        challenge.timeLimit = unlimited_constant
        challenge.save()
        ChallengesQuestions.addQuestionToChallenge(question, challenge, 0, 0)

        redirectVar = redirect(
            '/oneUp/instructors/challengeQuestionsList?problems', context_dict)
        return redirectVar

    elif request.method == 'GET':
        if 'view' in request.GET:
            context_dict['view'] = request.GET['view']
        context_dict['luaLibraries'] = getAllLuaLibraryNames()
        context_dict["initalTemplateTextPart"] = "What is [|r1|] + [|r2|]? [{make_answer('ans1','number',5,exact_equality(r1+r2),10,r1+r2)}]"
        context_dict['checkInitalTemplateTextPart'] = True

        if Challenges.objects.filter(challengeID=request.GET['challengeID'], challengeName=unassigned_problems_challenge_name):
            context_dict["unassign"] = 1

        if 'challengeQuestionID' in request.GET:
            context_dict['challengeQuestionID'] = request.GET['challengeQuestionID']

        if 'challengeID' in request.GET:
            context_dict['challengeID'] = request.GET['challengeID']
            chall = Challenges.objects.get(
                pk=int(request.GET['challengeID']))
            context_dict['challengeName'] = chall.challengeName
            context_dict['challenge'] = True

        # If questionId is specified then we load for editing.
        if 'questionId' in request.GET:
            question = TemplateDynamicQuestions.objects.get(
                pk=int(request.GET['questionId']))

            # Copy all of the attribute values into the context_dict to
            # display them on the page.
            context_dict['questionId'] = request.GET['questionId']
            for attr in passthrough_attributes:
                context_dict[attr] = getattr(question, attr)

            # TODO: get all matching templateTextPart objects and then add their code to the
            # context dictionary as templateTextParts
            # get form the database the matching question for the parts
            templateTextParts = TemplateTextParts.objects.filter(
                dynamicQuestion=question)
            context_dict['templateTextParts'] = templateTextParts
            context_dict['checkInitalTemplateTextPart'] = False

            context_dict['selectedLuaLibraries'] = getLibrariesForQuestion(
                question)

            testFiles = QuestionProgrammingFiles.objects.filter(
                questionID=question)
            testFileIDs = []
            testFileNames = []
            if(testFiles):
                for f in testFiles:
                    testFileIDs.append(f.programmingFileID)
                    testFileNames.append(f.programmingFileName)

            context_dict['programmingFiles'] = zip(testFileIDs, testFileNames)
            # Extract the tags from DB
            context_dict['tags'] = extractTags(question, "question")

            if 'challengeID' in request.GET:
                # get the challenge points for this problem to display
                if 'challengeQuestionID' in request.GET:
                    challenge_questions = ChallengesQuestions.objects.filter(pk=int(request.GET['challengeQuestionID']))
                    context_dict['points'] = challenge_questions[0].points
                else:
                    context_dict['points'] = 0

                # set default skill points - 1
                context_dict['q_skill_points'] = int('1')

                # Extract the skill
                context_dict['selectedSkills'] = getSkillsForQuestion(
                    currentCourse, question)

        else:
            context_dict['difficulty'] = 'Easy'
            context_dict["setupCode"] = "r1 = math.random(10) + 1 \nr2 = math.random(10) + 1"
            context_dict["numParts"] = 1
            context_dict['tags'] = []

    # question = LupaQuestion(code,[],5,"edit",1)
    # context_dict["test"] = question.getQuestionPart(1);

    if 'questionId' in request.POST:
        return redirect('challengesView')

    context_dict['ckeditor'] = config_ck_editor()

    return render(request, 'Instructors/TemplateDynamicQuestionForm.html', context_dict)

def HTMLquotesToRegularQuotes(str):
    return str.replace(r"'", "'", 10000).replace(r'"', '"', 10000)

# First we set up a regular expression to separate the templateText into parts.
# We do this here rather than in the function because we would rather have it only run once
# since the regular expression is always the same.
templateCodeSplitRegex = re.compile(r"\[\{(.*?)\}\]", re.DOTALL)
templateVarSplitRegex = re.compile(r"\[\|(.*?)\|\]", re.DOTALL)

def templateToCodeSegments(setupCode, templateArray):
    code_segments = list()
    sys_code = '''
        exact_equality = function(a)
            return function(b,pts)
                if tonumber(a)==tonumber(b) then
                    return {success=true,value=pts}
                else
                    return {success=false,value=0}
                end
            end
        end

        approximate_equality = function(a,fudgefraction)
            return function(b,pts)
                a = tonumber(a)
                b = tonumber(b)
                if a == 0 then
                    if b <= fudgefraction and b >= -fudgefraction then
                        return {success=true,value=pts}
                    else
                        return {success=false,value=0}
                    end
                else
                    if math.abs((a-b)/a)<=fudgefraction then
                        return {success=true,value=pts}
                    else
                        return {success=false,value=0}
                    end
                end
            end
        end

        string_equality_ignore_spaces = function(str)
            return function(b,pts)
                if b == nil then
                    return {success=false,value=0}
                end
                local str_no_space = str:gsub("%s*","")
                local b_no_space = b:gsub("%s*","")
                if string.upper(str_no_space) == string.upper(b_no_space) then
                    return {success=true,value=pts}
                else
                    return {success=false,value=0}
                end
            end
        end

        _answer_checkers = {}
        _pts = {}
        _sampleans = {}
        make_answer = function(name,type,size,checker,pts,sampleans)
            _answer_checkers[_part][name] = checker
            _pts[_part][name] = pts
            _sampleans[_part][name] = sampleans
            print(make_input(name,type,size))
        end
        _part_max_points = function(part)
            return function()
                local sum = 0
                for k,v in pairs(_pts[part]) do
                    sum = sum + v
                end
                return sum
            end
        end
        _evaluate_answer = function(part)
            return function(answers)
                results = {}
                for inputName,value in next, answers do --python.iter(answers) do
                    results[inputName] = _answer_checkers[part][inputName](
                        value,_pts[part][inputName])
                end
                return results
            end
        end
        _part_example_answers = function(part)
            return function()
                return _sampleans[part]
            end
        end
    '''
    code_segments.append(CodeSegment.new(CodeSegment.system_lua, sys_code, ""))
    code_segments.append(CodeSegment.new(CodeSegment.template_setup_code,
                                         setupCode + "\n", ""))  # Newline added to help readability

    count = int(1)

    for templateText in templateArray:
        code = ""
        code += 'part_'+str(count) + \
            '_max_points = _part_max_points('+str(count)+')\n'
        code += 'evaluate_answer_' + \
            str(count)+' = _evaluate_answer('+str(count)+')\n'
        code += 'part_' + \
            str(count)+'_example_answers = _part_example_answers('+str(count)+')\n'
        code += '''
part_'''+str(count)+'''_text = function ()
    _part = '''+str(count)+'''
    _answer_checkers[_part] = {}
    _pts[_part] = {}
    _sampleans[_part] = {}
    output = ""
    '''

        code_segments.append(CodeSegment.new(CodeSegment.system_lua, code, ""))
        count += 1
        # First we split out the variable eval parts and convert them to code print statements
        pieces = re.split(templateVarSplitRegex, templateText)
        templateTextNoValues = pieces[0]
        i = 1
        # l will always be odd because of how split works when parenthesis are used in the regular expression
        l = len(pieces)
        value_comment = '\n--value\n'
        while i < l:
            templateTextNoValues += "[{"+value_comment+"print("+pieces[i]+")}]"
            i += 1
            templateTextNoValues += pieces[i]
            i += 1

        pieces = re.split(templateCodeSplitRegex, templateTextNoValues)
        # TODO: escape quotation marks from pieces
        piece_code = "print([======["+pieces[0]+"]======])\n"
        code_segments.append(CodeSegment.new(CodeSegment.template_richtext,
                                             piece_code, pieces[0]))
        i = 1
        # l will always be odd because of how split works when parenthesis are used in the regular expression
        l = len(pieces)
        while i < l:
            piece_code = HTMLquotesToRegularQuotes(pieces[i]) + "\n"
            if pieces[i].startswith(value_comment):
                piece_type = CodeSegment.template_expression
            else:
                piece_type = CodeSegment.template_code
            code_segments.append(CodeSegment.new(
                piece_type, piece_code, pieces[i]))
            i += 1
            piece_code = "print([======["+pieces[i]+"]======])\n"
            code_segments.append(CodeSegment.new(CodeSegment.template_richtext,
                                                 piece_code, pieces[i]))
            i += 1

        code_segments.append(CodeSegment.new(
            CodeSegment.system_lua, "end\n", ""))
    return code_segments

def getAllLuaLibraryNames():
    return [ll.libraryName for ll in LuaLibrary.objects.all()]

def getLibrariesForQuestion(question):
    return [ql.library.libraryName for ql in QuestionLibrary.objects.filter(question=question)]

def makeDependentLibraries(question, libraryNameList):
    existingDeps = list(map(lambda x: x.library.libraryName,
                            QuestionLibrary.objects.filter(question=question)))
    namesWithoutExisting = [
        val for val in libraryNameList if val not in existingDeps]
    existingWithoutNames = [
        val for val in existingDeps if val not in libraryNameList]
    for name in namesWithoutExisting:
        ql = QuestionLibrary()
        ql.question = question
        ql.library = LuaLibrary.objects.get(libraryName=name)
        ql.save()
    for name in existingWithoutNames:
        QuestionLibrary.objects.filter(
            question=question, library__libraryName=name).delete()

def saveFiles(courseID, question, files, user, isModifying):

    LUA_PROBLEMS_ROOT = os.path.join(
        BASE_DIR, 'lua/problems/')  # This is for lua problems

    FILE_UPLOAD_DIR = LUA_PROBLEMS_ROOT + \
        str(question.questionID)

    if not isModifying:
        # define the access rights
        access_rights = 0o755
        try:
            os.mkdir(FILE_UPLOAD_DIR, access_rights)
        except:
            print("Creation of the directory %s failed" % FILE_UPLOAD_DIR)
            return
        else:
            print("Successfully created the directory %s" % FILE_UPLOAD_DIR)

    for f in files:
        fileName = f.name
        print("filename", fileName)
        # Someone put this in.  This is a terrible idea as our programming answer checker depends on the model directory being zipped.
        # It also means that file deletion likely doesn't work properly for .zip files.
        # We should not unzip uploaded .zip files.
        #if ".zip" in fileName:
        #    print("for zip file", fileName)
        #    with zipfile.ZipFile(f, 'r') as zipf:
        #        zipf.extractall(FILE_UPLOAD_DIR)

        completeDirName = os.path.join(FILE_UPLOAD_DIR, fileName)

        # if file with the same name already exists, remove it
        if os.path.exists(completeDirName):
            os.remove(completeDirName)
            relatedFile = QuestionProgrammingFiles.objects.filter(
                questionID=question, programmingFileName=fileName)
            for rF in relatedFile:
                rF.delete()

        try:
            # This line removed.  See previous comment.  If previously covered next three lines.
            #if not ".zip" in fileName:
            theFile = open(completeDirName, "wb")
            theFile.write(f.read())
            theFile.close()
            testFile = QuestionProgrammingFiles()
            testFile.questionID = question
            testFile.programmingFileName = fileName
            testFile.programmingFileUploader = user
            testFile.programmingFileFolderName = str(question.questionID)
            testFile.save()

        except:
            continue

    '''for f in files:
        fileName = f.name
        if ".head" in fileName or ".tail" in fileName:
            print("for head or tail", fileName)
            testFile = TestProblemFiles()
            testFile.questionID = question
            testFile.testProblemFile = f
            testFile.testProblemFileName = fileName
            testFile.testProblemFileUploader = user
            testFile.save()

        else:
            print("model", fileName)
            testFile = TestProblemModelFiles()
            testFile.questionID = question
            testFile.testProblemModelFile = f
            testFile.testProblemModelFileName = fileName
            testFile.testProblemModelFileUploader = user
            testFile.save()
    print("done saving files")'''

@login_required
@user_passes_test(instructorsCheck, login_url='/oneUp/students/StudentHome', redirect_field_name='')
def removeFileFromQuestion(request):
    import shutil
    if request.user.is_authenticated:
        if request.POST:

            if 'fileID' in request.POST and 'fileName' in request.POST:
                fileID = request.POST['fileID']
                testFile = QuestionProgrammingFiles.objects.get(
                    programmingFileID=int(fileID))
                fileName = testFile.programmingFileName
                folderName = testFile.programmingFileFolderName
                testFile.delete()
                LUA_PROBLEMS_ROOT = os.path.join(
                    BASE_DIR, 'lua/problems/')  # This is for lua problems

                #if ".zip" in fileName:
                #    subDir = fileName.split(".zip")[0]
                #    FILE_UPLOAD_DIR = LUA_PROBLEMS_ROOT + \
                #        folderName+"/"+subDir
                #    if os.path.exists(FILE_UPLOAD_DIR):
                #        shutil.rmtree(FILE_UPLOAD_DIR)

                #else:
                FILE_UPLOAD_DIR = LUA_PROBLEMS_ROOT + \
                    folderName+"/"+fileName
                if os.path.exists(FILE_UPLOAD_DIR):
                    os.remove(FILE_UPLOAD_DIR)

                return HttpResponse(200)
            else:
                return HttpResponse(403, 'something went wrong')
        return HttpResponse(403, 'something went wrong')
    else:
        return HttpResponse(403)


# 21611. 마법사 상어와 블리자드

import sys
input = sys.stdin.readline
from collections import deque

# 12시 3시 6시 9시 로의 이동 -> 왼쪽으로 회전하면서 이동할때 사용
dx_1 = [-1, 0, 1, 0]
dy_1 = [0, 1, 0, -1]

# 상 하 좌 우 방향 -> 마법의 방향
dx = [0] + [-1, 1, 0, 0]
dy = [0] + [0, 0, -1, 1]

# d방향, s거리만큼 마법 -> 해당 위치의 구슬들을 파괴 -> 자동으로 당겨짐
def blizard_magic(d, s):
    shark_x, shark_y = N // 2, N // 2
    count = 0 # 구슬을 파괴한 수 -> 파괴한 뒷 번호의 구슬에선 count만큼 땡겨서 확인해야함
    for i in range(s): # 거리만큼
        target_x = shark_x + dx[d] * (i + 1)
        target_y = shark_y + dy[d] * (i + 1)

        target_index = grid_index[target_x][target_y] - count

        if target_index < len(marble_q): # 해당 위치에 구슬이 놓여있는 경우
            # print(marble_q[target_index], "파괴")
            del marble_q[target_index] # 파괴

        count += 1

# 4개 이상 연속하는 구슬 폭발
def explode_and_change():
    global marble_q

    flag = True

    # print("폭발 함수 내")
    while flag:
        flag = False
        new_marble_q = deque() # 새로운 구슬

        prev_num = marble_q[0] # 이전에 확인한 구슬의 번호
        start_index = 0 # 번호가 연속되는 구슬 그룹의 시작 index
        count = 1
        curr_index = 1 # 확인할 index -> 처음부터 확인

        while True: # 끝에 도달할 때까지

            if curr_index == len(marble_q): # 마지막에 도달했을때
                if count > 4: # 길이가 4 이상인 경우 -> 지워줌
                    flag = True
                    exploded_marbles[prev_num] += count # 폭발한 구슬 개수 추가
                    for _ in range(count):
                        del marble_q[start_index]
                else:
                    new_marble_q.append(count)
                    new_marble_q.append(prev_num)
                break

            curr_num = marble_q[curr_index]
            if curr_num == prev_num: # 번호가 연속되는 경우
                count += 1
                curr_index += 1
            else: # 번호 연속이 끝난 경우
                if count >= 4: # 이전에 4번 이상 연속된 경우
                    flag = True
                    exploded_marbles[prev_num] += count # 폭발한 구슬 개수 추가
                    for _ in range(count):
                        del marble_q[start_index] # 연속된 구슬을 없애줌
                    curr_index = start_index + 1
                else: # 연속된게 끝났지만, 폭발하지 않은 경우 -> 변화
                    new_marble_q.append(count) # 이전 그룹의 개수
                    new_marble_q.append(prev_num) # 이전 그룹의 번호 로 변화

                    start_index = curr_index
                    curr_index += 1

                count = 1
                prev_num = curr_num

        if len(new_marble_q) >= N ** 2: # 길이를 넘어가는 경우 없앰
            over_count = len(new_marble_q) - N ** 2 + 1
            for _ in range(over_count):
                new_marble_q.pop()

        # print(marble_q)
    marble_q = new_marble_q

    # print("함수 끝")

def calc_result():
    result = 0
    for i in range(1,4):
        result += exploded_marbles[i] * i

    return result

if __name__ == "__main__":
    N, M = map(int, input().split())

    grid = []
    for i in range(N): # 구슬의 정보
        line = list(map(int, input().split()))
        grid.append(line)

    marble_q = deque() # 순서대로 구슬의 번호를 담음
    grid_index = [[-1 for _ in range(N)] for _ in range(N)] # 각 지점이 marble_q에서 몇번째 index 위치인지 -> 상어의 위치는 -1

    visited = [[0 for _ in range(N)] for _ in range(N)]
    curr_x, curr_y = N // 2, N // 2 # 상어 위치에서 시작
    d = 3 # 처음 시작할 때 왼쪽으로 이동
    count = 0
    while (curr_x, curr_y) != (0, 0): # grid를 길을 따라 돌며, grid_index 각 지점에 번호를 붙임
        visited[curr_x][curr_y] = 1
        curr_x = curr_x + dx_1[d]
        curr_y = curr_y + dy_1[d]

        grid_index[curr_x][curr_y] = count

        if grid[curr_x][curr_y] != 0:
            marble_q.append(grid[curr_x][curr_y]) # 구슬을 순서대로 담음

        if visited[curr_x + dx_1[(d - 1) % 4]][curr_y + dy_1[(d - 1) % 4]] == 0: # 왼쪽으로 꺽을 수 있으면 꺽음
            d = (d - 1) % 4

        count += 1

    # for i in range(N):
    #     print(grid_index[i])

    exploded_marbles = [0, 0, 0, 0] # [i] -> 폭발한 i번 구슬 개수
    # print(marble_q)
    # print("================")
    for _ in range(M): # 마법
        if not marble_q:
            break

        d, s = map(int, input().split()) # 방향, 거리

        blizard_magic(d, s)
        # print(marble_q)
        explode_and_change()

        # print(marble_q)
        # print("================")

    print(calc_result())

21611. 마법사 상어와 블리자드.py


## plot training of full convolutional neural network using partially / fully observable states

import numpy as np
import matplotlib.pyplot as plt
import pickle
import sys
import gym
import pandas as pd

sys.path.append('../../modules/')
from Analysis.analysis_utils import get_avg_std, get_grids, analysis_specs, LINCLAB_COLS, structured_unstructured
from modules.Utils import running_mean as rm

data_dir = '../../Data/results/'
groups_to_split = ['env_name','representation']

conv_df = pd.read_csv('../../Data/conv_mf_retraining.csv')
conv_df_gb = conv_df.groupby(groups_to_split)["save_id"]
labels_for_plot = {'conv':'Partially Observable State', 'reward_conv':'Fully Observable State'}
rep_to_col = {'unstructured':'blue', 'structured':'red'}

sh_df = pd.read_csv('../../Data/train_test_shallowAC.csv')
sh_df['representation'] = sh_df['representation'].apply(structured_unstructured)
sh_df_gb = sh_df.groupby(groups_to_split)["save_id"]

envs = ['gridworld:gridworld-v1', 'gridworld:gridworld-v4', 'gridworld:gridworld-v3', 'gridworld:gridworld-v5']
grids = get_grids(envs)

def compare_conv_fc(env, conv_gb,fc_gb):
    fig, ax = plt.subplots(1,2, sharex='col')
    if env[-1] == '5':
        rwd_colrow0 = (3,9)
        rwd_colrow1= (16,9)
    else:
        rwd_colrow0 = (5,5)
        rwd_colrow1=(14,14)

    rect0 = plt.Rectangle(rwd_colrow0, 1, 1, facecolor='b',edgecolor=None, alpha=0.3)
    rect1 = plt.Rectangle(rwd_colrow1, 1, 1, facecolor='g', edgecolor=None,alpha=0.3)
    ax[0].pcolor(grids[envs.index(env)],cmap='bone_r',edgecolors='k', linewidths=0.1)
    ax[0].axis(xmin=0, xmax=20, ymin=0,ymax=20)
    ax[0].set_aspect('equal')
    ax[0].add_patch(rect0)
    #ax[0].add_patch(rect1)
    ax[0].get_xaxis().set_visible(False)
    ax[0].get_yaxis().set_visible(False)
    ax[0].invert_yaxis()

    # show CONV Results
    id_list = list(conv_gb.get_group((env,'reward_conv')))
    train_array = []
    for i, id_num in enumerate(id_list):
        with open(data_dir+ f'{id_num}_data.p', 'rb') as f:
            dats = pickle.load(f)

            raw_score = dats['total_reward']#[0:5000]
            print(len(raw_score))
            normalization = analysis_specs['avg_max_rwd'][env+'1']
            training_transformed = rm((np.asarray(raw_score)+2.5)/(normalization +2.5),200)
            train_array.append(training_transformed)
            print('done', id_num)

    mean_perf = np.mean(train_array,axis=0)
    std_perf = np.std(train_array,axis=0)/np.sqrt(len(train_array))
    mins = mean_perf-std_perf
    maxes = mean_perf+std_perf

    ax[1].plot(np.arange(len(mean_perf)),mean_perf, color="gray", label='Image (Conv)')
    ax[1].fill_between(np.arange(len(mean_perf)),mins, maxes, color='gray', alpha=0.2)

    # show FC Results
    for rep in ['unstructured','structured']:
        id_list = list(fc_gb.get_group((env,rep)))
        train_array = []
        filler = np.zeros(10000)
        filler[:] = np.nan
        for i, id_num in enumerate(id_list):
            with open(data_dir+ f'{id_num}_data.p', 'rb') as f:
                dats = pickle.load(f)
                raw_score = dats['total_reward'][5000:-1]
                if len(raw_score)==9999:
                    raw_score+= list(filler)
                print(len(raw_score))
                normalization = analysis_specs['avg_max_rwd'][env+'1']
                training_transformed = rm((np.asarray(raw_score)+2.5)/(normalization +2.5),200)
                train_array.append(training_transformed)
                print('done', id_num)

        mean_perf = np.nanmean(train_array,axis=0)
        std_perf = np.nanstd(train_array,axis=0)/np.sqrt(len(train_array))
        mins = mean_perf-std_perf
        maxes = mean_perf+std_perf

        ax[1].plot(np.arange(len(mean_perf)),mean_perf, color=LINCLAB_COLS[rep_to_col[rep]], label=f'{rep} (FC)')
        ax[1].fill_between(np.arange(len(mean_perf)),mins, maxes, color=LINCLAB_COLS[rep_to_col[rep]], alpha=0.2)

    ax[1].set_ylim(0,1.1)
    ax[1].set_yticks([0,1])
    ax[1].set_yticklabels([0,100])
    ax[1].set_ylabel('Performance \n(% Optimal)')
    ax[1].set_xlabel('Episodes')
    ax[1].legend(loc='upper center', bbox_to_anchor = (0.5,1.1))
    plt.savefig(f'../figures/CH1/compare_conv_fc{env[-2:]}.svg')
    plt.show()

compare_conv_fc(envs[1],conv_df_gb,sh_df_gb)

def plot_train_test(df, df_gb, envs, reps, save=False):
    fig, ax = plt.subplots(len(envs),2, sharex='col')
    for e, env in enumerate(envs):
        if env[-1] == '5':
            rwd_colrow0 = (3,9)
            rwd_colrow1= (16,9)
        else:
            rwd_colrow0 = (5,5)
            rwd_colrow1=(14,14)

        rect0 = plt.Rectangle(rwd_colrow0, 1, 1, facecolor='b',edgecolor=None, alpha=0.3)
        rect1 = plt.Rectangle(rwd_colrow1, 1, 1, facecolor='g', edgecolor=None,alpha=0.3)
        ax[e,0].pcolor(grids[e],cmap='bone_r',edgecolors='k', linewidths=0.1)
        ax[e,0].axis(xmin=0, xmax=20, ymin=0,ymax=20)
        ax[e,0].set_aspect('equal')
        ax[e,0].add_patch(rect0)
        ax[e,0].add_patch(rect1)
        ax[e,0].get_xaxis().set_visible(False)
        ax[e,0].get_yaxis().set_visible(False)
        ax[e,0].invert_yaxis()

        for r, rep in enumerate(reps):
            train_test_array = []
            id_list = list(df_gb.get_group((env,rep)))
            print(env,rep)
            for i, id_num in enumerate(id_list):
                # get training data
                train_dat_id = list(df.loc[df['save_id']==id_num]['load_from'])[0]
                with open(data_dir+ f'{train_dat_id}_data.p', 'rb') as f:
                    dats = pickle.load(f)
                    raw_score = dats['total_reward'][0:5000]
                    normalization = analysis_specs['avg_max_rwd'][env+'1']
                    training_transformed = (np.asarray(raw_score)+2.5)/(normalization +2.5)
                # get testing data
                with open(data_dir+ f'{id_num}_data.p', 'rb') as f:
                    dats = pickle.load(f)
                    raw_score = dats['total_reward']
                    normalization = analysis_specs['avg_max_rwd'][env+'1']
                    testing_transformed = (np.asarray(raw_score)+2.5)/(normalization +2.5)

                train_test_data = rm(np.concatenate((training_transformed,testing_transformed)),200)
                train_test_array.append(train_test_data)
                print('done', id_num)

            mean_perf = np.mean(train_test_array,axis=0)
            std_perf = np.std(train_test_array,axis=0)/np.sqrt(len(train_test_array))
            mins = mean_perf-std_perf
            maxes = mean_perf+std_perf

            ax[e,1].plot(np.arange(len(mean_perf)),mean_perf, color=LINCLAB_COLS[rep_to_col[rep]], label=labels_for_plot[rep])
            ax[e,1].fill_between(np.arange(len(mean_perf)),mins, maxes, color=LINCLAB_COLS[rep_to_col[rep]], alpha=0.2)
            ax[e,1].set_ylim(0,1.1)
            ax[e,1].axvline(x=4801, linestyle=":",color='gray')
        ax[e,1].set_ylabel('Performance \n(% Optimal)')

    ax[e,1].set_xlabel('Episodes')
    ax[0,1].legend(loc='upper center', bbox_to_anchor = (0.5,1.1))
    plt.savefig('../figures/CH1/conv_net_retrain.svg')
    plt.show()

def plot_all(save=True, cutoff=25000):
    fig, axs = plt.subplots(4, 2, sharex='col')
    for i in range(len(grids)):
        rect = plt.Rectangle((5,5), 1, 1, color='g', alpha=0.3)
        axs[i,0].pcolor(grids[i],cmap='bone_r',edgecolors='k', linewidths=0.1)
        axs[i,0].axis(xmin=0, xmax=20, ymin=0,ymax=20)
        axs[i,0].set_aspect('equal')
        axs[i,0].add_patch(rect)
        axs[i,0].get_xaxis().set_visible(False)
        axs[i,0].get_yaxis().set_visible(False)
        axs[i,0].invert_yaxis()

    for ind, name in enumerate(envs):
        for rep_to_plot in reps:
            v_list = list(df_gb.get_group((name,rep_to_plot)))
            for i in v_list:
                print(i[0:8])
                if i[0:8] in ['69aa8807','9ea97939']:
                    v_list.remove(i)
            avg_, std_ = get_avg_std(v_list,cutoff=cutoff, smoothing=200)
            axs[ind,1].plot(avg_, label=f'{labels_for_plot[rep_to_plot]}')
            axs[ind,1].fill_between(np.arange(len(avg_)),avg_-std_/np.sqrt(len(v_list)), avg_+std_/np.sqrt(len(v_list)), alpha=0.3)
            axs[ind,1].set_ylim([-4,12])
        if ind == len(envs)-1:
            axs[ind,1].set_xlabel('Episodes')
            #axs[ind,1].set_ylabel('Cumulative \nReward')
    axs[0,1].legend(loc='upper center', ncol=1, bbox_to_anchor=(0.2,1.1))
    if save:
        plt.savefig('../figures/CH1/conv_retraining.svg',format='svg')

    plt.show()

#plot_all(cutoff=25000)


# Import necessary libraries
import re
import numpy as np
import pandas as pd
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from nltk.stem import PorterStemmer
from textblob import TextBlob
import plotly.graph_objects as go
import plotly.express as ex

# Read data from CSV files
modi_data = pd.read_csv('modi_reviews.csv')
rahul_data = pd.read_csv('rahul_reviews.csv')

# Explore the Modi data
modi_data.head()
modi_data.shape

# Explore the Rahul data
rahul_data.head()
rahul_data.shape

# Text Cleaning

# Define a function for text preprocessing
def preprocess_modi_text_data(data, text_column_name):
    # Lowercasing
    data[text_column_name] = data[text_column_name].str.lower()

    # Check and handle missing values
    print(f"Data type of '{text_column_name}' column before handling missing values: {data[text_column_name].dtype}")
    print(f"Number of missing values in '{text_column_name}' column before handling missing values: {data[text_column_name].isnull().sum()}")
    data = data.dropna(subset=[text_column_name])

    # Convert the column to strings
    data.loc[:, text_column_name] = data[text_column_name].astype(str)

    # Remove special characters, emojis, and emoticons
    data.loc[:, text_column_name] = data[text_column_name].apply(lambda x: re.sub(r'[^a-zA-Z\s😀-🙁]', '', x))

    # Remove stopwords
    stop_words = set(stopwords.words('english'))
    data.loc[:, text_column_name] = data[text_column_name].apply(lambda x: ' '.join([word for word in word_tokenize(x) if word not in stop_words]))

    # Stemming
    stemmer = PorterStemmer()
    data.loc[:, text_column_name] = data[text_column_name].apply(lambda x: ' '.join([stemmer.stem(word) for word in word_tokenize(x)]))

    # Remove numbers
    data.loc[:, text_column_name] = data[text_column_name].apply(lambda x: re.sub(r'\d+', '', x))

    return data

# Apply text preprocessing to Modi data
modi_data = preprocess_modi_text_data(modi_data, 'Tweet')
modi_data = modi_data.drop('Unnamed: 0', axis=1)

# Explore the cleaned Modi data
modi_data.head()

# Apply text preprocessing to Rahul data
def preprocess_rahul_text_data(data, text_column_name):
    # Lowercasing
    data[text_column_name] = data[text_column_name].str.lower()

    # Check and handle missing values
    print(f"Data type of '{text_column_name}' column before handling missing values: {data[text_column_name].dtype}")
    print(f"Number of missing values in '{text_column_name}' column before handling missing values: {data[text_column_name].isnull().sum()}")
    data = data.dropna(subset=[text_column_name])

    # Convert the column to strings
    data.loc[:, text_column_name] = data[text_column_name].astype(str)

    # Remove special characters, emojis, and emoticons
    data.loc[:, text_column_name] = data[text_column_name].apply(lambda x: re.sub(r'[^a-zA-Z\s😀-🙁]', '', x))

    # Remove stopwords
    stop_words = set(stopwords.words('english'))
    data.loc[:, text_column_name] = data[text_column_name].apply(lambda x: ' '.join([word for word in word_tokenize(x) if word not in stop_words]))

    # Stemming
    stemmer = PorterStemmer()
    data.loc[:, text_column_name] = data[text_column_name].apply(lambda x: ' '.join([stemmer.stem(word) for word in word_tokenize(x)]))

    # Remove numbers
    data.loc[:, text_column_name] = data[text_column_name].apply(lambda x: re.sub(r'\d+', '', x))

    return data

rahul_data = preprocess_rahul_text_data(rahul_data, 'Tweet')
rahul_data = rahul_data.drop('Unnamed: 0', axis=1)

# Define a function to find the polarity of a review using TextBlob
def find_polarity(review):
    return TextBlob(review).sentiment.polarity

# Apply polarity analysis to Modi data
modi_data['Polarity'] = modi_data['Tweet'].apply(find_polarity)

# Apply polarity analysis to Rahul data
rahul_data['Polarity'] = rahul_data['Tweet'].apply(find_polarity)

# Assign sentiment labels based on polarity
modi_data['Label'] = np.where(modi_data['Polarity'] > 0, 'positive', 'negative')
modi_data['Label'][modi_data['Polarity'] == 0] = 'neutral'

rahul_data['Label'] = np.where(rahul_data['Polarity'] > 0, 'positive', 'negative')
rahul_data['Label'][rahul_data['Polarity'] == 0] = 'neutral'

# Remove neutral Modi reviews
neutral_modi_reviews = modi_data[modi_data['Polarity'] == 0.0000]
remove_modi_neutral_reviews = modi_data['Polarity'].isin(neutral_modi_reviews['Polarity'])
modi_data.drop(modi_data[remove_modi_neutral_reviews].index, inplace=True)

# Remove neutral Rahul reviews
neutral_rahul_reviews = rahul_data[rahul_data['Polarity'] == 0.0000]
remove_rahul_neutral_reviews = rahul_data['Polarity'].isin(neutral_rahul_reviews['Polarity'])
rahul_data.drop(rahul_data[remove_rahul_neutral_reviews].index, inplace=True)

# Randomly remove reviews to balance the dataset
np.random.seed(10)
remove_n_modi = 8481
drop_indices_modi = np.random.choice(modi_data.index, remove_n_modi, replace=True)
df_modi_data = modi_data.drop(drop_indices_modi)

np.random.seed(10)
remove_n_rahul = 360
drop_indices_rahul = np.random.choice(rahul_data.index, remove_n_rahul, replace=True)
df_rahul_data = rahul_data.drop(drop_indices_rahul)

# Prediction about Election

# Calculate the percentage of negative and positive reviews for Modi
modi_count = df_modi_data.groupby('Label').count()
neg_modi = (modi_count['Polarity'][0] / 1000) * 100
pos_modi = (modi_count['Polarity'][1] / 1000) * 100

# Calculate the percentage of negative and positive reviews for Rahul
rahul_count = df_rahul_data.groupby('Label').count()
neg_rahul = (rahul_count['Polarity'][0] / 1000) * 100
pos_rahul = (rahul_count['Polarity'][1] / 1000) * 100

# Create a bar chart to visualize sentiment analysis results
politicians = ['Narendra Modi', 'Rahul Gandhi']
neg_list = [neg_modi, neg_rahul]
pos_list = [pos_modi, pos_rahul]

fig = go.Figure(
    data=[
        go.Bar(name='Negative', x=politicians, y=neg_list, marker_color='red'),
        go.Bar(name='Positive', x=politicians, y=pos_list, marker_color='green')
    ]
)
fig.update_layout(barmode='group')
fig.show()