# -*- coding: utf-8 -*-
"""
Created on Fri Oct 11 20:53:57 2019

@author: olivia
"""
#try:
 #   hours = float(input("Enter Hours:"))
 #   rate = float(input("Enter Rate:"))
 #   if hours < 40:
 #       pay = (hours * rate)
 #   else:
 #       pay = (rate*40) + ((rate*1.5)*(hours -40))
 #   print("Pay:"+str(pay))
#except:
 #   print("Please enter float values\n")

try:
   score = float(input("Enter Score:"))
   if score >= 0.9:
       grade = "A"
   elif score < 0.8:
          if score < 0.7:
              if score >= 0.6:
                  grade = "D"
              else:
                  grade = "F"
          else:
               grade = "C"
   else:
            grade = "B"

   print (grade)
except:
   print("Bad score\n")


import json
import mimetypes
import os
import requests

class UploadGH(object):
    def __init__(self, repo, token=None):
        self.token = os.getenv("GITHUB_TOKEN", token)
        self.endpoint = "https://api.github.com/repos/%s" % repo

    def headers(self, extra={}):
        headers = {'Authorization': "token %s" % self.token}
        headers.update(extra)
        return headers

    def create_release(self, tag):
        path = self.endpoint + "/releases"
        params = {"tag_name": tag,
                  "name": tag,
                  "draft": True,
                  "body": "Release %s" % tag}
        resp = requests.post(path, data=json.dumps(params), headers=self.headers())
        resp.raise_for_status()
        return resp

    def get_release(self, tag):
        path = self.endpoint + "/releases/tags/%s" % tag
        resp = requests.get(path)
        if resp.status_code == 404:
            resp = self.create_release(tag)
        resp.raise_for_status()
        return resp.json()

    def get_existing_asset(self, name, release_id):
        path = self.endpoint + "/releases/%s/assets" % release_id
        resp = requests.get(path)
        assets = resp.json()

        if resp.status_code < 299:
            for asset in assets:
                if asset['name'] == name:
                    return asset

        return None

    def delete_asset(self, asset):
        resp = requests.delete(asset['url'], headers=self.headers())
        resp.raise_for_status()

    def upload(self, filepath, tag, name=None,
               overwrite=True, contenttype="application/octet-stream"):
        release = self.get_release(tag)
        upload_url = release['upload_url'].split("{")[0]
        name = name or os.path.basename(filepath)
        data = open(filepath, "rb").read()

        if overwrite:
            previous_asset = self.get_existing_asset(name, release['id'])
            if previous_asset:
                self.delete_asset(previous_asset)

        if contenttype is None:
            mimetypes.init()
            contenttype = mimetypes.guess_type(filepath)[0]

        resp = requests.post(upload_url, data=data,
                             headers=self.headers({'Content-Type': contenttype}),
                             params={"name": name})

        return resp


from data import maskdata

from Xcept import xception , Xception
import time
import torch
from torchvision import datasets, models, transforms
import os
import torch.nn as nn

from sklearn.ensemble import AdaBoostClassifier

import copy
import torch.optim as optim
import torchvision
from torch.optim import lr_scheduler
from torch.utils.data import DataLoader ,Dataset , random_split

import numpy as np
import joblib
from efficientnet_pytorch import EfficientNet
from PIL import Image

augmentation = torchvision.transforms.Compose([torchvision.transforms.Resize(299),
                                                    torchvision.transforms.RandomCrop(299),
                                                    torchvision.transforms.RandomHorizontalFlip(),
                                                    torchvision.transforms.ToTensor(),
                                                    torchvision.transforms.Normalize(mean = [0.485, 0.456, 0.406],std = [0.229, 0.224, 0.225])
                                                    ])

class testdata(Dataset):
    def __init__(self ,Dir ,label ,transforms):
        self.dir = Dir
        self.label = label
        self.transforms = transforms

    def __len__(self):   #抓幾張圖片

        return 50   # idx 從 0 開始算

    def __getitem__(self  , idx ):   # 弄好 (img , label)

        if os.path.exists(self.dir+'/'+str(idx+1)+'.jpg'):
            pic = Image.open(self.dir+'/'+str(idx+1)+'.jpg').convert('RGB')
            if self.transforms is not None:
                pic = self.transforms(pic)

            sample = {'image': pic , 'label': self.label}
            return sample
        else:
            print('file not found')
            print(self.dir+'/'+str(idx+1)+'.jpg')
            return 0

def test(loader, model):
    model.eval()
    accuracy = 0.
    with torch.no_grad():
        for i,data in enumerate(loader , 0):
            inputs = data['image']
            labels = data['label']
            inputs, labels = inputs.to(device , dtype=torch.float32), labels.to(device)
            ou = model(inputs)
            _, pred = torch.max(torch.sigmoid(ou), 1)

            print()
            print(pred)
            print(labels)
            print()
            accuracy += torch.sum(pred==labels).item()

    print("Test Accuracy: {}".format(accuracy / len(face)))

    f = open('./res.txt' , 'w')
    f.write("Test Accuracy: {}".format(accuracy / len(face)))
    f.close()

def celeb_sum (path):   # 加總一個目錄下所有的
    l = []
    for i in os.listdir(path):
        l.append(i)

    for i in range(0,518):

        if i==0:
            if(len(l[i])>10):
                face = testdata(path+'/'+l[i] , 1 , transforms = augmentation)
            else:
                face = testdata(path+'/'+l[i] , 0 , transforms = augmentation)

        else:
            if(len(l[i])>10):
                face += testdata(path+'/'+l[i] , 1 , transforms = augmentation)
            else:
                face += testdata(path+'/'+l[i] , 0 , transforms = augmentation)

    return face

class MyEnsemble(nn.Module):
    def __init__(self, modelA, modelB, nb_classes=2):
        super(MyEnsemble, self).__init__()
        self.modelA = modelA
        self.modelB = modelB
        # Remove last linear layer
        self.modelA.fc = nn.Identity()
        self.modelB._fc = nn.Identity()

        # Create new classifier
        self.classifier = nn.Linear(2048+1536, nb_classes)

    def forward(self, x):
        x1 = self.modelA(x.clone())  # clone to make sure x is not changed by inplace methods
        x1 = x1.view(x1.size(0), -1)

        x2 = self.modelB(x)
        x2 = x2.view(x2.size(0), -1)

        x = torch.cat((x1, x2), dim=1)

        x = self.classifier(torch.relu(x))

        return x

def ff(fake_path , real_path):
    #fake_type = ['FaceShifter','NeuralTextures']

    fake_type = ['Deepfakes','Face2Face','FaceSwap']

    fake = []
    real = []
    for z in range(0,3):
        a = os.path.join(fake_path , fake_type[z] )
        for i in os.listdir(a):
            b = os.path.join(a , i )
            for j in range(1,41):
                c = os.path.join(b , str(j)+'.jpg' )
                fake.append(c)

    for i in os.listdir(real_path):
        b = os.path.join(real_path , i )
        for j in range(1,41):
            c = os.path.join(b , str(j)+'.jpg' )
            real.append(c)

    face = maskdata(real , fake ,transforms = augmentation)

    return face

if __name__ =="__main__":

    model = xception(pretrained=False)
    state_dict = torch.load(
        r'C:\Users\jeremy\Desktop\2021DF\model\FaceForensics-master\FaceForensics-master\classification\xception-b5690688.pth')
    for name, weights in state_dict.items():
        if 'pointwise' in name:
            state_dict[name] = weights.unsqueeze(-1).unsqueeze(-1)
    model.load_state_dict(state_dict)

    for param in model.parameters():
        param.requires_grad = False

    out_num = model.fc.in_features
    model.fc = nn.Linear(out_num,2)

    model2 = EfficientNet.from_pretrained('efficientnet-b3' , num_classes=2)

    for param in model2.parameters():
        param.requires_grad_(False)

    model3 = MyEnsemble(model, model2)

# =============================================================================
#     model = xception(pretrained=False)
#     model.fc = model.last_linear
#     del model.last_linear
#     state_dict = torch.load(
#         r'C:\Users\jeremy\Desktop\2021DF\model\FaceForensics-master\FaceForensics-master\classification\xception-b5690688.pth')
#     for name, weights in state_dict.items():
#         if 'pointwise' in name:
#             state_dict[name] = weights.unsqueeze(-1).unsqueeze(-1)
#     model.load_state_dict(state_dict)
#     model.last_linear = model.fc
#     out_num = model.fc.in_features
#     model.last_linear = nn.Linear(out_num,2)
#     model.load_state_dict(torch.load('./XceptionNet/mask2/m1.pth'))
# =============================================================================

# =============================================================================
#     model = Xception()
#     model.last_linear = model.fc
#     out_num = model.fc.in_features
#     model.last_linear = nn.Linear(out_num,2)
#     del model.fc
# =============================================================================

    #model.load_state_dict(torch.load('XceptionNet/m2.pth'))
    model3.load_state_dict(torch.load('ensemble.pth'))

# =============================================================================
#     p = r'C:\Users\jeremy\Desktop\2021DF\model\FaceForensics-master\FaceForensics-master\classification\all_c23.p'
#     q = r'C:\Users\jeremy\Desktop\2021DF\model\XceptionNet\mask\m2.pth'
#     model = torch.load(p)
#     model.load_state_dict(torch.load(q))
# =============================================================================

    #model.load_state_dict(torch.load('./EfficientNet/mask/3_5.pth'))

    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    model3 = model3.to(device)

# loaddata ===========================================================================

#----------------------------celceb-df------------------------------------------
    path = 'D:/Celeb-DF-v2/test'
    face = celeb_sum(path)

#-----------------------------FF++-----------------------------------------

    #face = ff(fake_path = r'D:\FF++\data\test',real_path = r'D:\FF++\data\test\original')
    #summary(model , (3,299,299))

    test_loader = DataLoader( face , batch_size = 16 , shuffle = True , num_workers = 0 )

    #test(test_loader , model3)


__title__ = "material cards utilities"
__author__ = "Bernd Hahnebach"
__url__ = "http://www.freecad.org"

import os
from os.path import join
from pathlib import Path

import FreeCAD
import Material

unicode = str

# TODO:
# implement method check_material_keys from FEM material task panel for material editor
# may be move out of the FEM material task panel to here
# make the method more generic to be compatible with all known params
# the material template knows the units

# ***** card handling data models ****************************************************************
'''
data model:
materials = { card_path: mat_dict, ... }
cards = { card_path: card_name, ... }
icons = { card_path: icon_path, ... }

- duplicates are allowed
- the whole card_path is saved into the combo box widget, this makes card unique
- sorting happens on adding to the combo box widgets

a data model which uses a class and attributes as well as methods to access the attributes
would makes sense, like some material library class
this has been done already by eivind see
https://forum.freecad.org/viewtopic.php?f=38&t=16714
'''

def get_material_preferred_directory(category=None):
    """
        Return the preferred material directory. In priority order they are:
        1. user specified
        2. user modules folder
        3. system folder
    """
    mat_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Resources")
    use_built_in_materials = mat_prefs.GetBool("UseBuiltInMaterials", True)
    use_mat_from_config_dir = mat_prefs.GetBool("UseMaterialsFromConfigDir", True)
    use_mat_from_custom_dir = mat_prefs.GetBool("UseMaterialsFromCustomDir", True)

    preferred = None

    if use_built_in_materials:
        if category == 'Fluid':
            preferred = join(
                FreeCAD.getResourceDir(), "Mod", "Material", "Resources", "Materials", "FluidMaterial"
            )

        elif category == 'Solid':
            preferred = join(
                FreeCAD.getResourceDir(), "Mod", "Material", "Resources", "Materials", "StandardMaterial"
            )

        else:
            preferred = join(
                FreeCAD.getResourceDir(), "Mod", "Material"
            )

    if use_mat_from_config_dir:
        user = join(
            FreeCAD.ConfigGet("UserAppData"), "Material"
        )
        if os.path.isdir(user):
            preferred = user

    if use_mat_from_custom_dir:
        custom = mat_prefs.GetString("CustomMaterialsDir", "")
        if len(custom.strip()) > 0:
            preferred = custom

    return preferred

def get_material_preferred_save_directory():
    """
        Return the preferred directory for saving materials. In priority order they are:
        1. user specified
        2. user modules folder
    """
    mat_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Resources")
    use_mat_from_config_dir = mat_prefs.GetBool("UseMaterialsFromConfigDir", True)
    use_mat_from_custom_dir = mat_prefs.GetBool("UseMaterialsFromCustomDir", True)

    if use_mat_from_custom_dir:
        custom = mat_prefs.GetString("CustomMaterialsDir", "")
        if len(custom.strip()) > 0:
            # Create the directory if it doesn't exist
            try:
                if not os.path.isdir(custom):
                    os.makedirs(custom)
                return custom
            except Exception as ex:
                print(ex)
                pass

    if use_mat_from_config_dir:
        user = join(
            FreeCAD.ConfigGet("UserAppData"), "Material"
        )
        try:
            if not os.path.isdir(user):
                os.makedirs(user)
            return user
        except Exception as ex:
            print(ex)
            pass

    return ""

# ***** get resources for cards ******************************************************************
def get_material_resources(category='Solid'):

    resources = {}  # { resource_path: icon_path, ... }

    mat_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Resources")
    use_built_in_materials = mat_prefs.GetBool("UseBuiltInMaterials", True)
    use_mat_from_modules = mat_prefs.GetBool("UseMaterialsFromWorkbenches", True)
    use_mat_from_config_dir = mat_prefs.GetBool("UseMaterialsFromConfigDir", True)
    use_mat_from_custom_dir = mat_prefs.GetBool("UseMaterialsFromCustomDir", True)

    if use_built_in_materials:
        if category == 'Fluid':
            builtin_mat_dir = join(
                FreeCAD.getResourceDir(), "Mod", "Material", "Resources", "Materials", "FluidMaterial"
            )

        else:
            builtin_mat_dir = join(
                FreeCAD.getResourceDir(), "Mod", "Material", "Resources", "Materials", "StandardMaterial"
            )
        resources[builtin_mat_dir] = ":/icons/freecad.svg"

    if use_mat_from_modules:
        module_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Resources/Modules")
        module_groups = module_prefs.GetGroups()
        for group in module_groups:
            module = module_prefs.GetGroup(group)
            module_mat_dir = module.GetString("ModuleDir", "")
            module_icon_dir = module.GetString("ModuleIcon", "")
            if len(module_mat_dir) > 0:
                resources[module_mat_dir] = module_icon_dir

    if use_mat_from_config_dir:
        config_mat_dir = join(
            FreeCAD.ConfigGet("UserAppData"), "Material"
        )
        if os.path.exists(config_mat_dir):
            resources[config_mat_dir] = ":/icons/preferences-general.svg"

    if use_mat_from_custom_dir:
        custom_mat_dir = mat_prefs.GetString("CustomMaterialsDir", "")
        if os.path.exists(custom_mat_dir):
            resources[custom_mat_dir] = ":/icons/user.svg"
        # fail silently
        # else:
        #     FreeCAD.Console.PrintError(
        #         'Custom material directory set by user: {} does not exist.\n'
        #         .format(custom_mat_dir)
        #     )

    return resources

def get_material_libraries():

    resources = {}  # { resource_path: icon_path, ... }

    mat_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Resources")
    use_built_in_materials = mat_prefs.GetBool("UseBuiltInMaterials", True)
    use_mat_from_modules = mat_prefs.GetBool("UseMaterialsFromWorkbenches", True)
    use_mat_from_config_dir = mat_prefs.GetBool("UseMaterialsFromConfigDir", True)
    use_mat_from_custom_dir = mat_prefs.GetBool("UseMaterialsFromCustomDir", True)

    if use_built_in_materials:
        builtin_mat_dir = join(
            FreeCAD.getResourceDir(), "Mod", "Material", "Resources", "Materials"
        )
        resources["System"] = (builtin_mat_dir, ":/icons/freecad.svg")

    if use_mat_from_modules:
        module_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Resources/Modules")
        module_groups = module_prefs.GetGroups()
        for group in module_groups:
            print("\tGroup - {0}".format(group))
            module = module_prefs.GetGroup(group)
            module_mat_dir = module.GetString("ModuleDir", "")
            module_icon = module.GetString("ModuleIcon", "")
            if len(module_mat_dir) > 0:
                resources[group] = (module_mat_dir, module_icon)

    if use_mat_from_config_dir:
        config_mat_dir = join(
            FreeCAD.ConfigGet("UserAppData"), "Material"
        )
        if os.path.exists(config_mat_dir):
            resources["User"] = (config_mat_dir, ":/icons/preferences-general.svg")

    if use_mat_from_custom_dir:
        custom_mat_dir = mat_prefs.GetString("CustomMaterialsDir", "")
        if os.path.exists(custom_mat_dir):
            resources["Custom"] = (custom_mat_dir, ":/icons/user.svg")

    return resources

def list_cards(mat_dir, icon):
    import glob
    a_path = mat_dir + '/**/*.FCMat'
    print("path = '{0}'".format(a_path))
    dir_path_list = glob.glob(a_path, recursive=True)
    # Need to handle duplicates

    cards = []
    for a_path in dir_path_list:
        p = Path(a_path)
        relative = p.relative_to(mat_dir)
        cards.append(relative)

    return cards

def output_resources(resources):
    FreeCAD.Console.PrintMessage('Directories in which we will look for material cards:\n')
    for path in resources.keys():
        FreeCAD.Console.PrintMessage('  {}\n'.format(path))

# ***** card handling ****************************************************************************
# used in material editor and FEM material task panels

def import_materials(category='Solid', template=False):
    materialManager = Material.MaterialManager()
    mats = materialManager.Materials
    materials = {}
    cards = {}
    icons = {}
    for matUUID in mats:
        mat = materialManager.getMaterial(matUUID)
        physicalModels = mat.PhysicalModels
        fluid = ('1ae66d8c-1ba1-4211-ad12-b9917573b202' in physicalModels)
        if not fluid:
            path = mat.LibraryRoot + "/" + mat.Directory
            print(path)
            materials[path] = mat.Properties
            cards[path] = mat.Name
            icons[path] = mat.LibraryIcon

            print(path)
            print(mat.Properties)

    return (materials, cards, icons)

def add_cards_from_a_dir(materials, cards, icons, mat_dir, icon, template=False):
    # fill materials and icons
    import glob
    from importFCMat import read
    dir_path_list = glob.glob(mat_dir + '/*' + ".FCMat")
    mat_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Cards")
    delete_duplicates = mat_prefs.GetBool("DeleteDuplicates", True)
    # duplicates are indicated on equality of mat dict
    # TODO if the unit is different two cards would be different too
    for a_path in dir_path_list:
        try:
            mat_dict = read(a_path)
        except Exception:
            FreeCAD.Console.PrintError(
                'Error on reading card data. The card data will be empty for card:\n{}\n'
                .format(a_path)
            )
            mat_dict = {}
        card_name = os.path.splitext(os.path.basename(a_path))[0]
        if (card_name == 'TEMPLATE') and (template is False):
            continue
        if delete_duplicates is False:
            materials[a_path] = mat_dict
            cards[a_path] = card_name
            icons[a_path] = icon
        else:
            if mat_dict not in materials.values():
                materials[a_path] = mat_dict
                cards[a_path] = card_name
                icons[a_path] = icon

    return (materials, cards, icons)

def output_trio(trio):
    materials, cards, icons = trio
    FreeCAD.Console.PrintMessage('\n\n')
    for mat_card in materials:
        FreeCAD.Console.PrintMessage(
            '{} --> {} -->{}\n'
            .format(cards[mat_card], mat_card, icons[mat_card])
        )
    FreeCAD.Console.PrintMessage('\n\n')

def output_cards(cards):
    FreeCAD.Console.PrintMessage('\n\n')
    for mat_card in cards:
        FreeCAD.Console.PrintMessage('{} --> {}\n'.format(mat_card, cards[mat_card]))
    FreeCAD.Console.PrintMessage('\n\n')

def output_icons(icons):
    FreeCAD.Console.PrintMessage('\n\n')
    for mat_card in icons:
        FreeCAD.Console.PrintMessage('{} --> {}\n'.format(mat_card, icons[mat_card]))
    FreeCAD.Console.PrintMessage('\n\n')

def output_materials(materials):
    FreeCAD.Console.PrintMessage('\n\n')
    for mat_card in materials:
        FreeCAD.Console.PrintMessage('{}\n'.format(mat_card))
        output_material_param(materials[mat_card])
    FreeCAD.Console.PrintMessage('\n\n')

def output_material_param(mat_dict):
    # thus we check for None
    if not mat_dict:
        FreeCAD.Console.PrintMessage('  empty matdict\n')
    else:
        for p in mat_dict:
            FreeCAD.Console.PrintMessage('   {} --> {}\n'.format(p, mat_dict[p]))
    FreeCAD.Console.PrintMessage('\n')

# ***** material card template *******************************************************************
def get_material_template(withSpaces=False):
    # material properties
    # see the following resources in the FreeCAD wiki for more
    # information about the material specific properties:
    # https://www.freecad.org/wiki/Material_data_model
    # https://www.freecad.org/wiki/Material

    print("Call to get_material_template() successful")

    import yaml
    template_data = yaml.safe_load(
        open(join(FreeCAD.ConfigGet('AppHomePath'), 'Mod/Material/Templatematerial.yml'))
    )
    if withSpaces:
        # on attributes, add a space before a capital letter
        # will be used for better display in the ui
        import re
        new_template = []
        for group in template_data:
            new_group = {}
            gg = list(group)[0]  # group dict has only one key
            # iterating over a dict and changing it is not allowed
            # thus it is iterated over a list of the keys
            new_group[gg] = {}
            for proper in list(group[gg]):
                new_proper = re.sub(r"(\w)([A-Z]+)", r"\1 \2", proper)
                # strip underscores of vectorial properties
                new_proper = new_proper.replace("_", " ")
                new_group[gg][new_proper] = group[gg][proper]
            new_template.append(new_group)
        template_data = new_template
    return template_data

def create_mat_tools_header():
    headers = join(get_source_path(), 'src/Mod/Material/StandardMaterial/Tools/headers')
    # print(headers)
    if not os.path.isfile(headers):
        FreeCAD.Console.PrintError(
            'file not found: {}'.format(headers)
        )
        return
    template_data = get_material_template()
    f = open(headers, "w")
    for group in template_data:
        gg = list(group)[0]  # group dict has only one key
        # do not write group UserDefined
        if gg != 'UserDefined':
            for prop_name in group[gg]:
                if prop_name != 'None':
                    f.write(prop_name + '\n')
    f.close

def create_mat_template_card(write_group_section=True):
    template_card = join(get_source_path(), 'src/Mod/Material/StandardMaterial/TEMPLATE.FCMat')
    if not os.path.isfile(template_card):
        FreeCAD.Console.PrintError(
            'file not found: {}'.format(template_card)
        )
        return
    rev = "{}.{}.{}".format(
        FreeCAD.ConfigGet("BuildVersionMajor"),
        FreeCAD.ConfigGet("BuildVersionMinor"),
        FreeCAD.ConfigGet("BuildRevision")
    )
    template_data = get_material_template()
    f = open(template_card, "w")
    f.write('; TEMPLATE\n')
    f.write('; (c) 2013-2015 Juergen Riegel (CC-BY 3.0)\n')
    f.write('; information about the content of such cards can be found on the wiki:\n')
    f.write('; https://www.freecad.org/wiki/Material\n')
    f.write(': this template card was created by FreeCAD ' + rev + '\n\n')
    f.write('; localized Name, Description and KindOfMaterial uses 2 letter codes\n')
    f.write('; defined in ISO-639-1, see https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes\n')
    f.write('; find unit information in src/App/FreeCADInit.py')
    # write sections
    # write standard FCMat section if write group section parameter is set to False
    if write_group_section is False:
        f.write("\n[FCMat]\n")
    for group in template_data:
        gg = list(group)[0]  # group dict has only one key
        # do not write groups Meta and UserDefined
        if (gg != 'Meta') and (gg != 'UserDefined'):
            # only write group section if write group section parameter is set to True
            if write_group_section is True:
                f.write("\n\n[" + gg + "]")
            for prop_name in group[gg]:
                f.write('\n')
                description = group[gg][prop_name]['Description']
                if not description.strip():
                    f.write('; Description to be updated\n')
                else:
                    f.write('; ' + description + '\n')
                url = group[gg][prop_name]['URL']
                if url.strip():
                    f.write('; ' + url + '\n')
                f.write(prop_name + ' =\n')
    f.close

# card tools will not be copied into build ... thus they are not there ...
# thus the source dir is needed, this might not work on windows
def get_source_path():
    # in the file 'Makefile' in build directory the cmake variable CMAKE_SOURCE_DIR has the dir
    source_dir = ''
    make_file = join(FreeCAD.ConfigGet('AppHomePath'), 'Makefile')
    f = open(make_file, 'r')
    lines = f.readlines()
    f.close()
    for line in lines:
        if line.startswith('CMAKE_SOURCE_DIR'):
            source_dir = line.lstrip('CMAKE_SOURCE_DIR = ')
            source_dir = source_dir.rstrip()  # get rid on new line and white spaces etc.
            break
    # print(source_dir)
    return source_dir

def get_known_material_quantity_parameter():
    # get the material quantity parameter from material card template
    template_data = get_material_template()
    known_quantities = []
    for group in template_data:
        gname = list(group)[0]  # group dict has only one key
        for prop_name in group[gname]:
            prop_type = group[gname][prop_name]['Type']
            if prop_type == 'Quantity':
                # print('{} --> {}'.format(prop_name, prop_type))
                known_quantities.append(prop_name)
    return known_quantities

# ***** debug known and unknown material parameter *********************************************
def get_and_output_all_carddata(cards):
    print('\n\n\nSTART--get_and_output_all_carddata\n--------------------')
    # get all registered material property keys
    registed_cardkeys = []
    template_data = get_material_template()
    # print(template_data)
    for group in template_data:
        gg = list(group)[0]  # group dict has only one key
        for key in group[gg]:
            registed_cardkeys.append(key)
    registed_cardkeys = sorted(registed_cardkeys)
    # print(registed_cardkeys)

    # get all data from all known cards
    all_cards_and_data = {}  # {cardfilename: ['path', materialdict]}
    for card in cards:
        from importFCMat import read
        d = read(cards[card])
        all_cards_and_data[card] = [cards[card], d]
    '''
    for card in all_cards_and_data:
        print(card)
        print(all_cards_and_data[card][0])
        print(all_cards_and_data[card][1])
        print('\n')
    '''

    # find not registered and registered keys in the used data
    used_and_registered_cardkeys = []
    used_and_not_registered_cardkeys = []
    registered_and_not_used_cardkeys = []
    for card in all_cards_and_data:
        for k in all_cards_and_data[card][1]:
            if k in registed_cardkeys:
                used_and_registered_cardkeys.append(k)
            else:
                used_and_not_registered_cardkeys.append(k)
    for k in registed_cardkeys:
        if (k not in used_and_registered_cardkeys) and (k not in used_and_not_registered_cardkeys):
            registered_and_not_used_cardkeys.append(k)

    used_and_registered_cardkeys = sorted(list(set(used_and_registered_cardkeys)))
    used_and_not_registered_cardkeys = sorted(list(set(used_and_not_registered_cardkeys)))
    registered_and_not_used_cardkeys = sorted(list(set(registered_and_not_used_cardkeys)))
    FreeCAD.Console.PrintMessage(
        '\nused_and_registered_cardkeys:\n{}\n'
        .format(used_and_registered_cardkeys)
    )
    FreeCAD.Console.PrintMessage(
        '\nused_and_not_registered_cardkeys:\n{}\n'
        .format(used_and_not_registered_cardkeys)
    )
    FreeCAD.Console.PrintMessage(
        '\nregistered_and_not_used_cardkeys:\n{}\n'
        .format(registered_and_not_used_cardkeys)
    )

    # still there might be lots of properties in the template
    # which are not used in other materials
    # but the tmplate is handled here like a material
    print('--------------------\nget_and_output_all_carddata--END\n\n\n')

# ***** process multiple material cards **********************************************************
def read_cards_from_path(cards_path):
    from os import listdir
    from os.path import isfile, join, basename, splitext
    from importFCMat import read
    only_files = [f for f in listdir(cards_path) if isfile(join(cards_path, f))]
    # to make sure all file lower and upper and mixed endings are found, use upper and .FCMAT
    mat_files = [f for f in only_files if basename(splitext(f)[1]).upper() == '.FCMAT']
    # print(mat_files)
    mat_cards = []
    for f in sorted(mat_files):
        mat_cards.append(read(join(cards_path, f)))
    return mat_cards

def write_cards_to_path(cards_path, cards_data, write_group_section=True, write_template=False):
    from importFCMat import write
    from os.path import join
    for card_data in cards_data:
        if (card_data['CardName'] == 'TEMPLATE') and (write_template is False):
            continue
        else:
            card_path = join(cards_path, (card_data['CardName'] + '.FCMat'))
            # print(card_path)
            if write_group_section is True:
                write(card_path, card_data, True)
            else:
                write(card_path, card_data, False)

# ***** material parameter units *********************************************
def check_parm_unit(param):
    # check if this parameter is known to FreeCAD unit system
    # for properties with underscores (vectorial values), we must
    # strip the part after the first underscore to obtain the bound unit
    from FreeCAD import Units
    if param.find("_") != -1:
        param = param.split("_")[0]
    if hasattr(Units, param):
        return True
    else:
        return False

def check_value_unit(param, value):
    # check unit
    from FreeCAD import Units
    # FreeCAD.Console.PrintMessage('{} --> {}\n'.format(param, value))
    if hasattr(Units, param):
        # get unit and other information known by FreeCAD for this parameter
        unit = getattr(Units, param)
        quantity = Units.Quantity(1, unit)
        user_prefered_unit = quantity.getUserPreferred()[2]
        # test unit from mat dict value
        some_text = "Parameter: {} --> value: {} -->".format(param, value)
        try:
            param_value = Units.Quantity(value)
            try:
                user_unit = param_value.getValueAs(user_prefered_unit)
                if user_unit:
                    return True
                elif user_unit == 0:
                    FreeCAD.Console.PrintMessage(
                        '{} Value {} = 0 for {}\n'
                        .format(some_text, value, param)
                    )
                    return True
                else:
                    FreeCAD.Console.PrintError(
                        '{} Unknown problem in unit conversion.\n'
                        .format(some_text)
                    )
            except ValueError:
                unitproblem = value.split()[-1]
                FreeCAD.Console.PrintError(
                    '{} Unit {} is known by FreeCAD, but wrong for parameter {}.\n'
                    .format(some_text, unitproblem, param)
                )
            except Exception:
                FreeCAD.Console.PrintError(
                    '{} Unknown problem.\n'
                    .format(some_text)
                )
        except ValueError:
            unitproblem = value.split()[-1]
            FreeCAD.Console.PrintError(
                '{} Unit {} is unknown to FreeCAD.\n'
                .format(some_text, unitproblem)
            )
        except Exception:
            FreeCAD.Console.PrintError(
                '{} Unknown problem.\n'
                .format(some_text)
            )
    else:
        FreeCAD.Console.PrintError(
            'Parameter {} is unknown to the FreeCAD unit system.\n'
            .format(param)
        )
    return False

def output_parm_unit_info(param):
    # check unit
    from FreeCAD import Units
    FreeCAD.Console.PrintMessage('{}\n'.format(param))
    if hasattr(Units, param):
        FreeCAD.Console.PrintMessage(
            '\nParameter {} is known to FreeCAD unit system.'
            .format(param)
        )

        # get unit and other information known by FreeCAD for this parameter
        unit = getattr(Units, param)
        FreeCAD.Console.PrintMessage(
            '{}\n'
            .format(unit)
        )

        quantity = Units.Quantity(1, unit)
        FreeCAD.Console.PrintMessage(
            '{}\n'
            .format(quantity)
        )

        user_prefered_unit = quantity.getUserPreferred()[2]
        FreeCAD.Console.PrintMessage(
            '{}\n'
            .format(user_prefered_unit)
        )

    else:
        FreeCAD.Console.PrintMessage(
            'Parameter {} is Unknown to the FreeCAD unit system.'
            .format(param)
        )

def output_value_unit_info(param, value):
    # check unit
    from FreeCAD import Units
    some_text = "Parameter: {} --> value: {} -->".format(param, value)
    FreeCAD.Console.PrintMessage('{} unit information:'.format(some_text))
    if hasattr(Units, param):

        # get unit and other information known by FreeCAD for this parameter
        unit = getattr(Units, param)
        FreeCAD.Console.PrintMessage(
            '{}\n'
            .format(unit)
        )

        quantity = Units.Quantity(1, unit)
        FreeCAD.Console.PrintMessage(
            '{}\n'
            .format(quantity)
        )

        user_prefered_unit = quantity.getUserPreferred()[2]
        FreeCAD.Console.PrintMessage(
            '{}\n'
            .format(user_prefered_unit)
        )

        # test unit from mat dict value
        try:
            param_value = Units.Quantity(value)
            try:
                user_unit = param_value.getValueAs(user_prefered_unit)
                FreeCAD.Console.PrintMessage(
                    '{} Value in preferred unit: {}\n'
                    .format(some_text, user_unit)
                )
            except ValueError:
                unitproblem = value.split()[-1]
                FreeCAD.Console.PrintError(
                    '{} Unit {} is known by FreeCAD, but wrong for parameter {}.\n'
                    .format(some_text, unitproblem, param)
                )
            except Exception:
                FreeCAD.Console.PrintError(
                    '{} Unknown problem.\n'
                    .format(some_text)
                )

        except ValueError:
            unitproblem = value.split()[-1]
            FreeCAD.Console.PrintError(
                '{} Unit {} is unknown by FreeCAD.\n'
                .format(some_text, unitproblem)
            )

        except Exception:
            FreeCAD.Console.PrintError(
                '{} Unknown problem.\n'
                .format(some_text)
            )

    else:
        FreeCAD.Console.PrintMessage(
            'Parameter {} is unknown to the FreeCAD unit system.'
            .format(param)
        )

def check_mat_units(mat):
    known_quantities = get_known_material_quantity_parameter()
    # check if the param is a Quantity according to the card template
    # then check unit
    # print(known_quantities)
    units_ok = True
    for param, value in mat.items():
        if param in known_quantities:
            if check_value_unit(param, value) is False:
                if units_ok is True:
                    units_ok = False
        else:
            pass
            # print('{} is not a known FreeCAD quantity.'.format(param))
    # print('')
    return units_ok

# ***** some code examples ***********************************************************************
'''
# cards, params, icons and resources **********
from materialtools.cardutils import get_material_resources as getres
from materialtools.cardutils import output_resources as outres
outres(getres())

from materialtools.cardutils import import_materials as getmats
from materialtools.cardutils import output_materials as outmats
from materialtools.cardutils import output_trio as outtrio

outmats(getmats()[0])

outtrio(getmats())

a,b,c = getmats()
materials, cards, icons = getmats()

# param template, header, template card **********
from materialtools.cardutils import get_material_template as gettemplate
gettemplate()

gettemplate()[1]['General']['Description']
gettemplate()[2]['Mechanical']['FractureToughness']

from materialtools.cardutils import get_material_template as gettemplate
template_data=gettemplate()
for group in template_data:
    gname = list(group)[0]  # group dict has only one key
    for prop_name in group[gname]:
        #prop_dict = group[gname][prop_name]
        #print(prop_dict)
        #print(prop_dict['Description'])
        print(group[gname][prop_name]['Description'])

from materialtools.cardutils import create_mat_tools_header as createheader
createheader()

from materialtools.cardutils import create_mat_template_card as createtemplate
createtemplate()
createtemplate(False)

from materialtools.cardutils import get_source_path as getsrc
getsrc()

# generate all cards **********
# run tools in source dir
./make_ods.sh
./make_FCMats.sh

# read cards
from materialtools.cardutils import read_cards_from_path as readcards
from materialtools.cardutils import get_source_path as getsrc
cards_data = readcards(getsrc() + '/src/Mod/Material/StandardMaterial/')

# print cards
for c in cards_data:
    print(c)

# write cards
from materialtools.cardutils import write_cards_to_path as writecards
from materialtools.cardutils import get_source_path as getsrc

# True writes sections ( method write_group_section is used =)
writecards(getsrc() + '/src/Mod/Material/StandardMaterial/', cards_data, True)

writecards(getsrc() + '/src/Mod/Material/StandardMaterial/', cards_data, False)

# last True writes the TEMPLATE card which has no mat params because they have no values
writecards(getsrc() + '/src/Mod/Material/StandardMaterial/', cards_data, True, True)

# material quantity parameter unit checks **********
from materialtools.cardutils import output_parm_unit_info as unitinfo
unitinfo('YoungsModulus')
unitinfo('FractureToughness')
unitinfo('PoissonRatio')

from materialtools.cardutils import check_parm_unit as checkparamunit
checkparamunit('YoungsModulus')
checkparamunit('FractureToughness')

from materialtools.cardutils import output_value_unit_info as valueunitinfo
valueunitinfo('YoungsModulus', '1 MPa')
valueunitinfo('FractureToughness', '25')
valueunitinfo('Density', '1 kg/m^3')
valueunitinfo('Density', '0 kg/m^3')

from materialtools.cardutils import check_value_unit as checkvalueunit
checkvalueunit('YoungsModulus', '1 MPa')
checkvalueunit('FractureToughness', '25')
checkvalueunit('Density', '1 kg/m^3')
checkvalueunit('Density', '0 kg/m^3')

# syntax error in unit system, only the try: except in the checkvalueunit let it work
checkvalueunit('ThermalConductivity', '0.02583 W/m/K')
checkvalueunit('ThermalConductivity', '123abc456 W/m/K')
checkvalueunit('ThermalConductivity', '25.83e−3 W/m/K')
checkvalueunit('ThermalConductivity', '25.83e-3 W/m/K')
from FreeCAD import Units
Units.Quantity('25.83e−3 W/m/K')

# test mat unit properties
mat = {
    'Name': 'Concrete',
    'AngleOfFriction' : '1 deg',
    'CompressiveStrength': '1 MPa',
    'Density': '1 kg/m^3',
    'ShearModulus' : '1 MPa',
    'UltimateTensileStrength' : '1 MPa',
    'YieldStrength' : '1 MPa',
    'YoungsModulus': '1 MPa',
    'SpecificHeat' : '1 J/kg/K',
    'ThermalConductivity' : '1 W/m/K',
    'ThermalExpansionCoefficient' : '1 mm/mm/K'
}
from materialtools.cardutils import check_mat_units as checkunits
checkunits(mat)

# unknown quantities, returns True too
mat = {
    'Name': 'Concrete',
    'FractureToughness' : '1',
    'PoissonRatio': '0.17'  # no unit but important too, proof somehow too
}
from materialtools.cardutils import check_mat_units as checkunits
checkunits(mat)

# wrong units
mat = {
    'Name': 'Concrete',
    'CompressiveStrength': '12356 MBa',  # type on unit, means unit not knwn
    'YoungsModulus': '654321 m',  # unit known, but wrong unit for this property
}
from materialtools.cardutils import check_mat_units as checkunits
checkunits(mat)

# missing unit, returns False
mat = {
    'Name': 'Concrete',
    'YoungsModulus' : '1'
}
from materialtools.cardutils import check_mat_units as checkunits
checkunits(mat)

# empty dict, returns True
from materialtools.cardutils import check_mat_units as checkunits
checkunits({})

# some unit code **********
from FreeCAD import Units
getattr(Units, 'Pressure')
Units.Pressure
Units.Quantity('25 MPa')
Units.Quantity('25 MPa').getValueAs('Pa')
Units.Quantity('25 MPa').getUserPreferred()[2]
Units.Quantity(25000, Units.Pressure)
Units.Quantity(25000, Units.Pressure).getValueAs('MPa')
Units.Unit('25 MPa')
Units.Unit(-1,1,-2,0,0,0,0,0)

# base units
from FreeCAD import Units
Units.Length
Units.Mass
Units.TimeSpan
Units.ElectricCurrent
Units.Temperature
Units.AmountOfSubstance
Units.LuminousIntensity
Units.Angle

'''


# coding=utf8
# 提取top50 数据并更新
import execjs
import pymongo
import ast
import requests
import urllib

import random
import json

def get_js():
    f = open(r"C:\env\新建文件夹\toutiao.js", 'r', encoding='UTF-8')  ##打开JS文件
    line = f.readline()
    htmlstr = ''
    while line:
        htmlstr = htmlstr + line
        line = f.readline()
    ctx = execjs.compile(htmlstr)
    ctx_dict = ast.literal_eval(ctx.call('get_as_cp_signature'))
    return ctx_dict

class Hotarticle():
    def __init__(self):
        self.clinet = pymongo.MongoClient(host='localhost', port=27017)
        self.db = self.clinet.mydb
        self.collection = self.db.article1
        self.collection_hot = self.db.hot_article

    def get_hot(self):

        sorts = self.collection.find().sort('impression_count', pymongo.DESCENDING)
        art_ids = list(sort for sort in sorts)[0:51]

        for art_id in art_ids:
            ctx_dict = get_js()
            print(art_id['article_id'])
            headers = {
                'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Mobile Safari/537.36',
                'Referer': 'https://m.toutiao.com/i%s/' % art_id['article_id']
            }
            link = 'https://m.toutiao.com/' + 'i' + str(art_id['article_id']) + '/info/'  # 详情页url  获取阅读量

            data = {
                '_signature': ctx_dict['_signature'],
                'i': art_id['article_id']
            }
            url = link + '?' + urllib.parse.urlencode(data)
            print(url)
            ip = [{'http': '112.87.70.11:9999'}, {'http': '58.253.155.237:9999'}, {'http': '115.223.108.253:8010'},
                  {'http': '120.83.101.152:9999'}, {'http': '112.85.129.176:9999'}]
            ip_random = random.choice(ip)

            response = requests.get(url, proxies=ip_random, headers=headers)
            text = response.text
            bodys = json.loads(text)
            if bodys['success'] == True:
                impression = bodys['data']['impression_count']

                hot = {
                    'hot_id': art_id['article_id'],
                    'hot_review': impression
                }
                result = self.collection_hot.find({'hot_id': hot['hot_id']}).count()

                counts = self.collection_hot.find().count()
                if result:
                    hot_ids = self.collection_hot.find({'hot_id':hot['hot_id']})
                    for hot_id in hot_ids:
                        print('数据已存在，准备数据更新', result, counts,hot_id)
                        self.collection_hot.update_one(hot_id,{'$set':{'hot_review':impression}})
                        print('数据更新成功',hot_id)
                else:
                    print('未查询到文章，存入数据库',result)
                    self.collection_hot.insert(hot)
            else:
                print('此文章失效')
                self.collection_hot.delete_one({'hot_id': art_id['article_id']})
                self.collection.delete_one({'article_id':art_id['article_id']})

            # time.sleep(1)

def main():
    hot = Hotarticle()
    hot.get_hot()
    # hot.get_count()

if __name__ == '__main__':
    main()


string = input().strip().split("e")
isDi = True
if len(string) > 2:
    isDi = False
for k in string:
    start = 0
    if k.count(".")>1:
        isDi = False
    if k[0] == "-" or k[0] == "+":
        start = 1
    for i in range(start, len(k)):
        if not ("0" <= k[i] <= "9" or k[i] == "."):
            isDi = False
            break
    if not isDi:
        break
print(isDi)


class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        # Reference 1: https://leetcode.com/problems/largest-rectangle-in-histogram/solutions/995249/python-increasing-stack-explained/
        # Reference 2: https://leetcode.com/problems/largest-rectangle-in-histogram/solutions/28917/ac-python-clean-solution-using-stack-76ms/
        stack, ans = [], 0
        for i, height in enumerate(heights + [0]):
            while stack and heights[stack[-1]] > height:
                h = heights[stack.pop()]
                w = i - 1 - stack[-1] if stack else i
                ans = max(ans, h * w)
            stack.append(i)
        return ans


# This is the starter code for the CS 3451 Ray Tracing project.
#
# The most important part of this code is the interpreter, which will
# help you parse the scene description (.cli) files.

import math

# used to store scene properties and lists of objects, lights, surfaces
class Stats():
    def __init__(self):
        self.fov = 0
        self.BGr = 0
        self.BGg = 0
        self.BGb = 0
        self.lightList = []
        self.shapeList = []

class Surface():
    def __init__(self, d1, d2, d3, a1, a2, a3, s1, s2, s3, phong, refl):
        self.Cdr = d1
        self.Cdg = d2
        self.Cdb = d3
        self.Car = a1
        self.Cag = a2
        self.Cab = a3
        self.Csr = s1
        self.Csg = s2
        self.Csb = s3
        self.P = phong
        self.Krefl = refl

class Light():
    def __init__(self, x, y, z, R, G, B):
        self.position = (x, y, z)
        self.r = R
        self.g = G
        self.b = B

class Ray():
    # o, d are tuples : (x, y, z)
    def __init__(self, o, d):
        self.origin = o
        self.direction = d

    def getPoint(self, t):
        o = self.origin
        d = self.direction
        return (o[0] + t*d[0], o[1] + t*d[1], o[2] + t*d[2])

class Sphere():
    def __init__(self, r, x, y, z, surf):
        self.center = (x, y, z)
        self.radius = r
        self.surface = surf

    # returns the normal given a vertex on the sphere (already normalized)
    def getNormal(self, intersection):
        ix, iy, iz = intersection
        cx, cy, cz = self.center
        N = PVector(ix-cx, iy-cy, iz-cz)
        N.normalize()
        return N

    # returns the ray-sphere intersect point, or None
    def intersect(self, ray):
        dx, dy, dz = ray.direction
        x0, y0, z0 = ray.origin
        cx, cy, cz = self.center
        r = self.radius

        a = dx**2 + dy**2 + dz**2
        b = 2 * ((x0*dx - cx*dx) + (y0*dy - cy*dy) + (z0*dz - cz*dz))
        c = (x0-cx)**2 + (y0-cy)**2 + (z0-cz)**2 - r**2
        discriminant = (b*b) - (4*a*c)

        # imaginary roots = no intersection
        t = 0
        if discriminant < 0:
            return None
        elif discriminant == 0:
            t = -b / (2*a)
            if t < 0:
                return None
        else:
            root1 = (-b + math.sqrt(discriminant)) / (2*a)
            root2 = (-b - math.sqrt(discriminant)) / (2*a)
            # picks the smallest t value
            t = min(root1, root2)
            if t < 0:
                return None

        return ray.getPoint(t)

class Triangle():
    def __init__(self, a, b, c, surf):
        self.v1 = b
        self.v2 = a
        self.v3 = c
        self.surface = surf

        # plane calculations
        x1, y1, z1 = self.v1
        x2, y2, z2 = self.v2
        x3, y3, z3 = self.v3
        vec1 = PVector(x2-x1, y2-y1, z2-z1)
        vec2 = PVector(x3-x1, y3-y1, z3-z1)
        # finds the normal vector. N = (a, b, c)
        n = vec1.cross(vec2)
        n.normalize()

        self.N = n
        self.d = - n.dot(PVector(x1, y1, z1))

    # returns the normal (already normalized)
    def getNormal(self, intersection):
        return self.N

    # return ray-triangle intersect point, or None
    def intersect(self, ray):
        dx, dy, dz = ray.direction
        x0, y0, z0 = ray.origin
        origin = PVector(x0, y0, z0)
        direction = PVector(dx, dy, dz)

        x1, y1, z1 = self.v1
        x2, y2, z2 = self.v2
        x3, y3, z3 = self.v3
        N = self.N
        d = self.d

        # if the ray and plane are orthogonal, no intersect
        bottom = N.dot(direction)
        if bottom == 0:
            return None

        top = N.dot(origin)
        t = - (top + d) / bottom
        if t < 0:
            return None

        intersection = ray.getPoint(t)
        # now have to check if the intersection is inside the triangle
        x, y, z = intersection

        e1 = PVector(x2-x1, y2-y1, z2-z1)
        p1 = PVector(x-x1, y-y1, z-z1)
        test1 = e1.cross(p1)
        if N.dot(test1) < 0:
            return None

        e2 = PVector(x3-x2, y3-y2, z3-z2)
        p2 = PVector(x-x2, y-y2, z-z2)
        test2 = e2.cross(p2)
        if N.dot(test2) < 0:
            return None

        e3 = PVector(x1-x3, y1-y3, z1-z3)
        p3 = PVector(x-x3, y-y3, z-z3)
        test3 = e3.cross(p3)
        if N.dot(test3) < 0:
            return None

        return intersection

def setup():
    size(500, 500)
    noStroke()
    colorMode(RGB, 1.0)  # Processing color values will be in [0, 1]  (not 255)
    background(0, 0, 0)

# read and interpret the appropriate scene description .cli file based on key press
def keyPressed():
    if key == '1':
        interpreter("i1.cli")
    elif key == '2':
        interpreter("i2.cli")
    elif key == '3':
        interpreter("i3.cli")
    elif key == '4':
        interpreter("i4.cli")
    elif key == '5':
        interpreter("i5.cli")
    elif key == '6':
        interpreter("i6.cli")
    elif key == '7':
        interpreter("i7.cli")
    elif key == '8':
        interpreter("i8.cli")
    elif key == '9':
        interpreter("i9.cli")
    elif key == '0':
        interpreter("i10.cli")

def interpreter(fname):
    # instantiate a stats object that stores all necessary information from the file
    stats = Stats()

    # used to store the vertices of the triangle
    v1 = None
    v2 = None
    v3 = None

    # used to store the surface info
    surface = None

    fname = "data/" + fname
    # read in the lines of a file
    with open(fname) as f:
        lines = f.readlines()

    # parse each line in the file in turn
    for line in lines:
        words = line.split()  # split the line into individual tokens
        if len(words) == 0:   # skip empty lines
            continue
        if words[0] == 'sphere':
            stats.shapeList.append(Sphere(float(words[1]), float(words[2]), float(words[3]), \
                                          float(words[4]), surface))
        elif words[0] == 'fov':
            # makes sure fov is in radians
            stats.fov = math.radians(float(words[1]))
        elif words[0] == 'background':
            stats.BGr = float(words[1])
            stats.BGg = float(words[2])
            stats.BGb = float(words[3])
        elif words[0] == 'light':
            stats.lightList.append(Light(float(words[1]), float(words[2]), float(words[3]), \
                                         float(words[4]), float(words[5]), float(words[6])))
        elif words[0] == 'surface':
            surface = Surface(float(words[1]), float(words[2]), float(words[3]), \
                              float(words[4]), float(words[5]), float(words[6]), \
                              float(words[7]), float(words[8]), float(words[9]), \
                              float(words[10]), float(words[11]))
        elif words[0] == 'begin':
            v1 = None
            v2 = None
            v3 = None
        elif words[0] == 'vertex':
            if v1 == None:
                v1 = (float(words[1]), float(words[2]), float(words[3]))
            elif v2 == None:
                v2 = (float(words[1]), float(words[2]), float(words[3]))
            else:
                v3 = (float(words[1]), float(words[2]), float(words[3]))
        elif words[0] == 'end':
            stats.shapeList.append(Triangle(v1, v2, v3, surface))
        elif words[0] == 'write':
            render_scene(stats)    # render the scene
            save(words[1])  # write the image to a file
            pass

# render the ray tracing scene
def render_scene(stats):

    k = math.tan(stats.fov/2)
    z = -1

    for y in range(height):
        for x in range(width):
            # create an eye ray for pixel (x,y) and cast it into the scene
            # perspective projection from 2D to 3D
            x1 = x / abs(z)
            y1 = (height-y) / abs(z)
            x2 = (x1 - (width/2)) * ((2*k) / width)
            y2 = (y1 - (height/2)) * ((2*k) / height)

            # ray origin is at 0, 0, 0
            ray = Ray((0, 0, 0), (x2, y2, z))

            closest = None
            intersection = None

            # for each shape, find the closest intersection point
            for object in stats.shapeList:

                v = object.intersect(ray)

                # finds the closest intersection from all the objects
                if not intersection == None and not v == None:
                    oldDistance = dist(0, 0, 0, intersection[0], intersection[1], intersection[2])
                    newDistance = dist(0, 0, 0, v[0], v[1], v[2])

                if not v == None and (intersection == None or (newDistance < oldDistance)):
                    intersection = v
                    closest = object

            # color calculation

            # if ray misses all objects, then color pixel with background color
            if closest == None:
                pix_color = color(stats.BGr, stats.BGg, stats.BGb)
            else:
                r, g, b = calculateColor(stats, closest, intersection, 0)
                pix_color = color(r, g, b)

            # fill the pixel with the calculated color
            set (x, y, pix_color)

# used to calculate the color of a pixel
def calculateColor(stats, object, intersection, depth):
    ix, iy, iz = intersection

    # retrieves the already normalized normal vector
    N = object.getNormal(intersection)

    surface = object.surface
    diffuse = (surface.Cdr, surface.Cdg, surface.Cdb)
    amb = (surface.Car, surface.Cag, surface.Cab)
    spec = (surface.Csr, surface.Csg, surface.Csb)
    phong = surface.P
    reflect = surface.Krefl

    # color (r,g,b) sum to be added to
    sum = [0, 0, 0]

    # caluclates the vector from the point to eye. Used for reflection and specular
    V = PVector(-ix, -iy, -iz)
    V.normalize()

    # reflection calculation
    if depth < 12 and reflect > 0:
        R = PVector.mult(N, 2 * N.dot(V))
        R = PVector.sub(R, V)
        R.normalize()

        # used to push ray origin out of object
        Err = PVector.mult(N, 1e-12)
        reflectRay = Ray((ix+Err.x, iy+Err.y, iz+Err.z), (R.x, R.y, R.z))

        closest = None
        hitPoint = None
        for obj in stats.shapeList:
            if obj is not object:
                v = obj.intersect(reflectRay)
                # finds the closest reflect ray intersection from the current intersection
                if not hitPoint == None and not v == None:
                    oldDistance = dist(ix, iy, iz, hitPoint[0], hitPoint[1], hitPoint[2])
                    newDistance = dist(ix, iy, iz, v[0], v[1], v[2])
                if not v == None and (hitPoint == None or (newDistance < oldDistance)):
                    hitPoint = v
                    closest = obj
        if closest == None:
            BGcolor = (stats.BGr, stats.BGg, stats.BGb)
            for i in range(0, 3):
                sum[i] += (reflect * BGcolor[i])
        else:
            reflectColor = calculateColor(stats, closest, hitPoint, depth+1)
            for i in range(0, 3):
                sum[i] += (reflect * reflectColor[i])

    # ambient shading
    for i in range(0, 3):
        sum[i] += amb[i]

    for light in stats.lightList:
        lx, ly, lz = light.position
        light_color = (light.r, light.g, light.b)

        shadow = False
        # creates a ray from the point to the light source
        lightRay = Ray((ix, iy, iz), (lx-ix, ly-iy, lz-iz))
        for obj in stats.shapeList:
            if obj is not object:
                v = obj.intersect(lightRay)
                if not v == None:
                    lightDistance = dist(ix, iy, iz, lx, ly, lz)
                    intersectDistance = dist(ix, iy, iz, v[0], v[1], v[2])
                    if intersectDistance < lightDistance:
                        shadow = True

        # if point is in shadow, light color does not contribute
        if shadow == True:
            light_color = (0, 0, 0)

        L = PVector(lx-ix, ly-iy, lz-iz)
        L.normalize()

        # for specular shading
        #V = PVector(-ix, -iy, -iz)
        #V.normalize()
        H = PVector.add(L, V)
        H.normalize()

        for i in range(0, 3):
            sum[i] += (diffuse[i] * light_color[i] * max(0, N.dot(L))) + (spec[i] * light_color[i] * max(0, N.dot(H))**phong)

    # makes sure sum can't add up to more than 255
    for i in range(0, 3):
        if sum[i] > 1:
            sum[i] = 1

    r, g, b = sum
    return (r, g, b)

# should remain empty for this assignment
def draw():
    pass


"""
Functions to manage dataset
"""

import json
import logging
from typing import Dict, List, Tuple, Any, Callable

import numpy as np

from src.sound_actions import make_file_spectrogram, give_many_fft, wave_file_to_time_data

def load_dataset_json(json_path: str):
    """From the json annotating all the wav files, get useful info"""
    with open(json_path, "r") as jf:
        return json.load(jf)

def extract_tracks_by_family(dataset_json: Dict[str, Any], exclude_families=None,
                             exclude_source=None) -> Tuple[Dict[int, List[str]], Dict[str, int]]:
    """From the dict coming from nsynth json, group instruments by family.
    :returns: {class_index -> files} and {class_name -> class_index}
    """
    exclude_families = [] if exclude_families is None else exclude_families
    exclude_source = [] if exclude_source is None else exclude_source

    classes_n2i: Dict[str, int] = {}

    corr = {}
    for s in dataset_json.values():
        # instrument family
        family = s["instrument_family_str"]
        if family in exclude_families:
            continue

        # track name and instrument source
        name = s["note_str"]
        source = s["instrument_source_str"]

        # register track name under index of {family}_{source} key
        if source not in exclude_source:
            fs = f"{family}_{source}"
            if fs not in classes_n2i:
                classes_n2i[fs] = len(classes_n2i)
                corr[classes_n2i[fs]] = []
            corr[classes_n2i[fs]].append(name)
    return corr, classes_n2i

def make_labels_and_spectrograms(corr: Dict[int, List[str]], file_access: Callable[[str], str] = lambda x: x):
    """Make the spectrogram of each file in the data dict
    :returns: Lists for ids, labels, spectrograms
    """
    ids: List[str] = []
    labels: List[int] = []
    spectrograms: List[np.ndarray] = []

    for k, file_names in corr.items():
        logging.info(f"Making {k} data...")
        for fn in file_names:
            ids.append(fn)
            labels.append(k)
            spectrograms.append(make_file_spectrogram(file_access(fn)))

    return ids, labels, spectrograms

def make_labels_and_fft(corr: Dict[int, List[str]], file_access: Callable[[str], str] = lambda x: x, **kwargs) -> Tuple[List[int], List[np.ndarray], List[str]]:
    """Make the fft of some samples from each file in the data dict
    :returns: Lists for ids, labels, spectrograms; lookups {class_index -> class_name}, {class_name -> class_index}
    """
    labels: List[int] = []
    data: List[np.ndarray] = []
    source: List[str] = []

    for k, file_names in corr.items():
        logging.info(f"Making {k} data...")
        for fn in file_names:
            file_full_name = file_access(fn)
            for out in give_many_fft(*wave_file_to_time_data(file_full_name), **kwargs):
                labels.append(k)
                data.append(out)
                source.append(fn)
        logging.info(f"- Total: {len(labels)} entries...")

    return labels, data, source


from mmcv.runner import OptimizerHook
# Copyright (c) OpenMMLab. All rights reserved.
import copy
from collections import defaultdict
from itertools import chain
from mmcv.runner.dist_utils import allreduce_grads
from .fp16_utils import LossScaler, wrap_fp16_model

class Fp16OptimizerHook(OptimizerHook):
    """FP16 optimizer hook (mmcv's implementation).

    The steps of fp16 optimizer is as follows.
    1. Scale the loss value.
    2. BP in the fp16 model.
    2. Copy gradients from fp16 model to fp32 weights.
    3. Update fp32 weights.
    4. Copy updated parameters from fp32 weights to fp16 model.

    Refer to https://arxiv.org/abs/1710.03740 for more details.

    Args:
        loss_scale (float | str | dict): Scale factor configuration.
            If loss_scale is a float, static loss scaling will be used with
            the specified scale. If loss_scale is a string, it must be
            'dynamic', then dynamic loss scaling will be used.
            It can also be a dict containing arguments of LossScaler.
            Defaults to 512.
    """

    def __init__(self,
                    grad_clip=None,
                    coalesce=True,
                    bucket_size_mb=-1,
                    loss_scale=512.,
                    distributed=True):
        self.grad_clip = grad_clip
        self.coalesce = coalesce
        self.bucket_size_mb = bucket_size_mb
        self.distributed = distributed
        if loss_scale == 'dynamic':
            self.loss_scaler = LossScaler(mode='dynamic')
        elif isinstance(loss_scale, float):
            self.loss_scaler = LossScaler(
                init_scale=loss_scale, mode='static')
        elif isinstance(loss_scale, dict):
            self.loss_scaler = LossScaler(**loss_scale)
        else:
            raise ValueError('loss_scale must be of type float, dict, or '
                                f'"dynamic", got {loss_scale}')

    def before_run(self, runner):
        """Preparing steps before Mixed Precision Training.

        1. Make a master copy of fp32 weights for optimization.
        2. Convert the main model from fp32 to fp16.
        """
        # keep a copy of fp32 weights
        old_groups = runner.optimizer.param_groups
        runner.optimizer.param_groups = copy.deepcopy(
            runner.optimizer.param_groups)
        state = defaultdict(dict)
        p_map = {
            old_p: p
            for old_p, p in zip(
                chain(*(g['params'] for g in old_groups)),
                chain(*(g['params']
                        for g in runner.optimizer.param_groups)))
        }
        for k, v in runner.optimizer.state.items():
            state[p_map[k]] = v
        runner.optimizer.state = state
        # convert model to fp16
        wrap_fp16_model(runner.model)
        # resume from state dict
        if 'fp16' in runner.meta and 'loss_scaler' in runner.meta['fp16']:
            scaler_state_dict = runner.meta['fp16']['loss_scaler']
            self.loss_scaler.load_state_dict(scaler_state_dict)

    def copy_grads_to_fp32(self, fp16_net, fp32_weights):
        """Copy gradients from fp16 model to fp32 weight copy."""
        for fp32_param, fp16_param in zip(fp32_weights,
                                            fp16_net.parameters()):
            if fp16_param.grad is not None:
                if fp32_param.grad is None:
                    fp32_param.grad = fp32_param.data.new(
                        fp32_param.size())
                fp32_param.grad.copy_(fp16_param.grad)

    def copy_params_to_fp16(self, fp16_net, fp32_weights):
        """Copy updated params from fp32 weight copy to fp16 model."""
        for fp16_param, fp32_param in zip(fp16_net.parameters(),
                                            fp32_weights):
            fp16_param.data.copy_(fp32_param.data)

    def after_train_iter(self, runner):
        """Backward optimization steps for Mixed Precision Training. For
        dynamic loss scaling, please refer `loss_scalar.py`

        1. Scale the loss by a scale factor.
        2. Backward the loss to obtain the gradients (fp16).
        3. Copy gradients from the model to the fp32 weight copy.
        4. Scale the gradients back and update the fp32 weight copy.
        5. Copy back the params from fp32 weight copy to the fp16 model.
        6. Save loss_scaler state_dict for resume purpose.
        """
        # clear grads of last iteration
        runner.model.zero_grad()
        runner.optimizer.zero_grad()
        # scale the loss value
        scaled_loss = runner.outputs['loss'] * self.loss_scaler.loss_scale
        scaled_loss.backward()
        # copy fp16 grads in the model to fp32 params in the optimizer
        #for i,param_group in enumerate(runner.optimizer.param_groups):
        #    if 'pooler.dense' in param_group['name']:
        #        print (i,param_group['name'])
        #        print (param_group['params'][0].grad)
        fp32_weights = []
        for param_group in runner.optimizer.param_groups:
            fp32_weights += param_group['params']
        self.copy_grads_to_fp32(runner.model, fp32_weights)
        # allreduce grads
        if self.distributed:
            allreduce_grads(fp32_weights, self.coalesce,
                            self.bucket_size_mb)

        has_overflow = self.loss_scaler.has_overflow(fp32_weights)
        # if has overflow, skip this iteration
        if not has_overflow:
            # scale the gradients back
            for param in fp32_weights:
                if param.grad is not None:
                    param.grad.div_(self.loss_scaler.loss_scale)
            if self.grad_clip is not None:
                grad_norm = self.clip_grads(fp32_weights)
                if grad_norm is not None:
                    # Add grad norm to the logger
                    runner.log_buffer.update(
                        {'grad_norm': float(grad_norm)},
                        runner.outputs['num_samples'])
            # update fp32 params
            runner.optimizer.step()
            # copy fp32 params to the fp16 model
            self.copy_params_to_fp16(runner.model, fp32_weights)
        self.loss_scaler.update_scale(has_overflow)
        if has_overflow:
            runner.logger.warning('Check overflow, downscale loss scale '
                                    f'to {self.loss_scaler.cur_scale}')

        # save state_dict of loss_scaler
        runner.meta.setdefault(
            'fp16', {})['loss_scaler'] = self.loss_scaler.state_dict()


class DoublyLinkedList : #Circular Doubly linked list with dummy
    class Node :
        def __init__(self,data,prev = None,next = None) :
            self.data = data
            if prev is None :
                self.prev = None
            else :
                self.prev = prev
            if next is None :
                self.next = None
            else :
                self.next = next
    def __init__(self):
            self.dummy = self.Node(None,None,None)
            self.dummy.next = self.dummy.prev = self.dummy
            self.size = 0
    def __str__(self):
        s = ''
        p = self.dummy.next
        for i in range(len(self)-1) :
            s += str(p.data) + ' '
            p = p.next
        s += str(p.data)
        return s
    def __len__(self) :
        return self.size
    def isEmpty(self) :
        return self.size == 0
    def indexOf(self,data) :
        q = self.dummy.next
        for i in range(len(self)) :
            if q.data == data :
                return i
            q = q.next
        return -1
    def isIn(self,data) :
        return self.indexOf(data) >= 0
    def nodeAt(self,i) :
        p = self.dummy
        for j in range(-1,i) :
            p = p.next
        return p
    def str_reverse(self):
        s = ''
        p = self.nodeAt(len(self)-1)
        for i in range(len(self)-1) :
            s += str(p.data) + ' '
            p = p.prev
        s += str(p.data)
        return s
    def add_before(self,q,data) :
        p = q.prev
        x = self.Node(data,p,q)
        p.next = q.prev = x
        self.size += 1
    def appending(self,data) :
        self.add_before(self.nodeAt(len(self)),data)
    def removeNode(self,q) :
        p = q.prev
        x = q.next
        p.next = x
        x.prev = p
        self.size -= 1
    def delete(self,i) :
        self.removeNode(self.nodeAt(i))
x=input("Enter Input : ").split()
print('------------------------------------------------------------')
pro = DoublyLinkedList()
red = DoublyLinkedList()
rad = 1
b = 0
round=1
for i in x:
    pro.appending(i)
linkdec = []
for i in range (10):
    t = DoublyLinkedList()
    linkdec.append(t)
linkdex = []
for i in range (10):
    t = DoublyLinkedList()
    linkdex.append(t)
for i in x:
    if  linkdec[abs(int(i))//rad%10].isEmpty() :
        linkdec[abs(int(i))//rad%10].appending(i)
    else :
        isadd = 0
        for k in range(len(linkdec[abs(int(i))//rad%10])) :
            if int(linkdec[abs(int(i))//rad%10].nodeAt(k).data)<=int(i):
                linkdec[abs(int(i))//rad%10].add_before(linkdec[abs(int(i))//rad%10].nodeAt(k),i)
                isadd =1
                break
        if isadd ==0:
            linkdec[abs(int(i))//rad%10].appending(i)
rad*=10
print('Round : '+str(round))
for i in range (10):
        print(str(i)+' : ',end='')
        if not linkdec[i].isEmpty() :
            print(linkdec[i])
        else :
            print()
print('------------------------------------------------------------')
round +=1
while(1):
    for i in range (10):
        if len(linkdec[i])==len(pro) and i==0:
            for j in range(len(linkdec[i])):
                red.appending(linkdec[i].nodeAt(j).data)
            b=1
    #    print(linkdec[i])
    if b==1:
       round -=1
       break
    temp = linkdec.copy()
    current = linkdex.copy()
    for i in range (10):
        current[i] = DoublyLinkedList()
    for i in range (10):
        if not temp[i].isEmpty():
            for j in range(len(temp[i])):
                if  current[abs(int(temp[i].nodeAt(j).data))//rad%10].isEmpty() :
                    current[abs(int(temp[i].nodeAt(j).data))//rad%10].appending(temp[i].nodeAt(j).data)
                else :
                    isadd = 0
                    for k in range(len(current[abs(int(temp[i].nodeAt(j).data))//rad%10])) :
                        if int(current[abs(int(temp[i].nodeAt(j).data))//rad%10].nodeAt(k).data)<=int(temp[i].nodeAt(j).data):
                            current[abs(int(temp[i].nodeAt(j).data))//rad%10].add_before(current[abs(int(temp[i].nodeAt(j).data))//rad%10].nodeAt(k),int(temp[i].nodeAt(j).data))
                            isadd = 1
                            break
                    if isadd==0:
                        current[abs(int(temp[i].nodeAt(j).data))//rad%10].appending(temp[i].nodeAt(j).data)
    linkdec = current.copy()
    print('Round : '+str(round))
    for i in range (10):
        print(str(i)+' : ',end='')
        if not linkdec[i].isEmpty() :
            print(linkdec[i])
        else :
            print()
    for i in range (10):
        if len(linkdec[i])==len(pro) and i==0:
            for j in range(len(linkdec[i])):
                red.appending(linkdec[i].nodeAt(j).data)
            b=1
    #    print(linkdec[i])
    if b==1:
       print('------------------------------------------------------------')
       break
    rad*=10
    round +=1
    print('------------------------------------------------------------')
print(str(round-1)+' Time(s)')
print('Before Radix Sort : ',end='')
for i in range(len(pro)-1):
    print(pro.nodeAt(i).data,end=' -> ')
print(pro.nodeAt(len(pro)-1).data)
print('After  Radix Sort : ',end='')
for i in range(len(red)-1):
    print(red.nodeAt(i).data,end=' -> ')
print(red.nodeAt(len(pro)-1).data)

#64 8 216 512 27 729 0 1 343 125


import os
from typing import List

import numpy as np
import pytest

from ambrosia.preprocessing import IQRPreprocessor, RobustPreprocessor

STORAGE_PATHS = {
    "robust": "tests/configs/robust_config.json",
    "iqr": "tests/configs/iqr_config.json",
}

@pytest.mark.smoke
def test_robust_constructor():
    """
    Check RobustPreprocessor constructor works.
    """
    robust = RobustPreprocessor(verbose=False)

@pytest.mark.unit
@pytest.mark.parametrize(
    "tail, column_names, alpha, transf_name",
    [
        ("both", "feature_1", 0.05, "robust_both_0.05_feature_1"),
        ("both", ["feature_2"], 0.05, "robust_both_0.05_feature_2"),
        ("both", ["feature_2", "feature_1"], [0.05, 0.05], "robust_both_0.05_feature_2after1"),
        ("left", "feature_1", 0.1, "robust_left_0.1_feature_1"),
        ("right", "feature_1", 0.1, "robust_right_0.1_feature_1"),
    ],
)
def test_robust(tail, column_names, alpha, transf_name, data_nonlin_var, robust_moments):
    """
    Test RobustPreprocessor quantile transformations via resulted moments.
    """
    robust = RobustPreprocessor(verbose=False)
    transformed_data = robust.fit_transform(data_nonlin_var, column_names, alpha, tail, inplace=False)
    if isinstance(column_names, List):
        column_names: str = column_names[0]
    col_mean: float = transformed_data[column_names].mean()
    col_std: float = transformed_data[column_names].std()
    moments: np.ndarray = robust_moments.loc[transf_name].values
    assert np.allclose(np.array([col_mean, col_std]), moments, atol=0.000001)

@pytest.mark.unit
def test_robust_load_store(data_nonlin_var, robust_moments):
    """
    Test RobustPreprocessor save and load methods.
    """
    store_path = STORAGE_PATHS["robust"]
    robust = RobustPreprocessor(verbose=False)
    robust.fit(data_nonlin_var, ["feature_2", "feature_1"], 0.05)
    robust.store_params(store_path)
    loaded_robust = RobustPreprocessor(verbose=False)
    loaded_robust.load_params(store_path)
    os.remove(store_path)
    transformed_data = loaded_robust.transform(data_nonlin_var, inplace=False)
    col_mean: float = transformed_data["feature_2"].mean()
    col_std: float = transformed_data["feature_2"].std()
    moments: np.ndarray = robust_moments.loc["robust_both_0.05_feature_2after1"].values
    assert np.allclose(np.array([col_mean, col_std]), moments, atol=0.000001)

@pytest.mark.smoke
def test_iqr_constructor():
    """
    Check IQRPreprocessor constructor works.
    """
    iqr = IQRPreprocessor(verbose=False)

@pytest.mark.unit
@pytest.mark.parametrize(
    "column_names, transf_name",
    [
        ("feature_1", "iqr_feature_1"),
        (["feature_2"], "iqr_feature_2"),
        (["feature_2", "feature_1"], "iqr_feature_2after1"),
    ],
)
def test_iqr(column_names, transf_name, data_nonlin_var, robust_moments):
    """
    Test IQRPreprocessor transformations via resulted moments.
    """
    iqr = IQRPreprocessor(verbose=False)
    transformed_data = iqr.fit_transform(data_nonlin_var, column_names, inplace=False)
    if isinstance(column_names, List):
        column_names: str = column_names[0]
    col_mean: float = transformed_data[column_names].mean()
    col_std: float = transformed_data[column_names].std()
    moments: np.ndarray = robust_moments.loc[transf_name].values
    assert np.allclose(np.array([col_mean, col_std]), moments, atol=0.000001)

@pytest.mark.unit
def test_iqr_load_store(data_nonlin_var, robust_moments):
    """
    Test IQRPreprocessor save and load methods.
    """
    store_path = STORAGE_PATHS["iqr"]
    iqr = IQRPreprocessor(verbose=False)
    iqr.fit(data_nonlin_var, ["feature_2", "feature_1"])
    iqr.store_params(store_path)
    loaded_iqr = IQRPreprocessor(verbose=False)
    loaded_iqr.load_params(store_path)
    os.remove(store_path)
    transformed_data = loaded_iqr.transform(data_nonlin_var, inplace=False)
    col_mean, col_std = transformed_data["feature_2"].mean(), transformed_data["feature_2"].std()
    moments: np.ndarray = robust_moments.loc["iqr_feature_2after1"].values
    assert np.allclose(np.array([col_mean, col_std]), moments, atol=0.000001)


import numpy as np
import pandas as pd
import numba as nb
import logging
import scipy.sparse.linalg as spl

from .autoregressive import AutoRegressive
from .baseline import HarmonicBaseline
from .greedy_grid_search import greedy_grid_search

logger = logging.getLogger(__name__)

__all__ = ['Autotune_AutoRegressive', 'AutotunedBaseline']

# TODO unisci la logica, greedy grid search, per ridurre
# la quantità di codice
def Autotune_AutoRegressive(train_residuals,
                            test_residuals,
                            future_lag,
                            P=None,
                            past_lag=None):

    P_range = range(0, train_residuals.shape[1] - 1) if P is None else [P]
    past_lag_range = range(1, future_lag *
                           2) if past_lag is None else [past_lag]

    ar_model = AutoRegressive(train_residuals,
                              test_residuals,
                              past_lag=1 if past_lag is None else past_lag,
                              future_lag=future_lag,
                              P=0 if P is None else P)

    # Ps = np.arange(0, P_range)
    # past_lags = np.arange(1, past_lag_range)
    result_RMSE = pd.DataFrame(index=past_lag_range,
                               columns=P_range)
    for test_past_lag in past_lag_range:
        ar_model.past_lag = test_past_lag
        for test_P in P_range:
            ar_model.P = test_P
            # if not np.isnan(result.loc[past_lag, P]):
            #     continue
            ar_model.fit_AR()

            print()
            print()
            print('past_lag = %d, P = %d' % (
                ar_model.past_lag, ar_model.P))
            print('test RMSE:', ar_model.test_RMSE)
            print()
            print()

            result_RMSE.loc[test_past_lag, test_P] = ar_model.test_RMSE
            if (P is not None) or ((test_P > 0) and result_RMSE.loc[
                    test_past_lag, test_P] > result_RMSE.loc[test_past_lag, test_P - 1]):
                break
        if (past_lag is not None) or (test_past_lag > 1 and result_RMSE.min(
                1)[test_past_lag] > result_RMSE.min(1)[test_past_lag - 1]):
            break
    print('converged!')
    best_P = result_RMSE.min().idxmin()
    best_past_lag = result_RMSE.min(1).idxmin()
    return AutoRegressive(train_residuals,
                          test_residuals,
                          past_lag=best_past_lag,
                          future_lag=future_lag,
                          P=best_P)

def baseline_autotune(train, test,
                      daily_harmonics=None,
                      weekly_harmonics=None,
                      annual_harmonics=None,
                      trend=None,
                      pre_gaussianize=None):

    train = train.dropna()
    test = test.dropna()

    print('autotuning baseline on %d train and %d test points' %
          (len(train), len(test)))

    daily_harmonics = np.arange(
        24) if daily_harmonics is None else [daily_harmonics]
    weekly_harmonics = np.arange(
        6) if weekly_harmonics is None else [daily_harmonics]
    annual_harmonics = np.arange(
        50) if annual_harmonics is None else [annual_harmonics]
    trend = [False, True] if trend is None else [trend]
    pre_gaussianize = [
        False, True] if pre_gaussianize is None else [pre_gaussianize]

    def test_RMSE(
            daily_harmonics,
            weekly_harmonics,
            annual_harmonics,
            trend,
            pre_gaussianize):
        baseline = HarmonicBaseline(train,
                                    daily_harmonics,
                                    weekly_harmonics,
                                    annual_harmonics,
                                    trend,
                                    pre_gaussianize)

        return np.sqrt(((test - baseline.baseline(
            test.index))**2).mean())

    res = greedy_grid_search(test_RMSE,
                             [daily_harmonics,
                              weekly_harmonics,
                              annual_harmonics,
                              trend,
                              pre_gaussianize],
                             num_steps=2)

    print('optimal params: %s' % res)
    print('test std. dev.: %.2f' % test.std())

    return res

# def baseline_autotune_OLD(train, test, min_harmonics=3,
#                           trend=None,
#                           daily_harmonics=None,
#                           weekly_harmonics=None,
#                           annual_harmonics=None):

#     results_test_RMSE = {}

#     train = train.dropna()
#     test = test.dropna()

#     BOUND_WEEKLY = 6

#     max_daily = min_harmonics
#     max_weekly = min_harmonics
#     max_annual = min_harmonics

#     while True:

#         daily_harmonics_range = range(max_daily) if \
#             daily_harmonics is None else [daily_harmonics]
#         weekly_harmonics_range = range(max_weekly) if \
#             weekly_harmonics is None else [weekly_harmonics]
#         annual_harmonics_range = range(max_annual) if \
#             annual_harmonics is None else [annual_harmonics]
#         trend_range = [False, True] if \
#             trend is None else [trend]

#         for daily_harmonics_test in daily_harmonics_range:
#             for weekly_harmonics_test in weekly_harmonics_range:
#                 for annual_harmonics_test in annual_harmonics_range:
#                     for trend_test in trend_range:
#                         if (daily_harmonics_test, weekly_harmonics_test,
#                                 annual_harmonics_test, trend_test) \
#                                 in results_test_RMSE:
#                             continue
#                         baseline = HarmonicBaseline(train,
#                                                     daily_harmonics_test,
#                                                     weekly_harmonics_test,
#                                                     annual_harmonics_test,
#                                                     trend_test)

#                         test_RMSE = np.sqrt(((test - baseline._predict_baseline(
#                             test.index))**2).mean())
#                         # print('test_RMSE:, ', test_RMSE)
#                         results_test_RMSE[(daily_harmonics_test,
#                                            weekly_harmonics_test,
#                                            annual_harmonics_test,
#                                            trend_test)] = test_RMSE

#         current_best = min(results_test_RMSE, key=results_test_RMSE.get)

#         current_best_daily = current_best[0]
#         current_best_weekly = current_best[1]
#         current_best_annual = current_best[2]

#         if ((current_best_daily < max_daily - 1) or
#             daily_harmonics is not None) and \
#            ((current_best_weekly < max_weekly - 1) or
#             weekly_harmonics is not None) and \
#            ((current_best_annual < max_annual - 1) or
#                 annual_harmonics is not None):
#             print('tried %d baseline parameter combinations' %
#                   len(results_test_RMSE))
#             print('optimal baseline parameters: ', current_best)
#             print('test RMSE: ', results_test_RMSE[current_best])
#             print('test std. dev.: ', test.std())
#             print()
#             return current_best

#         max_daily = max(max_daily, current_best_daily + 2)
#         max_weekly = max(max_weekly, current_best_weekly + 2)
#         max_annual = max(max_daily, current_best_annual + 2)

def AutotunedBaseline(train, test, **kwargs):
    print('autotuning baseline for column %s' % train.name)
    if len(train.dropna().value_counts()) == 1:
        kwargs['pre_gaussianize'] = False
    params = baseline_autotune(train.dropna(), test.dropna(), **kwargs)
    return HarmonicBaseline(train.dropna(), *params)


import itertools

from bokeh import palettes
from bokeh.plotting import figure
from bokeh.charts import show

from loggraph import accumulator
from loggraph.parser import log_record_generator

def accumulators_for_definitions(graph_definitions):
    accumulator_definitions = (
        tuple(definition[:-1].split('['))
        for definition in graph_definitions
    )

    return [
        accumulator.NAME_TO_ACCUMULATOR[name](path.split('.'))
        for name, path in accumulator_definitions
    ]

def generate_graph(
    filepath,
    graph_definitions,
    time_column_name
):
    accumulators = accumulators_for_definitions(graph_definitions)
    record_generator = log_record_generator(filepath)
    by_day = accumulator.ByDayAccumulator(accumulators, time_column_name)
    for record in record_generator:
        by_day.process(record)

    colors = itertools.cycle(palettes.Set2[8])

    plot = figure(width=800, height=400, x_axis_type='datetime')
    plot.xaxis.axis_label = by_day.time_column_name.capitalize()

    for x_axis, y_axis, legend in by_day.get_rendered_axes():
        plot.line(
            x_axis,
            y_axis,
            legend=legend,
            color=next(colors)
        )

    show(plot)


from flask import *
from functools import wraps
from datetime import datetime
import sqlite3

DATABASE = '/home/LionCubFearMe/mysite/sales.db'

app = Flask(__name__)
app.config.from_object(__name__)

app.secret_key = 'this is giving me headaches'

def connect_db():
    return sqlite3.connect(app.config['DATABASE'])

def login_required(test):
    @wraps(test)
    def wrap(*args, **kwargs):
        if 'logged_in' in session:
            return test(*args, **kwargs)
        else:
            flash('You need to login first.')
            return redirect(url_for('log'))
    return wrap

@app.route('/dashboard')
@login_required
def dashboard():
    return render_template('dashboard.html')

@app.route('/shop')
@login_required
def shop():
    g.db = connect_db()
    cur = g.db.execute('SELECT id, imgurl, item_name, price, availability FROM items')
    listofitems = [dict(id = row[0], imgurl = row[1], item_name = row[2], price = row[3], availability = row[4])
                   for row in cur.fetchall()]
    g.db.close()
    return render_template('shop.html', listofitems = listofitems)

@app.route('/buy', methods = ['POST'])
@login_required
def buy():
    item_id = request.form['id']
    g.db = connect_db()
    cur = g.db.execute('SELECT id, imgurl, item_name, price FROM items WHERE id ='+ str(item_id))
    listofdict = [dict(id=row[0], imgurl=row[1], item_name=row[2], price=row[3]) for row in cur.fetchall()]
    currentorder = listofdict[0]
    imgurl = currentorder['imgurl']
    item_name = currentorder['item_name']
    price = currentorder['price']
    g.db.execute('INSERT INTO orders (imgurl, item_name, price, quantity) '
                 'VALUES (?, ?, ?, 1)', [imgurl, item_name, price])
    g.db.commit()
    flash('Your order has been made')
    return redirect(url_for('shop'))

@app.route('/confirm')
@login_required
def confirm():
    g.db = connect_db()
    cur = g.db.execute('SELECT id, imgurl, item_name, price, quantity FROM orders')
    listorders = [dict(id=row[0], imgurl=row[1], item_name=row[2], price=row[3], quantity=row[4]) for row in cur.fetchall()]
    g.db.close()
    return render_template('confirm.html', listorders = listorders)

@app.route('/delete/<int:id>')
@login_required
def delete(id):
    g.db = connect_db()
    cur = g.db.execute('DELETE FROM orders WHERE id='+str(id))
    g.db.commit()
    g.db.close()
    flash('The item has been removed from your cart')
    return redirect(url_for('confirm'))

@app.route('/edit/<int:id>', methods=['POST'])
@login_required
def edit(id):
    new_quantity = request.form['quantity']
    g.db = connect_db()
    cur = g.db.execute('UPDATE orders SET quantity='+str(new_quantity)+' WHERE id='+str(id))
    g.db.commit()
    g.db.close()
    flash('Order has been edited')
    return redirect(url_for('confirm'))

@app.route('/clear')
@login_required
def clear():
    g.db = connect_db()
    g.db.execute('DELETE FROM orders')
    g.db.commit()
    g.db.close()
    flash('Your cart has been reset')
    return redirect(url_for('confirm'))

@app.route('/sendorders', methods=['POST'])
@login_required
def sendorders():
    g.db = connect_db()
    # get all information about current order and send it over to another database
    confirmed = g.db.execute('SELECT * FROM orders')
    listoforders = [dict(id=row[0], imgurl=row[1], item_name=row[2], price=row[3], quantity=row[4])
                    for row in confirmed.fetchall()]
    for i in range(0,len(listoforders)):
        currentorder = listoforders[i]
        imgurl = currentorder['imgurl']
        item_name = currentorder['item_name']
        price = currentorder['price']
        quantity = currentorder['quantity']
        g.db.execute('INSERT INTO confirmed (imgurl, item_name, price, quantity, date) '
                     'VALUES (?, ?, ?, ?, ?)', [imgurl, item_name, price, quantity, datetime.now()])
        g.db.commit()
    cur = g.db.execute('DELETE FROM orders')
    g.db.commit()
    flash('Your order has been confirmed and submitted for processing.')
    return redirect(url_for('history'))

@app.route('/history')
@login_required
def history():
    g.db = connect_db()
    cur = g.db.execute('SELECT * FROM confirmed')
    confirmedlist = [dict(id=row[0], date=row[1], imgurl=row[2], item_name=row[3], price=row[4], quantity=row[5])
                     for row in cur.fetchall()]
    g.db.close()
    return render_template('history.html', confirmedlist = confirmedlist)

@app.route('/clearhistory')
@login_required
def clearhistory():
    g.db = connect_db()
    g.db.execute('DELETE FROM confirmed')
    g.db.commit()
    g.db.close()
    flash('Your order history has been cleared')
    return redirect(url_for('history'))

@app.route('/logout')
def logout():
    session.pop('logged_in', None)
    flash('You were logged out')
    return redirect(url_for('log'))

@app.route('/log', methods=['GET', 'POST'])
def log():
    error = None
    if request.method == 'POST':
        if request.form['username'] != 'admin' or request.form['password'] != 'admin':
            error = 'Invalid Credentials. Please try again.'
        else:
            session['logged_in'] = True
            return redirect(url_for('dashboard'))
    return render_template('log.html', error=error)

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

if __name__ == '__main__':
    app.run(debug=True)


class Solution:
    def isPalindrome(self, s: str) -> bool:
        start, end = 0, len(s) - 1
        while start < end:
            if s[start] != s[end]:
                return False

            start += 1
            end -= 1

        return True

    def longestPalindrome(self, s: str) -> str:
        n = len(s) - 1

        while True:
            for i in range(len(s) - n + 1):
                if self.isPalindrome(s[i:i + n + 1]):
                    return s[i:i + n + 1]

            n -= 1

            if n == 0:
                break

leetcode/5. Longest Palindromic Substring.py


import json

from code_names_bot_text_graph.text_disambiguator.consec_compound_text_disambiguator import ConsecCompoundTextDisambiguator

from config import DICTIONARY
import time

def main():
    with open(DICTIONARY, "r") as file:
        dictionary = json.loads(file.read())

    """
    token_senses = [
        ("I", []),
        ("have", []),
        ("a", []),
        ("beautiful", ["m_en_gbus0081680.006"]),
        ("dog", ["m_en_gbus0287810.007", "m_en_gbus0287810.012", "m_en_gbus0287810.013", "m_en_gbus0287810.019", "m_en_gbus0287810.020", "m_en_gbus0287810.023"])
    ]
    """

    token_senses = [
        ("The", []),
        ("Amazing", ['The_Amazing_Spider-Man_(film)']),
        ("Spider", ['The_Amazing_Spider-Man_(film)']),
        ("-", ['The_Amazing_Spider-Man_(film)']),
        ("Man", ['The_Amazing_Spider-Man_(film)']),
        ("Annual", [])
    ]

    compound_indices = [
        ("The_Amazing_Spider-Man_(film)", (2, 5)),
        ("The_Amazing_Spider-Man_(film)", (0, 5))
    ]

    disambiguator = ConsecCompoundTextDisambiguator(dictionary, True)
    start = time.time()
    senses = disambiguator.disambiguate(token_senses, compound_indices)
    print("Time", time.time() - start)
    print(senses)

if __name__ == "__main__":
    main()


if __name__ == '__main__':
    ls1 = input().split(' ')
    ls1 = list(map(int, ls1))
    n, m = ls1[0], ls1[1]
    word = []
    for _ in range(n):
        word.append(input())
    res = []
    for _ in range(m):
        ls2 = input().split(' ')
        ls2 = list(map(int, ls2))
        start = ls2[0] - 1
        end = ls2[1]
        res.append(max(word[start:end]))
    for i in res:
        print(i)


import DirectedGraph
import collections
class TopSort:
  def Kahns(self, graph):
    inDegree = dict()
    for node in graph.vertices:
      inDegree[node] = 0

    for node in graph.vertices:
      for neighbor in node.neighbors:
        inDegree[neighbor] = inDegree[neighbor] + 1

    topSort = list()
    queue = collections.deque()
    #add all elements of M whose values are 0 to Q
    for curr in list(inDegree.keys())[::-1]:
      if inDegree[curr] == 0:
        queue.append(curr)
        inDegree[curr] = inDegree[curr] - 1

    #while Q is not empty
    while queue:
      #N←first element in Q
      current = queue.popleft()
      #add N to A
      topSort.append(curr)
      for neighbor in curr.neighbors:
        #decrement the in-degrees of all dependents of N
        inDegree[neighbor] = inDegree[neighbor] -1

      for curr in list(inDegree.keys())[::-1]:
        if inDegree[curr] == 0:
          queue.append(curr)
          inDegree[curr] = inDegree[curr] - 1

    return topSort

  def mDFS(self, graph):
    stack = list()
    for vertex in graph.vertices:
      if not vertex.visited:
        self.mDFSHelper(vertex, stack)

    inOrderStack = stack[::-1]

    return inOrderStack

  def mDFSHelper(self, vertex, stack):
    vertex.visited = True
    for neighbor in vertex.neighbors:
      if not neighbor.visited:
        self.mDFSHelper(vertex, stack)

    stack.append(vertex)