# -*- coding: utf-8 -*-
from PyQt5.QtCore import Qt, pyqtSignal, QMimeData
from PyQt5.QtGui import QFont, QDrag, QPixmap
from PyQt5.QtWidgets import QLabel, QWidget, QGridLayout, QHBoxLayout, QStackedWidget, QSizePolicy
from model import Card, DeckType
from logic.DirPath import CardResDir
import math

# 单个牌视图
class CardLabel(QLabel):
    mousePressSign = pyqtSignal(object, object)

    def __init__(self, *__args):
        super().__init__(*__args)
        self._model = None
        self._deckView = None

    # 与model绑定
    @property
    def model(self):
        return self._model

    @model.setter
    def model(self, model):
        self._model = model

    # 属于哪个牌组
    @property
    def deckView(self):
        return self._deckView

    @deckView.setter
    def deckView(self, view):
        self._deckView = view

    def mouseMoveEvent(self, e):
        if e.buttons() != Qt.LeftButton:
            return

        mimeData = QMimeData()
        drag = QDrag(self)
        drag.setMimeData(mimeData)
        drag.setPixmap(self.pixmap().scaled(self.size()))
        drag.setHotSpot(self.rect().center())  # 设置跟随的中心点
        drag.exec_(Qt.MoveAction)

    def mousePressEvent(self, e):
        super().mousePressEvent(e)

        self.mousePressSign.emit(self, e)

# 牌组
class DeckWidget(QStackedWidget):
    dropDownSign = pyqtSignal(object, object)

    def __init__(self, isDrops=False):
        super().__init__()
        self._model = None
        self.tipLabel = None
        self._isDefaultLayout = None

        self.setAcceptDrops(isDrops)
        # 构造两个widget 切换
        cardWidget = QWidget()
        defaultWidget = QWidget()

        self.cardLayout = QGridLayout()
        self.cardLayout.setSpacing(0)
        self.cardLayout.setAlignment(Qt.AlignTop | Qt.AlignLeft)

        self.defaultLayout = QHBoxLayout()
        self.defaultLayout.setAlignment(Qt.AlignCenter)

        defaultWidget.setLayout(self.defaultLayout)
        cardWidget.setLayout(self.cardLayout)
        self.addWidget(defaultWidget)
        self.addWidget(cardWidget)

        self.initUI()

    @property
    def deckType(self):
        return self._deckType

    @deckType.setter
    def deckType(self, t):
        if isinstance(t, DeckType):
            self._deckType = t

    # 与 model 绑定
    @property
    def model(self):
        return self._model

    @model.setter
    def model(self, model):
        self._model = model

    @property
    def cardViews(self):
        viewList = []
        for index in range(0, self.cardLayout.count()):
            viewList.append(self.cardLayout.itemAt(index).widget())
        return viewList

    @property
    def cardCount(self):
        return self.cardLayout.count()

    def initUI(self):
        label = QLabel('拖到此处')
        label.setFont(QFont('Roman times', 20, QFont.Bold))
        label.setParent(self)
        label.setStyleSheet('QLabel{color:rgb(204,204,204)}')
        self.tipLabel = label
        self.defaultLayout.addWidget(label)
        self.showDefaultLayout(True)

    def initCards(self, model, calllback=None, maxWidth=None):
        # 移除已有牌
        self.clear()

        isDefaultLayout = True
        for card in model.lists:
            isDefaultLayout = False
            cardView = ViewGenerator.createCardView(card)
            cardView.deckView = self
            if calllback:
                cardView.mousePressSign.connect(calllback)
            col, row = self.getColAndRow(None, maxWidth=maxWidth)
            self.cardLayout.addWidget(cardView, row, col)

        self.showDefaultLayout(isDefaultLayout)

    def setLabelText(self, text):
        self.tipLabel.setText(text)

    # 根据index获取相应的 行号和列号
    def getColAndRow(self, index=None, maxWidth=None):
        # 根据宽度自动变换行数
        col, row = 0, 0
        count = self.cardCount if (index is None) else index
        totalWidth = self.size().width() if maxWidth is None else maxWidth
        colMaxCount = math.ceil(totalWidth / Card.WIDTH) - 1
        col = count % colMaxCount
        row = math.floor(count / colMaxCount)
        return col, row

    def addCard(self, cardView):
        cardView.deckView = self

        col, row = self.getColAndRow()
        self.cardLayout.addWidget(cardView, row, col)

        if self._model:
            self._model.addCard(cardView.model)
        self.showDefaultLayout(False)

    def removeCard(self, cardView):
        removeIndex = self.cardLayout.indexOf(cardView)
        # 后面的元素往前移
        self.moveCard(removeIndex+1, self.cardCount, -1)

        if self._model:
            self._model.removeCard(cardView.model)
        cardView.setParent(None)
        cardView.deleteLater()
        if self.cardLayout.count() == 0:
            self.showDefaultLayout(True)

    def clear(self):
        while self.cardLayout.itemAt(0):
            item = self.cardLayout.takeAt(0)
            item.widget().setParent(None)
            del item
        self.showDefaultLayout(True)

    # cardView : 需要插入的牌
    # insertedView : 被插入的位置的牌
    def insertCard(self, cardView, insertedView):
        insertedIndex = self.cardLayout.indexOf(insertedView)
        insertIndex = self.cardLayout.indexOf(cardView)

        if insertedIndex >= 0:
            pos = self.cardLayout.getItemPosition(insertedIndex)

            if insertIndex < insertedIndex:
                # move left
                start, end, distance = insertIndex+1, insertedIndex+1, -1
            else:
                # move right
                start, end, distance = insertedIndex, insertIndex, 1
            self.moveCard(start, end, distance)
            cardView.setParent(None)
            self.cardLayout.addWidget(cardView, pos[0], pos[1])
            self.updateGrid()
            if self._model:
                self._model.insertCard(insertedIndex, cardView.model)

    """
       移动牌
        @start 牌开始的索引
        @end   牌结束的索引
        @distance 移动的距离
    """
    def moveCard(self, start, end, distance):
        movedItem = []  # 需要移动的item
        for i in range(start, end):
            item = self.cardLayout.itemAt(i)
            if item:
                movedItem.append(item)

        for item in movedItem:
            self.cardLayout.removeItem(item)

        # 重新加入到布局之中
        newStart = start + distance
        for item in movedItem:
            col, row = self.getColAndRow(newStart)
            self.cardLayout.addWidget(item.widget(), row, col)
            newStart += 1

    # 重新更新 index
    def updateGrid(self):
        removeList = []
        for row in range(self.cardLayout.rowCount()):
            for col in range(self.cardLayout.columnCount()):
                item = self.cardLayout.itemAtPosition(row, col)
                if item:
                    removeList.append(item.widget())
                    item.widget().setParent(None)
        for i, widget in enumerate(removeList):
            col, row = self.getColAndRow(i)
            self.cardLayout.addWidget(widget, row, col)

    def showDefaultLayout(self, isShow):
        if self._isDefaultLayout == isShow:
            return
        self._isDefaultLayout = isShow
        if isShow:
            self.setCurrentIndex(0)
        else:
            self.setCurrentIndex(1)

    def dragEnterEvent(self, e):
        if isinstance(e.source(), CardLabel):
            e.accept()

    def dropEvent(self, e):
        # 将牌添加到 列表中
        self.dropDownSign.emit(self, e)
        e.setDropAction(Qt.MoveAction)
        e.accept()

# 视图生成器
class ViewGenerator(object):
    @staticmethod
    def createModelDeckView(model):
        # model 绑定视图
        # 可以管理model数据
        deckWidget = DeckWidget(True)
        deckWidget.model = model
        deckWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        return deckWidget

    @staticmethod
    def createDefaultDeckView():
        # 固定视图
        deckWidget = DeckWidget(False)
        deckWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        return deckWidget

    @staticmethod
    def createCardView(model):
        import os
        cardView = CardLabel()
        cardView.setFixedSize(model.width, model.height)
        cardImg = QPixmap(os.path.join(CardResDir, model.pathName))
        cardView.model = model
        cardView.setPixmap(cardImg)
        cardView.setScaledContents(True)
        return cardView


from GdcLib import *
from GdcUtils import *
from openpyxl import Workbook
import matplotlib.pyplot as plt
import numpy as np

# ======================================================================================================
def SortByDisease( aCase ):
  index = 1                                                                      # Indices chosen for consistency with old code
  if MutationOfInterest in aCase.Mutations:
    if aCase.Mutations[ MutationOfInterest ].Classification == SilentOrSplice : return
    index = 0

  lDiseaseType = str( aCase.DiseaseType )
  if not lDiseaseType in lCases2: lCases2[ lDiseaseType ] = [ [] , [] ]
  lCases2[ lDiseaseType ][ index ].append( aCase )
# ======================================================================================================

# ======================================================================================================
def Flatten( Data , index ):
  lRet = []
  for j in Data:
    for i in j.StarCounts:
      lRet.append( i.TpmUnstranded[ index ] )
  return lRet
# ======================================================================================================

DiseaseTypeLut = {
  "Brain Lower Grade Glioma" : "Brain Lower\nGrade Glioma",
  "Sarcoma" : "Sarcoma",
  "Osteosarcoma" : "Osteosarcoma",
  "Glioblastoma Multiforme" : "Glioblastoma Multiforme",
  "Pheochromocytoma and Paraganglioma" : "Pheochromocytoma\nand Paraganglioma",
  "Neuroblastoma" : "Neuroblastoma",
  "Acute Myeloid Leukemia" : "Acute Myeloid Leukemia",
  "Adrenocortical Carcinoma" : "Adrenocortical Carcinoma",
  "Bladder Urothelial Carcinoma" : "Bladder Urothelial Carcinoma",
  "Breast Invasive Carcinoma" : "Breast Invasive Carcinoma",
  "Cervical Squamous Cell Carcinoma and Endocervical Adenocarcinoma" : "Cervical Squamous Cell Carcinoma\n& Endocervical Adenocarcinoma",
  # "Cholangiocarcinoma" : "Cholangiocarcinoma",
  "Colon Adenocarcinoma" : "Colon Adenocarcinoma",
  "Esophageal Carcinoma" : "Esophageal Carcinoma",
  "Head and Neck Squamous Cell Carcinoma" : "Head and Neck\nSquamous Cell Carcinoma",
  # "High-Risk Wilms Tumor" : "High-Risk Wilms Tumor",
  # "Kidney Chromophobe" : "Kidney Chromophobe",
  "Kidney Renal Clear Cell Carcinoma" : "Kidney Renal\nClear Cell Carcinoma",
  # "Kidney Renal Papillary Cell Carcinoma" : "Kidney Renal Papillary Cell Carcinoma",
  "Liver Hepatocellular Carcinoma" : "Liver Hepatocellular Carcinoma",
  "Lung Adenocarcinoma" : "Lung Adenocarcinoma",
  "Lung Squamous Cell Carcinoma" : "Lung Squamous Cell Carcinoma",
  # "Lymphoid Neoplasm Diffuse Large B-cell Lymphoma" : "Lymphoid Neoplasm Diffuse Large B-cell Lymphoma",
  # "Mesothelioma" : "Mesothelioma",
  # "None" : "None",
  "Ovarian Serous Cystadenocarcinoma" : "Ovarian Serous\nCystadenocarcinoma",
  "Pancreatic Adenocarcinoma" : "Pancreatic Adenocarcinoma",
  "Prostate Adenocarcinoma" : "Prostate Adenocarcinoma",
  "Rectum Adenocarcinoma" : "Rectum Adenocarcinoma",
  "Skin Cutaneous Melanoma" : "Skin Cutaneous Melanoma",
  "Stomach Adenocarcinoma" : "Stomach Adenocarcinoma",
  # "Testicular Germ Cell Tumors" : "Testicular Germ Cell Tumors",
  # "Thymoma" : "Thymoma",
  "Thyroid Carcinoma" : "Thyroid Carcinoma",
  "Uterine Carcinosarcoma" : "Uterine Carcinosarcoma",
  "Uterine Corpus Endometrial Carcinoma" : "Uterine Corpus\nEndometrial Carcinoma",
  # "Uveal Melanoma" : "Uveal Melanoma"
}

# ======================================================================================================
def Finally():
  Data = {}

  # Fill the plots
  # for lDiseaseType , lCases in tqdm.tqdm( sorted( lCases2.items() ) , ncols=Ncol , desc="Analysing" ):

  for lDiseaseType , DiseaseName in tqdm.tqdm( DiseaseTypeLut.items() , ncols=Ncol , desc="Analysing" ):
    lCases = lCases2[ lDiseaseType ]

    lMut , lWt = lCases[0] , lCases[1]
    if len( lMut ) == 0 or len( lWt ) == 0 : continue

    x0 , y0 , x1 , y1 , x2 , y2 = [] , [] , [] , [] , [] , []
    for GeneName , Gene in tqdm.tqdm( sorted( StarCounts.GeneCatalogue.items() ) , leave=False , ncols=Ncol , desc=lDiseaseType ):
      if Gene.type != "protein_coding" : continue
      lRet = GdcStatistics( Flatten( lMut , Gene.index ) , Flatten( lWt , Gene.index ) )
      if lRet is None : continue
      if np.isnan( lRet.neg_log_pvalue ) : continue
      if ( GeneName == "DRG2" ):
        x0.append( lRet.log_mean_ratio_with_error[0] )
        y0.append( lRet.neg_log_pvalue )
      elif ( lRet.neg_log_pvalue < 2.3 ) or ( np.fabs( lRet.log_mean_ratio_with_error[0] ) < 1 ):
        x1.append( lRet.log_mean_ratio_with_error[0] )
        y1.append( lRet.neg_log_pvalue )
      else:
        x2.append( lRet.log_mean_ratio_with_error[0] )
        y2.append( lRet.neg_log_pvalue )

    if len( x0 ) or len( x1 ) or len( x2 ) : Data[ DiseaseName ] = ( ( x0 , y0 ), ( x1 , y1 ), ( x2 , y2 ) )

  # Draw the plots
  fig , axs = plt.subplots( 5 , 6 , sharey=True )
  for x in axs.flat[len(DiseaseTypeLut):]: x.set_visible( False )
  for Cases , ax1 in zip( Data.items() , fig.axes ):
    lDiseaseType , lData = Cases
    ax1.set_xlabel( lDiseaseType , style='italic' , labelpad=1 )
    ax1.set_xlim( -25 , 25 )
    ax1.set_ylim( 1 , 100 )
    ax1.scatter( lData[1][0] , lData[1][1] , color="0.75" , s=1 )
    ax1.scatter( lData[2][0] , lData[2][1] , color="b" , s=1 )
    ax1.scatter( lData[0][0] , lData[0][1] , color="r" , s=1 )
    # ax1.text( 0.6 , 50 , f'$N_{{Mutant}} = {len(lData[0])}$\n$N_{{Wild-type}} = {len(lData[1])}$\n$p_{{value}}={lStats.pvalue:.2e}$' , fontsize="x-small" )
  plt.yscale( "log" )

  #Add the common y-axis label
  fig.add_subplot(111, frameon=False)
  plt.tick_params(labelcolor='none', which='both', top=False, bottom=False, left=False, right=False)
  plt.ylabel( "$-log_{10}($ p-value $)$" , style='italic' )
  plt.xlabel( "$log_{1.5}($ fold-ratio $)$" , style='italic', labelpad=30 )

  # Draw the images
  fig.set_size_inches( 16 , 20 )
  plt.tight_layout()
  fig.subplots_adjust( hspace = 0.2 , wspace = 0.0 )
  plt.savefig( 'DRG2-volcano.pdf' )
# ======================================================================================================

# ======================================================================================================
if len( args.mutations ) != 1 : raise Exception( "Exactly 1 mutation must be specified on the commandline" )
MutationOfInterest , lCases2 = args.mutations[0] , {}
LoadAndForEach( args.src , SortByDisease , After = Finally ) # Load src and analyze on-the-fly, making use of the optional After function
# ======================================================================================================


# encoding: utf-8
import json

from django.http import HttpResponseBadRequest, HttpResponse
from django.shortcuts import render, render_to_response
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.template import RequestContext

from notipub_message.models import DeviceToken
from helper import get_district, get_weathersummary

from dowant.lib.logs import logs as logging
logger = logging.get_logger(__name__)

def home(request,
         template="notipub_message/index.html"):
    context = {}
    return render_to_response(template,
                                context, context_instance=RequestContext(request))

def register_token(request):
    token = request.GET.get('token', None)
    uuid = request.GET.get('uuid', None)
    lat = request.GET.get('lat', None)
    lng = request.GET.get('lng', None)

    dev = DeviceToken(token=token, uuid=uuid, lat=lat, lng=lng)
    dev.save()

    data = {
        "result_code": 0,
        "message": token,
    }

    response = json.dumps(data)
    return HttpResponse(response)

def get_current_weather(request):
    lat = request.GET.get('lat', None)
    lng = request.GET.get('lng', None)

    message = get_weathersummary(lat, lng)[1]
    district = get_district(lat, lng)

    data = {
        "result_code": 1,
        "message": message,
        "district": district,
    }

    response = json.dumps(data)
    return HttpResponse(response)


#!/usr/bin/env python3

from typing import Dict, Tuple, List, Union
from enum import Enum

import argparse
import math
import sys

Point2 = Tuple[float, float]
Point3 = Tuple[float, float, float]

ROUNDING = 3

class LensStyle(Enum):
    CONCAVE = 1
    CONVEX = 2

class Arc:
    def __init__(
            self,
            center: Tuple[float, ...],
            radius: float,
            start_angle: float,
            end_angle: float,
            start_height: float=0,
            end_height: float=0):
        self.center = center
        if len(center) == 2:
            self.center = (center[0], center[1], 0.0)
        self.radius = radius
        self.start_angle = start_angle
        self.end_angle = end_angle
        self.start_height = start_height
        self.end_height = end_height

    def start_point(self) -> Point3:
        return (
                round(
                    math.cos(math.radians(-self.start_angle)) * self.radius + self.center[0],
                    ROUNDING),
                round(
                    math.sin(math.radians(-self.start_angle)) * self.radius + self.center[1],
                    ROUNDING),
                self.start_height
                )

    def end_point(self) -> Point3:
        return (
                round(
                    math.cos(math.radians(-self.end_angle)) * self.radius + self.center[0],
                    ROUNDING),
                round(
                    math.sin(math.radians(-self.end_angle)) * self.radius + self.center[1],
                    ROUNDING),
                self.end_height
                )

def spiral(center: Union[Point2, Point3], apature: float, step_size: float) -> List[Arc]:
    arcs: List[Arc] = []
    loop: float = 0.25
    offset: List[float] = [0.0, 0.0]
    while loop * step_size < apature / 2:
        orientation = round(loop * 4) % 4
        if orientation == 0:
            start_angle = 0
            end_angle = 90
            offset[0] -= step_size / 4
            section_radius = loop * step_size
        elif orientation == 1:
            start_angle = 90
            end_angle = 180
            offset[1] += step_size / 4
            section_radius = loop * step_size
        elif orientation == 2:
            start_angle = 180
            end_angle = 270
            offset[0] += step_size / 4
            section_radius = loop * step_size
        elif orientation == 3:
            start_angle = 270
            end_angle = 0
            offset[1] -= step_size / 4
            section_radius = loop * step_size
        else:
            raise

        section_center = (center[0] + offset[0], center[1] + offset[1])
        arcs.append(Arc(section_center, section_radius, start_angle, end_angle))

        loop += 0.25  # 1/4 turn.
    arcs.append(Arc(center, apature / 2, end_angle, end_angle))

    return arcs

def surface_height(
        point: Point3,
        center_curvature: Point3,
        radius_curvature: float,
        style: LensStyle) -> Point3:
    # x**2 + y**2 + z**2 == radius**2
    centered_x = point[0] - center_curvature[0]
    centered_y = point[1] - center_curvature[1]
    if style is LensStyle.CONVEX:
        height_squared = radius_curvature ** 2 - centered_x ** 2 - centered_y ** 2
    else:
        height_squared = radius_curvature ** 2 + centered_x ** 2 + centered_y ** 2
    if height_squared < 0:
        height = 0
    else:
        height = math.sqrt(height_squared)
    height = round(height + center_curvature[2], ROUNDING)

    return tuple(point[:2] + (height,))

def spiral_to_lens(
        arcs: List[Arc],
        center_curvature: Point3,
        radius_curvature: float,
        style: LensStyle = LensStyle.CONVEX,
        z_offset = 0
        ) -> List[Arc]:
    previous_arc = None
    for arc in arcs:
        point = surface_height(arc.start_point(), center_curvature, radius_curvature, style)
        arc.start_height = point[2] + z_offset

        if previous_arc is not None:
            previous_arc.end_height = arc.start_height
        previous_arc = arc

    last_end_point = surface_height(
            arcs[-1].end_point(), center_curvature, radius_curvature, style)
    arcs[-1].end_height = last_end_point[2] + z_offset

def header_gcode(safe_z: float) -> List[str]:
    output = []
    output.append('(Block-name: header)')
    output.append(f'G0 Z{str(safe_z)}')

    return output

def footer_gcode(safe_z: float) -> List[str]:
    output = []
    output.append('(Block-name: footer)')
    output.append(f'G0 Z{str(safe_z)} ')

    return output

def free_part_gcode(
        center: Point3,
        apature: float,
        diameter: float,
        doc: float,
        material_thickness: float,
        safe_z: float,
        feed_z: float,
        feed_xy: float
        ) -> List[str]:

    if not diameter or diameter <= 0:
        return []
    if not doc or doc <= 0:
        return []
    if not material_thickness or material_thickness <= 0:
        return []

    combined_diamiter = apature / 2 + diameter
    output = []
    output.append(f'(Block-name: Free part)')
    output.append(f'G0 Z{str(safe_z)}')
    output.append(f'G0 X{str(center[0] + combined_diamiter)} Y{str(center[1])}')
    output.append(f'F{str(feed_z)}')
    output.append('G1 Z0')
    output.append(f'F{str(feed_xy)}')

    height = 0
    while height > -material_thickness:
        height -= doc
        output.append(
                f'G2 X{str(center[0] + combined_diamiter)} Y{str(center[1])} '
                f'Z{str(height)} '
                f'I{str(-combined_diamiter)} J0.0')

    output.append(
            f'G2 X{str(center[0] + combined_diamiter)} Y{str(center[1])} '
            f'Z{str(-material_thickness)} '
            f'I{str(-combined_diamiter)} J0.0')
    return output

def arcs_to_gcode(
        arcs: List[Arc],
        safe_z: float,
        feed_z: float,
        feed_xy: float
        ) -> Tuple[List[str], Dict[str, int]]:
    output = []
    summary_data = {
            'lowest': None,
            'highest': None,
            }

    if arcs:
        arc = arcs[0]
        output.append(f'(Block-name: Spiral)')
        output.append(f'G0 Z{str(safe_z)}')
        start_point = arc.start_point()
        output.append(f'G0 X{str(start_point[0])} Y{str(start_point[1])}')
        output.append(f'F{str(feed_z)}')
        output.append(f'G1 Z{str(start_point[2])}')
        output.append(f'F{str(feed_xy)}')

        summary_data['highest'] = start_point[2]
        summary_data['lowest'] = start_point[2]

    for arc in arcs:
        start_point = arc.start_point()
        end_point = arc.end_point()
        offset_i = arc.center[0] - start_point[0]
        offset_j = arc.center[1] - start_point[1]
        output.append(
                f'G2 X{str(end_point[0])} Y{str(end_point[1])} Z{str(end_point[2])} '
                f'I{str(offset_i)} J{str(offset_j)}')

        summary_data['highest'] = max(summary_data['highest'], end_point[2])
        summary_data['lowest'] = min(summary_data['lowest'], end_point[2])

    return (output, summary_data)

def write_gcode(gcode_lines: List[str], filename: str) -> None:
    with open(filename, 'w') as f:
        f.write('\n'.join(gcode_lines))

def check_integrity(arcs: List[Arc]) -> None:
    last_point = None
    for arc in arcs:
        print(f'{arc.start_point()}\t{arc.start_angle}\t{arc.end_point()}\t{arc.end_angle}')
        if last_point is not None:
            assert arc.start_point() == last_point
        last_point = arc.end_point()

def args_summary(args) -> None:
    print('Ran with parameters:')
    command_line = f'\t{sys.argv[0]}'
    for key, value in vars(args).items():
        command_line += f' --{key}={value}'
    print(command_line)
    if args.free_part or args.free_part_doc:
        if not args.free_part or not args.free_part_doc or not args.material_thickness:
            print()
            print("  WARNING: If either free_part or free_part_doc is set, "
            "free_part, free_part_doc and material_thickness must all be set.")
            print(f'    free_part: {args.free_part}')
            print(f'    free_part_doc: {args.free_part_doc}')
            print(f'    material_thickness: {args.material_thickness}')

def summary(summary_data, args) -> None:
    print()
    print(f'Highest point: {summary_data["highest"]}')
    print(f'Lowest point:  {summary_data["lowest"]}')
    if summary_data["highest"] >= args.safe_z:
        print('  WARNING: safe_z is lower than highest point on lens.')
    if (args.material_thickness is not None and
            summary_data["highest"] - summary_data['lowest'] >= args.material_thickness):
        print('  WARNING: Lens thicker than material.')
        print(f'    material_thickness: {args.material_thickness}')

def main():
    parser = argparse.ArgumentParser(description='Generate gcode for lens shapes.')
    parser.add_argument(
            '-f',
            '--filename',
            metavar='FILENAME',
            help='output filename',
            default='/tmp/lens.gcode')
    parser.add_argument(
            '-t',
            '--lens_type',
            metavar='TYPE',
            choices=['concave', 'convex'],
            default='convex',
            help='type of lens. Default: convex')
    parser.add_argument(
            '-a',
            '--aperture',
            metavar='APERTURE',
            help='diameter of lens',
            type=float,
            default='100')
    parser.add_argument(
            '-c',
            '--radius_curvature',
            metavar='RADIUS_CURVATURE',
            help='radius curvature of lens. 2 * focal_length.',
            type=float,
            default='500')
    parser.add_argument(
            '-x',
            '--x_offset',
            metavar='X_OFFSET',
            help='offset X coordinate of lens and center of curvature',
            type=float,
            default='0')
    parser.add_argument(
            '-y',
            '--y_offset',
            metavar='Y_OFFSET',
            help='offset Y coordinate of lens and center of curvature',
            type=float,
            default='0')
    parser.add_argument(
            '-z',
            '--z_offset',
            metavar='Z_OFFSET',
            help='offset Z coordinate of center of lens',
            type=float,
            default='0')
    parser.add_argument(
            '-s',
            '--safe_z',
            metavar='SAFE_Z_POS',
            help='safe Z coordinate in gcode',
            type=float,
            default='1')
    parser.add_argument(
            '-fz',
            '--feed_z',
            metavar='Z_FEED_RATE',
            help='Z coordinate gcode feed rate',
            type=float,
            default='200')
    parser.add_argument(
            '-fxy',
            '--feed_xy',
            metavar='XY_FEED_RATE',
            help='X and Y coordinate gcode feed rate',
            type=float,
            default='1000')
    parser.add_argument(
            '-F',
            '--free_part',
            metavar='ADDITIONAL_DIAMETER',
            help=('generate gcode for a final circle to cut the lens free. '
                'This value is added to the --aperture value.')
            ,
            type=float
            )
    parser.add_argument(
            '-D',
            '--free_part_doc',
            metavar='DEPTH_OF_CUT',
            help=('Depth of cut if cutting part free with final circle. '
                'Used with the --free_part parameter.'),
            type=float
            )
    parser.add_argument(
            '-m',
            '--material_thickness',
            metavar='STOCK_MATERIAL_THICKNESS',
            help='thickness of stock. Used with the --free_part parameter.',
            type=float
            )

    args = parser.parse_args()

    if args.lens_type.lower() == 'convex':
        lens_type = LensStyle.CONVEX
    else:
        lens_type = LensStyle.CONCAVE

    args_summary(args)

    arcs = spiral((args.x_offset, args.y_offset), args.aperture, 1)

    center_curvature = (args.x_offset, args.y_offset, -args.radius_curvature)
    spiral_to_lens(arcs, center_curvature, args.radius_curvature, lens_type, args.z_offset)
    #check_integrity(arcs)

    gcode_lines = header_gcode(args.safe_z)
    spiral_gcode, summary_data = arcs_to_gcode(
            arcs, args.safe_z, args.feed_z, args.feed_xy)
    gcode_lines += spiral_gcode
    gcode_lines += free_part_gcode(center_curvature, args.aperture, args.free_part, args.free_part_doc, args.material_thickness, args.safe_z, args.feed_z, args.feed_xy)
    gcode_lines += footer_gcode(args.safe_z)

    write_gcode(gcode_lines, args.filename)

    summary(summary_data, args)

if __name__ == "__main__":
   main()


"""
Name: tabular_input.py

Description:

This demo illustrates creating a Tabular `Input`.
"""
import json

import aqueduct.aqueduct as aq_module

# a guard to make sure we have an Aqueduct instance "aqueduct" in scope
aqueduct: aq_module.Aqueduct
if not globals().get("aqueduct"):
    aqueduct = aq_module.Aqueduct("G", None, None, None)
else:
    aqueduct = globals().get("aqueduct")

print("Input not yet created...")

rows = [
    dict(
        hint=f"Enter an integer value for Param1",
        value=10,
        dtype=int.__name__,
        name=f"Param1"
    ),
    dict(
        hint=f"Enter a float for Param2",
        value=24.1,
        dtype=float.__name__,
        name=f"Param2"
    ),
    dict(
        hint=f"Enter a string for Param3",
        value="a string value",
        dtype=str.__name__,
        name=f"Param3"
    ),
]

# prompt the user to confirm the uploaded csv data looks correct
tabular_ipt = aqueduct.input(
    message="Confirm the uploaded data.",
    input_type="table",
    dtype="str",
    rows=rows,
)

# format the confirmed data (str) into a list and return the list new_rates.
values = json.loads(tabular_ipt.get_value())

# [{'value': 10, 'name': 'Param1'}, {'value': 24.1, 'name': 'Param2'}, {'value': 'a string value', 'name': 'Param3'}]
print(values)

print("Recipe complete...")


import os
import argparse
import json
import torch
import librosa.display
import torchvision.transforms as transforms
import simpleaudio as sa
from dataloaders.image_caption_dataset import ImageCaptionDataset
from davenet_scorer import DaveNetScorer
import cv2
import numpy as np
import matplotlib.animation as anim
import matplotlib.pyplot as plt
import scipy
from PIL import Image

from textwrap import wrap

DAVENET_PATH = "eval_scorers/trained_models/davenet_vgg16_MISA_1024_pretrained/"
DAVENET_AUDIO = os.path.join(DAVENET_PATH, "audio_model.pth")
DAVENET_IMAGE = os.path.join(DAVENET_PATH, "image_model.pth")

def play_audio(audio, sample_rate, bytes_per_sample, wait=True):
    play_obj = sa.play_buffer(audio, 1, bytes_per_sample, sample_rate)
    if wait:
        play_obj.wait_done()

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--dataset", type=str, default="data/PlacesAudioEnglish/samples.json", help="Path to the dataset.")
    parser.add_argument("--model_dir", type=str, default="./eval_scorers/trained_models", help="Path to pretrained models.")
    parser.add_argument("--audio_model", type=str, default=DAVENET_AUDIO, help="Path to the DaveNet audio model.")
    parser.add_argument("--image_model", type=str, default=DAVENET_IMAGE , help="Path to the DaveNet image model.")
    parser.add_argument("--window_size", type=int, default=7, help="Size of the temporal window to conduct smoothing of potential matches.")
    parser.add_argument("--smoothing", type=str, default="max", help="Either max or mean")
    parser.add_argument("--mass_p", type=float, default=0.3, help="The percentage of image mass to retain within a matchup when masking the image.")
    parser.add_argument("--sample_rate", type=int, default=16000, help="Audio sample rate.")
    parser.add_argument("--device", type=str, default="cpu", help="Either cuda or cpu.")
    parser.add_argument("--outdir", type=str, default="./scores", help="Output dir for plots, reports, etc.")
    args = parser.parse_args()

    if not os.path.isdir(args.outdir):
        os.makedirs(args.outdir)

    smoothing_fn = None
    if args.smoothing == "max":
        smoothing_fn = np.max
    elif args.smoothing == "mean":
        smoothing_fn = np.mean
    else:
        print("Defaulting to max smoothing...")
        smoothing_fn = np.max

    # Load DaveNet
    dave_scorer = DaveNetScorer(args.audio_model, args.image_model)

    # Dataset
    audio_conf = {"use_raw_length": False}
    dataset = ImageCaptionDataset(args.dataset, audio_conf=audio_conf, normalize=False)
    data_key = {x["wav"]:x for x in dataset.data}
    loader = torch.utils.data.DataLoader(dataset, num_workers=8, batch_size=1)

    for img, audio, p, wavpath in loader:
        l = data_key[wavpath[0][wavpath[0].find("wavs"):]]
        uid = l["uttid"]
        asr_text = l["asr_text"]

        if uid != "A2WQT33K6LD9Z5-GSUN_3B1FB5BDCB2390BFB13047C583E9F82A":
            continue

        wav, _ = librosa.load(wavpath[0], args.sample_rate)

        heatmap, _, _, _, _ = dave_scorer.score(audio.squeeze(0), img.squeeze(0))
        N_t, N_r, N_c = heatmap.shape

        temporal_heatmap = heatmap.reshape((N_t, N_r * N_c))
        smoothed_heatmap = np.zeros(temporal_heatmap.shape)

        for i in range(0, N_t - args.window_size):
          smoothed_heatmap[i, :] = np.max(temporal_heatmap[i: i + args.window_size, :], axis = 0)

        # Normalize Matches
        total_mass = np.sum(smoothed_heatmap)
        matchmap = smoothed_heatmap / total_mass

        # Sort cells
        N = N_t * N_r * N_c
        matchmap = matchmap.reshape(N)
        sorted_cells = np.argsort(matchmap)

        # Retain only cells accounting for mass_p percent of the total density in the image
        mass_thresh = args.mass_p * np.sum(matchmap)
        sum_mass = 0.0
        for i in range(N - 1, -1, -1):
            idx = sorted_cells[i]
            if (matchmap[idx] + sum_mass) <= mass_thresh:
                sum_mass += matchmap[idx]

            else:
                matchmap[idx] = 0.0

        matchmap = matchmap.reshape((N_t, N_r, N_c))
        img_t = np.transpose(img.squeeze(0).numpy(), [1, 2, 0])
        wav_duration = librosa.get_duration(wav, sr=args.sample_rate)
        time_step = wav_duration / (N_t)
        max_val = np.max(matchmap)

        # Play Audio While Plotting
        play_audio(wav, args.sample_rate, 4, wait=False)

        # Animate plot
        for i in range(0, (N_t - args.window_size)):
            f, ax = plt.subplots(3, 1, figsize = (5, 10), gridspec_kw={'height_ratios': [2, 2, 1]})
            title = "\n".join(wrap("%s: %s" % (uid, asr_text), 40))
            f.suptitle(title)
            ax[0].imshow(img_t, aspect='auto')

            # Filter to matchmap at this time step
            full_matchmap = np.array(Image.fromarray(matchmap[i, :, :]).resize((img_t.shape[0], img_t.shape[1])))

            # Trying to remove vmin and vmax helps make it clearer to see changes through time.
            ax[1].imshow(full_matchmap, aspect='auto', vmin=0.0, vmax=max_val)
            ax[0].get_shared_x_axes().join(ax[0], ax[1])
            librosa.display.waveplot(wav, sr=args.sample_rate, ax=ax[2])
            ax[2].axvline(i * time_step, linewidth=2, color='k', linestyle='dashed')
            plt.savefig(args.outdir + "/%s_%d.jpg" % (uid, i))
            plt.close()

        break

if __name__ == "__main__":
    main()


def extract(name):
    file = open(name,'r')
    text = file.readlines()
    for i in range(len(text)) :
        text[i] = text[i].strip('\n')
    for i in range(1,len(text)):
        text[i] = (text[i][0],int(text[i][-1]))
    text.pop(0)
    reverse_text = reverseTuple(text)
    return reverse_text

def reverseTuple(lstOfTuple):
    return [tup[::-1] for tup in lstOfTuple]


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import numpy as np
import tensorflow as tf

from tensorflow.contrib.rnn import RNNCell

class DCGRUCell(RNNCell):
    """Graph Convolution Gated Recurrent Unit cell.
    """

    def call(self, inputs, **kwargs):
        pass

    def compute_output_shape(self, input_shape):
        pass

    def __init__(self, num_units, input_dim, num_graphs, supports, max_diffusion_step, num_node, num_proj=None,
                 activation=tf.nn.tanh, reuse=None, use_gc_for_ru=True, name=None):
        """

        :param num_units:
        :param adj_mx:
        :param max_diffusion_step:
        :param num_node:
        :param input_size:
        :param num_proj:
        :param activation:
        :param reuse:
        :param filter_type: "laplacian", "random_walk", "dual_random_walk".
        :param use_gc_for_ru: whether to use Graph convolution to calculate the reset and update gates.
        """
        super(DCGRUCell, self).__init__(_reuse=reuse)
        self._activation = activation
        self._num_node = num_node
        self._input_dim = input_dim
        self._num_graphs = num_graphs
        self._num_proj = num_proj
        self._num_units = num_units
        self._max_diffusion_step = max_diffusion_step
        self._use_gc_for_ru = use_gc_for_ru
        self._supports = supports
        self._num_diff_matrix = supports.get_shape()[0].value
        self._name = name

    @property
    def state_size(self):
        return self._num_node * self._num_units

    @property
    def output_size(self):
        output_size = self._num_node * self._num_units
        if self._num_proj is not None:
            output_size = self._num_node * self._num_proj
        return output_size

    def __call__(self, inputs, state, scope=None):
        """Gated recurrent unit (GRU) with Graph Convolution.
        :param inputs: (B, num_node * input_dim)

        :return
        - Output: A `2-D` tensor with shape `[batch_size x self.output_size]`.
        - New state: Either a single `2-D` tensor, or a tuple of tensors matching
            the arity and shapes of `state`
        """
        with tf.variable_scope(scope or "dcgru_cell"):
            with tf.variable_scope("gates"):  # Reset gate and update gate.
                output_size = 2 * self._num_units
                # We start with bias of 1.0 to not reset and not update.
                if self._use_gc_for_ru:
                    fn = self._gconv
                else:
                    fn = self._fc
                value = tf.nn.sigmoid(fn(inputs, state, output_size, bias_start=1.0))
                value = tf.reshape(value, (-1, self._num_node, output_size))
                r, u = tf.split(value=value, num_or_size_splits=2, axis=-1)
                r = tf.reshape(r, (-1, self._num_node * self._num_units))
                u = tf.reshape(u, (-1, self._num_node * self._num_units))
            with tf.variable_scope("candidate"):
                c = self._gconv(inputs, r * state, self._num_units)
                if self._activation is not None:
                    c = self._activation(c)
            output = new_state = u * state + (1 - u) * c
            if self._num_proj is not None:
                with tf.variable_scope("projection"):
                    w = tf.get_variable('w', shape=(self._num_units, self._num_proj))
                    output = tf.reshape(new_state, shape=(-1, self._num_units))
                    output = tf.reshape(tf.matmul(output, w), shape=(-1, self.output_size))
        return output, new_state

    @staticmethod
    def _concat(x, x_):
        x_ = tf.expand_dims(x_, 0)
        return tf.concat([x, x_], axis=0)

    def _fc(self, inputs, state, output_size, bias_start=0.0):
        dtype = inputs.dtype
        batch_size = inputs.get_shape()[0].value
        inputs = tf.reshape(inputs, (batch_size * self._num_node, -1))
        state = tf.reshape(state, (batch_size * self._num_node, -1))
        inputs_and_state = tf.concat([inputs, state], axis=-1)
        input_size = inputs_and_state.get_shape()[-1].value
        weights = tf.get_variable(
            'weights', [input_size, output_size], dtype=dtype,
            initializer=tf.contrib.layers.xavier_initializer())
        value = tf.nn.sigmoid(tf.matmul(inputs_and_state, weights))
        biases = tf.get_variable("biases", [output_size], dtype=dtype,
                                 initializer=tf.constant_initializer(bias_start, dtype=dtype))
        value = tf.nn.bias_add(value, biases)
        return value

    def _gconv(self, inputs, state, output_size, bias_start=0.0):
        """Graph convolution between input and the graph matrix.

        :param args: a 2D Tensor or a list of 2D, batch x n, Tensors.
        :param output_size:
        :param bias:
        :param bias_start:
        :param scope:
        :return:
        """
        # Reshape input and state to (batch_size, num_node, input_dim/state_dim)
        last_dim = inputs.get_shape()[-1].value
        inputs = tf.reshape(inputs, (-1, self._num_node, int(last_dim / self._num_node)))
        state = tf.reshape(state, (-1, self._num_node, self._num_units))
        inputs_and_state = tf.concat([inputs, state], axis=2)
        input_size = inputs_and_state.get_shape()[2].value
        dtype = inputs.dtype

        x = inputs_and_state
        x0 = tf.transpose(x, perm=[1, 2, 0])  # (num_node, total_arg_size, batch_size)
        x0 = tf.reshape(x0, shape=[self._num_node, -1])
        x = tf.expand_dims(x0, axis=0)

        scope = tf.get_variable_scope()
        with tf.variable_scope(scope.name + (self.name or ''), reuse=False):
            if self._max_diffusion_step == 0:
                pass
            else:
                for index in range(self._num_diff_matrix):
                    x1 = tf.matmul(self._supports[index], x0)
                    x = self._concat(x, x1)

                    for k in range(2, self._max_diffusion_step + 1):
                        x2 = 2 * tf.matmul(self._supports[index], x1) - x0
                        x = self._concat(x, x2)
                        x1, x0 = x2, x1

            num_matrices = self._num_diff_matrix * self._max_diffusion_step + 1  # Adds for x itself.
            x = tf.reshape(x, shape=[num_matrices, self._num_node, input_size, -1])
            x = tf.transpose(x, perm=[3, 1, 2, 0])  # (batch_size, num_node, input_size, order)
            x = tf.reshape(x, shape=[-1, input_size * num_matrices])

            weights = tf.get_variable(
                'weights', [input_size * num_matrices, output_size], dtype=dtype,
                initializer=tf.contrib.layers.xavier_initializer())
            x = tf.matmul(x, weights)  # (batch_size * self._num_node, output_size)

            biases = tf.get_variable("biases", [output_size], dtype=dtype,
                                     initializer=tf.constant_initializer(bias_start, dtype=dtype))
            x = tf.nn.bias_add(x, biases)
        # Reshape res back to 2D: (batch_size, num_node, state_dim) -> (batch_size, num_node * state_dim)
        return tf.reshape(x, [-1, self._num_node * output_size])


import os
import sys
import random
from PIL import Image
from torch.utils.data import DataLoader, Dataset
from torchvision.transforms import transforms

'''
    Source Dataset : GTA5 (labeled)
    Target Dataset : bdd100k (unlabeled)
    Resize datasets into (1024, 576) size
'''

class ImageDataset(Dataset):
    def __init__(self, root_dir, S_transform, T_transform, fixed_pair=False, mode='train'):
        '''
            root_dir : Dataset directory
            fixed_pair : Source dataset과 Target dataset의 pair가 fixed하지 않도록 randomize
            혹시 모를 경우를 대비해서 확장자 확인
        '''
        S_image_path = os.path.join(root_dir, mode, 'Source', 'img')
        S_label_path = os.path.join(root_dir, mode, 'Source', 'label')
        T_image_path = os.path.join(root_dir, mode, 'Target', 'img')
        T_label_path = os.path.join(root_dir, mode, 'Target', 'label')

        self.S_imgnames = sorted(os.listdir(S_image_path))
        self.T_imgnames = sorted(os.listdir(T_image_path))
        self.S_imgnames = [os.path.join(S_image_path, f) for f in self.S_imgnames if f.endswith('.png')]
        self.T_imgnames = [os.path.join(T_image_path, f) for f in self.T_imgnames if f.endswith('.jpg')]

        # 상응하는 label path도 parsing 할 것 --> for segmentation

        self.fixed_pair = fixed_pair
        self.S_size = len(self.S_imgnames)
        self.T_size = len(self.T_imgnames)
        self.S_transform = S_transform
        self.T_transform = T_transform

    def __len__(self): # 두 데이터 셋의 크기가 다를 수 있으므로 max
        return max(self.S_size, self.T_size)

    def __getitem__(self, idx):
        S_img = self.S_transform(Image.open(self.S_imgnames[idx%self.S_size]))
        # S_label = self.S_label[idx%self.S_size]

        if self.fixed_pair:
            T_img = self.T_transform(Image.open(self.T_imgnames[idx%self.T_size]))
            # T_label = self.T_label[idx%self.T_size]
        else:
            T_img = self.T_transform(Image.open(self.T_imgnames[random.randint(0, self.T_size-1)]))
            # T_label = self.T_label[random.randint(0, self.T_size-1)]

        return {'S_img': S_img, 'T_img': T_img}  # 'S_label': S_label, 'T_label': T_label

def get_transformer(H, W):
    '''
        transforms.ToTensor() --> Tensor의 범위가 [0, 1]
        transfroms.Normarlize((0.5, ), (0.5, ))는 [0, 1] --> [-1, 1]로 변환
    '''

    S_transformer = transforms.Compose([
        transforms.Resize((H, W)),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) # (mean), (std) --> 0 에서 1사이로 normalize
    ])

    T_transformer = transforms.Compose([
        transforms.Resize((H, W)),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
    ])
    return S_transformer, T_transformer

def get_dataloaders(types, params):
    dataloaders = {}

    S_transformer, T_transformer = get_transformer(params.resize_H, params.resize_W)
    for option in ['train', 'val', 'test']:
        if option in types:
            data_loader = DataLoader(ImageDataset(params.root_dir, S_transformer, T_transformer,
                                                  params.fixed_pair,mode=option),
                                     batch_size=params.batch_size, shuffle=True,
                                     num_workers=params.num_workers, pin_memory=params.cuda)
            dataloaders[option] = data_loader

    return dataloaders


from source.database.db_connect import mydb
from variables.path import path_dir

myCursor = mydb.cursor()

def select_everything():
    location = path_dir + 'select_everything.sql'

    with open(location, 'r') as file:
        query = file.read()
        file.close()
    try:
        myCursor.execute(query)
        for i in myCursor:
            print(i)
        return 'Success'
    except Exception as e:
        print(e)

select_everything()


'''
Thoughts:

Iterate the tokens:
If token is a number, push it to the stack
If token is an operator, pop the top two numbers, perform calculation and push the result back to the stack
Pop the last element when the iteration ends
If stack is empty, RPN is valid, return the final result

Be careful '-X'.isdigit() returns False
use try and except instead

'''

class Solution:
	def evalRPN(self, tokens):
		stack = []
		for t in tokens:
			try:
				stack.append(int(t))
			except:
				num2 = stack.pop()
				num1 = stack.pop()
				if t == '+':
					num = num1 + num2
				elif t == '-':
					num = num1 - num2
				elif t == '*':
					num = num1 * num2
				else:
					if num1 * num2 > 0:
						sign = 1
					else:
						sign = -1
					num = abs(num1) // abs(num2) * sign
				stack.append(num)
		res = stack.pop()
		if not stack:
			return res

tokens = ["2", "1", "+", "3", "*"]
tokens = ["4", "13", "5", "/", "+"]
tokens = ["3", "-4", "+"]
tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]

inst = Solution()
print(inst.evalRPN(tokens))

Q424 Evaluate Reverse Polish Notation.py


from abc import abstractmethod
from typing import Callable
from src.Model.PropositionalExpressionTree import Expr, Not, And, Impl, Or, Eq
import copy

false_exprs = "false"
true_exprs = "true"
false_atoms = "false_atoms"
true_atoms = "true_atoms"
false_processed = "false_processed"
true_processed = "true_processed"
processed_true_impls = "processed_true_impls"
processed_true_quantor_expressions = "processed_true_quantor_expressions"
processed_false_quantor_expressions = "processed_false_quantor_expressions"
established_constants = "established_constants"
established_functions = "established_functions"
variable_constant_mapping = "variable_constant_mapping"
certain_falsehood_exprs = "certain_falsehood_exprs"
certain_falsehood_processed = "certain_falsehood_processed"
certain_falsehood_atoms = "certain_falsehood_atoms"
processed_certain_false_exquantor_exprs = "processed_certain_false_exquantor_exprs"
processed_certain_false_allquantor_exprs = "processed_certain_false_allquantor_exprs"

class BaseTableauxBuilder:
    visiting_false = True
    visiting_certain_falsehood_exprs = False

    left_side_sign = "T"
    right_side_sign = "F"

    last_multiprocess_cf = None
    last_multiprocess_false = None
    last_multiprocess_true = None
    clears_false_exprs = False

    function_depth = 0

    def __init__(self, sequent: dict = None, **kwargs):
        self.visit_idx = kwargs.get('visit_idx', 0)
        self.constant_idx = kwargs.get('constant_idx', 0)
        if sequent is not None:
            self.sequent = sequent
        else:
            self.sequent = {
                false_exprs: [ex for ex in kwargs.get('false_exprs', []) if not ex.is_atom],
                true_exprs: [ex for ex in kwargs.get('true_exprs', []) if not ex.is_atom],
                false_atoms: [at for at in kwargs.get('false_exprs', []) if at.is_atom],
                true_atoms: [at for at in kwargs.get('true_exprs', []) if at.is_atom],
                false_processed: kwargs.get('false_processed', []),
                true_processed: kwargs.get('true_processed', []),
                certain_falsehood_exprs: kwargs.get('cf_exprs', []),
                certain_falsehood_atoms: [],
                certain_falsehood_processed: [],
                processed_true_impls: dict(),
                processed_true_quantor_expressions: dict(),
                processed_false_quantor_expressions: dict(),
                processed_certain_false_exquantor_exprs: dict(),
                processed_certain_false_allquantor_exprs: dict(),
                established_constants: kwargs.get('constants', []),
                established_functions: kwargs.get('functions', []),
                variable_constant_mapping: dict(),
            }
        self.children = []
        self.parent = kwargs.get('parent')

    def auto_resolve(self, debug=False, max_steps=1000):
        while not self.is_done():
            max_steps -= 1
            if max_steps <= 0:
                raise RuntimeError('Max calculation steps reached')
            if debug:
                print(max_steps)
            if len(self.children) > 0:
                for child in self.children:
                    child.auto_resolve(debug, max_steps)
                return

            # Options Tuple (Priority, False_Side, Expression)
            options = [(expr.priority(False), True, expr) for expr in self.sequent[false_exprs]]
            options.extend([(expr.priority(True), False, expr) for expr in self.sequent[true_exprs]])
            options.sort(key=lambda tpl: tpl[0])

            if len(options) == 0:
                self.process_multiprocess_exprs()
                continue

            self.visiting_certain_falsehood_exprs = False
            self.visit_expr(options[0][1], options[0][2])

    def visit_expr(self, false_side, expr):
        self.visiting_false = false_side
        expr.visit(self)
        side = self.get_expr_side()
        processed_side = self.get_processed_side()
        partially_processed_side = processed_false_quantor_expressions if false_side else processed_true_quantor_expressions
        last = self.last_multiprocess_false if false_side else self.last_multiprocess_true
        last = self.last_multiprocess_cf if self.visiting_certain_falsehood_exprs else last
        if expr == last and expr in self.sequent[side]:
            # if expr is a partially processed, only remove it from exprs and add to partially processed
            self.sequent[side].remove(expr)
            if self.parent is not None:
                self.parent.add_multiprocess(side, partially_processed_side, expr)
        elif expr in self.sequent[side]:
            self.add_processed(side, processed_side, expr)

    def add_processed(self, side, processed_side, expr):
        if expr in self.sequent[side]:
            self.sequent[side].remove(expr)
            self.sequent[processed_side].append(expr)

            if self.parent is not None:
                self.parent.add_processed(side, processed_side, expr)

    def add_multiprocess(self, side, m_p_side, expr):
        if expr in self.sequent[side]:
            self.sequent[side].remove(expr)
            if expr not in self.sequent[m_p_side]:
                self.sequent[m_p_side][expr] = []

            if self.parent is not None:
                self.parent.add_multiprocess(side, m_p_side, expr)

    def create_copy(self, remove_false=None, remove_true=None, clears_false_exprs=False):
        cpy = type(self)(sequent=copy.deepcopy(self.sequent),
                         parent=self,
                         visit_idx=self.visit_idx+1,
                         constant_idx=self.constant_idx)
        cpy.sequent[true_processed] = list()
        cpy.sequent[false_processed] = list()
        cpy.sequent[certain_falsehood_processed] = list()

        if remove_false is not None and remove_false in cpy.sequent[false_exprs]:
            cpy.sequent[false_exprs].remove(remove_false)
        if remove_true is not None and remove_true in cpy.sequent[true_exprs]:
            cpy.sequent[true_exprs].remove(remove_true)

        if clears_false_exprs:
            cpy.parent = None
            cpy.clears_false_exprs = True
            cpy.sequent[false_exprs] = []
            cpy.sequent[false_atoms] = []
            cpy.sequent[processed_false_quantor_expressions] = dict()
            for x in cpy.sequent[processed_certain_false_allquantor_exprs]:
                cpy.sequent[processed_certain_false_allquantor_exprs][x] = []
            for x in cpy.sequent[processed_certain_false_exquantor_exprs]:
                cpy.sequent[processed_certain_false_exquantor_exprs][x] = []

        return cpy

    def add_to(self, side: str, expr: Expr, always_index=False):
        self.sequent[side].append(expr)

        if side not in [true_atoms, false_atoms] or always_index:
            expr.visit_idx = self.visit_idx
            self.visit_idx += 1

    def get_expr_side(self):
        if self.visiting_certain_falsehood_exprs:
            return certain_falsehood_exprs
        return false_exprs if self.visiting_false else true_exprs

    def get_processed_side(self):
        if self.visiting_certain_falsehood_exprs:
            return certain_falsehood_processed
        return false_processed if self.visiting_false else true_processed

    def get_atom_side(self):
        if self.visiting_certain_falsehood_exprs:
            return certain_falsehood_atoms
        else:
            return false_atoms if self.visiting_false else true_atoms

    @abstractmethod
    def is_done(self) -> bool:
        pass

    @abstractmethod
    def process_multiprocess_exprs(self) -> bool:
        pass

    def is_closed(self):
        if len(self.children) == 0:
            for true_atom in self.sequent[true_atoms]:
                if true_atom in self.sequent[false_atoms] or true_atom in self.sequent[certain_falsehood_atoms]:
                    return True
        else:
            for child in self.children:
                if not child.is_closed():
                    return False
            return True
        return False

    def visit(self):
        if len(self.children) > 0:
            for child in self.children:
                if not child.is_done():
                    child.visit()
                    return
            return
        if len(self.sequent[false_exprs]) > 0:
            self.visiting_false = True
            expr = self.sequent[false_exprs][-1]
            expr.visit(self)
            self.sequent[false_exprs].remove(expr)
        else:
            self.visiting_false = False
            expr = self.sequent[true_exprs][-1]
            expr.visit(self)
            self.sequent[true_exprs].remove(expr)

    def visited_Not(self, n: Not):
        self.add_to(true_exprs if self.visiting_false else false_exprs, n.expr)

    def visited_And(self, a: And):
        if self.visiting_false:
            # Create new fork -> Children of same TableauxBuilder type as self
            lhs = self.create_copy(remove_false=a)
            rhs = self.create_copy(remove_false=a)
            lhs.add_to(false_exprs, a.lhs)
            rhs.add_to(false_exprs, a.rhs)
            self.children.append(lhs)
            self.children.append(rhs)
        else:
            self.add_to(true_exprs, a.lhs)
            self.add_to(true_exprs, a.rhs)

    def visited_Or(self, o: Or):
        if self.visiting_false:
            self.add_to(false_exprs, o.lhs)
            self.add_to(false_exprs, o.rhs)
        else:
            # Create new fork -> Children of same TableauxBuilder type as self
            lhs = self.create_copy(remove_true=o)
            rhs = self.create_copy(remove_true=o)
            lhs.add_to(true_exprs, o.lhs)
            rhs.add_to(true_exprs, o.rhs)
            self.children.append(lhs)
            self.children.append(rhs)

    def visited_Impl(self, impl: Impl):
        if self.visiting_false:
            self.add_to(true_exprs, impl.lhs)
            self.add_to(false_exprs, impl.rhs)
        else:
            # Create new fork -> Children of same TableauxBuilder type as self
            lhs = self.create_copy(remove_true=impl)
            rhs = self.create_copy(remove_true=impl)
            lhs.add_to(false_exprs, impl.lhs)
            rhs.add_to(true_exprs, impl.rhs)
            self.children.append(lhs)
            self.children.append(rhs)

    def visited_Eq(self, eq: Eq):
        if self.visiting_false:
            # Create new fork -> Children of same TableauxBuilder type as self
            lhs = self.create_copy(remove_false=eq)
            rhs = self.create_copy(remove_false=eq)

            lhs.add_to(false_exprs, eq.lhs)
            lhs.add_to(true_exprs, eq.rhs)

            rhs.add_to(true_exprs, eq.lhs)
            rhs.add_to(false_exprs, eq.rhs)
            self.children.append(lhs)
            self.children.append(rhs)
        else:
            # Create new fork -> Children of same TableauxBuilder type as self
            lhs = self.create_copy(remove_true=eq)
            rhs = self.create_copy(remove_true=eq)

            lhs.add_to(true_exprs, eq.lhs)
            lhs.add_to(true_exprs, eq.rhs)

            rhs.add_to(false_exprs, eq.lhs)
            rhs.add_to(false_exprs, eq.rhs)

            self.children.append(lhs)
            self.children.append(rhs)

    def merge(self, other_tableau):
        if self.is_closed():
            return

        if len(self.children) > 0:
            for child in self.children:
                if not child.clears_false_exprs:
                    child.merge(other_tableau)
            return

        if len(other_tableau.children) > 0:
            for child in other_tableau.children:
                cpy = self.create_copy(clears_false_exprs=child.clears_false_exprs)
                cpy._merge_sequents(child.sequent)
                self.children.append(cpy)
        elif other_tableau.clears_false_exprs:
            cpy = self.create_copy(clears_false_exprs=True)
            cpy._merge_sequents(other_tableau.sequent)
            self.children.append(cpy)
        else:
            self._merge_sequents(other_tableau.sequent)
            self._add_constants(other_tableau.sequent[established_constants])

    def _merge_sequents(self, other_sequent: dict):
        add_list = []
        for exprs, atoms in [
            (false_exprs, false_atoms),
            (true_exprs, true_atoms),
            (certain_falsehood_exprs, certain_falsehood_atoms),
        ]:
            for other in other_sequent[exprs]:
                if other.is_atom:
                    add_list.append((other.visit_idx, other, atoms))
                else:
                    add_list.append((other.visit_idx, other, exprs))

        add_list.sort(key=lambda x: x[0])
        for idx, expr, side in add_list:
            self.add_to(side, expr, True)

        # merge mutliprocessed exprs
        for exprs in [processed_true_quantor_expressions, processed_false_quantor_expressions,
                        processed_certain_false_allquantor_exprs, processed_certain_false_exquantor_exprs,
                        processed_true_impls]:
            for other in other_sequent[exprs]:
                if other not in self.sequent[exprs]:
                    self.sequent[exprs][other] = other_sequent[exprs][other]
                else:
                    if exprs in [processed_certain_false_allquantor_exprs, processed_true_impls]:
                        self.sequent[exprs][other] += other_sequent[exprs][other]
                    else:
                        for x in other_sequent[exprs]:
                            if x not in self.sequent[exprs][other]:
                                self.sequent[exprs][other].append(x)

    def _add_constants(self, constants):
        # merge constants
        for const in constants:
            if const not in self.sequent[established_constants]:
                self.sequent[established_constants].append(const)

        if self.parent is not None:
            self.parent._add_constants(constants)

    def get_drawn_width(self, get_width_from_str: Callable[[str], int],
                        margin: int, partially_in_trees=False) -> (int, int):
        """
        Calculates the width of this Tableau Branch
        """
        t, f, cf = self.get_all_exprs(partially_in_trees)
        max_expr_width_left = max(
                                [get_width_from_str(str(expr))
                                    for expr in t],
                                default=0)

        max_expr_width_right = max(
                                [get_width_from_str(str(expr))
                                    for expr in f],
                                default=0)
        max_expr_width_cf = max(
                                [get_width_from_str(f"[{str(expr)}]")
                                    for expr in cf],
                                default=0)
        max_expr_width_right = max(max_expr_width_right, max_expr_width_cf)

        if len(self.children) == 0:
            return (max_expr_width_left, max_expr_width_right)

        if len(self.children) == 1:
            width_l, width_r = self.children[0].get_drawn_width(
                                                    get_width_from_str,
                                                    margin, partially_in_trees)
            w_l = max(width_l, max_expr_width_left)
            w_r = max(width_r, max_expr_width_right)

            return (w_l + margin, w_r + margin)

        left_child_width = self.children[0].get_drawn_width(
                                                    get_width_from_str,
                                                    margin, partially_in_trees)
        right_child_width = self.children[1].get_drawn_width(
                                                    get_width_from_str,
                                                    margin, partially_in_trees)

        width_left = max([sum(left_child_width), max_expr_width_left])
        width_right = max([sum(right_child_width), max_expr_width_right])

        return (width_left + margin, width_right + margin)

    def get_all_exprs(self, partially_in_trees=False) -> (list, list, list):
        """
        Returns all expressions left and right in the tableau
        """
        exprs = (list(), list(), list())
        for fun in [
                    self.get_processed_exprs,
                    self.get_atom_exprs,
                    self.get_unprocessed_exprs,
                    self.get_partially_processed_exprs,
                    ]:
            tmp = fun(partially_in_trees)
            exprs[0].extend(tmp[0])
            exprs[1].extend(tmp[1])
            exprs[2].extend(tmp[2])
        return exprs

    def get_processed_exprs(self, *args):
        """
        Returns all fully processed expressions
        """
        return (
            self.sequent[true_processed],
            self.sequent[false_processed],
            self.sequent[certain_falsehood_processed],)

    def get_partially_processed_exprs(self, partially_in_trees=False):
        """
        Returns all partially unprocessed expressions that are not
        partially unprocessed in parent
        """
        return ([], [], [])

    def get_atom_exprs(self, *args):
        """
        Returns all atoms not in the parent tableau
        """
        true_atoms_parent = len(self.parent.sequent[true_atoms]) if self.parent else 0
        false_atoms_parent = len(self.parent.sequent[false_atoms]) if self.parent else 0
        cf_atoms_parent = len(self.parent.sequent[certain_falsehood_atoms]) if self.parent else 0

        return  (
            self.sequent[true_atoms][true_atoms_parent:],
            self.sequent[false_atoms][false_atoms_parent:],
            self.sequent[certain_falsehood_atoms][cf_atoms_parent:],)

    def get_unprocessed_exprs(self, *args):
        """
        Returns all unprocessed expressions that are not unprocessed in parent
        """
        true_parent = len(self.parent.sequent[true_exprs]) if self.parent else 0
        false_parent = len(self.parent.sequent[false_exprs]) if self.parent else 0
        cf_parent = len(self.parent.sequent[certain_falsehood_exprs]) if self.parent else 0

        return (
            self.sequent[true_exprs][true_parent:],
            self.sequent[false_exprs][false_parent:],
            self.sequent[certain_falsehood_exprs][cf_parent:],)


#pip install konlpy 하시면 됩니다
#https://github.com/ssut/py-hanspell
#노션-ASAP프로젝트-GPT 안에 DataSet 아래에 kkma-2.0.zip 다운 받고 압축 해제하면 kkma-2.0.jar 나옴
#......\Lib\site-packages\konlpy\java 파일 들어가면 kkma-2.0.jar 있는데 압축 해제한거로 대체하면 단어 인식 훨씬 잘해줌
from hanspell import spell_checker
from konlpy.tag import Kkma
import re

class Konlp():
    def __init__(self):
        self.kkma = Kkma()

    # 바꿀 단어들을 사전 형태로 정의
        self.replacements = {
            "알러지": "알레르기",
            "슈레드치즈": "슈레디드치즈",
            "모짜렐라치즈":"슈레디드치즈",
            "강판치즈":"슈레디드치즈",
            "마늘칩":"마늘",
            "열량":"칼로리",
            "헤ㄹ로디아블로와푸어":"헬로디아블로와퍼",
            "헤ㄹ로릴리트와푸어":"헬로릴리트와퍼",
            "헤ㄹ로이나리우스와푸어":"헬로이나리우스와퍼",
            "몬스터엑스":"몬스터X",
            "블랙바비큐와푸어":"블랙바비큐와퍼",
            "비프앤슈림프버거":"비프&슈림프버거",
            "하어쉬브라운":"해쉬브라운",
            "치즈스틱":"21치즈스틱",
            "얼니얼ㄴ링":"어니언링",
            "크리미모짜아보ㄹ":"크리미모짜볼",
            "코우리스ㄹ로":"코울슬로",
            "굽ㄴ갈릭시즈닝":"구운갈릭시즈닝",
            "스윗얼니얼ㄴ시즈닝":"스윗어니언시즈닝",
            "망고서ㄴ데":"망고선데",
            "초코망고서ㄴ데":"초코망고선데",
            "아이스아아메리카노":"아이스아메리카노",
            "순수":"순수(미네랄워터)",
            "하ㄹ라피뇨":"할라피뇨",
            "비엘티":"BLT",
            "비앨티":"BLT",
            "헤ㄹ로":"헬로",
            "와푸어":"와퍼",
            "오아푸어":"와퍼",
            "망고설ㄴ데":"망고선데",
            "굽ㄴ갈릭":"구운갈릭"
            # 다른 단어들도 필요하다면 추가로 정의할 수 있습니다.
        }

        self.queryName = {'헬로디아블로와퍼':'헬로_디아블로_와퍼', '헬로릴리트와퍼':'헬로_릴리트_와퍼','헬로이나리우스와퍼':'헬로_이나리우스_와퍼',
                    '구운갈릭시즈닝':'구운갈릭_시즈닝', '스윗어니언시즈닝':'스윗어니언_시즈닝','매콤치즈시즈닝':'매콤치즈_시즈닝',
                    '망고선데':'망고_선데','초코망고선데':'초코_망고_선데','컵망고아이스크림':'컵_망고_아이스크림','코카콜라제로':'코카콜라_제로',
                    '스프라이트제로':'스프라이트_제로','미닛메이드오렌지':'미닛메이드_오렌지','아이스아메리카노':'아이스_아메리카노'}

        self.toQ = {'칼로리': 'N_calories','포화지방': 'N_saturated_fat','단백질': 'N_protein','당': 'N_sugars','설탕': 'N_sugars','나트륨': 'N_sodium','카페인':'N_caffeine',
                    '우유알레르기': 'A_milk','치킨알레르기': 'A_Chicken','돼지고기알레르기': 'A_pork','돼지알레르기': 'A_pork','소고기알레르기': 'A_beef','소알레르기':'A_beef',
                    '비프알레르기': 'A_beef','계란알레르기': 'A_egg','달걀알레르기': 'A_egg','오징어알레르기': 'A_squid','토마토알레르기': 'A_tomato',
                    '조개알레르기': 'A_clam','새우알레르기': 'A_shrimp','갑각류알레르기': 'A_clam A_shrimp','치즈': 'or I_sliced_cheese I_shredded_cheese','슬라이스치즈': 'I_sliced_cheese','슈레디드치즈': 'I_shredded_cheese',
                    '피클': 'I_pickle','할라피뇨': 'I_jalapeno','통새우': 'I_whole_shrimp','베이컨': 'I_bacon','양상추': 'I_lettuce','양파': 'I_onion','해쉬브라운': 'I_hashbrown',
                    '토마토': 'I_tomato','마늘': 'I_garlic_chip','마늘칩': 'I_garlic_chip','마요': 'S_mayo','마요네즈': 'S_mayo','마요네즈소스': 'S_mayo','불고기': 'S_bulgogi',
                    '불고기소스': 'S_bulgogi','바베큐': 'S_barbecue','바베큐소스': 'S_barbecue','케찹': 'S_ketchup','케찹소스': 'S_ketchup','디아블로': 'S_diablo',
                    '디아블로소스': 'S_diablo','매운토마토': 'S_spicy_tomato','매운토마토소스': 'S_spicy_tomato','매운': 'S_diablo S_spicy_tomato','치즈소스': 'S_cheese','타르타르': 'S_tartar',
                    '타르타르소스': 'S_tartar','베이컨잼': 'S_baconjam','베이컨잼소스': 'S_baconjam','머스타드': 'S_mustard','머스타드소스': 'S_mustard',
                    '소고기': 'or P_beef P_steak','비프': 'P_beef','새우': 'P_shrimp','쉬림프': 'P_shrimp','슈림프': 'P_shrimp','치킨': 'P_chicken','닭': 'P_chicken','스테이크': 'P_steak',
                    '알레르기':'a', '영양소':'n', '영양성분':'n', '가격':'price','정보':'info','상세정보':'info','맵기':'spicy',
                    '햄버거':'M','버거':'M','아침':'M','점심':'M','저녁':'M','메뉴':'M','음식':'M','끼니':'M','배고프':'M','드시':'M','먹':'M',
                    '사이드':'S','디저트':'DD','음료수':'DD','아이스크림':'DD','높':'desc','낮':'asc','많':'desc','적':'asc','차갑':'ice','차':'ice',
                    '시원':'ice','따시':'hot','따듯':'hot','뜨겁':'hot'}

        self.ham = ['와퍼','치즈와퍼','불고기와퍼','갈릭불고기와퍼','콰트로치즈와퍼','통새우와퍼','롱치킨버거',
                    '와퍼주니어','치즈와퍼주니어','불고기와퍼주니어','콰트로치즈와퍼주니어','통새우와퍼주니어',
                    '헬로디아블로와퍼','헬로이나리우스와퍼','헬로릴리트와퍼','치킨킹BLT','치킨킹','롱치킨','바비큐치킨버거',
                    '치킨버거','슈림프버거','통새우슈림프버거','비프슈림프버거','블랙바비큐콰트로치즈와퍼','블랙바비큐와퍼',
                    '비프불고기버거','비프앤슈림프버거','비프&슈림프버거','몬스터와퍼','몬스터X','더블비프불고기버거','더블오리지날치즈버거',
                    '치킨와퍼','콰트로','주니어','롱치킨','헬로','이나리우스','릴리트','BLT','몬스터','더블비프','바비큐치킨','블랙']
        self.side = ['너겟킹','치즈스틱','어니언링','바삭킹','쉐이킹프라이','크리미모짜볼','코코넛슈림프','21치즈스틱',
                    '치즈프라이','프렌치프라이','코울슬로','콘샐러드','구운갈릭시즈닝','스윗어니언시즈닝','매콤치즈시즈닝']
        self.drink = ['망고선데','초코망고선데','레드애플맛제로','레몬라임맛제로','컵망고아이스크림','아메리카노','아이스아메리카노','핫초코','아이스초코','코카콜라',
                    '코카콜라제로','스프라이트','스프라이트제로','미닛메이드오렌지','순수','순수(미네랄워터)','제로']
        self.neu = ['칼로리','열량','포화지방','단백질','당','설탕','나트륨','카페인',
                    'N_calories','N_staurated_fat','N_protein','N_sugars','N_sodium','N_caffeine']
        self.al = ['우유알레르기','치킨알레르기','돼지고기알레르기','돼지알레르기','소고기알레르기','소알레르기','비프알레르기','계란알레르기','달걀알레르기',
                '오징어알레르기','토마토알레르기','조개알레르기','새우알레르기','갑각류알레르기']
        self.ing = ['치즈','슬라이스치즈','슈레디드치즈','피클','할라피뇨','통새우','베이컨','양상추','양파','해쉬브라운','토마토','마늘','마늘칩']
        self.sau = ['마요','마요네즈','마요네즈소스','불고기','불고기소스','바베큐','바베큐소스','케찹','케찹소스','디아블로','디아블로소스',
            '매운토마토','매운토마토소스','치즈소스','타르타르','타르타르소스','베이컨잼','베이컨잼소스','머스타드','머스타드소스']
        self.pat = ['소고기','비프','새우','쉬림프','슈림프','치킨','닭','스테이크']
        self.etc = ['영양소','영양성분','알레르기','가격','정보','상세정보','맵기','맵','안맵','nutrition_info','allergy',
                    'N','A','price','info','spicy','높','많','낮','적','차갑','차','시원','따시','따듯','뜨겁','ice','hot']
        self.cat = ['M','S','DD','햄버거','버거','사이드','디저트','음료수','아이스크림','아침','점심','배고프','저녁','메뉴','음식','끼니','드시','먹']
        self.eve = self.ham+self.side+self.drink+self.neu+self.al+self.ing+self.sau+self.pat+self.etc+self.cat

    def replace_multiple_words(self,text):
        for old_word, new_word in self.replacements.items():
            text = text.replace(old_word, new_word)
        return text

    def toQuery(self,a):
        a = self.replace_multiple_words(a)
        m = self.kkma.morphs(a) # 형태소 추출
        n = self.kkma.nouns(a) # 명사만 추출

        #print('원래 문장 : ' + a)

        mor = []
        ct = 0
        full = ''
        count=0
        what = 'M'

        for i in range(ct,len(m)):
            full+=m[i]
        while ct<len(m)-1:
            tmp = full
            for i in range(len(m)-1, ct-1, -1):
                if i==ct:
                    mor.append(m[ct])
                    full=full[len(m[ct]):]
                    ct+=1
                    break
                if tmp in self.replacements: tmp = self.replacements[tmp]
                if tmp in self.eve:
                    if tmp in self.side+['사이드'] : what = 'S'
                    elif tmp in self.drink+['디저트','음료수','아이스크림'] : what = 'DD'
                    mor.append(tmp)
                    for j in range(ct, i+1) : full=full[len(m[j]):]
                    ct = i+1
                    break

                tmp=tmp[:len(tmp)-len(m[i])]
        if full!='' : mor.append(full)

        #print('mor')
        #print(mor)

        re1 = [] # 결과
        sg = ['추가','넣', '들어가', '좋', '들어가', '듣', '있'] # 주문 - 추가 키워드
        si = [] # 주문 - 들어가는 키워드
        sb = ['없', '빼주', '빼', '싫','안','빠지'] # 주문 - 빼는
        en = ['에', '에다', '에다가'] # 공백 키워드

        #주문 토큰화
        for i in mor: # 형태소로 나뉘었을 때
            if i in self.eve:
                re1.append(i)
            elif i in sg+sb: # 형태소 단위로 주문 키워드 넣기
                if i in sg:
                    re1.append('1') # 들어가는거
                elif i in si:
                    re1.append('i') # 정보
                elif i in sb:
                    re1.append('0') # 빼는거
                #else : print('어라' + 'g') # 혹시 오류
        #print('re1')
        #print(re1) # 첫 결과

        #토큰 결합
        re2 = [] # 찐 결과 리스트
        tmp = '' # 임시로 이을 문장
        for i in re1: # 토큰
            if i in self.toQ.keys() : i = self.toQ[i]
            if i in en: # 공백 키워드가 들어오면 리스트에 넣고 tmp 초기화
                tmp = '1 ' + tmp
                re2.append(tmp)
                tmp = ''
            elif i in ['0','1']: # 주문 키워드 들어오면 tmp에 추가 후 리스트 넣고 tmp 초기화
                tmp = i + ' ' + tmp
                re2.append(tmp)
                tmp = ''
            elif tmp == '' : # tmp가 빈 배열일 때 무조건 더하기
                tmp+=(i + ' ')
            else : tmp += (i + ' ') # 그 이외 (명사)는 추가
        if tmp!='' : re2.append('1 ' + tmp)

        #print(re2)

        isOrder = ''
        re3 = []
        for i in range(len(re2)):
            how = ''
            for j in re2[i].split():
                if j in self.neu+self.cat+['A','N','or']:
                    re3.append(j)
                elif j in ['asc','desc']: isOrder = j
                elif j in self.ham+self.side+self.drink:
                    if j in self.ham: what = 'M'
                    elif j in self.side : what = 'S'
                    elif j in self.drink : what = 'DD'
                    if j in self.queryName: j = self.queryName[j]
                    re3.append('menu_name ' + j)
                elif j in self.etc:
                    if j == '맵': re3.append('spicy' + ' 1')
                    elif j == '안맵': re3.append('spicy' + ' 0')
                    elif j == 'ice' : re3.append('ishot' + ' 0')
                    elif j == 'hot' : re3.append('ishot' + ' 1')
                    else:
                        re3.append(j)
                elif j in ['0','1'] : how = j
                else :
                    re3.append(j + ' ' + how)
        if isOrder != '' : re3.append(isOrder)
        return re3


from . import *

class WordEmbedding(nn.Module):
    '''
    Word embedding layer for gpt2
    '''
    def __init__(self, vocab_size, d_model, init_range=0.02, verbose = False):
        super().__init__()
        self.We = nn.Parameter(torch.empty(vocab_size, d_model))
        self.verbose = verbose
        nn.init.normal_(self.We, mean=0, std=init_range)

    def forward(self, tokens):
        # tokens shape: batch_size x words_per_sentence
        if(self.verbose):
            print("Embedding layer input shape: ", tokens.shape)

        # Embedding layer picks the nth row of the embedding matrix for each token in the sentence
        # Output shape: batch_size x words_per_sentence x d_model
        # So the token(last dim) gets inflated to a vector of size d_model
        out = self.We[tokens]
        if(self.verbose):
            print("Embedding layer output shape: ", out.shape)
        return out

class PositionEmbedding(nn.Module):
    '''
    Positional embedding layer for gpt2
    gpt uses learned positional embeddings
    '''
    def __init__(self, n_ctx, d_model, init_range=0.02, verbose = False):
        super().__init__()
        self.Pe = nn.Parameter(torch.empty(n_ctx, d_model))
        self.verbose = verbose
        nn.init.normal_(self.Pe, mean=0, std=init_range)

    def forward(self, word_embeddings):
        # word_embeddings shape: batch_size x words_per_sentence x d_model
        if(self.verbose):
            print("Positional embedding layer input shape: ", word_embeddings.shape)

        # Positional embedding layer adds the positional embedding to the word embedding
        # Output shape: batch_size x words_per_sentence x d_model
        out = word_embeddings + self.Pe[torch.arange(word_embeddings.shape[1])]
        if(self.verbose):
            print("Positional embedding layer output shape: ", out.shape)
        return out


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
This script illustrates early models of electrode saturation.

1. Reproduces Figure 17 of Dubarry et al.:
https://doi.org/10.1016/j.jpowsour.2012.07.016

The .mat file was obtained from Matthieu.

2. Reproduces Figure 1 of Smith et al.:
https://doi.org/10.23919/ACC.2017.7963578

The code was generated by Paul
"""

from pathlib import Path

import numpy as np
import scipy.io as sio
import matplotlib.pyplot as plt

import config

path = Path().cwd() / "data"
data = sio.loadmat(path / "dubarry_synthesize_2012_fig17.mat")

# Kandler Smith figure spaghetti code
t = np.arange(365 * 30)
N = t*0.2
b1 = 1e-3
b2 = 1e-4
p = 1.5
qLi = 1.06 - b1 * t ** 0.5
qPos = 1 + 0.02 * (1 - np.exp(- t / 150))
qNeg = (1.1 ** (1 + p) - b2 * 1.1 ** p * (1 + p) * N) ** (1 / (1 + p))
qCell = np.min(np.array([qLi, qNeg, qPos]).T, axis=1)

# Generate figure handles
fig, ax = plt.subplots(figsize=(config.FIG_WIDTH, 2 * config.FIG_HEIGHT),
                       nrows=2, ncols=1)

# Plots
ax[0].plot(
    data["x2"].flatten(),
    data["y2"].flatten(),
    "--",
    color="tab:blue",
    label="Loss of lithium inventory"
)

ax[0].plot(
    data["x3"].flatten(),
    data["y3"].flatten(),
    ":",
    color="tab:red",
    label="Loss of delithiated cathode active material"
)

ax[0].plot(
    data["x1"].flatten(),
    data["y1"].flatten(),
    color="k",
    label="Calculated capacity loss"
)

ax[1].plot(t / 1000, qLi, color="tab:purple", label="Lithium inventory, $Q_{Li}$")
ax[1].plot(t / 1000, qNeg, color="tab:blue", label="Negative electrode capacity, $Q_{neg}$")
ax[1].plot(t / 1000, qPos, color="tab:green", label="Positive electrode capacity, $Q_{pos}$")
ax[1].plot(t / 1000, qCell, "--k", label="Cell capacity = min($Q_{Li}$, $Q_{neg}$, $Q_{pos}$)")

# Set axes labels
ax[0].set_xlabel("Cycle number")
ax[0].set_ylabel("Degradation or capacity loss (%)")
ax[1].set_xlabel("Time (arbitrary)")
ax[1].set_ylabel("Relative capacity")

# Add axes limits
ax[0].set_xlim([0, 400])
ax[1].set_xlim([0, 11.5])
ax[0].set_ylim([0, 100])

# Add legends
l1 = ax[0].legend(title="Dubarry et al.")
l2 = ax[1].legend(title="Smith et al.")
l1._legend_box.align = "left"
l2._legend_box.align = "left"

ax[0].set_title("a", loc="left", weight="bold")
ax[1].set_title("b", loc="left", weight="bold")

# Save figure as both .PNG and .EPS
fig.tight_layout()
fig.savefig(config.FIG_PATH / "electrode_saturation.png", format="png", dpi=300)
fig.savefig(config.FIG_PATH / "electrode_saturation.eps", format="eps")


from flask import Flask, request, jsonify, render_template
#import pickle
import sigma_cabs
import numpy as np

app=Flask(__name__)

@app.route('/')
def form():
    return render_template('index.html')

@app.route("/",methods=["POST","Get"])
def le_ip():
    if request.method=="POST":
        v1=int(request.form["Trip_Distance"])
        v2=request.form["Type_of_Cab"]
        v3=int(request.form["Customer_Since_Months"])
        v4=request.form["Destination_Type"]
        v5=float(request.form["Customer_Rating"])
        v6=int(request.form["Var3"])

        final_features=[v1,v2,v3,v4,v5,v6]

        w=sigma_cabs.Loaded_model(final_features)

    return render_template("index.html",prediction=w)
if __name__=="__main__":
    app.run(debug=True)


import csv
import logging
import os
import uuid

from django.conf import settings
from django.contrib import admin, messages
from indicators.models import DataSource, IndicatorList, Indicator, \
    IndicatorPregenPart, IndicatorData
from django.utils.translation import ugettext_lazy as _
from django.contrib.admin.filterspecs import FilterSpec
from indicators.fields import RoundingDecimalField, FileNameField

class IndicatorSourceListFilter(FilterSpec):

    """
    Add "By Indicator Source" filter option on the admin/indicators/indicators page.

    Ideally, there would be two filter values listed:
    1) PreGenCSV
    2) HUB-Core

    PreGenCSV=true if the indicator's FileName attribute is populated;
    else HUB-Core=true.
    """

    def test(cls, field):
        return field.null and isinstance(field, cls.fields) and not field._choices

    test = classmethod(test)

    def title(self):
        return "Indicator Source"

    def __init__(self, f, request, params, model, model_admin):
        super(IndicatorSourceListFilter, self).__init__(f, request, params, model, model_admin)

        self.file_exists_lookup_kwarg     = 'file_name__gt'
        self.file_not_exists_lookup_kwarg = 'file_name'
        self.file_exists_lookup_val       = request.GET.get(self.file_exists_lookup_kwarg, None)
        self.file_not_exists_lookup_val   = request.GET.get(self.file_not_exists_lookup_kwarg, None)

    def choices(self, cl):
        yield {
                'selected'     : self.file_exists_lookup_val is None and self.file_not_exists_lookup_val is None,
                'query_string' : cl.get_query_string({}, [self.file_exists_lookup_kwarg, self.file_not_exists_lookup_kwarg]),
                'display'      : 'All',
        }
        yield {
                'selected'     : self.file_exists_lookup_val is not None,
                'query_string' : cl.get_query_string({self.file_exists_lookup_kwarg : ""}, [self.file_not_exists_lookup_kwarg]),
                'display'      : 'PreGenCSV',
        }
        yield {
                'selected'     : self.file_not_exists_lookup_val is not None,
                'query_string' : cl.get_query_string({self.file_not_exists_lookup_kwarg : ""}, [self.file_exists_lookup_kwarg]),
                'display'      : 'HUB-Core',
        }

def _register_front(cls, test, factory):
    cls.filter_specs.insert(0, (test, factory))

FilterSpec.register_front = classmethod(_register_front)
FilterSpec.register_front(lambda f: isinstance(f, FileNameField), IndicatorSourceListFilter)

# Actions available in Core
def batch_debug_indicators(modeladmin, request, queryset):
    """ Run selected indicators, and store output and a "debug" csv

    Each call to this view generates a view batch folder. The contents of the
    folder:

    - [indicator name].csv for each indicator selected
    - [indicator name]_debug.csv for each indicator selected
    - batch.log

    The indicator generation is scheduled in celery, and output is directed to
    batch.log.
    """
    try:
        from core.indicators import indicator_list
    except ImportError:
        return
    from indicators.tasks import indicator_debug_batch

    # create a directory to store the results of this debug batch
    batch_id = unicode(uuid.uuid1())
    batch_folder = os.path.join(settings.MEDIA_ROOT, 'batches', batch_id)
    os.makedirs(batch_folder)

    # map the queryset to names, for matching against definition classes
    indicators_to_run = [indicator.name for indicator in queryset]

    indicator_debug_batch(indicators_to_run, batch_folder)
batch_debug_indicators.short_description = \
    "Run a debug batch on the selected indicators"

def load_indicators(modeladmin, request, queryset):
    from indicators.load import DataImporter
    DataImporter().run_all(indicator_list=queryset)
load_indicators.short_description = "Load data for the selected Indicators"

# Actions available in Portal
def publish(modeladmin, request, queryset):
    queryset.update(published=True)
publish.short_description = "Publish selected indicators"

def unpublish(modeladmin, request, queryset):
    queryset.update(published=False)
unpublish.short_description = "Unpublish selected indicators"

class IndicatorPregenPartInline(admin.TabularInline):
    extra = 10
    model = IndicatorPregenPart

class IndicatorAdmin(admin.ModelAdmin):
    class Media:
        css = {
            "all": ("stylesheets/extend_tag_textbox.css",
                    "stylesheets/extend_universe_textbox.css",)
        }
    list_display = ('name', 'data_type', 'visible_in_all_lists', 'published',
                    'load_pending', 'last_load_completed', 'last_audited',)
    list_editable = ('visible_in_all_lists', 'published',)
    list_filter = ('data_type', 'visible_in_all_lists', 'datasources', 'load_pending', 'published', 'last_audited', 'file_name')
    search_fields = ('name', 'datasources__short_name', 'short_definition',
                     'long_definition', 'notes', 'file_name')
    exclude = ('raw_tags', 'raw_datasources', 'years_available_display',
               'years_available', )
    prepopulated_fields = {"slug": ("name",)}
    inlines = [
        IndicatorPregenPartInline,
    ]

    try:
        from indicators.load import DataImporter
        actions = [batch_debug_indicators, load_indicators, publish, unpublish]
    except ImportError:
        actions = [publish, unpublish]

    fieldsets = (
        ('Basic Information', { 'fields':(
            'name',
            'file_name',
            'display_name',
            'short_definition',
            'long_definition',
            'purpose',
            'universe',
            'limitations',
            'routine_use',
            'last_audited',
        )}),

        ('Numerical/Addtional Information', { 'fields':(
            'min',
            'max',
            'unit',
            'data_type',
            'notes',
        )}),

        ('Metadata', { 'fields':(
            'data_levels_available',
            'query_level',
            'suppression_numerator',
            'suppression_denominator',
            'datasources',
        )}),

        ('Django Internals', { 'fields':(
            'published',
            'visible_in_all_lists',
            'slug',
            'tags',
            'load_pending',
            'last_load_completed'
        )}),
    )

    def response_add(self, request, new_obj):
        obj = self.handle_pregen_data(new_obj, request)
        return super(IndicatorAdmin, self).response_add(request, obj)

    def response_change(self, request, new_obj):
        obj = self.handle_pregen_data(new_obj, request)
        return super(IndicatorAdmin, self).response_add(request, obj)

    def handle_pregen_data(self, obj, request):
        if obj.pregenparts.count():
            new_data = []
            for pregenpart in obj.pregenparts.all():
                filename = settings.DATAHUB_PREGEN_CSV_FILE \
                    + pregenpart.file_name
                try:
                    csv_file = open(filename, 'rb')
                except IOError:
                    messages.add_message(
                        request, messages.ERROR,
                        'Unable to open the file "'
                        + filename + '" for the pregen data. '
                        'Meta-data saved.  Indicator Data unchanged.'
                    )
                    return obj
                reader = csv.reader(csv_file)
                cols = reader.next()
                if pregenpart.column_name in cols:
                    col = cols.index(pregenpart.column_name)
                    for row in reader:
                        val = row[col]
                        try:
                            float(val)
                            data_type = 'numeric'
                            numeric = val
                            string = None
                        except ValueError:
                            data_type = 'string'
                            string = val
                            numeric = None
                        new_data.append({
                            'time_type': pregenpart.time_type,
                            'time_key': pregenpart.time_value,
                            'key_unit_type': pregenpart.key_type,
                            'key_value': val,
                            'data_type': data_type,
                            'numeric': numeric,
                            'string': string
                        })
            if len(new_data):
                IndicatorData.objects.filter(indicator=obj).delete()
                for d in new_data:
                    IndicatorData.objects.create(
                        indicator=obj,
                        time_type=d['time_type'],
                        time_key=d['time_key'],
                        key_unit_type=d['key_unit_type'],
                        key_value=d['key_value'],
                        data_type=d['data_type'],
                        numeric=d['numeric'],
                        string=d['string']
                    )
                messages.add_message(
                    request, messages.INFO,
                    'Cleared the Indicator Data and added '
                    + str(len(new_data)) +
                    ' Indicator Data records from the pregen csv file.'
                )
        return obj

admin.site.register(DataSource)
admin.site.register(IndicatorList)
admin.site.register(Indicator, IndicatorAdmin)


# -*- codind: UTF -*-

'''
#139
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

Note:

The same word in the dictionary may be reused multiple times in the segmentation.
You may assume the dictionary does not contain duplicate words.

Example 1:

Input: s = "leetcode", wordDict = ["leet", "code"]
Output: true
Explanation: Return true because "leetcode" can be segmented as "leet code".
'''

from typing import List
class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        dp = [False for _ in range(len(s)+1)]
        dp[0] = True
        for i in range(len(s)):
            for j in range(i+1, len(s)+1):
                if dp[i] and s[i:j] in wordDict:
                    dp[j] = True
        return dp[-1]

if __name__ == '__main__':
    print(Solution().wordBreak(s="aaaaaaa", wordDict=["aaaa", "aaa"]))