from nltk.tokenize import sent_tokenize
from nltk.corpus import stopwords
from nltk.probability import FreqDist
from string import punctuation
import logging
from heapq import nlargest
from collections import defaultdict
import freeling

from . import frequency_naive

logger = logging.Logger(__name__)
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
logger.addHandler(ch)

FREELINGDIR = "/usr/local"

DATA = FREELINGDIR + "/share/freeling/"
LANG = "es"

class FrequencyPostTagger(frequency_naive.FrequencySummarizer):

    def summarize(self):
        logger.debug("Extracting sentences")
        self.sentences = sent_tokenize(self._text, language='spanish')
        logger.debug("Extracting frequencies")
        self._frequency_distributions = FreqDist(self._cleaned_text)
        ranking = defaultdict(int)
        for i, sentence in enumerate(self.sentences):
            for word in sentence:
                scale_factor = 1
                tag = word.split("-")
                if len(tag) > 1:
                    tag = tag[1]
                    if tag.startswith("A"):
                        # Adjective
                        scale_factor = 1.4
                    elif tag.startswith("R"):
                        # Adverb
                        scale_factor = 1.1
                    elif tag.startswith("D"):
                        # Determinant
                        scale_factor = 0.9
                    elif tag.startswith("N"):
                        # Noun
                        scale_factor = 2.2
                    elif tag.startswith("V"):
                        # Verb
                        scale_factor = 1.6
                    elif tag.startswith("P"):
                        # Pronoun
                        scale_factor = 1.1
                    elif tag.startswith("Z"):
                        # Number
                        scale_factor = 1.5
                    elif tag.startswith("W"):
                        # Date
                        scale_factor = 1.5

                ranking[i] += self._frequency_distributions.freq(word) * scale_factor
        ordered_sentences_by_priority = nlargest(int(len(self.sentences)/10) + 1, ranking, key=ranking.get)
        return [self.sentences[i] for i in ordered_sentences_by_priority]

    def __init__(self, text):
        super().__init__(text)
        self.stop_words = set(stopwords.words('spanish') + list(punctuation))
        self._cleaned_text = list()
        freeling.util_init_locale("default")

        # create language analyzer
        la = freeling.lang_ident(DATA + "common/lang_ident/ident.dat")

        # create options set for maco analyzer. Default values are Ok, except for data files.
        op = freeling.maco_options("es")
        op.set_data_files("",
                          DATA + "common/punct.dat",
                          DATA + LANG + "/dicc.src",
                          DATA + LANG + "/afixos.dat",
                          "",
                          DATA + LANG + "/locucions.dat",
                          DATA + LANG + "/np.dat",
                          DATA + LANG + "/quantities.dat",
                          DATA + LANG + "/probabilitats.dat")

        # create analyzers
        tk = freeling.tokenizer(DATA + LANG + "/tokenizer.dat")
        sp = freeling.splitter(DATA + LANG + "/splitter.dat")
        sid = sp.open_session()
        mf = freeling.maco(op)

        # activate mmorpho odules to be used in next call
        mf.set_active_options(True, True, True, True,  # select which among created
                              True, True, True, True,  # submodules are to be used.
                              True, True, True, True)  # default: all created submodules are used

        # create tagger, sense anotator, and parsers
        tg = freeling.hmm_tagger(DATA + LANG + "/tagger.dat", True, 2)
        sen = freeling.senses(DATA + LANG + "/senses.dat")
        parser = freeling.chart_parser(DATA + LANG + "/chunker/grammar-chunk.dat")

        l = tk.tokenize(self.text)
        ls = sp.split(sid, l, False)

        ls = mf.analyze(ls)
        ls = tg.analyze(ls)
        ls = sen.analyze(ls)
        ls = parser.analyze(ls)

        for s in ls:
            ws = s.get_words()
            for w in ws:
                # Removing all stopped words, including prepositions, conjunctions, interjections and punctuation
                tag = w.get_tag()
                word = w.get_form()
                if tag.startswith("S") or \
                    tag.startswith("I") or \
                    tag.startswith("C") or \
                    tag.startswith("F") or \
                    tag.startswith("D") or \
                    tag.startswith("P"):
                    pass
                else:
                    self._cleaned_text.append("{}-{}".format(word, tag))

    def get_cleaned_frequency(self):
        new_frequency = FreqDist()
        for word, count in self._frequency_distributions.items():
            new_frequency[word.split("-")[0]] = count
        return new_frequency


from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
from django.urls import reverse
from slugify import slugify   # pip install awesome-slugify 支持中文
# from django.utils.text import slugify  # python 自带的

class ArticleColumn(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='article_column', verbose_name='用户名')
    column = models.CharField(max_length=200, verbose_name='栏目')
    created = models.DateField(auto_now_add=True, verbose_name='创建时间')

    class Meta:
        verbose_name = '文章表'

    def __str__(self):
        return self.column

class ArticleTag(models.Model):
    # 关于文章标签的数据模型类
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="tag")
    # user获取articletag 使用request.user.tag.all()
    tag = models.CharField(max_length=500)

    def __str__(self):
        return self.tag

class ArticlePost(models.Model):
    """文章"""
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="article")
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=500)
    column = models.ForeignKey(ArticleColumn, on_delete=models.CASCADE, related_name="article_column")

    body = models.TextField()
    created = models.DateTimeField(default=timezone.now)
    updated = models.DateTimeField(auto_now=True)
    # 点赞
    users_like = models.ManyToManyField(User, related_name="articles_like", blank=True)
    #
    article_tag = models.ManyToManyField(ArticleTag, related_name='article_tag', blank=True)

    class Meta:
        ordering = ("-updated",)
        index_together = (('id', 'slug'),)  # 对数据库中这两个字段建立索引

    def __str__(self):
        return self.title

    def save(self, *args, **kargs):
        self.slug = slugify(self.title)  # 重新save，self.slug赋值
        super(ArticlePost, self).save(*args, **kargs)

    def get_absolute_url(self):
        """给每篇文章添加明细路径"""
        return reverse("article:article_detail", args=[self.id, self.slug])
        # 通过reverse('article:article_detail')实现了'/article/article-list/'
        # 通过ArticlePost.get_absolute_url使每个文章都有链接

    def get_url_path(self):
        """给每篇文章添加路径"""
        return reverse("article:article_content", args=[self.id, self.slug])

class Comment(models.Model):
    article = models.ForeignKey(ArticlePost, on_delete=models.CASCADE, related_name="comments")
    commentator = models.CharField(max_length=90)  # 评论人
    body = models.TextField()  # 评论内容
    created = models.DateTimeField(auto_now_add=True)  # 时间

    class Meta:
        ordering = ('-created',)

    def __str__(self):
        return "Comment by {0} on {1}".format(self.commentator.username, self.article)


import utils
from itertools import combinations

def format_naked_hidden_sets_text(result_dict, naked_hidden_set_name):
    text = []
    for conjugate, data in result_dict.items():
        candidates = "/".join(map(str, data['candidates']))
        cells = "/".join([utils.format_cell(cell) for cell in conjugate])

        # If there are common units, add them to the text
        if 'Naked' in naked_hidden_set_name:

            for unit_type, cells_to_remove_from in data['common_units'].items():
                if cells_to_remove_from:  # Check if set is not empty
                    removal_cells = ", ".join([utils.format_cell(c) for c in cells_to_remove_from])
                    unit_name = unit_type[1:]
                    text.append(
                        f"{naked_hidden_set_name} ({unit_name}): {cells} removes {candidates} from {removal_cells}")

        else:
            removal_cells = ", ".join([utils.format_cell(c) for c in conjugate])
            text.append(f"{naked_hidden_set_name} {cells} removes {candidates} from {removal_cells}")

    return text

def format_hidden_single_text(cell, hidden_single, hidden_in_units):
    """Formats the descriptive text for a found hidden single."""
    units_text = ', '.join([unit[1:] for unit in hidden_in_units])

    # If there are multiple units, use 'and' for the last one
    if len(hidden_in_units) > 1:
        last_comma_idx = units_text.rfind(',')
        units_text = units_text[:last_comma_idx] + ' and' + units_text[last_comma_idx + 1:]

    text = f"{utils.pos2cord(cell)} set to {hidden_single}. Unique in {units_text}"
    return text

def get_combinations(iterable, r):
    return combinations(iterable, r)

def get_cell_unit_keys(cell):
    """Return the keys for the units the cell belongs to.
    example:
        cell = (0, 0)
        unit_keys = {'row': 0, 'col': 0, 'box': 0}
        cell = (3, 5)
        unit_keys = {'row': 3, 'col': 5, 'box': 1}
    """
    row, col = cell
    box = (row // 3) * 3 + (col // 3)
    return {'Arow': row, 'Bbox': box, 'Ccol': col}

def get_common_units(all_units, *cells):
    """Return the common units for multiple cells if they exist, classified by unit type.
    example:
        cells = [(0, 0), (0, 1)]
        common_units = {
        'row': ((0, 0), (0, 1), (0, 2), (0, 3), (0, 4), ..., (0, 8)),
        'col': ((0, 0), (1, 0), (2, 0), (3, 0), (4, 0), ..., (8, 0)),
        'box': None}
    """
    # Get the unit keys for all cells
    cells_unit_keys = [get_cell_unit_keys(cell) for cell in cells]

    common_units = {unit_type: tuple() for unit_type in ['Arow', 'Bbox', 'Ccol']}

    # Iterate over each unit type

    for unit_type in ['Arow', 'Ccol', 'Bbox']:
        # Check if all cells belong to the same unit for the current unit type
        unit_key = cells_unit_keys[0][unit_type]
        if all(unit_key == cell_unit_keys[unit_type] for cell_unit_keys in cells_unit_keys):
            unit_cells = all_units[unit_type][unit_key]
            common_units[unit_type] = tuple(sorted(cell for cell in unit_cells if cell not in cells))
        else:
            common_units[unit_type] = None

    # If all the units are None, there are no common units among the cells
    if all(value is None or value == () for value in common_units.values()):
        return None

    return common_units


import random
import itertools
import sys

"""
students = Range[400]

spots = 100

inc = 20;
inclist = RandomInteger[{1, 400}, {inc, 2}]

solutionlist = {};

For[i = 1, i < inc, i++,

For[j = 1, j < Length[students], j++,

    If[inclist[[i]][[2]] != students[[j]],

      AppendTo[solutionlist, {inclist[[i]][[1]], students[[j]]}];
      students = Delete[students, j];
      j = Length[students];

      ];

    ];

  ];

For[i = Length[solutionlist], i < spots/2, i = i + 2,
  AppendTo[solutionlist, {students[[i]], students[[i + 1]]}]];
"""

class Solution():
    NUM_STUDENTS = 400
    AVAIL_SPOTS = 100

    def __init__(self, random_seed):
        self.random_seed = random_seed
        self.students = list(range(self.NUM_STUDENTS))
        self.exclusions = random.sample(
            list(itertools.product(range(self.NUM_STUDENTS), repeat=2)), 20)

    @property
    def avail_spots(self):
      return self.AVAIL_SPOTS

    def get_exclusions(self):
      return self.exclusions

    def generate_soltn(self):
        random.seed(self.random_seed)

        solution = []

        for i in range(0, len(self.exclusions)):
            templength=len(self.students)
            for j in range(0, templength):
                if (self.exclusions[i][1] != self.students[j]):
                    solution.append((self.exclusions[i][0], self.students[j]))
                    try:
                      self.students.remove(self.students[j])
                      self.students.remove(self.exclusions[i][0])
                    except:
                      pass
                    break

        idx = len(solution)
        while (len(solution) < self.AVAIL_SPOTS):
          solution.append((self.students[idx], self.students[idx + 1]))
          idx += 2

        return solution

if __name__ == '__main__':

  if len(sys.argv) < 2:
    print("Usage: python students_np.py [RANDOM_SEED]")
    sys.exit(1)

  s = Solution(sys.argv[1])
  res = s.generate_soltn()

  print(res)


import matplotlib.pyplot as plt
from matplotlib import cm               # Colour maps for the contour graph
import numpy as np

def f(x, y):                            # Example of a function of two independent variables
    return x**4 - 2*x**2 + x + y**2

numSteps = 100                          # Number of points in the mesh
numContours = 30                        # Number of contours in the graph

x = y = np.linspace(-2.0, 2.0, numSteps)# Range of x and y values for the graph

X, Y = np.meshgrid(x, y)                # Grid for calculating values of the function
Z = f(X, Y)                             # numpy is powerful and can handle this

# cmap specifies one of the colour map. All colour maps are given in
# https://matplotlib.org/stable/tutorials/colors/colormaps.html
plt.contourf(X, Y, Z, numContours, cmap=cm.hot)
plt.colorbar()                          # Legend for the contour graph
plt.show()


from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

import tensorflow as tf
sess = tf.InteractiveSession()
x = tf.placeholder(tf.float32, [None, 784])   # x is the value for each pixel
W = tf.Variable(tf.zeros([784, 10]))    # Weight for each pixel
b = tf.Variable(tf.zeros([10]))         # bias

#定義演算法公式
y = tf.nn.softmax(tf.matmul(x, W) + b)        # y = softmax(Wx+b)
y_ = tf.placeholder(tf.float32, [None, 10])   # y' for the real label

#定義loss function和選擇最佳化模組
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y),           # cross_entropy as
                                              reduction_indices=[1]))   # loss function
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) # use GradientDescentOptimizer with rate is 0.5

#訓練步驟
tf.global_variables_initializer().run()   # initial variables
for i in range(1000):   # training step 1000 times
  batch_xs, batch_ys = mnist.train.next_batch(100)  # random select 100 data for training
  train_step.run({x: batch_xs, y_: batch_ys})

# For calculate accuracy
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(accuracy.eval({x: mnist.test.images, y_: mnist.test.labels}))


"""
--- Part Two ---

Time to improve the polymer.

One of the unit types is causing problems; it's preventing the polymer from collapsing as much as it should. Your goal is to figure out which unit type is causing the most problems, remove all instances of it (regardless of polarity), fully react the remaining polymer, and measure its length.

For example, again using the polymer dabAcCaCBAcCcaDA from above:

Removing all A/a units produces dbcCCBcCcD. Fully reacting this polymer produces dbCBcD, which has length 6.
Removing all B/b units produces daAcCaCAcCcaDA. Fully reacting this polymer produces daCAcaDA, which has length 8.
Removing all C/c units produces dabAaBAaDA. Fully reacting this polymer produces daDA, which has length 4.
Removing all D/d units produces abAcCaCBAcCcaA. Fully reacting this polymer produces abCBAc, which has length 6.
In this example, removing all C/c units was best, producing the answer 4.

What is the length of the shortest polymer you can produce by removing all units of exactly one type and fully reacting the result?
"""

import os
import time

start_time = time.time()
f = open("./inputs/day5","r")

line = f.readline()
set_of_input = set(line.lower())
minim_length = 200000

def explode(s):
    upper = str.upper
    lower = str.lower
    new = line.replace(lower(s), '')
    new = new.replace(upper(s), '')
    old = ""
    while len(new) != len(old):
        old = new
        for i in set_of_input:
            new = new.replace(i+upper(i),'')
            new = new.replace(upper(i)+i,'')
    return(len(new))

lengths = [explode(s) for s in set_of_input]
print(min(lengths))
print("--- Day 5 Part TWO Optimized  %s seconds ---" % (time.time() - start_time))


import numpy as np
import matplotlib.pyplot as plt
from  AircraftSpecs import *
from random import random

C_Dmin = 0.028
C_L_TO = 1.1
C_D_TO = 0.05

e = 1.78*(1-0.045*(AR**0.68)) - 0.64
k = 1/(np.pi * AR * e)
n = 1.2
mu = 0.04

WtoS = np.linspace(2,80,1000)

TtoW_Bank = []
TtoW_Cruise = []
TtoW_TO = []
TtoW_Climb = []

PtoW_Bank = []
PtoW_Cruise = []
PtoW_TO = []
PtoW_Climb = []

for i in AverageMinSpeed:
    TtoW_b = (0.5*rho*(i**2))*((C_Dmin/WtoS)+(k*((n/(0.5*rho*(i**2)))**2)*WtoS))
    TtoW_c = (0.5*rho*(i**2))*C_Dmin*(1/WtoS)+(k*(1/(0.5*rho*(i**2)))* WtoS)
    TtoW_to = ((i**2)/(2*g*15))+((C_D_TO*0.5*rho*i**2)/WtoS) + mu*(1-((C_L_TO*0.5*rho*i**2)/(WtoS)))
    TtoW_climb = (0.4/(0.75*i))+((C_Dmin*0.5*rho*i**2)/WtoS)+(k*(1/(0.5*rho*(i**2)))* WtoS)

    TtoW_Bank.append(TtoW_b)
    TtoW_Cruise.append(TtoW_c)
    TtoW_TO.append(TtoW_to)
    TtoW_Climb.append(TtoW_climb)

    PtoW_Bank.append(735.5*(i/(eta_engine*eta_prop*550))*TtoW_b)  ### W per lb
    PtoW_Cruise.append(735.5*(i/(eta_engine*eta_prop*550))*TtoW_c)  ### W per lb
    PtoW_TO.append(735.5*(i/(eta_engine*eta_prop*550))*TtoW_to)  ### W per lb
    PtoW_Climb.append(735.5*(i/(eta_engine*eta_prop*550))*TtoW_climb)  ### W per lb

    C_L_max = (1/(0.5*rho*(i*0.7)**2))*(50)
    print(C_L_max)

##Cruise Condition:

#PtoW_cruise =

plt.figure()

plotlaps = [3]

for i in plotlaps:

    lableplot = 'Laps: ' + str(i)
    color = [random(),random(),random()]
    plt.title('4 Lap Constraint Diagam')
    """ plt.plot(WtoS,PtoW_Bank[i-1],color=color, label = lableplot)
    plt.plot(WtoS,PtoW_Cruise[i-1],color=color, linestyle='dotted')
    plt.plot(WtoS,PtoW_TO[i-1],color=color, linestyle='dashed')
    plt.plot(WtoS,PtoW_Climb[i-1],color=color, linestyle='dashdot') """

    color_r = [1,0,0]
    color_b = [0,0,1]
    plt.plot(WtoS,PtoW_Bank[i-1],color=color_b, linestyle='solid', label = 'Bank Power')
    plt.plot(WtoS,PtoW_Cruise[i-1],color=color_b, linestyle='dotted', label = 'Cruise Power')
    plt.plot(WtoS,PtoW_TO[i-1],color=color_b, linestyle='dashed', label = 'Take Off Power')
    plt.plot(WtoS,PtoW_Climb[i-1],color=color_b, linestyle='dashdot', label = 'Climb Power')

plt.xlabel('W/S [N/m^2]')
plt.ylabel('P/W [W/N]')
plt.grid()
plt.legend()
plt.show()


from django.conf.urls import url
from django.urls import path
from user import views
from django.contrib.auth.decorators import login_required #进行登录验证django自带的user才可行，在本案例中就是重写了django的user表

app_name = 'apps.user'
urlpatterns = [
    # url('register/', views.register, name='register'),   # 注册页面 FBV
    url('register', views.RegisterView.as_view(), name='register'),# 注册页面 CBV
    # url('register_handle/', views.register_handle, name='register_handle'),#注册处理
    path('active/<token>', views.ActiveView.as_view(), name='active'),  # 激活地址
    url('login', views.LoginView.as_view(), name='login'),  # 登录页面
    url('logout/', views.LogoutView.as_view(), name='logout'),  # 退出登录连接

    # url('order/', login_required(views.UserOrderView.as_view()), name='order'),  # 用户中心-订单页
    # url('address/', login_required(views.AddressView.as_view()), name='address'),  # 用户中心-地址页
    # url('', login_required(views.UserInfoView.as_view()), name='user'),  # 用户中心-信息页  ''记得放到最后匹配，否则出错

    #在utils的mixin中做了视图的验证封装，只需要在需要登录验证的views函数中继承mixin中的LoginRequiredMixin类就行要放在左边
    # path('list/<int:types_id>/<int:page>', views.ListView.as_view(), name='list'),  # 详情页
    path('order/<int:page>', views.UserOrderView.as_view(), name='order'),  # 用户中心-订单页
    url('address', views.AddressView.as_view(), name='address'),  # 用户中心-地址页
    url('', views.UserInfoView.as_view(), name='user'),  # 用户中心-信息页  ''记得放到最后匹配，否则出错
]


from my_package import my_IO
from varSavePath import Vars
import os
import searchRecommend as sr
import jieba
from gensim import corpora, models, similarities
import globarVar

globarVar.set('overWrite',1)

def caseReccommend(casePath,rootPath):
    content = my_IO.readFile(casePath)
    doc_vectors = sr.loadDocVec(rootPath)
    dictionary = sr.loadDictionary(rootPath)
    kw_vector = dictionary.doc2bow(filter(
        lambda x:x not in [w.strip() for w in open('哈工大停用词表.txt', encoding='utf-8').readlines()],
        jieba.lcut(content)))
    feature_cnt = len(dictionary.token2id)
    fileNames = sr.loadFilePath(rootPath)
    tfidf = models.TfidfModel(doc_vectors)
    index = similarities.SparseMatrixSimilarity(tfidf[doc_vectors], feature_cnt)
    sim = index[tfidf[kw_vector]]  # 很多0的稀疏矩阵
    fileSimDic: dict = dict(zip(fileNames, sim))
    fileSimDic = sorted(fileSimDic.items(), key=lambda x: x[1], reverse=True)  # 从大到小排
    count = 0
    caseRecommendFileName = []
    caseRecommendScore=[]
    for k, v in tqdm(fileSimDic):
        if v > 0:
            caseRecommendFileName.append(k)
            caseRecommendScore.append(v)
            count += 1
        if count == 6: # 由于文书读进去必定推荐自己，所以推荐按五个要6个
            break
    return caseRecommendFileName,caseRecommendScore

import pandas as pd
from tqdm import tqdm
def saveRecommend():
    rootPath = 'caseRec'
    index_columns = ['currentFile', 'recommend1', 'recommend2', 'recommend3', 'recommend4', 'recommend5']
    currentFilePath=[]
    recFilePaths=[]
    recFileSocres=[]
    for type in my_IO.getTypeNameList():
        caseRootPath = '../project-dev/judicature/src/main/resources/case/txt/{}'.format(type)
        caseNames=my_IO.getFileNameList(caseRootPath)
        for caseName in tqdm(caseNames):
            recFileNameList,recFileSocreList = caseReccommend(caseRootPath+'/'+caseName, rootPath)
            currentFilePath.append(type+'/'+caseName)
            recFilePaths.append(list(map(lambda x:type+'/'+x,recFileNameList)))
            recFileSocres.append(recFileSocreList)
        print('{} done'.format(type))
    pathDic={
        'currentFilePath':currentFilePath,
        'recFilePaths':recFilePaths
    }
    dfPath=pd.DataFrame(pathDic)
    dfPath.to_excel('相似文章路径.xlsx')

    socreDic={
        'currentFilePath':currentFilePath ,
        'recFileScores': recFileSocres
    }
    dfScore=pd.DataFrame(socreDic)
    dfScore.to_excel('相似文章得分.xlsx')

def loadRecommend():
    pass
if __name__=='__main__':
    # 以下是生成本地已有文章的相似文章xlsx
    # 我已经生成好了，最好不要取消注释运行。如果运行了就等运行完，我在控制台做了进度输出
    # saveRecommend()
    # print('{} done'.format(__file__))

    # 输入单个文章，给出推荐文章路径列表和分数
    rootPath='caseRec'
    casePath='../project-dev/judicature/src/main/resources/case/txt/adjudication/中欧汽车电器有限公司吴国琳等合伙协议纠纷股权转让纠纷其他民事民事裁定书.txt'
    recFilename,recFileScore=caseReccommend(casePath, rootPath)
    print(recFilename,recFileScore)


import numpy as np
import math
import matplotlib as plot

p = [0.0, 0.41, 0.79, 1.13, 1.46, 1.76, 2.04, 2.3, 2.55, 2.79, 3.01]
m = 5.33
k = 13

data = [
    [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
    [p[i] + ((-1) ** k) * m for i in range(len(p))]
]

print(data)

def weight_coefficient(data_src=None, x=0, exclude=None, top_value=None):
    result = 1
    if top_value is None:
        top_value = len(data_src)
    for i in range(top_value):
        if i == exclude:
            continue
        result *= (x - data_src[0][i])
    return result

def lagrange_interpolation(_data_, x=0.1):
    result = 0
    for i in range(len(_data_)):
        result += _data_[1][i] * (
                    weight_coefficient(data_src=_data_, x=x, exclude=i) /
                    weight_coefficient(data_src=_data_, x=data[0][i], exclude=i))
    return result

def newton_interpolation(_data_, x=0.1):
    def _a_(_data=None, top_idx=None):
        result = 0
        for k in range(top_idx + 1):
            result += _data_[1][k] / weight_coefficient(data_src=_data_, x=_data[0][k],
            exclude=k, top_value=top_idx + 1)
        return result

    result = 0
    for i in range(len(_data_)):
        result += _a_(_data_, i) * weight_coefficient(data_src=_data_, x=x, top_value=i)
    return result

print(newton_interpolation(data, x=0.47))
print(lagrange_interpolation(data, x=0.47))


from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen,ScreenManager
from kivy.lang import Builder

#Builder String
helper_string = '''
ScreenManager:
    Hello:
    Bye:

<Hello>:
    name: 'hello'
    NavigationLayout:
        ScreenManager:
            Screen:
                BoxLayout:
                    orientation: 'vertical'
                    MDToolbar:
                        title: "Navigation Drawer"
                        elevation: 10
                        left_action_items: [['menu', lambda x: nav_drawer.toggle_nav_drawer()]]
                    Widget:
        MDNavigationDrawer:
            id: nav_drawer

<Bye>
    name: 'bye'
    MDLabel:
        text: 'Good Bye'

'''
class Hello(Screen):
    pass
class Bye(Screen):
    pass

sm = ScreenManager()

sm.add_widget(Hello(name = 'hello'))
sm.add_widget(Bye(name='bye'))

class DemoApp(MDApp):
    def build(self):
        screen = Screen()

        help_str = Builder.load_string(helper_string)

        screen.add_widget(help_str)
        return screen

DemoApp().run()


"""Show MultiplePi creating ticks for a tau intervaled graph."""
import matplotlib.pyplot as plt
import numpy as np

from matplot_fmt_pi.ticker import MultiplePi

fig = plt.figure()
axes = fig.add_subplot(111)
tau = np.pi * 2
x = np.linspace(-tau / 60, tau * 8 / 60, 512)
axes.plot(x, np.exp(-x) * np.cos(60 * x))

axes.grid(True)
axes.axhline(0, color='black', lw=2)
axes.axvline(0, color='black', lw=2)
axes.set_title("MultiplePi tau formatting")

major_pi_manager = MultiplePi(60, base=tau, symbol=r"\tau")
minor_pi_manager = MultiplePi(240, base=tau, symbol=r"\tau")

axes.xaxis.set_major_locator(major_pi_manager.locator())
axes.xaxis.set_major_formatter(major_pi_manager.formatter())
axes.xaxis.set_minor_locator(minor_pi_manager.locator())

plt.tight_layout()
plt.savefig("./tau_graph.png", dpi=120)


import colorama
import os
import sys

colorama.init()

try:
    msg = sys.argv[1]
    branch = sys.argv[2]
except:
    print(colorama.Fore.RED + "Usage: onegit [message] [branch]" + colorama.Style.RESET_ALL)
    sys.exit(-1)

def run(cmd):
    print(colorama.Fore.GREEN + "running {}".format(cmd) + colorama.Style.RESET_ALL)

    os.system(cmd)

stage = "git stage ."
run(stage)

commit = "git commit -m \"{}\"".format(msg)
run(commit)

push = "git push -u origin {}".format(branch)
run(push)


from plone.rest.interfaces import IAPIRequest

def __before_publishing_traverse__(self, arg1, arg2=None):
    """Pre-traversal hook that stops traversal to prevent the default view
    to be appended. Appending the default view would break REST calls.
    """
    # XXX hack around a bug(?) in BeforeTraverse.MultiHook
    REQUEST = arg2 or arg1

    if IAPIRequest.providedBy(REQUEST):
        return

    return self._old___before_publishing_traverse__(arg1, arg2)

PERMANENT_REDIRECT = {308: "Permanent Redirect"}

def patch_zpublisher_status_codes(scope, unused_original, unused_replacement):
    """Add '308 Permanent Redirect' to the list of status codes the ZPublisher
    knows about. Otherwise setStatus() will turn it into a 500.

    This is needed for up to and including Plone 5.1.
    """
    status_reasons = getattr(scope, "status_reasons", {})
    if 308 in status_reasons:
        # Already present in zExceptions >= 3.2 / Zope >= 4.0a1 / Plone 5.2
        return

    # Patch the forward mapping (code -> reason)
    status_reasons.update(PERMANENT_REDIRECT)

    # Update the reverse mapping
    status_codes = getattr(scope, "status_codes", {})
    key, val = PERMANENT_REDIRECT.items()[0]

    status_codes["".join(val.split(" ")).lower()] = key
    status_codes[val.lower()] = key
    status_codes[key] = key
    status_codes[str(key)] = key


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Feb 15 22:09:13 2020

@author: insauer
"""

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.lines import Line2D

"""Script to reproduce main Figure 4!"""

fig3 = plt.figure(constrained_layout=True, figsize=(7., 9.9))
gs = fig3.add_gridspec(20, 14)
plt.subplots_adjust(wspace=-0.2, hspace=0)

DATA_ATTR_Full = pd.read_csv('../../data/reconstruction/attribution_MetaData_regions.csv')

DATA_ATTR = pd.read_csv('../../data/reconstruction/attribution_MetaData_subregions.csv')

DATA_FIT_Full = pd.read_csv('../../data/reconstruction/vulnerability_adjustment_MetaData_regions.csv')
DATA_FIT = pd.read_csv('../../data/reconstruction/vulnerability_adjustment_MetaData_subregions.csv')

region_names={'GLB': 'Global (GLB)',
              'NAM':'North America (NAM)',
              'EAS':'Eastern Asia (EAS)',
              'OCE':'Oceania (OCE)',
              'LAM':'Latin America (LAM)',
              'EUR':'Europe (EUR)',
              'CAS':'Central Asia (CAS)',
              'SSA':'South & Sub-Sahara Africa (SSA)',
              'SEA':'South & South-East Asia (SEA)',
              'NAF':'North Africa & Middle East (NAF)'
              }

region_abs={'NAM':'NAM',
          'LAM':'LAM',
          'EUR':'WEU',
          'NAF':'NAR',
          'SSA':'SSA',
          'CAS':'CAS',
          'SEA':'SEA',
          'EAS':'EAS',
          'OCE':'OCE',
          'GLB': 'GLB'}

regions = list(region_names)

#order = [9,0,1,2,]
r =0

for i in range(4):
    for j in range(3):

        if i == 0 and (j ==0 or j ==2):
            continue

        f3_ax1 = fig3.add_subplot(gs[5*i:5*i+2,j*5:(j*5)+4])
        f3_ax2 = fig3.add_subplot(gs[5*i+2:5*i+4,j*5:(j*5)+4])

        r_lin = DATA_FIT_Full.loc[DATA_FIT_Full['Region']==regions[r], 'R2_D_Full_D_Obs'].sum()

        r_lin_pos = DATA_FIT.loc[DATA_FIT['Region']==regions[r]+'_pos', 'R2_D_Full_D_Obs'].sum()
        r_lin_neg = DATA_FIT.loc[DATA_FIT['Region']==regions[r]+'_neg', 'R2_D_Full_D_Obs'].sum()

        data_attr_reg = DATA_ATTR_Full[DATA_ATTR_Full['Region'] == regions[r]]
        data_attr_reg_pos = DATA_ATTR[DATA_ATTR['Region'] == regions[r]+'_pos']
        data_attr_reg_neg = DATA_ATTR[DATA_ATTR['Region'] == regions[r]+'_neg']

        h7 = data_attr_reg.loc[:,'C_1980_71'].sum()
        h_pos7 =  data_attr_reg_pos.loc[:,'C_1980_71'].sum()
        h_neg7 =  data_attr_reg_neg.loc[:,'C_1980_71'].sum()

        h7_up = data_attr_reg.loc[:,'C_1980_71up'].sum()
        h_pos7_up =  data_attr_reg_pos.loc[:,'C_1980_71up'].sum()
        h_neg7_up =  data_attr_reg_neg.loc[:,'C_1980_71up'].sum()

        h7_bot = data_attr_reg.loc[:,'C_1980_71bot'].sum()
        h_pos7_bot =  data_attr_reg_pos.loc[:,'C_1980_71bot'].sum()
        h_neg7_bot =  data_attr_reg_neg.loc[:,'C_1980_71bot'].sum()

        h8 = data_attr_reg.loc[:,'C_1980_80'].sum()
        h_pos8 =  data_attr_reg_pos.loc[:,'C_1980_80'].sum()
        h_neg8 =  data_attr_reg_neg.loc[:,'C_1980_80'].sum()

        h8_up = data_attr_reg.loc[:,'C_1980_80up'].sum()
        h_pos8_up =  data_attr_reg_pos.loc[:,'C_1980_80up'].sum()
        h_neg8_up =  data_attr_reg_neg.loc[:,'C_1980_80up'].sum()

        h8_bot = data_attr_reg.loc[:,'C_1980_80bot'].sum()
        h_pos8_bot =  data_attr_reg_pos.loc[:,'C_1980_80bot'].sum()
        h_neg8_bot =  data_attr_reg_neg.loc[:,'C_1980_80bot'].sum()

        h8_sig = data_attr_reg.loc[:,'p_val_C_1980_80'].sum()
        h_pos8_sig =  data_attr_reg_pos.loc[:,'p_val_C_1980_80'].sum()
        h_neg8_sig =  data_attr_reg_neg.loc[:,'p_val_C_1980_80'].sum()

        h7_sig = data_attr_reg.loc[:,'p_val_C_1980_71'].sum()
        h_pos7_sig =  data_attr_reg_pos.loc[:,'p_val_C_1980_71'].sum()
        h_neg7_sig =  data_attr_reg_neg.loc[:,'p_val_C_1980_71'].sum()

        h107 = data_attr_reg.loc[:,'C_2010_71'].sum()
        h_pos107 =  data_attr_reg_pos.loc[:,'C_2010_71'].sum()
        h_neg107 =  data_attr_reg_neg.loc[:,'C_2010_71'].sum()

        h107_up = data_attr_reg.loc[:,'C_2010_71up'].sum()
        h_pos107_up =  data_attr_reg_pos.loc[:,'C_2010_71up'].sum()
        h_neg107_up =  data_attr_reg_neg.loc[:,'C_2010_71up'].sum()

        h107_bot = data_attr_reg.loc[:,'C_2010_71bot'].sum()
        h_pos107_bot =  data_attr_reg_pos.loc[:,'C_2010_71bot'].sum()
        h_neg107_bot =  data_attr_reg_neg.loc[:,'C_2010_71bot'].sum()

        h108 = data_attr_reg.loc[:,'C_2010_80'].sum()
        h_pos108 =  data_attr_reg_pos.loc[:,'C_2010_80'].sum()
        h_neg108 =  data_attr_reg_neg.loc[:,'C_2010_80'].sum()

        h108_up = data_attr_reg.loc[:,'C_2010_80up'].sum()
        h_pos108_up =  data_attr_reg_pos.loc[:,'C_2010_80up'].sum()
        h_neg108_up =  data_attr_reg_neg.loc[:,'C_2010_80up'].sum()

        h108_bot = data_attr_reg.loc[:,'C_2010_80bot'].sum()
        h_pos108_bot =  data_attr_reg_pos.loc[:,'C_2010_80bot'].sum()
        h_neg108_bot =  data_attr_reg_neg.loc[:,'C_2010_80bot'].sum()

        h108_sig = data_attr_reg.loc[:,'p_val_C_2010_80'].sum()
        h_pos108_sig =  data_attr_reg_pos.loc[:,'p_val_C_2010_80'].sum()
        h_neg108_sig =  data_attr_reg_neg.loc[:,'p_val_C_2010_80'].sum()

        h107_sig = data_attr_reg.loc[:,'p_val_C_2010_71'].sum()
        h_pos107_sig =  data_attr_reg_pos.loc[:,'p_val_C_2010_71'].sum()
        h_neg107_sig =  data_attr_reg_neg.loc[:,'p_val_C_2010_71'].sum()

        x=[0,1,2,4,5,6]
        colour_code = ['#4575b4', '#4575b4', '#4575b4', '#4575b4', '#4575b4', '#4575b4']
        y1= [h_pos8,h8,h_neg8,h_pos7,h7,h_neg7]
        y1err_up= [h_pos8_up,h8_up,h_neg8_up,h_pos7_up,h7_up,h_neg7_up]
        y1err_bot= [h_pos8_bot,h8_bot,h_neg8_bot,h_pos7_bot,h7_bot,h_neg7_bot]
        y1_sig= [h_pos8_sig,h8_sig,h_neg8_sig,h_pos7_sig,h7_sig,h_neg7_sig]

        y2= [h_pos108,h108,h_neg108,h_pos107,h107,h_neg107]
        y2err_up= [h_pos108_up,h108_up,h_neg108_up,h_pos107_up,h107_up,h_neg107_up]
        y2err_bot= [h_pos108_bot,h108_bot,h_neg108_bot,h_pos107_bot,h107_bot,h_neg107_bot]

        y2_sig= [h_pos108_sig,h108_sig,h_neg108_sig,h_pos107_sig,h107_sig,h_neg107_sig]

        ax1_lims_up = [10,10,10,6,5,8,5,35,20,15]

        ax1_lims_low = [-6,-10,-5,-5.2,-4,-8,-5,-5,-10,-10]

        ax2_lims_up = [10,10,10,6,5,8,5,35,20,15]

        ax2_lims_low = [-6,-10,-5,-5,-4,-8,-5,-5,-10,-10]

        ax1_ticks_up = [5,5,5,3,2,5,2,20,10,5]

        ax1_ticks_low = [-5,-5,-5,-3,-2,-5,-2,-5,-5,-5]

        ax2_ticks_up = [5,5,5,3,2,5,2,20,10,5]

        ax2_ticks_low = [-5,-5,-5,-3,-2,-5,-2,-5,-5, -5]

        ax1_labels_up = ['5%', '5%','5%','3%','2%','5%', '2%', '20%','10%','5%']

        ax1_labels_low = ['-5%','-5%','-5%','-3%','-2%','-5','-2%','','-5%','-5%']

        ax2_labels_up = ['5%','5%','5%','3%','2%', '5%','2%', '20%','10%','5%']

        ax2_labels_low = ['-5%','-5%','-5%','-3%','-2%','-5%','-2%','','-5%','-5%']

        if r_lin_pos > 0.2*100:

            f3_ax1.axvspan(-1,0.5, facecolor='gainsboro')
            f3_ax2.axvspan(-1,0.5, facecolor='gainsboro')
            f3_ax1.axvspan(3,4.5, facecolor='gainsboro')
            f3_ax2.axvspan(3,4.5, facecolor='gainsboro')
            #f3_ax2.axvspan(4, 9, facecolor='gainsboro')

        if r_lin_neg > 0.2*100:
            f3_ax1.axvspan(1.5,3., facecolor='gainsboro')
            f3_ax2.axvspan(1.5,3., facecolor='gainsboro')
            f3_ax1.axvspan(5.5,7., facecolor='gainsboro')
            f3_ax2.axvspan(5.5,7., facecolor='gainsboro')

        if r_lin > 0.2*100:

            f3_ax1.axvspan(0.5,1.5, facecolor='gainsboro')
            f3_ax2.axvspan(0.5,1.5, facecolor='gainsboro')
            f3_ax1.axvspan(4.5,5.5, facecolor='gainsboro')
            f3_ax2.axvspan(4.5,5.5, facecolor='gainsboro')

        for a in range(6):

            if not ((r==1 and a==0)or (r==1 and a==3)) :

                if y1_sig[a]<0.1:
                    if y1_sig[a] < 0.01:

                        f3_ax1.errorbar(x[a],y1[a], color =colour_code[a], fmt='D', yerr=np.reshape(np.array([y1err_bot[a],y1err_up[a]]), (2,1)),ecolor=colour_code[a])
                    elif y1_sig[a] < 0.05:

                        f3_ax1.errorbar(x[a],y1[a], color =colour_code[a], fmt='s', yerr=np.reshape(np.array([y1err_bot[a],y1err_up[a]]), (2,1)),ecolor=colour_code[a])

                    else:
                        f3_ax1.errorbar(x[a],y1[a], color =colour_code[a], fmt='^', yerr=np.reshape(np.array([y1err_bot[a],y1err_up[a]]), (2,1)),ecolor=colour_code[a])

                else:
                    f3_ax1.errorbar(x[a],y1[a], color = colour_code[a], fmt='o', yerr=np.reshape(np.array([y1err_bot[a],y1err_up[a]]), (2,1)), ecolor=colour_code[a],mfc ='w')

        for a in range(6):

            if not ((r==1 and a==0)or (r==1 and a==3)) :

                if y2_sig[a]<0.1:

                    if y2_sig[a] < 0.01:

                        f3_ax2.errorbar(x[a],y2[a], color =colour_code[a], yerr=np.reshape(np.array([y2err_bot[a],y2err_up[a]]), (2,1)), ecolor=colour_code[a], fmt= 'D')

                    elif y2_sig[a] < 0.05:

                        f3_ax2.errorbar(x[a],y2[a], color =colour_code[a], yerr=np.reshape(np.array([y2err_bot[a],y2err_up[a]]), (2,1)), ecolor=colour_code[a], fmt= 's')
                    else:

                        f3_ax2.errorbar(x[a],y2[a], color =colour_code[a], yerr=np.reshape(np.array([y2err_bot[a],y2err_up[a]]), (2,1)), ecolor=colour_code[a], fmt= '^')

                else:
                    f3_ax2.errorbar(x[a],y2[a], color =colour_code[a], yerr=np.reshape(np.array([y2err_bot[a],y2err_up[a]]), (2,1)), ecolor=colour_code[a], fmt='o',mfc ='w')

        f3_ax1.set_ylim(ax1_lims_low[r],ax1_lims_up[r])

        f3_ax1.set_yticks([ax1_ticks_low[r] , 0, ax1_ticks_up[r]])

        f3_ax1.set_yticklabels([ax1_labels_low[r],'0', ax1_labels_up[r] ],fontsize =5.5)

        f3_ax2.set_ylim(ax2_lims_low[r],ax2_lims_up[r])

        f3_ax2.set_yticks([ax2_ticks_low[r] , 0, ax2_ticks_up[r]])

        f3_ax2.set_yticklabels([ax2_labels_low[r],'0', ax2_labels_up[r] ],fontsize =5.5)
        f3_ax1.tick_params(axis="y",length = 3, pad = 0.7)
        f3_ax2.tick_params(axis="y",length = 3, pad = 0.7)
        f3_ax1.set_xlim(-1.,7)
        f3_ax2.set_xlim(-1.,7)

        f3_ax1.axvline(x=3,linewidth=0.3, color='k', linestyle = '-', alpha = 0.5)
        f3_ax2.axvline(x=3,linewidth=0.3, color='k', linestyle = '-', alpha = 0.5)

        f3_ax2.set_xticks([0,1,2,4,5,6])

        f3_ax2.set_xticklabels(['$R_{+}$', '$R$', '$R_{-}$','$R_{+}$',  '$R$', '$R_{-}$'], fontsize = 7)

        lab = [0,1,4,7]

        if r in lab:
            f3_ax1.set_ylabel('$C_{1980}$ in % per year',  fontsize = 6.5, labelpad=0.1)
            f3_ax2.set_ylabel('$C_{2010}$',  fontsize = 6.5, labelpad=0.1, )

        f3_ax1.set_xlabel('1980-2010               1971-2010',  fontsize = 5.5, labelpad=-7)
        f3_ax1.xaxis.set_label_position('top')
        #f3_ax2.axhline(y=-5,linewidth=0.2, color='k', linestyle = '-.')
        f3_ax1.axhline(y=0,linewidth=0.3, color='k', linestyle = '-')
        f3_ax2.axhline(y=0,linewidth=0.3, color='k', linestyle = '-')

        if (i == 1) and (j==1):
            f3_ax1.set_title(' '+ region_names[regions[r]], position = (0.5,1.), fontsize = 7)

        elif (i == 2) and ((j ==0) or (j==1)):

            f3_ax1.set_title(' '+ region_names[regions[r]], position = (0.5,1.), fontsize = 7)
        else:
            f3_ax1.set_title(' '+ region_names[regions[r]], position = (0.5,1.), fontsize = 7)

        r+=1

f3_ax4 = fig3.add_subplot(gs[0:5,10:14])
handles, labels = f3_ax4.get_legend_handles_labels()
f3_ax4.axis('off')

circle = Line2D([0], [0], marker='o', color='w', label='non-significant',
                        markeredgecolor='#4575b4', markersize=5.5)
triangle = Line2D([0], [0], marker='^', color='w', label='significant at 10%',
                        markerfacecolor='#4575b4', markersize=6.5)
square = Line2D([0], [0], marker='s', color='w', label='significant at 5%',
                        markerfacecolor='#4575b4', markersize=6)
diam = Line2D([0], [0], marker='D', color='w', label='significant at 1%',
                        markerfacecolor='#4575b4', markersize=5.5)

f3_ax4.legend(handles = [diam, square,triangle,circle], frameon=True, fontsize = 6, loc = 'center', edgecolor = 'k')

plt.savefig('../../data/figures/Figure4.pdf',bbox_inches = 'tight', format = 'pdf')


"""LLM Model Endpoint routes for the hosted model inference service.
"""
import traceback
from datetime import datetime
from typing import Optional

import pytz
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Query, Request
from model_engine_server.api.dependencies import (
    ExternalInterfaces,
    get_external_interfaces,
    get_external_interfaces_read_only,
    verify_authentication,
)
from model_engine_server.common.dtos.llms import (
    CancelFineTuneResponse,
    CompletionStreamV1Request,
    CompletionStreamV1Response,
    CompletionSyncV1Request,
    CompletionSyncV1Response,
    CreateFineTuneRequest,
    CreateFineTuneResponse,
    CreateLLMModelEndpointV1Request,
    CreateLLMModelEndpointV1Response,
    DeleteLLMEndpointResponse,
    GetFineTuneEventsResponse,
    GetFineTuneResponse,
    GetLLMModelEndpointV1Response,
    ListFineTunesResponse,
    ListLLMModelEndpointsV1Response,
    ModelDownloadRequest,
    ModelDownloadResponse,
    StreamError,
    StreamErrorContent,
    TokenUsage,
    UpdateLLMModelEndpointV1Request,
    UpdateLLMModelEndpointV1Response,
)
from model_engine_server.common.dtos.model_endpoints import ModelEndpointOrderBy
from model_engine_server.core.auth.authentication_repository import User
from model_engine_server.core.loggers import (
    LoggerTagKey,
    LoggerTagManager,
    logger_name,
    make_logger,
)
from model_engine_server.core.utils.timer import timer
from model_engine_server.domain.exceptions import (
    DockerImageNotFoundException,
    EndpointDeleteFailedException,
    EndpointLabelsException,
    EndpointResourceInvalidRequestException,
    EndpointUnsupportedInferenceTypeException,
    ExistingEndpointOperationInProgressException,
    InvalidRequestException,
    LLMFineTuningMethodNotImplementedException,
    LLMFineTuningQuotaReached,
    ObjectAlreadyExistsException,
    ObjectHasInvalidValueException,
    ObjectNotAuthorizedException,
    ObjectNotFoundException,
    UpstreamServiceError,
)
from model_engine_server.domain.gateways.monitoring_metrics_gateway import MetricMetadata
from model_engine_server.domain.use_cases.llm_fine_tuning_use_cases import (
    CancelFineTuneV1UseCase,
    CreateFineTuneV1UseCase,
    GetFineTuneEventsV1UseCase,
    GetFineTuneV1UseCase,
    ListFineTunesV1UseCase,
)
from model_engine_server.domain.use_cases.llm_model_endpoint_use_cases import (
    CompletionStreamV1UseCase,
    CompletionSyncV1UseCase,
    CreateLLMModelBundleV1UseCase,
    CreateLLMModelEndpointV1UseCase,
    DeleteLLMEndpointByNameUseCase,
    GetLLMModelEndpointByNameV1UseCase,
    ListLLMModelEndpointsV1UseCase,
    ModelDownloadV1UseCase,
    UpdateLLMModelEndpointV1UseCase,
)
from model_engine_server.domain.use_cases.model_bundle_use_cases import CreateModelBundleV2UseCase
from sse_starlette.sse import EventSourceResponse

def format_request_route(request: Request) -> str:
    url_path = request.url.path
    for path_param in request.path_params:
        url_path = url_path.replace(request.path_params[path_param], f":{path_param}")
    return f"{request.method}_{url_path}".lower()

async def get_metric_metadata(
    request: Request,
    auth: User = Depends(verify_authentication),
) -> MetricMetadata:
    model_name = request.query_params.get("model_endpoint_name", None)
    return MetricMetadata(user=auth, model_name=model_name)

async def record_route_call(
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces_read_only),
    route: str = Depends(format_request_route),
    metric_metadata: MetricMetadata = Depends(get_metric_metadata),
):
    external_interfaces.monitoring_metrics_gateway.emit_route_call_metric(route, metric_metadata)

llm_router_v1 = APIRouter(prefix="/v1/llm", dependencies=[Depends(record_route_call)])
logger = make_logger(logger_name())

def handle_streaming_exception(
    e: Exception,
    code: int,
    message: str,
):
    tb_str = traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__)
    request_id = LoggerTagManager.get(LoggerTagKey.REQUEST_ID)
    timestamp = datetime.now(pytz.timezone("US/Pacific")).strftime("%Y-%m-%d %H:%M:%S %Z")
    structured_log = {
        "error": message,
        "request_id": str(request_id),
        "traceback": "".join(tb_str),
    }
    logger.error("Exception: %s", structured_log)
    return {
        "data": CompletionStreamV1Response(
            request_id=str(request_id),
            error=StreamError(
                status_code=code,
                content=StreamErrorContent(
                    error=message,
                    timestamp=timestamp,
                ),
            ),
        ).json()
    }

@llm_router_v1.post("/model-endpoints", response_model=CreateLLMModelEndpointV1Response)
async def create_model_endpoint(
    request: CreateLLMModelEndpointV1Request,
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces),
) -> CreateLLMModelEndpointV1Response:
    """
    Creates an LLM endpoint for the current user.
    """
    logger.info(f"POST /llm/model-endpoints with {request} for {auth}")
    try:
        create_model_bundle_use_case = CreateModelBundleV2UseCase(
            model_bundle_repository=external_interfaces.model_bundle_repository,
            docker_repository=external_interfaces.docker_repository,
            model_primitive_gateway=external_interfaces.model_primitive_gateway,
        )
        create_llm_model_bundle_use_case = CreateLLMModelBundleV1UseCase(
            create_model_bundle_use_case=create_model_bundle_use_case,
            model_bundle_repository=external_interfaces.model_bundle_repository,
            llm_artifact_gateway=external_interfaces.llm_artifact_gateway,
            docker_repository=external_interfaces.docker_repository,
        )
        use_case = CreateLLMModelEndpointV1UseCase(
            create_llm_model_bundle_use_case=create_llm_model_bundle_use_case,
            model_endpoint_service=external_interfaces.model_endpoint_service,
            docker_repository=external_interfaces.docker_repository,
        )
        return await use_case.execute(user=auth, request=request)
    except ObjectAlreadyExistsException as exc:
        raise HTTPException(
            status_code=400,
            detail="The specified model endpoint already exists.",
        ) from exc
    except EndpointLabelsException as exc:
        raise HTTPException(
            status_code=400,
            detail=str(exc),
        ) from exc
    except ObjectHasInvalidValueException as exc:
        raise HTTPException(status_code=400, detail=str(exc))
    except EndpointResourceInvalidRequestException as exc:
        raise HTTPException(
            status_code=400,
            detail=str(exc),
        ) from exc
    except (ObjectNotFoundException, ObjectNotAuthorizedException) as exc:
        raise HTTPException(
            status_code=404,
            detail="The specified model bundle could not be found.",
        ) from exc
    except DockerImageNotFoundException as exc:
        raise HTTPException(
            status_code=404,
            detail="The specified docker image could not be found.",
        ) from exc

@llm_router_v1.get("/model-endpoints", response_model=ListLLMModelEndpointsV1Response)
async def list_model_endpoints(
    name: Optional[str] = Query(default=None),
    order_by: Optional[ModelEndpointOrderBy] = Query(default=None),
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces_read_only),
) -> ListLLMModelEndpointsV1Response:
    """
    Lists the LLM model endpoints owned by the current owner, plus all public_inference LLMs.
    """
    logger.info(f"GET /llm/model-endpoints?name={name}&order_by={order_by} for {auth}")
    use_case = ListLLMModelEndpointsV1UseCase(
        llm_model_endpoint_service=external_interfaces.llm_model_endpoint_service,
    )
    return await use_case.execute(user=auth, name=name, order_by=order_by)

@llm_router_v1.get(
    "/model-endpoints/{model_endpoint_name}", response_model=GetLLMModelEndpointV1Response
)
async def get_model_endpoint(
    model_endpoint_name: str,
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces_read_only),
) -> GetLLMModelEndpointV1Response:
    """
    Describe the LLM Model endpoint with given name.
    """
    logger.info(f"GET /llm/model-endpoints/{model_endpoint_name} for {auth}")
    try:
        use_case = GetLLMModelEndpointByNameV1UseCase(
            llm_model_endpoint_service=external_interfaces.llm_model_endpoint_service
        )
        return await use_case.execute(user=auth, model_endpoint_name=model_endpoint_name)
    except (ObjectNotFoundException, ObjectNotAuthorizedException) as exc:
        raise HTTPException(
            status_code=404,
            detail=f"Model Endpoint {model_endpoint_name}  was not found.",
        ) from exc

@llm_router_v1.put(
    "/model-endpoints/{model_endpoint_name}", response_model=UpdateLLMModelEndpointV1Response
)
async def update_model_endpoint(
    model_endpoint_name: str,
    request: UpdateLLMModelEndpointV1Request,
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces),
) -> UpdateLLMModelEndpointV1Response:
    """
    Updates an LLM endpoint for the current user.
    """
    logger.info(f"PUT /llm/model-endpoints/{model_endpoint_name} with {request} for {auth}")
    try:
        create_model_bundle_use_case = CreateModelBundleV2UseCase(
            model_bundle_repository=external_interfaces.model_bundle_repository,
            docker_repository=external_interfaces.docker_repository,
            model_primitive_gateway=external_interfaces.model_primitive_gateway,
        )
        create_llm_model_bundle_use_case = CreateLLMModelBundleV1UseCase(
            create_model_bundle_use_case=create_model_bundle_use_case,
            model_bundle_repository=external_interfaces.model_bundle_repository,
            llm_artifact_gateway=external_interfaces.llm_artifact_gateway,
            docker_repository=external_interfaces.docker_repository,
        )
        use_case = UpdateLLMModelEndpointV1UseCase(
            create_llm_model_bundle_use_case=create_llm_model_bundle_use_case,
            model_endpoint_service=external_interfaces.model_endpoint_service,
            llm_model_endpoint_service=external_interfaces.llm_model_endpoint_service,
            docker_repository=external_interfaces.docker_repository,
        )
        return await use_case.execute(
            user=auth, model_endpoint_name=model_endpoint_name, request=request
        )
    except EndpointLabelsException as exc:
        raise HTTPException(
            status_code=400,
            detail=str(exc),
        ) from exc
    except ObjectHasInvalidValueException as exc:
        raise HTTPException(status_code=400, detail=str(exc))
    except EndpointResourceInvalidRequestException as exc:
        raise HTTPException(
            status_code=400,
            detail=str(exc),
        ) from exc
    except (ObjectNotFoundException, ObjectNotAuthorizedException) as exc:
        raise HTTPException(
            status_code=404,
            detail="The specified LLM endpoint could not be found.",
        ) from exc
    except DockerImageNotFoundException as exc:
        raise HTTPException(
            status_code=404,
            detail="The specified docker image could not be found.",
        ) from exc

@llm_router_v1.post("/completions-sync", response_model=CompletionSyncV1Response)
async def create_completion_sync_task(
    model_endpoint_name: str,
    request: CompletionSyncV1Request,
    background_tasks: BackgroundTasks,
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces_read_only),
    metric_metadata: MetricMetadata = Depends(get_metric_metadata),
) -> CompletionSyncV1Response:
    """
    Runs a sync prompt completion on an LLM.
    """
    logger.info(
        f"POST /completion_sync with {request} to endpoint {model_endpoint_name} for {auth}"
    )
    try:
        use_case = CompletionSyncV1UseCase(
            model_endpoint_service=external_interfaces.model_endpoint_service,
            llm_model_endpoint_service=external_interfaces.llm_model_endpoint_service,
            tokenizer_repository=external_interfaces.tokenizer_repository,
        )
        with timer() as use_case_timer:
            response = await use_case.execute(
                user=auth, model_endpoint_name=model_endpoint_name, request=request
            )
        background_tasks.add_task(
            external_interfaces.monitoring_metrics_gateway.emit_token_count_metrics,
            TokenUsage(
                num_prompt_tokens=response.output.num_prompt_tokens if response.output else None,
                num_completion_tokens=response.output.num_completion_tokens
                if response.output
                else None,
                total_duration=use_case_timer.duration,
            ),
            metric_metadata,
        )
        return response
    except UpstreamServiceError:
        request_id = LoggerTagManager.get(LoggerTagKey.REQUEST_ID)
        logger.exception(f"Upstream service error for request {request_id}")
        raise HTTPException(
            status_code=500,
            detail=f"Upstream service error for request_id {request_id}.",
        )
    except (ObjectNotFoundException, ObjectNotAuthorizedException) as exc:
        raise HTTPException(
            status_code=404,
            detail="The specified endpoint could not be found.",
        ) from exc
    except ObjectHasInvalidValueException as exc:
        raise HTTPException(status_code=400, detail=str(exc))
    except InvalidRequestException as exc:
        raise HTTPException(status_code=400, detail=str(exc))
    except EndpointUnsupportedInferenceTypeException as exc:
        raise HTTPException(
            status_code=400,
            detail=f"Unsupported inference type: {str(exc)}",
        ) from exc

@llm_router_v1.post("/completions-stream", response_model=CompletionStreamV1Response)
async def create_completion_stream_task(
    model_endpoint_name: str,
    request: CompletionStreamV1Request,
    background_tasks: BackgroundTasks,
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces_read_only),
    metric_metadata: MetricMetadata = Depends(get_metric_metadata),
) -> EventSourceResponse:
    """
    Runs a stream prompt completion on an LLM.
    """
    logger.info(
        f"POST /completion_stream with {request} to endpoint {model_endpoint_name} for {auth}"
    )
    use_case = CompletionStreamV1UseCase(
        model_endpoint_service=external_interfaces.model_endpoint_service,
        llm_model_endpoint_service=external_interfaces.llm_model_endpoint_service,
        tokenizer_repository=external_interfaces.tokenizer_repository,
    )
    response = use_case.execute(user=auth, model_endpoint_name=model_endpoint_name, request=request)

    async def event_generator():
        try:
            with timer() as use_case_timer:
                async for message in response:
                    yield {"data": message.json()}
            background_tasks.add_task(
                external_interfaces.monitoring_metrics_gateway.emit_token_count_metrics,
                TokenUsage(
                    num_prompt_tokens=message.output.num_prompt_tokens if message.output else None,
                    num_completion_tokens=message.output.num_completion_tokens
                    if message.output
                    else None,
                    total_duration=use_case_timer.duration,
                ),
                metric_metadata,
            )
        except (InvalidRequestException, ObjectHasInvalidValueException) as exc:
            yield handle_streaming_exception(exc, 400, str(exc))
        except (
            ObjectNotFoundException,
            ObjectNotAuthorizedException,
            EndpointUnsupportedInferenceTypeException,
        ) as exc:
            yield handle_streaming_exception(exc, 404, str(exc))
        except Exception as exc:
            yield handle_streaming_exception(
                exc, 500, "Internal error occurred. Our team has been notified."
            )

    return EventSourceResponse(event_generator())

@llm_router_v1.post("/fine-tunes", response_model=CreateFineTuneResponse)
async def create_fine_tune(
    request: CreateFineTuneRequest,
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces),
) -> CreateFineTuneResponse:
    logger.info(f"POST /fine-tunes with {request} for {auth}")
    try:
        use_case = CreateFineTuneV1UseCase(
            llm_fine_tuning_service=external_interfaces.llm_fine_tuning_service,
            model_endpoint_service=external_interfaces.model_endpoint_service,
            llm_fine_tune_events_repository=external_interfaces.llm_fine_tune_events_repository,
            file_storage_gateway=external_interfaces.file_storage_gateway,
        )
        return await use_case.execute(user=auth, request=request)
    except (ObjectNotFoundException, ObjectNotAuthorizedException) as exc:
        raise HTTPException(status_code=404, detail=str(exc)) from exc
    except (
        LLMFineTuningMethodNotImplementedException,
        LLMFineTuningQuotaReached,
        InvalidRequestException,
    ) as exc:
        raise HTTPException(
            status_code=400,
            detail=str(exc),
        ) from exc

@llm_router_v1.get("/fine-tunes/{fine_tune_id}", response_model=GetFineTuneResponse)
async def get_fine_tune(
    fine_tune_id: str,
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces_read_only),
) -> GetFineTuneResponse:
    logger.info(f"GET /fine-tunes/{fine_tune_id} for {auth}")
    try:
        use_case = GetFineTuneV1UseCase(
            llm_fine_tuning_service=external_interfaces.llm_fine_tuning_service,
        )
        return await use_case.execute(user=auth, fine_tune_id=fine_tune_id)
    except (ObjectNotFoundException, ObjectNotAuthorizedException) as exc:
        raise HTTPException(
            status_code=404,
            detail="The specified fine-tune job could not be found.",
        ) from exc

@llm_router_v1.get("/fine-tunes", response_model=ListFineTunesResponse)
async def list_fine_tunes(
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces_read_only),
) -> ListFineTunesResponse:
    logger.info(f"GET /fine-tunes for {auth}")
    use_case = ListFineTunesV1UseCase(
        llm_fine_tuning_service=external_interfaces.llm_fine_tuning_service,
    )
    return await use_case.execute(user=auth)

@llm_router_v1.put("/fine-tunes/{fine_tune_id}/cancel", response_model=CancelFineTuneResponse)
async def cancel_fine_tune(
    fine_tune_id: str,
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces),
) -> CancelFineTuneResponse:
    logger.info(f"PUT /fine-tunes/{fine_tune_id}/cancel for {auth}")
    try:
        use_case = CancelFineTuneV1UseCase(
            llm_fine_tuning_service=external_interfaces.llm_fine_tuning_service,
        )
        return await use_case.execute(user=auth, fine_tune_id=fine_tune_id)
    except (ObjectNotFoundException, ObjectNotAuthorizedException) as exc:
        raise HTTPException(
            status_code=404,
            detail="The specified fine-tune job could not be found.",
        ) from exc

@llm_router_v1.get("/fine-tunes/{fine_tune_id}/events", response_model=GetFineTuneEventsResponse)
async def get_fine_tune_events(
    fine_tune_id: str,
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces_read_only),
) -> GetFineTuneEventsResponse:
    logger.info(f"GET /fine-tunes/{fine_tune_id}/events for {auth}")
    try:
        use_case = GetFineTuneEventsV1UseCase(
            llm_fine_tune_events_repository=external_interfaces.llm_fine_tune_events_repository,
            llm_fine_tuning_service=external_interfaces.llm_fine_tuning_service,
        )
        return await use_case.execute(user=auth, fine_tune_id=fine_tune_id)
    except (ObjectNotFoundException, ObjectNotAuthorizedException) as exc:
        raise HTTPException(
            status_code=404,
            detail="The specified fine-tune job's events could not be found.",
        ) from exc

@llm_router_v1.post("/model-endpoints/download", response_model=ModelDownloadResponse)
async def download_model_endpoint(
    request: ModelDownloadRequest,
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces),
) -> ModelDownloadResponse:
    logger.info(f"POST /model-endpoints/download with {request} for {auth}")
    try:
        use_case = ModelDownloadV1UseCase(
            filesystem_gateway=external_interfaces.filesystem_gateway,
            model_endpoint_service=external_interfaces.model_endpoint_service,
            llm_artifact_gateway=external_interfaces.llm_artifact_gateway,
        )
        return await use_case.execute(user=auth, request=request)
    except (ObjectNotFoundException, ObjectHasInvalidValueException) as exc:
        raise HTTPException(
            status_code=404,
            detail="The requested fine-tuned model could not be found.",
        ) from exc

@llm_router_v1.delete(
    "/model-endpoints/{model_endpoint_name}", response_model=DeleteLLMEndpointResponse
)
async def delete_llm_model_endpoint(
    model_endpoint_name: str,
    auth: User = Depends(verify_authentication),
    external_interfaces: ExternalInterfaces = Depends(get_external_interfaces),
) -> DeleteLLMEndpointResponse:
    logger.info(f"DELETE /model-endpoints/{model_endpoint_name} for {auth}")
    try:
        use_case = DeleteLLMEndpointByNameUseCase(
            llm_model_endpoint_service=external_interfaces.llm_model_endpoint_service,
            model_endpoint_service=external_interfaces.model_endpoint_service,
        )
        return await use_case.execute(user=auth, model_endpoint_name=model_endpoint_name)
    except ObjectNotFoundException as exc:
        raise HTTPException(
            status_code=404,
            detail="The requested model endpoint could not be found.",
        ) from exc
    except ObjectNotAuthorizedException as exc:
        raise HTTPException(
            status_code=403,
            detail="You don't have permission to delete the requested model endpoint.",
        ) from exc
    except ExistingEndpointOperationInProgressException as exc:
        raise HTTPException(
            status_code=409,
            detail="Existing operation on endpoint in progress, try again later.",
        ) from exc
    except EndpointDeleteFailedException as exc:  # pragma: no cover
        raise HTTPException(
            status_code=500,
            detail="deletion of endpoint failed.",
        ) from exc


def solution(answers):
    rules = [
        0,
        [1,2,3,4,5],
        [2,1,2,3,2,4,2,5],
        [3,3,1,1,2,2,4,4,5,5]
    ]
    repeat = [0,5,8,10]
    correct = [0,0,0,0]
    for i,answer in enumerate(answers):
        for j in range(1,4):
            if answer == rules[j][i%repeat[j]]:
                correct[j] += 1
    max_correct = correct[1]
    result = [1]
    for i in range(2,4):
        if correct[i] > max_correct:
            max_correct = correct[i]
            result = [i]
        elif correct[i] == max_correct:
            result.append(i)
    return result

answers = [1,2,3,4,5]
print(solution(answers))


import requests
from requests.auth import HTTPBasicAuth
import sys

# PRE-DEFINED VAR
auth = HTTPBasicAuth(str(sys.argv[2]), str(sys.argv[3]))
redmine_url = str(sys.argv[1])
headers = {"Content-Type": "application/json"}

# PRE-DEFINED DEF
# def get_user_id():
#     r = requests.get(redmine_url + '/users/current.json', auth=auth)
#     user_id = r.json()['user']['id']
#     return user_id
#
#
# def get_spent_time_on_date(date):
#     r = requests.get(redmine_url + '/time_entries.json?from=' + date + '&to=' + date + '&user_id=' +
#                      str(get_user_id()), auth=auth)
#     spent_time = 0
#     for time_entry in r.json()['time_entries']:
#         spent_time += time_entry['hours']
#     return spent_time

# get UNCONFIRMED tasks (status_id=2) and set to CONFIRMED
response = requests.get(redmine_url + '/issues.json?assigned_to_id=me&status_id=2&limit=200', auth=auth)
for issue in response.json()['issues']:
    try:
        r = requests.put(redmine_url + '/issues/' + str(issue['id']) + ".json", data='{"issue": {"status_id": 3}}',
                         auth=auth, headers=headers)
        if r.status_code == 200:
            print("Updated issue(" + str(issue['id']) + ") status from UNCONFIRMED to CONFIRMED successfully")
        else:
            print("Can not update issue(" + str(issue['id']) + ") status from UNCONFIRMED to CONFIRMED ")
    except Exception as e:
        print(e)

# log time for CONFIRMED tasks (currently only support tasks have start_date==due_date)
response = requests.get(redmine_url + '/issues.json?assigned_to_id=me&status_id=3&limit=200', auth=auth)
for issue in response.json()['issues']:
    try:
        if issue['start_date'] == issue['due_date']:
            estimated_hours = issue['estimated_hours']
            r = requests.get(redmine_url + '/time_entries.json?issue_id=' + str(issue['id']), auth=auth)
            data_time_entries = r.json()
            spent_time = 0
            for time_entry in data_time_entries['time_entries']:
                spent_time += time_entry['hours']
            if estimated_hours > spent_time:
                r_data = '{"time_entry": {"issue_id": ' + str(issue['id']) + ', "spent_on": "' + issue["due_date"] + \
                         '", "hours": ' + str(estimated_hours - spent_time) + '}}'
                r = requests.post(redmine_url + '/time_entries.json', data=r_data, auth=auth,
                                  headers=headers)
                if r.status_code == 404:
                    print("Logged time for issue(" + str(issue['id']) + ") successfully")
                else:
                    print("Can not log time for issue(" + str(issue['id']) + ") successfully")
            # get CONFIRMED tasks (status_id=3) and set to RESOLVED
            # (currently only support tasks have start_date==due_date)
            r = requests.put(redmine_url + '/issues/' + str(issue['id']) + ".json", data='{"issue": {"status_id": 5}}',
                             auth=auth, headers=headers)
            if r.status_code == 200:
                print("Updated issue(" + str(issue['id']) + ") status from CONFIRMED to RESOLVED successfully")
            else:
                print("Can not update issue(" + str(issue['id']) + ") status from CONFIRMED to RESOLVED ")
        else:
            print("Currently not support logging time for tasks that have start_date!=due_date, "
                  "log time manually by yourself, task id: " + str(issue['id']))
    except Exception as e:
        print(e)


import re
from datetime import datetime

class LinksysParser:
    """
    This class parses the HTML returned by the Linksys EA3500 router's
    web-based management UI. The HTML is peppered with JavaScript calls
    to document.write, and so is not parsable with a standard HTML parser.
    """

    def parse_mac_blacklist(self, html):
        """
        Parses the HTML from the router's MAC Address Filter
        page and returns a list of MAC addresses currently on
        the blocked list.
        """
        # The easiest way to parse the addresses on the MAC blacklist
        # is to pull them out of the diagnostic output that the router
        # puts in plain text at the top of the page. Otherwise, we have
        # to parse it from the JavaScript, which is quite messy on this
        # page. The entries look like this:
        #
        # //			1. 22:22:22:22:22:22
        # //			2. 00:33:33:33:33:33
        mac_addrs = []
        for m in re.finditer(r'//\s+\d+\. (\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)',
                             html):
            mac_addrs.append(m.group(1))
        return mac_addrs

    def parse_dhcp_clients(self, html):
        """
        Parses the HTML from the router's DHCP clients
        page and returns a list of clients currently that have a
        leased DHCP address. The returned list contains dictionaries
        with these entries:

        hostname:       Hostname of the machine holding the lease
        ip_address:     IP address assigned to the machine
        mac_address:    The client machine's MAC address
        interface:      WLAN for wireless, LAN for wired
        lease_expires:  Time today when the client's DHCP lease expires
        """
        clients = []
        # DHCP client entries appear in JavaScript like this:
        # new AAA('Wii','192.168.1.108','00:23:31:6b:a9:89','23:53:37','WLAN')
        # Let's extract what's inside the parens.
        for m in re.finditer(r'AAA\((.*)\);', html):
            client = m.group(1).replace("'", "").split(",")

            # Skip dummy entries
            if client[0] == "wlanadv.none":
                continue

            clients.append({ 'hostname': client[0],
                             'ip_address': client[1],
                             'mac_address': client[2],
                             'interface': client[4],
                             'lease_expires': client[3] })
        return clients

    # No longer in use
    def parse_time(self, time_str):
        """
        Given a string in hh:mm:ss format, returns a datetime object
        representing that time on today's date.
        """
        time = time_str.split(":")
        return datetime.now().replace(hour = int(time[0], 10),
                                      minute = int(time[1], 10),
                                      second = int(time[2], 10))


'''List of movies rendered in a HTML page and opened in a browser. '''
# Created by Ramiro Trejo, 2015.

import media
import fresh_tomatoes

# creating instances of class Movie
goonies = media.Movie(
                "Goonies",
                "https://www.youtube.com/watch?v=kFEfHCJG4G4",
                "https://upload.wikimedia.org/wikipedia/" +
                "en/c/c6/The_Goonies.jpg",
                "1985",
                "Richard Donner",
                "Adventure",
                "114")

blade_runner = media.Movie(
                "Blade Runner",
                "https://www.youtube.com/watch?v=hiH4hxhKBmY",
                "https://upload.wikimedia.org/wikipedia/" +
                "en/5/53/Blade_Runner_poster.jpg",
                "1982",
                "Ridley Scott",
                "Science Fiction",
                "116")

juno = media.Movie(
                "Juno",
                "https://www.youtube.com/watch?v=K0SKf0K3bxg",
                "https://upload.wikimedia.org/wikipedia/en" +
                "/e/ec/Junoposter2007.jpg",
                "2007",
                "Jason Reitman",
                "Drama",
                "96")

inception = media.Movie(
                "Inception",
                "https://www.youtube.com/watch?v=1g4PLj0PlOM",
                "https://upload.wikimedia.org/wikipedia/en" +
                "/7/7f/Inception_ver3.jpg",
                "2010",
                "Christopher Nolan",
                "Thriller",
                "148")

pans_labyrinth = media.Movie(
                "Pan's Labyrinth",
                "https://www.youtube.com/watch?v=EqYiSlkvRuw",
                "https://upload.wikimedia.org/wikipedia/en" +
                "/6/67/Pan%27s_Labyrinth.jpg",
                "2006",
                "Guillermo del Torro",
                "Fantasy",
                "119")

space_oydessy_2001 = media.Movie(
                "2001: A Space Odyssey",
                "https://www.youtube.com/watch?v=E8TABIFAN4o",
                "https://upload.wikimedia.org/wikipedia/en" +
                "/e/ef/2001_A_Space_Odyssey_Style_B.jpg",
                "1968",
                "Stanley Kubrick",
                "Science Fiction",
                "142")

terminator_2 = media.Movie(
                "Terminator 2: Judgement Day",
                "https://www.youtube.com/watch?v=F1os6UU6jhU",
                "https://upload.wikimedia.org/" +
                "wikipedia/en/8/85/Terminator2poster.jpg",
                "1991",
                "James Cameron",
                "Science Fiction",
                "136")

elm_street = media.Movie(
                "A Nightmare on Elm Street",
                "https://www.youtube.com/watch?v=dCVh4lBfW-c",
                "https://upload.wikimedia.org/wikipedia/en" +
                "/a/a1/Nightmare01.jpg",
                "1984",
                "Wes Craven",
                "Horror",
                "91")

# holds all movie objects in a list
list_fav_movies = [
            goonies,
            blade_runner,
            juno,
            inception,
            pans_labyrinth,
            space_oydessy_2001,
            terminator_2,
            elm_street]

# opens html page with movie data embedded
fresh_tomatoes.open_movies_page(list_fav_movies)


from flask import Flask, render_template, request, redirect, session, url_for
import time
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import spotipy.util as util
import random
import json
import sys
import webbrowser
import uuid
from flask_session import Session
import os
import pandas as pd
import requests
import subprocess

debug = False

class Song:
    def __init__(self, name, artist, album, album_id, play_count, sound_clip, image):
        self.name = name
        self.artist = artist
        self.album = album
        self.album_id = album_id
        self.play_count = play_count
        self.sound_clip = sound_clip
        self.image = image

    def update_play_count(self):
        self.play_count = self.get_play_count()
        return self

    def get_play_count(self):
        r = requests.get(f"https://api.t4ils.dev/albumPlayCount?albumid={self.album_id}").json()   # gets all the metatdata from the public API
        album_discs = r['data']['discs']    # list of album discs
        for disc in album_discs:            # goes thru each disc
            album_tracks = disc['tracks']   # gets list of song on a disc
            for track in album_tracks:      # goes thru each song in the list
                if track['name'] == self.name:
                    return track['playcount']
        return -1

class Playlist:
    def __init__(self, name, id):
        self.id = id
        self.name = name
        self.songs = []

    def populate(self, sp):
        tracks = get_all_playlist_tracks(playlist_id_in=self.id, sp = sp)
        for song in tracks:
            temp_name = song['track']['name']
            temp_artist = song['track']['artists'][0]['name']
            temp_album = song['track']['album']['name']
            temp_album_id = song['track']['album']['id']
            temp_play_count = 0
            temp_clip = song['track']['preview_url']
            temp_image = song['track']['album']['images'][0]['url']
            self.songs.append(Song(temp_name, temp_artist, temp_album, temp_album_id, temp_play_count, temp_clip, temp_image))

    def toJson(self):
        return json.dumps(self, default=lambda o: o.__dict__)

    def size(self):
        return len(self.songs)

def get_all_playlist_tracks(playlist_id_in, sp):
    if playlist_id_in == 'liked_songs':
        results = sp.current_user_saved_tracks()
    else:
        results = sp.user_playlist_tracks(playlist_id = playlist_id_in)
    tracks = results['items']
    while results['next']:
        results = sp.next(results)
        tracks.extend(results['items'])
    return tracks

def create_playlists(sp):
    lists = sp.current_user_playlists()['items']
    ret_pls = []
    for playlist in lists:
        ret_pls.append(Playlist(playlist['name'], playlist['id']))
    ret_pls.append(Playlist("Liked Songs", "liked_songs"))
    return ret_pls

def playlist_to_id(pls, id):
    for pl in pls:
        if(pl.id == id):
            return pl
    return None

def create_playlist(sp, id):
    if id == "liked_songs":
        return Playlist("Liked Songs", "liked_songs")
    pl = sp.playlist(id)
    return Playlist(pl['name'], pl['id'])

client_id = os.environ.get('SPOTIFY_CLIENT_ID')
client_secret = os.environ.get('SPOTIFY_CLIENT_SECRET')
scope = "user-library-read playlist-read-private playlist-read-collaborative"

if debug:
    redirect_uri = 'http://localhost:5000'
else:
    redirect_uri = 'https://playlistbattle.herokuapp.com'

#CREATE SERVER
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(64)
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_FILE_DIR'] = './.flask_session/'
Session(app)

# set up cache folder stuff
caches_folder = './.spotify_caches/'
if not os.path.exists(caches_folder):
    os.makedirs(caches_folder)

def session_cache_path():
    return caches_folder + session.get('uuid')

@app.route('/')
def index():
    if not session.get('uuid'):
        session['uuid'] = str(uuid.uuid4())

    auth_manager = spotipy.oauth2.SpotifyOAuth(scope='user-library-read playlist-read-private playlist-read-collaborative',
                                                client_id = client_id,
                                                client_secret = client_secret,
                                                redirect_uri = redirect_uri,
                                                cache_path=session_cache_path(),
                                                show_dialog=True)
    if request.args.get("code"):
        auth_manager.get_access_token(request.args.get("code"))
        return redirect('/')

    if not auth_manager.get_cached_token():
        auth_url = auth_manager.get_authorize_url()
        return render_template("index.html", auth_url = auth_url)

    sp = spotipy.Spotify(auth_manager=auth_manager)
    access_token = auth_manager.get_access_token()['access_token']
    return redirect(url_for('choose', access_token = access_token))

# Choose Screen: Where you choose which playlist to select
@app.route('/choose/<access_token>', methods = ['GET', 'POST'])
def choose(access_token):
    sp = spotipy.Spotify(auth = access_token)
    score = -1
    playlists = create_playlists(sp)
    seed = int(round(time.time() * 1000))
    return render_template('choose.html', playlists = playlists, name = sp.me()['display_name'], access_token = access_token, seed = seed)

# Game Screen: Where one instance of the game is
@app.route('/game/<access_token>/<pl_id>/<int:seed>/<int:song_counter>/<int:score>/<int:pl_made>', methods = ['GET', 'POST'])
def game(access_token, pl_id, song_counter, score, pl_made, seed):
    sp = spotipy.Spotify(auth = access_token)
    if pl_id == 'none':
        pl_id = request.form.get('action')
    chosen_playlist = create_playlist(sp, pl_id)
    chosen_playlist.populate(sp)
    random.Random(seed).shuffle(chosen_playlist.songs) # shuffle playlist the same way using the generated seed
    if song_counter+1 < chosen_playlist.size():
        song1 = chosen_playlist.songs[song_counter].update_play_count()
        song2 = chosen_playlist.songs[song_counter+1].update_play_count()
    else:
        return render_template("win.html", access_token = access_token)
    return render_template('game.html', playlist = chosen_playlist, song1 = song1, song2 = song2, pl_id = pl_id,
        score = score, song_counter = song_counter, access_token = access_token, seed = seed)

# Restart Function: returns a redirect to the game screen
@app.route('/restart/<access_token>/<pl_id>', methods = ['GET', 'POST'])
def restart(access_token, pl_id):
    seed = int(round(time.time() * 1000))
    return redirect(f"/game/{access_token}/{pl_id}/{seed}/0/0/1")

# Sign out function, returns a redirect to the sign in screen
@app.route('/sign_out')
def sign_out():
    os.remove(session_cache_path())
    try:
        # Remove the CACHE file (.cache-test) so that a new user can authorize.
        os.remove(session_cache_path())
    except OSError as e:
        print ("Error: %s - %s." % (e.filename, e.strerror))
    session.clear()
    return redirect('/')

# Runs the app
if __name__ == "__main__":
    app.run()


# -*- coding: utf-8 -*-
"""
Created on Fri Aug  9 15:24:55 2019

@author: Yems
"""

from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from matplotlib import pyplot as plt
import os
from scipy.io import wavfile
from scipy import signal
import numpy
import mFeatExtract as mfe
#from playsound import playsound

# Parameters
FILT=1
fcl = 15000 #Cut-off freq. lower limit
fcu = 23000 #Cut-off freq. upper limit

# Define sound file of interest
#DET 5D0A00B6
#active forest 5D3329A0
#quiet forest 5D34A0A0
path = 'C:\\Users\\Yems\\Desktop\\repos\\SS_sheperd'
#sound = '5D3329A0.WAV'
X = []
S = []
for sound in os.listdir(path):
    if '.WAV' in sound:
        # Load the data and calculate the time of each sample
        samplerate, data = wavfile.read(os.path.join(path, sound))
        times = numpy.arange(len(data))/float(samplerate)
        ##data=data[:,1] #mono

        if FILT == 1:
            # Filter (working parameters
            w = fcl / (samplerate/2) #Normalize freq
            b, a = signal.butter(5,w,'high')
            temp = signal.filtfilt(b,a,data)
            w = fcu / (samplerate/2) #Normalize freq
            b, a = signal.butter(5,w,'low')
            data = signal.filtfilt(b,a,temp)

        mX = mfe.FeatArray(data,samplerate,0.1*samplerate, 0.025*samplerate)
        X.append(numpy.mean(mX,1))
        S.append(numpy.var(mX,1))
X=numpy.array(X)
S=numpy.array(S)

A=numpy.concatenate((X,S),axis=1)
A=StandardScaler().fit_transform(A)
# create kmeans object
kmeans = KMeans(n_clusters=4)
# fit kmeans object to data
kmeans.fit(A)
# print location of clusters learned by kmeans object
print(kmeans.cluster_centers_)
# save new clusters for chart
g = kmeans.fit_predict(A)

# dimension reduction
pca = PCA(n_components=2)
PC = pca.fit_transform(A)

# Plot clusters
plt.scatter(PC[g ==0,0], PC[g == 0,1], s=1, c='magenta')
plt.scatter(PC[g ==1,0], PC[g == 1,1], s=1, c='cyan')
plt.scatter(PC[g ==2,0], PC[g == 2,1], s=1, c='orange')
plt.scatter(PC[g ==3,0], PC[g == 3,1], s=1, c='green')

#plt.scatter(list(range(len(g))), g, s=1)

numpy.savetxt(os.path.join(path, "clusters_g")+".csv", g, delimiter=",")
numpy.savetxt(os.path.join(path, "clusters_A")+".csv", A, delimiter=",")

# Plot clusters
x=0
y=1
plt.scatter(A[g ==0,x], A[g == 0,y], s=1, c='magenta')
plt.scatter(A[g ==1,x], A[g == 1,y], s=1, c='cyan')
plt.scatter(A[g ==2,x], A[g == 2,y], s=1, c='orange')
plt.scatter(A[g ==3,x], A[g == 3,y], s=1, c='green')


from datetime import datetime, date

def date_from_string(value, format='%Y-%m-%d'):
    if type(value) == date:
        return value

    return datetime.strptime(value, format).date()

def datetime_from_string(value, format='%Y-%m-%dT%H:%M'):
    alternate_formats = (
        '%Y-%m-%dT%H:%M:%S',
    )

    all_formats = set((format,) + alternate_formats)

    for fmt in all_formats:
        try:
            return datetime.strptime(value, fmt)
        except ValueError:
            pass

    raise ValueError

def date_to_age(value, now=None):
    now = now if now else datetime.now()

    if value > now.date().replace(year = value.year):
        return now.date().year - value.year - 1
    else:
        return now.date().year - value.year

def datetime_round(value):
    return datetime(value.year, value.month, value.day, value.hour, tzinfo=value.tzinfo)


import json
from datetime import datetime, timedelta

import falcon

from db import db

"""
created with guidance from the Falcon quickstart guide:
https://falcon.readthedocs.io/en/stable/user/quickstart.html
"""
class MessengerResource():

    def __init__(self, db_conn):
        """
        On Falcon startup, create connection to local database
        """
        self.db_conn = db_conn

    def on_get(self, req, resp, message_id=None):
        """
        HTTP GET request handler
        :param req: the Falcon request object
        :param resp: the Falcon response object
        :param message_id: optional, an ID of a message
        :return: a status code and message body
        """
        enable_message_limit = 'limit' in req.params
        enable_message_range = 'range' in req.params
        is_single_message_stream = 'sender' in req.params \
                                   and 'recipient' in req.params
        invalidate_no_sender = 'recipient' in req.params \
                               and 'sender' not in req.params
        invalidate_no_recipient = 'sender' in req.params \
                                  and 'recipient' not in req.params

        # if sender sent without recipient or recipient without sender, invalid
        if invalidate_no_recipient or invalidate_no_sender:
            resp.body = json.dumps({
                "message": "sender AND recipient are required parameters"})
            resp.status = falcon.HTTP_400

        # request for a specific message by it's ID
        if message_id:
            print(f"request received for message with ID: {message_id}")
            message = db.get_message_by_id(self.db_conn, message_id)
            if message:
                print(f"message found by ID: {message_id}\n{message}")
                resp.body = json.dumps(
                    self._format_message(self.db_conn, message))
            else:
                print(f"no messages found with ID: {message_id}")
                resp.body = json.dumps({
                    "error": f"no messages found with ID: {message_id}"})
                resp.status = falcon.HTTP_404

        # no sender OR recipient query params --> get all messages
        elif not is_single_message_stream:
            print("retrieving all messages")
            messages = db.get_all_messages(self.db_conn)
            if enable_message_limit:
                limit = int(req.params['limit'])
                print(f"limiting messages to {limit} most recent")
                messages = messages[-limit:]
            if enable_message_range:
                messages = self._filter_messages_by_range(
                    messages, req.params['range'])
            resp.body = json.dumps([
                self._format_message(self.db_conn, msg) for msg in messages])
            if not messages:
                resp.status = falcon.HTTP_404
                resp.body = json.dumps({"error": "no messages in DB"})

        # fall-through case is sender AND recipient params sent
        else:
            print("retrieving message stream for "\
                  f"sender[{req.params['sender']}] and "\
                  f"recipient[{req.params['recipient']}]")
            sender_name = req.params['sender']
            recipient_name = req.params['recipient']

            messages = db.select_messages_by_recipient_and_sender(
                self.db_conn, recipient_name, sender_name)
            if enable_message_limit:
                limit = int(req.params['limit'])
                print(f"limiting messages to {limit} most recent")
                messages = messages[-limit:]
            if enable_message_range:
                messages = self._filter_messages_by_range(
                    messages, req.params['range'])

            if messages:
                resp.body = json.dumps([
                    self._format_message(self.db_conn, msg) for msg in messages
                ])
            else:
                resp.body = json.dumps({
                    "not_found": "no messages found between requested users " \
                                 f"sender[{sender_name}] and " \
                                 f"recipient[{recipient_name}]"})
                resp.status = falcon.HTTP_404

    def on_post(self, req, resp):
        """
        HTTP POST request handler
        :param req: the Falcon request object
        :param resp: the Falcon response object
        :return: a status code and message location header
        """
        message = req.media
        print(f"creating new message: {message}")
        new_db_entry = {"message": message["message"]}

        sender_db_entry = db.select_user_id_by_name(
            self.db_conn, message['sender'])
        sender_id = sender_db_entry['id'] if sender_db_entry is not None else 0
        recipient_db_entry = db.select_user_id_by_name(
            self.db_conn, message['recipient'])
        recipient_id = recipient_db_entry['id'] \
            if recipient_db_entry is not None else 0

        # if sender or recipient haven't been users before, add them
        if not sender_id:
            sender_id = db.create_user(self.db_conn, message['sender'])
        if not recipient_id:
            recipient_id = db.create_user(self.db_conn, message['recipient'])

        new_db_entry["sender_id"] = sender_id
        new_db_entry["recipient_id"] = recipient_id

        message_id = db.create_message(self.db_conn, new_db_entry)
        print(f"message created successfully with ID: {message_id}")
        resp.location = f"/{message_id}"
        resp.body = json.dumps(message)
        resp.status = falcon.HTTP_201

    @staticmethod
    def _format_message(db_conn, message):
        """
        converts the message dict and populates user names
        :param db_conn: the DB connection
        :param message: a message row from the DB
        """
        return {
            "sender": db.select_user_name_by_id(
                db_conn, message['sender_id'])['name'],
            "recipient": db.select_user_name_by_id(
                db_conn, message['recipient_id'])['name'],
            "message": message['content'],
            "message_date": message['creation_date']
        }

    @staticmethod
    def _filter_messages_by_range(messages, message_range):
        """
        Removes messages older than the provided range day
        :param messages: an array of messages
        :param message_range: a str indicating a day range
        """
        day_range = int(message_range.replace('d', ''))
        print(f"filtering messages older than {day_range} days old")
        oldest_date = datetime.today() - timedelta(days=day_range)
        for index, message in enumerate(messages):
            message_date = datetime.fromisoformat(message['creation_date'])
            if message_date < oldest_date:
                messages.pop(index)
        return messages

database_file = "messenger.db"
messenger = MessengerResource(db.create_connection(database_file))

app = falcon.API()
app.add_route('/messages', messenger)
app.add_route('/messages/{message_id}', messenger)


import logging
import json
import re
import azure.functions as func
import os
from azure.cosmos import CosmosClient, PartitionKey
from azure.storage.blob import ContainerClient
import urllib
import uuid
import copy

from utils import cosmos_helpers
from utils import storage
from utils import cv_helpers

from utils.env_vars import *

def remove_urls(text):
    text = re.sub(r'(https|http)?:\/\/(\w|\.|\/|\?|\=|\&|\%)*\b', '', text, flags=re.MULTILINE)
    return text

re_strs = [
    "customXml\/[-a-zA-Z0-9+&@#\/%=~_|$?!:,.]*",
    "ppt\/[-a-zA-Z0-9+&@#\/%=~_|$?!:,.]*",
    "\.MsftOfcThm_[-a-zA-Z0-9+&@#\/%=~_|$?!:,.]*[\r\n\t\f\v ]\{[\r\n\t\f\v ].*[\r\n\t\f\v ]\}",
    "SlidePowerPoint",
    "PresentationPowerPoint",
    '[a-zA-Z0-9]*\.(?:gif|emf)'
    ]

def analyze_doc(data_dict):

    ret_dict = {}
    ret_dict['status'] = ''
    db_status = ''
    data_dict['text'] = remove_urls(data_dict['content'].replace("\n\n\n", "\n").replace("....", "."))
    data_dict['contentType'] = 'text'
    data_dict['container'] = storage.get_container_name(data_dict['doc_url'])

    try:
        if isinstance(data_dict['timestamp'], list):
            data_dict['timestamp'] = ' '.join(data_dict['timestamp'])
    except:
        data_dict['timestamp'] = "1/1/1970 00:00:00 AM"

    for re_str in re_strs:
        matches = re.findall(re_str, data_dict['text'], re.DOTALL)
        for m in matches: data_dict['text'] = data_dict['text'].replace(m, '')

    try:
        if PROCESS_IMAGES == 1:

            url = data_dict['doc_url']

            fn = storage.get_filename(url)
            extension = os.path.splitext(fn)[1]

            if extension in ['.jpg', '.jpeg', '.png']:
                sas_url = storage.create_sas(url)
                cvr = cv_helpers.CV()

                res = cvr.analyze_image(img_url=sas_url)

                data_dict['text'] = res['text'] + data_dict['text']
                data_dict['cv_image_vector'] = cvr.get_img_embedding(sas_url)
                data_dict['cv_text_vector'] = cvr.get_text_embedding(res['text'])
                data_dict['contentType'] = 'image'

    except Exception as e:
        logging.error(f"Exception: Image {doc_id} created an exception.\n{e}")
        print(f"Exception: Image {doc_id} created an exception.\n{e}")
        ret_dict['status'] = f"Exception: Image {doc_id} created an exception.\n{e}"

    try:
        if DATABASE_MODE == 1:
            db_status = cosmos_helpers.cosmos_store_contents(data_dict)
            logging.info(db_status)
            print(db_status)
    except Exception as e:
        doc_id = data_dict.get('id', 'Unknown ID')
        logging.error(f"Exception: Document {doc_id} created an exception.\n{e}")
        ret_dict['status'] = ret_dict['status'] + '\n' + f"Exception: Document {doc_id} created an exception.\n{e}"

    try:
        ret_dict = storage.save_json_document(data_dict, OUTPUT_BLOB_CONTAINER)
        logging.info(ret_dict['status'])
    except Exception as e:
        doc_id = data_dict.get('id', 'Unknown ID')
        logging.error(f"Exception: Document {doc_id} created an exception.\n{e}")
        ret_dict['status'] = ret_dict['status'] + '\n' + f"Exception: Document {doc_id} created an exception.\n{e}"

    return ret_dict

## Perform an operation on a record
def transform_value(value):
    try:
        recordId = value['recordId']
    except AssertionError  as error:
        logging.info(error)
        return None

    # Validate the inputs
    try:
        assert ('data' in value), "'data' field is required."
        data = value['data']
        logging.info(f"Data received: {data}")
        assert ('content' in data), "'content' field is required in 'data' object."
        assert ('id' in data), "'id' field is required in 'data' object."

    except AssertionError as error:
        logging.info(error)
        return (
            {
            "recordId": recordId,
            "errors": [ { "message": "Error:" + error.args[0] }   ]
            })

    try:
        ret_dict = analyze_doc(value['data'])

        # Here you could do something more interesting with the inputs

    except AssertionError  as error:
        logging.info(error)
        return (
            {
            "recordId": recordId,
            "errors": [ { "message": "Could not complete operation for record." }   ]
            })

    return ({
            "recordId": recordId,
            "data": ret_dict
            })

def compose_response(json_data):
    values = json.loads(json_data)['values']

    # Prepare the Output before the loop
    results = {}
    results["values"] = []

    for value in values:
        output_record = transform_value(value)
        if output_record != None:
            results["values"].append(output_record)

    return json.dumps(results, ensure_ascii=False)

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    try:
        body = json.dumps(req.get_json())
    except ValueError:
        return func.HttpResponse(
             "Invalid body",
             status_code=400
        )

    if body:
        result = compose_response(body)
        return func.HttpResponse(result, mimetype="application/json")
    else:
        return func.HttpResponse(
             "Invalid body",
             status_code=400
        )