# -*- coding: utf-8 -*-
"""
Created on Sat Jul 11 20:03:36 2020

@author: Meihaonan
"""
import os
import paddle
import numpy as np
import paddle.fluid as fluid
from multiprocessing import cpu_count
import matplotlib.pyplot as plt

def to_image(L):            #将1*2400连续胎心率数据点转化成120*2400胎心率曲线图
    image=np.zeros([120,2400],dtype=np.int)
    #np.zero(120,2400)好像有点问题
    for i in range(2400):
        if(L[i]<80):
            L[i]=80
        if(L[i]>=200):
            L[i]=199
        image[L[i]-80][i]=1
    return image

def data_reader(data,label,buffered_size=512):
  def reader():
      x=data.shape[0]
      for i in range(0,x):
          image=to_image(data[i,:])
          yield image,[label[i]-1]  #算交叉熵label要从0开始
  return reader

train_data=np.loadtxt("heart_data/train_data.txt",
                      delimiter=" ",dtype=int)
train_data_label=np.loadtxt("heart_data/train_label.txt",
                            delimiter=" ",dtype=int)

test_data=np.loadtxt("heart_data/test_data.txt",
                     delimiter=" ",dtype=int)
test_data_label=np.loadtxt("heart_data/test_label.txt",
                           delimiter=" ",dtype=int)

#构造训练、测试数据提供器
BATCH_SIZE = 16
train_r =data_reader(train_data,train_data_label)
train_reader =paddle.batch(paddle.reader.shuffle(reader=train_r,buf_size=128),
                          batch_size=BATCH_SIZE)

test_r=data_reader(test_data,test_data_label)
test_reader = paddle.batch(test_r,batch_size=BATCH_SIZE)

def mknet(input,type_size): #输入图片，分出的类别
    def conv_block(ipt, num_filter, groups, dropouts):
        return fluid.nets.img_conv_group(
            input=ipt,
            pool_size=2,
            pool_stride=2,
            conv_num_filter=[num_filter] * groups,
            conv_filter_size=3,
            conv_act='relu',
            conv_with_batchnorm=True,
            conv_batchnorm_drop_rate=dropouts,
            pool_type='max')

    conv1 = conv_block(input, 64, 2, [0, 0])
    conv2 = conv_block(conv1, 128, 2, [0, 0])
    conv3 = conv_block(conv2, 256, 3, [0, 0, 0])
    conv4 = conv_block(conv3, 512, 3, [0, 0, 0])
    conv5 = conv_block(conv4, 512, 3, [0, 0, 0])

    drop = fluid.layers.dropout(x=conv5, dropout_prob=0.5)
    fc1 = fluid.layers.fc(input=drop, size=512, act=None)
    bn = fluid.layers.batch_norm(input=fc1, act='relu')
    drop2 = fluid.layers.dropout(x=bn, dropout_prob=0.5)
    fc2 = fluid.layers.fc(input=drop2, size=512, act=None)
    predict = fluid.layers.fc(input=fc2, size=type_size, act='softmax')
    return predict

# 定义输入输出层
# 定义两个张量
image =fluid.layers.data(name='image', shape=[1, 120, 2400], dtype='float32')
label =fluid.layers.data(name='label', shape=[1], dtype='int64')

# 获取分类器
predict=mknet(image,3) #分成3类

# 定义损失函数和准确率函数
cost =fluid.layers.cross_entropy(input=predict, label=label)
avg_cost =fluid.layers.mean(cost)
accuracy =fluid.layers.accuracy(input=predict, label=label)

# 克隆main_program得到test_program，使用参数for_test来区分该程序是用来训练还是用来测试
# 该fluid.default_main_program().clone()要在optimization之前使用.
test_program =fluid.default_main_program().clone(for_test=True)

# 使用Adam优化器，定学习率为0.002。
optimizer = fluid.optimizer.AdamOptimizer(learning_rate=0.002)
opts = optimizer.minimize(avg_cost)

#定义使用CPU还是GPU，使用CPU时use_cuda = False,使用GPU时use_cuda = True
use_cuda = False
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
#创建一个Executor实例exe
exe =fluid.Executor(place)
#正式进行网络训练前，需先执行参数初始化
exe.run(fluid.default_startup_program())

feeder = fluid.DataFeeder(place=place, feed_list=[image, label])

EPOCH_NUM = 60
#训练过程数据记录
all_train_iter=0
all_train_iters=[]
all_train_costs=[]
all_train_accs=[]

#测试过程数据记录
all_test_iter=0
all_test_iters=[]
all_test_costs=[]
all_test_accs=[]
model_save_dir ="work"

for pass_id in range(EPOCH_NUM):
    # 开始训练
    for batch_id, data in enumerate(train_reader()):      #遍历训练集，并为数据加上索引batch_id
        train_cost,train_acc =exe.run(program=fluid.default_main_program(),#运行主程序
                             feed=feeder.feed(data),                 #喂入一个batch的数据
                            fetch_list=[avg_cost, accuracy])         #fetch均方误差和准确率
        all_train_iter=all_train_iter+BATCH_SIZE
        all_train_iters.append(all_train_iter)
        all_train_costs.append(train_cost[0])
        all_train_accs.append(train_acc[0])
        #每10次batch打印一次训练、进行一次测试
        if batch_id % 10== 0:
            print('Pass:%d, Batch:%d,Cost:%0.5f, Accuracy:%0.5f' %
            (pass_id, batch_id, train_cost[0],train_acc[0]))
    # 开始测试
    test_costs = []                                                        #测试的损失值
    test_accs = []                                                         #测试的准确率
    for batch_id, data in enumerate(test_reader()):
        test_cost, test_acc =exe.run(program=test_program,              #执行训练程序
                                     feed=feeder.feed(data),            #喂入数据
                                     fetch_list=[avg_cost, accuracy])         #fetch 误差、准确率
        test_costs.append(test_cost[0])                                #记录每个batch的误差
        test_accs.append(test_acc[0])                             #记录每个batch的准确率
        all_test_iter=all_test_iter+BATCH_SIZE
        all_test_iters.append(all_test_iter)
        all_test_costs.append(test_cost[0])
        all_test_accs.append(test_acc[0])
# 求测试结果的平均值
    test_cost = (sum(test_costs) /len(test_costs))        #计算误差平均值（误差和/误差的个数）
    test_acc = (sum(test_accs) /len(test_accs))  #计算准确率平均值（ 准确率的和/准确率的个数）
    print('Test:%d, Cost:%0.5f, ACC:%0.5f' %(pass_id, test_cost, test_acc))

# 每轮训练完成后，对模型进行一次保存，使用飞桨提供的fluid.io.save_inference_model()进行模型保存：
# 保存模型
# 如果保存路径不存在就创建
if not os.path.exists(model_save_dir):
    os.makedirs(model_save_dir)
print('savemodels to %s' % (model_save_dir))
fluid.io.save_inference_model(model_save_dir,  # 保存预测Program的路径
                              ['image'],      #预测需要feed的数据
                              [predict],       #保存预测结果
                              exe)             #executor 保存预测模型

def draw_cost_process(title,iters,costs,label_cost):
    plt.title(title, fontsize=24)
    plt.xlabel("iter", fontsize=20)
    plt.ylabel("cost", fontsize=20)
    plt.plot(iters,costs,color='red',label=label_cost)
    plt.legend()
    plt.grid()
    plt.show()

def draw_acc_process(title,iters,acc,label_acc):
    plt.title(title, fontsize=24)
    plt.xlabel("iter", fontsize=20)
    plt.ylabel("acc", fontsize=20)
    plt.plot(iters,acc,color='green',label=label_acc)
    plt.legend()
    plt.grid()
    plt.show()

#调用绘制曲线
draw_acc_process("training",all_train_iters, all_train_accs, "trainning acc")
draw_acc_process("testing",all_test_iters, all_test_accs, "test acc")
draw_cost_process("training",all_train_iters, all_train_costs, "trainning acc")
draw_cost_process("testing",all_test_iters, all_test_costs, "test acc")


# WAP to remove duplicates from dictionary

# Note - we have to remove duplicate values because keys are never duplicate

d1 = {1:10,2:20,3:10,4:20,5:50}
d2 = {}
for k,v in d1.items():
    if v not in d2.values():
        d2[k] = v               # d2.update({k:v})

print(d2)


import math
from microbit import *

class COMMS: # character, json
    BUTTON_A = ('a', '{"Ba":true}')
    BUTTON_B = ('b', '{"Bb":true}')

def roll_pitch_heading():
    last_tilt = False
    last_roll = False
    last_pitch = False
    last_heading = False
    while True:
        if button_a.is_pressed() and button_b.is_pressed():
            compass.calibrate()
        elif button_a.was_pressed():
            print(COMMS.BUTTON_A[1])
        elif button_b.was_pressed():
            print(COMMS.BUTTON_B[1])
        heading = compass.heading()
        if (heading != last_heading):
            last_heading = heading
            print('{"He":'+str(heading)+'}') # sent as degrees from 0 to 360
        display.show(' ')
        x = accelerometer.get_x()/1024
        y = accelerometer.get_y()/1024
        z = accelerometer.get_z()/1024
        roll = math.pi-(math.atan2(x, z)%(math.pi*2))
        pitch = math.pi-(math.atan2(y, z)%(math.pi*2))
        if roll != last_roll or pitch != last_pitch:
            if roll != last_roll:
                print('{"Ro":'+str(roll)+'}') # sent as radians
            if pitch != last_pitch:
                print('{"Pi":'+str(pitch)+'}') # sent as radians
            last_pitch = pitch
            last_roll = roll
            sleep(20)
            display.show('+')
            sleep(10)
            display.show('-')
        sleep(20)
    return # never does
#Main program
print('{"started":true}')
image = Image("00008:00080:00800:08000:88888")
display.show(image)
sleep(750)
roll_pitch_heading()


from bisect import bisect
from random import random

class Solution:

    def __init__(self, w: List[int]):
      self.sorted = sorted([(num, i) for (i, num) in enumerate(w)])
      self.acc = [0]

      for (num, i) in self.sorted:
        self.acc.append(num + self.acc[-1])

      self.max = self.acc[-1]

    def pickIndex(self) -> int:
        rand = random() * self.max
        i = bisect(self.acc, rand) - 1
        return self.sorted[i][1]

# Your Solution object will be instantiated and called as such:
# obj = Solution(w)
# param_1 = obj.pickIndex()


v = [1, 2, 3]
out = 0
# if the v list contains one element set the out to 1
# if the v list contains two element set the out to 2
# if the v list contains more than 2 set the out to 10
# if the v contains no elements it should set to -1
if len(v) == 0:
    out = -1
elif len(v) == 1:
    out = 1
elif len(v) == 2:
    out = 2
else:
    out = 10

print(out)


'''
The colors
'''

import random as r

red = '\033[0;31m'
orange = '\033[1;31m'
pink = '\033[0;35m'
yellow = '\033[0;33m'
green = '\033[0;32m'
blue = '\033[0;34m'
black = '\033[0;30m'
grey = '\033[1;34m'
gray = '\033[1;32m'
purple = '\033[1;35m'
white = '\033[0;37m'
turquoise = '\033[0;36m'
reset = '\033[0m'
clear = '\033[H\033[2J'

colors = [red,
orange,
pink,
yellow,
green,
blue,
black,
grey,
gray,
purple,
white,
turquoise,
reset,
clear]

def random_color():
    return r.choice(colors)

if __name__ == '__main__':
    print(clear)
    print(red + 'red' + reset)
    print(blue + 'blue' + reset)
    print(yellow + 'yellow' + reset)
    print(orange + 'orange' + reset)
    print(pink + 'pink' + reset)
    print(green + 'green' + reset)
    print(black + 'black' + reset)
    print(grey + 'grey' + reset)
    print(gray + 'gray' + reset)
    print(purple + 'purple' + reset)
    print(white + 'white' + reset)
    print(turquoise + 'turquoise' + reset)


from mitreattack.stix20 import MitreAttackData

def main():
    mitre_attack_data = MitreAttackData("enterprise-attack.json")

    subtechniques = mitre_attack_data.get_subtechniques(remove_revoked_deprecated=True)

    print(f"Retrieved {len(subtechniques)} ATT&CK sub-techniques.")

if __name__ == "__main__":
    main()


# For each elve, take a string with their current values and return
# the sum of those values
def extractAndSumCounts(s):
    counts = [int(n) for n in s.splitlines()]
    return sum(counts)

# Build two arrays from the input file
with open("input/day1.txt") as f:
    # Create a string for each elve that contains its counts
    elves  = f.read().split("\n\n")

    # Convert those counts into a sum
    elveTotals = [extractAndSumCounts(e) for e in elves]

# Sort in reverse order by summed value
sorted_elves = sorted(elveTotals, reverse=True)

# Print the largest value
print(sorted_elves[0])

print(sum(sorted_elves[0:3]))


from django.shortcuts import render,redirect
from django.contrib.auth.decorators import login_required
from carts.models import CartItem
from .forms import OrderForm
from .models import Order

from greatkart.settings import TAX_RATE

import datetime

# Create your views here.

@login_required(login_url='login')
def payment(request):

    current_user=request.user

    cartItems=CartItem.objects.filter(user=current_user)
    if cartItems.count()<=0:
        return redirect('store')

    grand_total=0
    for item in cartItems:
        grand_total+=item.product.price*item.quantity

    tax=float(grand_total)*float(TAX_RATE)

    order_already_exists=Order.objects.filter(user=current_user,status='New',is_ordered=False).exists()
    if order_already_exists:
             order=Order.objects.get(user=current_user,status='New',is_ordered=False)
    else:
            if request.method == 'POST':
                form =OrderForm(request.POST)
                if not form.is_valid():
                     return redirect('/cart/checkout')
                else:

                    data=Order()

                    data.first_name     =form.cleaned_data['first_name']
                    data.last_name      =form.cleaned_data['last_name']
                    data.email          =form.cleaned_data['email']
                    data.phone          =form.cleaned_data['phone']
                    data.address_line_1 =form.cleaned_data['address_line_1']
                    data.address_line_2 =form.cleaned_data['address_line_2']
                    data.postcode       =form.cleaned_data['postcode']
                    data.city           =form.cleaned_data['city']
                    data.country        =form.cleaned_data['country']
                    data.order_note     =form.cleaned_data['order_note']

                    data.order_total   =grand_total

                    data.tax           =tax

                    data.user=current_user

                    data.ip=request.META.get('REMOTE_ADDR')
                    data.save()

                    #Generate order number
                    yr=int(datetime.date.today().strftime('%Y'))
                    dt=int(datetime.date.today().strftime('%d'))
                    mt=int(datetime.date.today().strftime('%m'))

                    d=datetime.date(yr,mt,dt)
                    current_date=d.strftime('%Y%m%d')

                    order_number=current_date+str(data.id)

                    data.order_number=order_number

                    data.save()

                    order=Order.objects.get(user=current_user,is_ordered=False,order_number=order_number)

    context={
        'order': order,
        'cartItems': cartItems,
        'total_amount': grand_total,
        'total_payment':float(grand_total)+float(tax),
        'tax': tax,
    }

    return render(request,'orders/payment.html',context)

def deleteOrder(request,order_number):
     Order.objects.get(order_number=order_number).delete()
     return redirect('checkout')


import sys

from PyQt5.QtWidgets import QApplication, QMessageBox, QMainWindow, QAction

class  Ui_MainWindow(QMainWindow):
    def __init__(self):

        QMainWindow.__init__(self)

    def setupUI(self):

        self.setGeometry(500, 300, 700, 700)

        self.setWindowTitle("window")

        finish = QAction("Quit", self)
        finish.triggered.connect(self.closeEvent)

        menubar = self.menuBar()
        fmenu = menubar.addMenu("File")
        fmenu.addAction(finish)

    def retranslateUi(self):
        ## codes
        codes = "___"

    def closeEvent(self, event):
        close = QMessageBox.question(self,
                                     "QUIT",
                                     "Sure?",
                                      QMessageBox.Yes | QMessageBox.No)
        if close == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Ui_MainWindow()
    window.setupUI()
    window.show()
    sys.exit(app.exec_())


import os
import random
import shutil

from tqdm import tqdm
import cv2

random.seed(359244)

DIM = 700

SRC = os.path.join('/home','jupyter','shiptype')
modes = ['train','valid','test']
n = 850
n_modes = [550, 150, 150]

mode_paths = []
for m in modes:
    mode_path = os.path.join(SRC, m)
    mode_paths.append(mode_path)
    for type_id in [30,31,33,35,36,37,60,70,80]:
        path = os.path.join(mode_path, str(type_id))
        if not os.path.exists(path):
            os.makedirs(path)

for type_id in [30,31,33,35,36,37,60,70,80]:
    type_id = str(type_id)
    img_list = os.listdir(os.path.join(SRC, type_id))
    sample = random.sample(img_list, n)
    start = 0
    end = 0
    for mode, n_m, mode_path in zip(modes, n_modes, mode_paths):
        src_path = os.path.join(SRC, type_id)
        dest_path = os.path.join(mode_path, type_id)
        end = end + n_m
        for fn in tqdm(sample[start:end]):
            if fn[-4:] not in ['.jpg','.png']:
                continue
            src = os.path.join(src_path, fn)
            dest = os.path.join(dest_path, fn)

            img = cv2.imread(src)
            h, w, _ = img.shape
            if h > dim or w > dim:
                scale_h = dim/h
                scale_w = dim/w
                scale = min(scale_h,scale_w)
                img = cv2.resize(img, None, fx=scale, fy=scale, interpolation=cv2.INTER_AREA)
            cv2.imwrite(dest, img)
            shutil.copy(src, dest)
        start = end


#!/usr/bin/python

import os

if not hasattr(os.path, 'relpath'):
    import stupid
    os.path.relpath = stupid.relpath

import sys
import logging
import subprocess
import ConfigParser
import re

import app
import ssh
import svn
import hookscript

re_valid_repo = re.compile('^[\w\d]+$')

class Main(hookscript.Main):
    logtag = 'svnbiosis.post-commit-user'

    def handle_args(self, args):
        try:
            repo, rev = args
        except ValueError:
            self.parser.error('Missing arguments REPO and REV.')

        self.opts.instancedir = os.path.abspath(os.path.join(repo, '../../'))

        admindir = os.path.join(self.opts.instancedir, 'admin')
        reporoot = os.path.join(self.opts.instancedir, 'repositories')

        self.log.debug('starting post-commit for %s (via %s)' %
                (self.opts.instancedir, repo))

        self.run_script(
                os.path.join(self.opts.instancedir, 'hooks', 'post-commit'),
                repo, rev)
        self.run_script(
                os.path.join(self.opts.datadir, 'hooks', 'post-commit'),
                repo, rev)

    def run_script(self, path, repo, rev):
        self.log.debug('checking for: %s' % path)
        if not os.access(path, os.X_OK):
            return

        self.log.info('running post-commit hook: %s' % path)
        rc = subprocess.call([path, repo, rev])
        self.log.debug('%s returned rc = %d' % (path, rc))

if __name__ == '__main__':
    Main().main()


from factory import db

class StockLocations(db.Model):
    location_id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False, unique=True)  # Unique location name
    is_flexible = db.Column(db.Boolean, default=True)  # By default, it's flexible
    is_occupied = db.Column(db.Boolean, default=False)  # Is this spot occupied?

    # Relationships
    tire_id = db.Column(db.Integer, db.ForeignKey('tires.tire_id'), nullable=True)
    tire = db.relationship('Tires', back_populates='stock_location')


#!/usr/bin/python
import rospy
from std_msgs.msg import String, Bool
import multirobot_behavior_tree # note this is not the standard behavior_tree!
import bt_manipulation
import cv2
import zlib
import os

def get_output_filename(config_filename):
    # return 'test_output.tree'
    # add a string to the filename to get the output filename
    # see https://stackoverflow.com/questions/37487758/how-to-add-an-id-to-filename-before-extension
    suffix = 'manipulated'
    return "{0}_{2}{1}".format(*os.path.splitext(config_filename) + (suffix,))

class BTManipulationNode:
    def __init__(self, config_filename):

        # Read in the given tree
        rospy.loginfo('reading in tree: ' + config_filename)
        self.tree1 = multirobot_behavior_tree.BehaviorTree(config_filename)
        self.tree2 = multirobot_behavior_tree.BehaviorTree(config_filename)

        # Manipulate the tree in some way
        # Pick some of the following options...
        rospy.loginfo('manipulating the tree...')
        bt_manipulation.reverse_first_level(self.tree1)
        self.tree = bt_manipulation.combine_two_trees(self.tree1, self.tree2)

        # Save the output to a new config file
        output_filename = get_output_filename(config_filename)
        rospy.loginfo('saving new config file to: ' + output_filename)
        self.save_tree(self.tree, output_filename)

    def save_tree(self, tree, output_filename):
        tree.write_config(output_filename)

if __name__ == '__main__':
    # Start the ROS node
    rospy.init_node('bt_manipulation_node')

    # Read in tree filename
    config_filename = rospy.get_param('~config', '')

    # Create an instance of BTManipulationNode (defined above)
    node = BTManipulationNode(config_filename)

    rospy.loginfo('bt_manipulation_node shutting down')


import os
import sys

sistema_operativo = sys.platform
if sistema_operativo.startswith('win'):
	os.system("cls")
else:
	os.system("clear")

print("INTRODUCCIÓN A LAS LISTAS - POP & REMOVE")

lista1 = [1, 3, 5, 7, 9, 0, 2, 4, 6, 8, 1, 3, 5]

print("Lista inicial:",lista1)

lista1.remove(5)

print("Lista despues de remover el primer elemento '5':",lista1)

lista1.pop(5)
lista1.pop(30)

print("Lista despues de remover el elemento de la posicion 5:",lista1)

print()


#!/usr/bin/env python

import gtk

class AspectFrame:
    def __init__(self):
        window = gtk.Window()
        window.set_default_size(200, 200)

        frame = gtk.AspectFrame("Frame", 0.5, 0.5, 0.5, False)
        image = gtk.Image()
        image.set_from_file("android.jpg")
        frame.add(image)

        window.connect("destroy", lambda w: gtk.main_quit())

        window.add(frame)
        window.show_all()

AspectFrame()
gtk.main()


class Usecase:
    def __init__(self, file, material=None, style=None, context=None, should_use_presentation_style_assignment=False):
        """Assigns a style to a material

        A style may either be assigned directly to an object's representation,
        or to a material which is then associated with the object. If both
        exist, then the style assigned directly to the object's representation
        takes precedence. It is recommended to use materials and assign styles
        to materials. This API function provides that capability.

        :param material: The IfcMaterial which you want to assign the style to.
        :type material: ifcopenshell.entity_instance.entity_instance
        :param style: The IfcPresentationStyle (typically IfcSurfaceStyle) that
            you want to assign to the material. This will then be applied to all
            objects that have that material.
        :type style: ifcopenshell.entity_instance.entity_instance
        :param context: The IfcGeometricRepresentationSubContext at which this
            style should be used. Typically this is the Model BODY context.
        :type context: ifcopenshell.entity_instance.entity_instance
        :param should_use_presentation_style_assignment: This is a technical
            detail to accomodate a bug in Revit. This should always be left as
            the default of False, unless you are finding that colours aren't
            showing up in Revit. In that case, set it to True, but keep in mind
            that this is no longer a valid IFC. Blame Autodesk.
        :type should_use_presentation_style_assignment: bool
        :return: None
        :rtype: None

        Example:

        .. code:: python

            # A model context is needed to store 3D geometry
            model3d = ifcopenshell.api.run("context.add_context", model, context_type="Model")

            # Specifically, we want to store body geometry
            body = ifcopenshell.api.run("context.add_context", model,
                context_type="Model", context_identifier="Body", target_view="MODEL_VIEW", parent=model3d)

            # Let's create a new wall. The wall does not have any geometry yet.
            wall = ifcopenshell.api.run("root.create_entity", model, ifc_class="IfcWall")

            # Let's use the "3D Body" representation we created earlier to add a
            # new wall-like body geometry, 5 meters long, 3 meters high, and
            # 200mm thick
            representation = ifcopenshell.api.run("geometry.add_wall_representation", model,
                context=body, length=5, height=3, thickness=0.2)

            # Assign our new body geometry back to our wall
            ifcopenshell.api.run("geometry.assign_representation", model,
                product=wall, representation=representation)

            # Place our wall at the origin
            ifcopenshell.api.run("geometry.edit_object_placement", model, product=wall)

            # Let's prepare a concrete material. Note that our concrete material
            # does not have any colours (styles) at this point.
            concrete = ifcopenshell.api.run("material.add_material", model, name="CON01", category="concrete")

            # Assign our concrete material to our wall
            ifcopenshell.api.run("material.assign_material", model,
                product=wall, type="IfcMaterial", material=concrete)

            # Create a new surface style
            style = ifcopenshell.api.run("style.add_style", model)

            # Create a simple grey shading colour and transparency.
            ifcopenshell.api.run("style.add_surface_style", model,
                style=style, ifc_class="IfcSurfaceStyleShading", attributes={
                    "SurfaceColour": { "Name": None, "Red": 0.5, "Green": 0.5, "Blue": 0.5 },
                    "Transparency": 0., # 0 is opaque, 1 is transparent
                })

            # Now any element (like our wall) with a concrete material will have
            # a grey colour applied.
            ifcopenshell.api.run("style.assign_material_style", model, material=concrete, style=style, context=body)
        """
        self.file = file
        self.settings = {
            "material": material,
            "style": style,
            "context": context,
            "should_use_presentation_style_assignment": should_use_presentation_style_assignment,
        }

    def execute(self):
        self.style = self.settings["style"]
        if self.file.schema == "IFC2X3" or self.settings["should_use_presentation_style_assignment"]:
            self.style = self.file.createIfcPresentationStyleAssignment([self.settings["style"]])

        if self.settings["material"].HasRepresentation:
            self.modify_existing_definition_representation()
        else:
            self.create_new_definition_representation()

    def modify_existing_definition_representation(self):
        definition_representation = self.settings["material"].HasRepresentation[0]
        representation = self.get_styled_representation(definition_representation)
        if representation:
            potential_orphans = []
            items = list(representation.Items)
            new_items = []
            removed_items = []
            for item in items:
                if not item.is_a("IfcStyledItem"):
                    continue
                if self.has_proposed_style(item):
                    return
                if self.has_same_style_type(item):
                    removed_items.append(item)
                else:
                    new_items.append(item)
            new_items.append(self.create_styled_item())
            representation.Items = new_items
            for item in removed_items:
                if len(self.file.get_inverse(item)) == 0:
                    self.file.remove(item)
        else:
            representations = list(definition_representation.Representations)
            representations.append(self.create_styled_representation())
            definition_representation.Representations = representations

    def has_proposed_style(self, styled_item):
        return bool([s for s in styled_item.Styles if s == self.settings["style"]])

    def has_same_style_type(self, styled_item):
        return bool([s for s in styled_item.Styles if s.is_a() == self.settings["style"].is_a()])

    def create_new_definition_representation(self):
        representation = self.create_styled_representation()
        definition_representation = self.file.create_entity(
            "IfcMaterialDefinitionRepresentation",
            **{"Representations": [representation], "RepresentedMaterial": self.settings["material"]}
        )

    def get_styled_representation(self, definition_representation):
        representations = [
            r
            for r in definition_representation.Representations
            if r.is_a("IfcStyledRepresentation") and r.ContextOfItems == self.settings["context"]
        ]
        if representations:
            return representations[0]

    def create_styled_representation(self):
        return self.file.create_entity(
            "IfcStyledRepresentation",
            **{
                "ContextOfItems": self.settings["context"],
                "RepresentationIdentifier": self.settings["context"].ContextIdentifier,
                "Items": [self.create_styled_item()],
            }
        )

    def create_styled_item(self):
        return self.file.create_entity("IfcStyledItem", **{"Styles": [self.style], "Name": self.settings["style"].Name})


from gcsl.algo import buffer, networks
from gcsl.envs.env_utils import DiscretizedActionEnv
from gym.spaces import Box, Discrete
import numpy as np

"""
Main function defined up top. Helpers below.
"""

def get_params(env, env_params):
    env = discretize_environment(env, env_params)
    policy = default_markov_policy(env, env_params)
    buffer_kwargs = dict(
        env=env,
        max_trajectory_length=get_horizon(env_params),
        buffer_size=20000,
    )
    replay_buffer = buffer.ReplayBuffer(**buffer_kwargs)
    gcsl_kwargs = default_gcsl_params(env, env_params)
    gcsl_kwargs['validation_buffer'] = buffer.ReplayBuffer(**buffer_kwargs)
    return env, policy, replay_buffer, gcsl_kwargs

def get_horizon(env_params):
    return env_params.get('max_trajectory_length', 50)

def discretize_environment(env, env_params):
    if isinstance(env.action_space, Discrete):
        return env
    granularity = env_params.get('action_granularity', 3)
    env_discretized = DiscretizedActionEnv(env, granularity=granularity)
    return env_discretized

def default_markov_policy(env, env_params):
    assert isinstance(env.action_space, Discrete)
    if env.action_space.n > 100: # Too large to maintain single action for each
        policy_class = networks.IndependentDiscretizedStochasticGoalPolicy
    else:
        policy_class = networks.DiscreteStochasticGoalPolicy
    return policy_class(
                env,
                state_embedding=None,
                goal_embedding=None,
                layers=[400, 300], #[400, 300], # TD3-size
                max_horizon=None, # Do not pass in horizon.
                # max_horizon=get_horizon(env_params), # Use this line if you want to include horizon into the policy
                freeze_embeddings=True,
                add_extra_conditioning=False,
            )

def default_gcsl_params(env, env_params):
    return dict(
        max_path_length=env_params.get('max_trajectory_length', 50),
        goal_threshold=env_params.get('goal_threshold', 0.05),
        explore_timesteps=10000,
        start_policy_timesteps=1000,
        eval_freq=env_params.get('eval_freq', 2000),
        eval_episodes=env_params.get('eval_episodes', 50),
        save_every_iteration=False,
        max_timesteps=env_params.get('max_timesteps', 1e6),
        expl_noise=0.0,
        batch_size=256,
        n_accumulations=1,
        policy_updates_per_step=1,
        train_policy_freq=None,
        lr=5e-4,
    )


from django.shortcuts import render
from api import models
from publicFunc import Response
from publicFunc import account
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt, csrf_protect
import time
import datetime
from publicFunc.condition_com import conditionCom
from api.forms.action import AddForm, UpdateForm, SelectForm
import json
from django.db.models import Q

# cerf  token验证 用户展示模块
@csrf_exempt
@account.is_token(models.userprofile)
def action(request):
    response = Response.ResponseObj()
    if request.method == "GET":
        forms_obj = SelectForm(request.GET)
        if forms_obj.is_valid():
            current_page = forms_obj.cleaned_data['current_page']
            length = forms_obj.cleaned_data['length']
            company_id = forms_obj.cleaned_data['company_id']
            role_id = forms_obj.cleaned_data['role_id']
            print('forms_obj.cleaned_data -->', forms_obj.cleaned_data)
            order = request.GET.get('order', '-create_date')
            field_dict = {
                'id': '',
                'name': '__contains',
                'create_date': '',
                'oper_user__username': '__contains',
                'project_id': '',
            }

            q = conditionCom(request, field_dict)
            if role_id == 2:  # 管理员角色
                q.add(Q(**{'project__company_id': company_id}), Q.AND)

            print('q -->', q)
            objs = models.action.objects.select_related('project').filter(q).order_by(order)
            count = objs.count()

            if length != 0:
                start_line = (current_page - 1) * length
                stop_line = start_line + length
                objs = objs[start_line: stop_line]

            # 返回的数据
            ret_data = []

            for obj in objs:
                #  如果有oper_user字段 等于本身名字
                if obj.oper_user:
                    oper_user_username = obj.oper_user.username
                else:
                    oper_user_username = ''
                # print('oper_user_username -->', oper_user_username)
                #  将查询出来的数据 加入列表
                ret_data.append({
                    'id': obj.id,
                    'name': obj.name,
                    'project__name': obj.project.name,
                    'project_id': obj.project_id,
                    'create_date': obj.create_date.strftime('%Y-%m-%d %H:%M:%S'),
                    'oper_user__username': oper_user_username,
                })
            #  查询成功 返回200 状态码
            response.code = 200
            response.msg = '查询成功'
            response.data = {
                'ret_data': ret_data,
                'data_count': count,
            }
        else:
            response.code = 402
            response.msg = "请求异常"
            response.data = json.loads(forms_obj.errors.as_json())
    return JsonResponse(response.__dict__)

#  增删改
#  csrf  token验证
@csrf_exempt
@account.is_token(models.userprofile)
def action_oper(request, oper_type, o_id):
    response = Response.ResponseObj()
    if request.method == "POST":
        if oper_type == "add":
            form_data = {
                'oper_user_id': request.GET.get('user_id'),
                'name': request.POST.get('name'),
                'project_id': request.POST.get('project_id'),
            }
            #  创建 form验证 实例（参数默认转成字典）
            forms_obj = AddForm(form_data)
            if forms_obj.is_valid():
                print("验证通过")
                # print(forms_obj.cleaned_data)
                #  添加数据库
                print('forms_obj.cleaned_data-->',forms_obj.cleaned_data)
                obj = models.action.objects.create(**forms_obj.cleaned_data)
                response.code = 200
                response.msg = "添加成功"
                response.data = {'testCase': obj.id}
            else:
                print("验证不通过")
                # print(forms_obj.errors)
                response.code = 301
                # print(forms_obj.errors.as_json())
                response.msg = json.loads(forms_obj.errors.as_json())

        elif oper_type == "delete":
            # 删除 ID
            # 如果产品需求表中有数据，则不允许删除
            demand_objs = models.demand.objects.filter(action_id=o_id)
            if not demand_objs:
                objs = models.action.objects.filter(id=o_id)
                if objs:
                    objs.delete()
                    response.code = 200
                    response.msg = "删除成功"
                else:
                    response.code = 302
                    response.msg = '删除ID不存在'
            else:
                response.code = 304
                response.msg = '含有子级数据,请先删除或转移子级数据'
        elif oper_type == "update":
            # 获取需要修改的信息
            form_data = {
                'o_id': o_id,
                'oper_user_id': request.GET.get('user_id'),
                'name': request.POST.get('name'),
                'project_id': request.POST.get('project_id'),
            }

            forms_obj = UpdateForm(form_data)
            if forms_obj.is_valid():
                print("验证通过")
                print(forms_obj.cleaned_data)
                o_id = forms_obj.cleaned_data['o_id']
                name = forms_obj.cleaned_data['name']
                project_id = forms_obj.cleaned_data['project_id']
                #  查询数据库  用户id
                objs = models.action.objects.filter(
                    id=o_id
                )
                #  更新 数据
                if objs:
                    objs.update(
                        name=name,
                        project_id=project_id
                    )

                    response.code = 200
                    response.msg = "修改成功"
                else:
                    response.code = 303
                    response.msg = json.loads(forms_obj.errors.as_json())

            else:
                print("验证不通过")
                # print(forms_obj.errors)
                response.code = 301
                # print(forms_obj.errors.as_json())
                #  字符串转换 json 字符串
                response.msg = json.loads(forms_obj.errors.as_json())
        elif oper_type == "update_status":
            status = request.POST.get('status')
            print('status -->', status)
            models.userprofile.objects.filter(id=o_id).update(status=status)
            response.code = 200
            response.msg = "状态修改成功"

    else:
        response.code = 402
        response.msg = "请求异常"

    return JsonResponse(response.__dict__)


class CoffeeMachine:
    def __init__(self):
        self.milk = 1000
        self.sugar = 1000
        self.coffee = 1000

    def make_coffee(self,milk,sugar, coffee):
        if self.milk < milk and self.sugar < sugar and self.coffee < coffee:
            res1 = milk - self.milk
            res2 = sugar - self.sugar
            res3 = coffee - self.coffee
            print(f'Пополните запасы молока на {res1} мл! ')
            print(f'Пополните запасы сахара на {res2} гр!')
            print(f'Пополните запасы кофе на {res3} гр!')

        elif  self.milk < milk and self.coffee < coffee:
            res1 = milk - self.milk
            res2 = coffee - self.coffee
            print(f'Пополните запасы молока на  {res1} мл. и запас кофе на {res2} гр.')

        elif  self.milk < milk and self.sugar < sugar:
            res1 = milk - self.milk
            res2 = sugar - self.sugar
            print(f'Пополните запасы молока на  {res1} мл. и запас сахара на {res2} гр.')

        elif  self.sugar < sugar and self.coffee < coffee:
            res1 = sugar - self.sugar
            res2 = coffee - self.coffee
            print(f'Пополните запасы сахара на  {res1} гр. и запас кофе на {res2} гр.')

        elif self.milk > milk and self.sugar < sugar and self.coffee > coffee:
            res = sugar - self.sugar
            print(f'Пополните запасы сахара на {res} гр!')

        elif self.milk < milk and self.sugar > sugar and self.coffee > coffee:
            res = milk - self.milk
            print(f'Пополните запасы молока на {res} мл!')

        elif self.milk > milk and self.sugar > sugar and self.coffee < coffee:
            res = coffee - self.coffee
            print(f'Пополните запасы кофе на {res} гр!')

        else:
            print('Процесс приготовления кофе завершен!')
            self.__subtract_milk(milk)
            self.__subtract_sugar(sugar)
            self.__subtract_coffee(coffee)

    def __subtract_milk(self,milk):
        self.milk -= milk
        print(f'Осталось {self.milk} мл. молока')

    def __subtract_sugar(self,sugar):
        self.sugar -= sugar
        print(f'Осталось {self.sugar} гр. сахара')

    def __subtract_coffee(self,coffee):
        self.coffee -= coffee
        print(f'Осталось {self.coffee} гр. кофе')

def main():
    a = CoffeeMachine()
    a.make_coffee(100,10000,10000)

if __name__ == '__main__':
    main()


import sys
_module = sys.modules[__name__]
del sys
dataset = _module
layer = _module
lfw_eval = _module
main = _module
net = _module

from _paritybench_helpers import _mock_config, patch_functional
from unittest.mock import mock_open, MagicMock
from torch.autograd import Function
from torch.nn import Module
import abc, collections, copy, enum, functools, inspect, itertools, logging, math, matplotlib, numbers, numpy, pandas, queue, random, re, scipy, sklearn, string, tensorflow, time, torch, torchaudio, torchtext, torchvision, types, typing, uuid, warnings
import numpy as np
from torch import Tensor
patch_functional()
open = mock_open()
yaml = logging = sys = argparse = MagicMock()
ArgumentParser = argparse.ArgumentParser
_global_config = args = argv = cfg = config = params = _mock_config()
argparse.ArgumentParser.return_value.parse_args.return_value = _global_config
yaml.load.return_value = _global_config
sys.argv = _global_config
__version__ = '1.0.0'
xrange = range
wraps = functools.wraps

import torch.utils.data as data

import torch

import torch.nn as nn

import torch.nn.functional as F

from torch.nn import Parameter

import math

import numpy as np

from torchvision.transforms import functional as F

import torchvision.transforms as transforms

from torch.autograd import Variable

import torch.backends.cudnn as cudnn

import time

import torch.utils.data

import torch.optim

def cosine_sim(x1, x2, dim=1, eps=1e-08):
    ip = torch.mm(x1, x2.t())
    w1 = torch.norm(x1, 2, dim)
    w2 = torch.norm(x2, 2, dim)
    return ip / torch.ger(w1, w2).clamp(min=eps)

class MarginCosineProduct(nn.Module):
    """Implement of large margin cosine distance: :
    Args:
        in_features: size of each input sample
        out_features: size of each output sample
        s: norm of input feature
        m: margin
    """

    def __init__(self, in_features, out_features, s=30.0, m=0.4):
        super(MarginCosineProduct, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.s = s
        self.m = m
        self.weight = Parameter(torch.Tensor(out_features, in_features))
        nn.init.xavier_uniform_(self.weight)

    def forward(self, input, label):
        cosine = cosine_sim(input, self.weight)
        one_hot = torch.zeros_like(cosine)
        one_hot.scatter_(1, label.view(-1, 1), 1.0)
        output = self.s * (cosine - one_hot * self.m)
        return output

    def __repr__(self):
        return self.__class__.__name__ + '(' + 'in_features=' + str(self.in_features) + ', out_features=' + str(self.out_features) + ', s=' + str(self.s) + ', m=' + str(self.m) + ')'

class AngleLinear(nn.Module):

    def __init__(self, in_features, out_features, m=4):
        super(AngleLinear, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.m = m
        self.base = 1000.0
        self.gamma = 0.12
        self.power = 1
        self.LambdaMin = 5.0
        self.iter = 0
        self.weight = Parameter(torch.Tensor(out_features, in_features))
        nn.init.xavier_uniform_(self.weight)
        self.mlambda = [lambda x: x ** 0, lambda x: x ** 1, lambda x: 2 * x ** 2 - 1, lambda x: 4 * x ** 3 - 3 * x, lambda x: 8 * x ** 4 - 8 * x ** 2 + 1, lambda x: 16 * x ** 5 - 20 * x ** 3 + 5 * x]

    def forward(self, input, label):
        self.iter += 1
        self.lamb = max(self.LambdaMin, self.base * (1 + self.gamma * self.iter) ** (-1 * self.power))
        cos_theta = F.linear(F.normalize(input), F.normalize(self.weight))
        cos_theta = cos_theta.clamp(-1, 1)
        cos_m_theta = self.mlambda[self.m](cos_theta)
        theta = cos_theta.data.acos()
        k = (self.m * theta / 3.14159265).floor()
        phi_theta = (-1.0) ** k * cos_m_theta - 2 * k
        NormOfFeature = torch.norm(input, 2, 1)
        one_hot = torch.zeros_like(cos_theta)
        one_hot.scatter_(1, label.view(-1, 1), 1)
        output = one_hot * (phi_theta - cos_theta) / (1 + self.lamb) + cos_theta
        output *= NormOfFeature.view(-1, 1)
        return output

    def __repr__(self):
        return self.__class__.__name__ + '(' + 'in_features=' + str(self.in_features) + ', out_features=' + str(self.out_features) + ', m=' + str(self.m) + ')'

class Block(nn.Module):

    def __init__(self, planes):
        super(Block, self).__init__()
        self.conv1 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.prelu1 = nn.PReLU(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.prelu2 = nn.PReLU(planes)

    def forward(self, x):
        return x + self.prelu2(self.conv2(self.prelu1(self.conv1(x))))

class sphere(nn.Module):

    def __init__(self, type=20, is_gray=False):
        super(sphere, self).__init__()
        block = Block
        if type is 20:
            layers = [1, 2, 4, 1]
        elif type is 64:
            layers = [3, 7, 16, 3]
        else:
            raise ValueError('sphere' + str(type) + ' IS NOT SUPPORTED! (sphere20 or sphere64)')
        filter_list = [3, 64, 128, 256, 512]
        if is_gray:
            filter_list[0] = 1
        self.layer1 = self._make_layer(block, filter_list[0], filter_list[1], layers[0], stride=2)
        self.layer2 = self._make_layer(block, filter_list[1], filter_list[2], layers[1], stride=2)
        self.layer3 = self._make_layer(block, filter_list[2], filter_list[3], layers[2], stride=2)
        self.layer4 = self._make_layer(block, filter_list[3], filter_list[4], layers[3], stride=2)
        self.fc = nn.Linear(512 * 7 * 6, 512)
        for m in self.modules():
            if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):
                if m.bias is not None:
                    nn.init.xavier_uniform_(m.weight)
                    nn.init.constant_(m.bias, 0.0)
                else:
                    nn.init.normal_(m.weight, 0, 0.01)

    def _make_layer(self, block, inplanes, planes, blocks, stride):
        layers = []
        layers.append(nn.Conv2d(inplanes, planes, 3, stride, 1))
        layers.append(nn.PReLU(planes))
        for i in range(blocks):
            layers.append(block(planes))
        return nn.Sequential(*layers)

    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

    def save(self, file_path):
        with open(file_path, 'wb') as f:
            torch.save(self.state_dict(), f)

class BlockIR(nn.Module):

    def __init__(self, inplanes, planes, stride, dim_match):
        super(BlockIR, self).__init__()
        self.bn1 = nn.BatchNorm2d(inplanes)
        self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)
        self.prelu1 = nn.PReLU(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn3 = nn.BatchNorm2d(planes)
        if dim_match:
            self.downsample = None
        else:
            self.downsample = nn.Sequential(nn.Conv2d(inplanes, planes, kernel_size=1, stride=stride, bias=False), nn.BatchNorm2d(planes))

    def forward(self, x):
        residual = x
        out = self.bn1(x)
        out = self.conv1(out)
        out = self.bn2(out)
        out = self.prelu1(out)
        out = self.conv2(out)
        out = self.bn3(out)
        if self.downsample is not None:
            residual = self.downsample(x)
        out += residual
        return out

class LResNet(nn.Module):

    def __init__(self, block, layers, filter_list, is_gray=False):
        self.inplanes = 64
        super(LResNet, self).__init__()
        if is_gray:
            self.conv1 = nn.Conv2d(1, filter_list[0], kernel_size=3, stride=1, padding=1, bias=False)
        else:
            self.conv1 = nn.Conv2d(3, filter_list[0], kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(filter_list[0])
        self.prelu1 = nn.PReLU(filter_list[0])
        self.layer1 = self._make_layer(block, filter_list[0], filter_list[1], layers[0], stride=2)
        self.layer2 = self._make_layer(block, filter_list[1], filter_list[2], layers[1], stride=2)
        self.layer3 = self._make_layer(block, filter_list[2], filter_list[3], layers[2], stride=2)
        self.layer4 = self._make_layer(block, filter_list[3], filter_list[4], layers[3], stride=2)
        self.fc = nn.Sequential(nn.BatchNorm1d(filter_list[4] * 7 * 6), nn.Dropout(p=0.4), nn.Linear(filter_list[4] * 7 * 6, 512), nn.BatchNorm1d(512))
        for m in self.modules():
            if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):
                nn.init.xavier_uniform_(m.weight)
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0.0)
            elif isinstance(m, nn.BatchNorm2d) or isinstance(m, nn.BatchNorm1d):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

    def _make_layer(self, block, inplanes, planes, blocks, stride):
        layers = []
        layers.append(block(inplanes, planes, stride, False))
        for i in range(1, blocks):
            layers.append(block(planes, planes, stride=1, dim_match=True))
        return nn.Sequential(*layers)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.prelu1(x)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

    def save(self, file_path):
        with open(file_path, 'wb') as f:
            torch.save(self.state_dict(), f)

import torch
from torch.nn import MSELoss, ReLU
from _paritybench_helpers import _mock_config, _mock_layer, _paritybench_base, _fails_compile

TESTCASES = [
    # (nn.Module, init_args, forward_args, jit_compiles)
    (Block,
     lambda: ([], {'planes': 4}),
     lambda: ([torch.rand([4, 4, 4, 4])], {}),
     True),
    (BlockIR,
     lambda: ([], {'inplanes': 4, 'planes': 4, 'stride': 1, 'dim_match': 4}),
     lambda: ([torch.rand([4, 4, 4, 4])], {}),
     True),
]

class Test_MuggleWang_CosFace_pytorch(_paritybench_base):
    def test_000(self):
        self._check(*TESTCASES[0])

    def test_001(self):
        self._check(*TESTCASES[1])


import math
import re

TOP, RIGHT, BOTTOM, LEFT = range(4)

class Tile():
    def __init__(self, text):
        self.number = ""
        self.data = []
        if text:
            self.number, *self.data = text.strip().split("\n")
            self.number = self.number.replace("Tile ", "").replace(":", "")
            self._update_edges()

    def _update_edges(self):
        self.edges = [self.data[0], "", self.data[-1], ""]
        for r in self.data:
            self.edges[1] += r[-1]
            self.edges[3] += r[0]

    def rotate(self):
        nd = ["" for _ in range(len(self.data))]
        for x in range(len(self.data)):
            for y in range(len(self.data)-1, -1,-1):
                nd[x] += self.data[y][x]
        self.data = nd
        self._update_edges()

    def flip(self):
        for i, row in enumerate(self.data):
            self.data[i] = row[::-1]
        self._update_edges()

    def inner_data(self):
        for row in self.data[1:-1]:
            yield row[1:-1]

    def edge(self, dir):
        return self.edges[dir]

    def __repr__(self):
        return self.number

def candidate_spots(grid, size):
    miny = min([y for x,y in grid])
    minx = min([x for x,y in grid])
    y = miny
    while True:
        rowlen = len([1 for gx,gy in grid if gy == y])
        if 1 <= rowlen < size:
            return [(minx+rowlen, y), (minx-1 if y == 0 else minx, y)]
        if rowlen == 0:
            return [(minx, y), (minx, miny-1)]
        y += 1

def solve_pussle(grid, tiles, size):
    if not tiles:
        return grid

    for spot in candidate_spots(grid, size):
        for t in tiles:
            if fits(t, spot, grid):
                subgrid = grid.copy()
                subgrid[(spot)] = t
                subtiles = tiles.copy()
                subtiles.remove(t)
                resgrid = solve_pussle(subgrid, subtiles, size)
                if len(resgrid) == size**2:
                    return resgrid
    return grid

def neighbors(spot, grid):
    return [grid.get((spot[0]+d[0], spot[1]+d[1]), None) for d in ((-1, 0), (1, 0), (0,-1), (0,1))]

def fits(t, spot, grid):
    left, right, top, bottom = neighbors(spot, grid)
    num_neighbors = sum([1 for n in (left, right, bottom, top) if n])

    for _ in range(2):
        for _ in range(4):
            num_match = 0
            if left:
                num_match += 1 if left.edge(RIGHT) == t.edge(LEFT) else 0
            if right:
                num_match += 1 if right.edge(LEFT) == t.edge(RIGHT) else 0
            if bottom:
                num_match += 1 if bottom.edge(TOP) == t.edge(BOTTOM) else 0
            if top:
                num_match += 1 if top.edge(BOTTOM) == t.edge(TOP) else 0
            if num_match == num_neighbors:
                return True
            t.rotate()
        else:
            t.flip()
    return False

def p1(tiles):
    gridsize = int(math.sqrt(len(tiles)))
    grid = {
        (0,0): tiles[0],
    }
    tiles = tiles[1:]
    grid = solve_pussle(grid, tiles, gridsize)

    miny = min([y for x,y in grid.keys()])
    minx = min([x for x,y in grid.keys()])

    corners = (
        (minx, miny),
        (minx, miny+gridsize-1),
        (minx+gridsize-1, miny),
        (minx+gridsize-1,miny+gridsize-1)
    )

    p = 1
    for tile in [grid[p] for p in corners]:
        p *= int(tile.number)
    print("p1", p)
    assert p == 64802175715999 or p == 20899048083289
    return grid

def p2(grid):
    grid_size = int(math.sqrt(len(grid)))
    tile_size = len(next(grid[(0,0)].inner_data()))

    picture_rows = ['' for _ in range(grid_size*tile_size)]

    miny = min([y for x,y in grid.keys()])
    minx = min([x for x,y in grid.keys()])

    # here I used only y first, but that will insert into picture_rows[-5] or whatever instead of 0
    # hence very deceptively scrampling the picture because monsters mostly stay intact
    for iy, y in enumerate(range(miny,miny+grid_size)):
        for x in range(minx, minx+grid_size):
            for i, data_row in enumerate(grid[(x,y)].inner_data()):
                picture_rows[iy*tile_size+i] += data_row

    # put picture in a tile to be able to rotate n flip it
    picture = Tile("")
    picture.data = picture_rows

    monster = (
        "..................#.",
        "#....##....##....###",
        ".#..#..#..#..#..#...",
    )

    # pad monster
    bigmonster = ("."*(len(picture.data)-len(monster[0]))).join(monster)
    # add regex magic to find overlapping monsters
    bigmonster = "(?=(" + bigmonster + "))"

    # flip n rotate picture until we find any monster
    for _ in range(2):
        for _ in range(4):
            bigsea = "".join(picture.data)
            monsters = list(re.finditer(bigmonster, bigsea))
            if monsters:
                break
            picture.rotate()
        if monsters:
            break
        picture.flip()

    # not necessary, could just do bigsea.count("#")-len(monsters)*bigmonster.count("#")
    # but nice for debugging
    bigsea = list(bigsea)
    for m in monsters:
        monster_sea = bigsea[m.start(1):m.end(1)]
        highlight = "".join(["O" if m == "#" else s for m,s in zip(bigmonster[4:-2], monster_sea)])
        bigsea[m.start(1):m.end(1)] = highlight

    assert bigsea.count("#") == 2146
    print("p2", bigsea.count("#"), "water roughness")

tiles = []
tile_data = ""
for l in open("input.txt"):
    if not l.strip():
        tiles.append(Tile(tile_data))
        tile_data = ""
    elif l.strip():
        tile_data += l
if tile_data:
    tiles.append(Tile(tile_data))
    tile_data = ""

grid = p1(tiles)
p2(grid)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri May 27 16:07:02 2022

@author: jimmyfitpatrick

general simulation encomapssing
-asymmetric + symmetric scattering
-uniform non-instantaneous injection
-arbitrary form of diffusion coefficient
-focused transport (if requested)

"""

import numpy as np
import os
from scipy import constants
from scipy import special
import sys
from pathlib import Path

#importing the global functions file
import util.global_functions as funcs

'''
Class for extracting the D_mumu functions and mean free path functions
'''

#class that holds functions regarding the mean free path and
class SIM_funcs:
    def __init__(self, D_mumu_func,mfp_bool,h_val):
      self.D_mumu_func = D_mumu_func
      self.mfp_bool=mfp_bool
      self.h_val = h_val

    def return_mfp_func(self):
        #constant meanfree path if the boolean is true
        if self.mfp_bool==True:
            def meanfreepath(p,z,lamda,alph,kappa):
                mfp=lamda
                return mfp
            return meanfreepath
        #use the general form otherwise
        #takes in the ALREADY NORMALISED TO THE LOWEST MOMEMENTUM momentum
        if self.mfp_bool==False:
            def meanfreepath(p,z,lamda,alph,kappa):
                # z coming in au/day momentum already pre-normalised to lowest particle momentum
                mfp= lamda*((np.abs(z/1.2))**kappa)*((p)**(2*alph))
                return mfp
            return meanfreepath

    #function that returns the D_mumu and dD_mumu functions
    def return_D_mumu_funcs(self):
        #defining the constant meanfreepath diffusion coefficient
        if self.D_mumu_func=='constant':
            def D_mumu(mu,v,lamda):
                D = v/(lamda)*mu/mu
                return D
            def dD_mumu(mu,v,lamda):
                dD = 0*mu/mu
                return dD
            return D_mumu,dD_mumu

        #defining the standard quasilinear diffusion coefficient
        if self.D_mumu_func=='quasilinear':
            def D_mumu(mu,v,lamda):
                h=self.h_val
                q=5/3
                D = ((3*v)/(lamda*(4-q)*(2-q)*2))*(1-np.power(mu,2))*(np.power(np.abs(mu),q-1)+h)
                return D
            def dD_mumu(mu,v,lamda):
                h=self.h_val
                q=5/3
                A = (3*v)/(2*lamda*(4-q)*(2-q))
                B = 2*mu*(1-np.power(mu,2))
                C = 6*mu*np.power(np.abs(mu),q)*np.power(np.abs(mu),1/3)
                D = 6*mu*h*np.abs(mu)*np.power(np.abs(mu),1/3)
                E = 3*np.abs(mu)*np.power(np.abs(mu),1/3)
                dD = A*((B-C-D)/E)
                #dD = A*(2*mu*(1-mu**2)-6*mu*abs(mu)**(q)*abs(mu)**(1/3)-6*mu*h*abs(mu)*abs(mu)**(1/3))/(3*abs(mu)*abs(mu)**(1/3))
                return dD
            return D_mumu,dD_mumu

        #defining the standard isotropic diffusion coefficient
        if self.D_mumu_func=='isotropic':
              def D_mumu(mu,v,lamda):
                  D = (v/(2*lamda))*(1-mu**2)
                  return D

              #and its respective derivative
              def dD_mumu(mu,v,lamda):
                  dD = -(v*mu)/lamda
                  return dD
              return D_mumu,dD_mumu

#primary simulating class
class transport_functions:
    def __init__(self,dicts):
        self.sim_dict=dicts['sim_dict']
        #unpacking the variables of sim_dict
        #unpacking the variables
        self.Np=self.sim_dict['num_particles']
        self.alpha_vals=np.array(self.sim_dict['alpha_vals'])
        self.kappa=self.sim_dict['kappa']
        self.mfp0_vals = np.array(self.sim_dict['mfp0_vals[AU]'])
        self.ee=np.array(self.sim_dict['energies[keV]'])
        self.t_end = self.sim_dict['t_end[days]']
        self.inj_set=self.sim_dict['injection_type']
        self.custom_end = self.sim_dict['custom_end[days]']
        self.z_init=self.sim_dict['z_injection[AU]']
        self.mu_IC_set=self.sim_dict['mu_IC']
        self.D_mumu_set=self.sim_dict['D_mumu_type']
        self.mfp_const=self.sim_dict['mfp_constant']
        self.consider_focusing=self.sim_dict['consider_focusing']
        self.h_val = self.sim_dict['h_val']

        #extracting the requested temporal resolution, so to compare against
        self.sort_dict=dicts['sort_dict']
        self.requested_t_binwidth = self.sort_dict['t_binwidth[s]']

    #returns speed of an electron given its energy (input in keV)
    def energy_vel(self,E):
        m_e = 9.10938356e-31
        # Converting keV to Joules
        E = 1.60218e-16*E
        # Returns velocity in au/day
        return constants.c*np.sqrt(1-((m_e**(2)*constants.c**(4))/(E+m_e*constants.c**2)**2))*5.77548e-7

    # returns relativistic momentum of an electron, given particle velocity in au/day
    def rel_momentum(self,v):
        m_e = 9.10938356e-31
        # Returns momentum in units, where v is au/day and mass is kg
        return self.gamma(v)*m_e*(v)

    #returns relativistic gamma factor, given particle velocity in au/day
    def gamma(self,v):
        return (1-(v/(constants.c*5.77548e-7))**2)**(-1/2)

    ## function that returns the simulation timestep (based on diffusive timescale)
    def finddt(self,l,v):
        return (l/v)/100

    #return the index of a value in an 1Darray closest to the input value
    def return_mindex(self,ar,val):
        ar = abs(ar-val)
        minim = np.min(ar)
        ind = np.where(ar==minim)
        return ind[0][0]

    #defining the constant injection function
    def const_inj_function(self,size,dt_spec,t1,t2):
        #constructing the time array for the given dt for a specific energy channel
        t = np.arange(0,size,1)*dt_spec
        #tau1 and tau2 hold the index of the elements that contains times closest to t1 and t2
        tau1 = self.return_mindex(t,t1)
        tau2 = self.return_mindex(t,t2)
        #counting how many time steps between the two times
        N = tau2-tau1
        #stopping singularity if two points fall on coincident timesteps
        if N==0:
            N=1
        #number of electrons to inject per timestep within the bounds
        n_perstep = self.Np/N
        frac=1
        #if n_perstep is more than 1 just set frac=1
        if n_perstep<1:#if it is less than one
            #if n_perstep is less than 1 then we will need to 'skip' steps
            print('skipping steps!')
            frac=int(np.floor(1/n_perstep))
        #print(n_perstep)
        #this array will hold the number of psuedo-particles to inject at time t (w.r.t the default time array)
        inj = np.zeros(len(t))
        #for each timestep,
        for tau in range(len(t)):
            #if the time falls within the injection period,
            if tau>=tau1 and tau<=tau2:
                #extra line that deals with if n_perstep<1
                boole = tau%frac==0
                #inject relevent number of particles on appropriate timesteps
                inj[tau]=np.ceil(n_perstep)*boole
            else:#otherwise inject no particles
                inj[tau]=0
        #return the time array and injection function
        return t,inj

    def return_boole_asym(self,particles_insim,inj_function,tau,tup):
        #label each particle in the simulation from 0,Np based on which index it lies on
        ind = np.ones(tup)
        Np=tup[-1]
        counting = np.arange(0,Np,1)
        ind[:,:,:]=counting

        #add relevent injected particles into the simulation
        particles_insim = particles_insim+inj_function[:,:,:,tau]

        #the compare array will be a boolean type array that will release the particle if index<particles_insim
        #this is mediated by the injection function
        compare = np.zeros(np.shape(ind))
        #pull Np axis to the front to place in relevent injected particle numbers
        compare = np.moveaxis(compare,-1,0)
        compare[:,:,:,:] = particles_insim
        #return compare array to shape before
        compare = np.moveaxis(compare,0,-1)
        #release if the index of each particle is less than the compare
        release = np.where(ind<compare)
        #if the particle has been released, set to one
        ind[release]=1
        #if particle has not been released yet, set to 0
        ind[ind!=1]=0
        #emphasis that ind has become the boolean array we needed
        boole = ind
        return  boole,particles_insim

    #function for asymmetric diffusion
    #first two arguments are functions
    def asym_diffusion(self,diffusion,ddiffusion,mu,v,l_n,l_p):
        #implicately assuming that no particle has mu exactly zero
        #need to apply boolean logic
        #mu is an array
        #arrays that are the same shape as mu, and hold true for the elements satisfying the conditions, and false if not
        true_pos = mu>0
        #true_neg will be inferred from ~true_pos
        true_zero = mu==0
        #converting true_zeroes to nans to not interfere with the decomposition into positve and negative values
        mu[true_zero] = np.nan

        #decomposing the array into positive and negative parts
        #i.e. here, all non-positive entries will be made to be 0 after the multiplication
        pos_mu = true_pos*mu
        #converting all particles with non-positive mu values to nans
        pos_mu[pos_mu==0]=np.nan

        #same for negative mu values
        neg_mu = ~true_pos*mu
        neg_mu[neg_mu==0]=np.nan

        #calling in existing diffusion function, b
        #to allow for antisymmetric diffusion coefficient
        #positive mu values use positive mean free path
        D_p = diffusion(pos_mu,v,l_p)
        #vice versa for negative diffusion values
        D_n = diffusion(neg_mu,v,l_n)

        #finding the nanvalues  after computation and turning back to zeros
        true_nan_pos_D = np.isnan(D_p)
        true_nan_neg_D = np.isnan(D_n)

        #converting these arrays back to 0
        D_p[true_nan_pos_D] = 0
        D_n[true_nan_neg_D] = 0

        #identically byt for the derivative
        dD_p = ddiffusion(pos_mu,v,l_p)
        #vice versa for negative diffusion values
        dD_n = ddiffusion(neg_mu,v,l_n)

        true_nan_pos_dD = np.isnan(dD_p)
        true_nan_neg_dD = np.isnan(dD_n)

        dD_p[true_nan_pos_dD] = 0
        dD_n[true_nan_neg_dD] = 0

        #recompose to form the entire D_mumu array
        D = D_p + D_n
        dD=dD_p+dD_n
        return D,dD

    '''
    correcting mu functions via additive boundaries
    '''

    '''
    #Boolean arrays for correcting mu vals
    # Returns a boolean array which says true if any vals are above 1
    #takes in the array of mu values for each test particle
    def maxbound(self,muvals):
        trueif = muvals>1
        return trueif

    # Returns a boolean array which says true if any mu vals are below -1
    def minbound(self,muvals):
        trueif = muvals<-1
        #trueif = muvals<0
        return trueif
    # Function that returns True if any of the boolean values in a multi dim array are true, False if there are no trues
    def has_true(self,arr):
        return arr.any()
    '''
    '''
    #should be able to optimise this.
    # Function that corrects mu values by rules of reflective boundaries (-1,1)
    def mucor(self,muvals):
        k=0
        # a returns True for all elements maxbound, and b analogously for elements below 0
        #a = self.maxbound(muvals)
        a=muvals>1
        #b = self.minbound(muvals)
        b=muvals<-1
        while a.any()==True or b.any()==True:
            #debugging loop to stop corrections applying indefinitely for a failsafe
    #         if k>1000:
    #             #print(muvals[a])
    #             #print(muvals[b])
    #             print("too many iterations, stopping")
    #             break
    #       # applying corrections if any boolean values are true for below 1
            #if b.any() == True:
            muvals[b]= -1+abs(muvals[b]+1)

            #if a.any() == True:
            muvals[a]= 1-abs(muvals[a]-1)

            # After a single correction, seeing if any further corrections are necessary. Loops until all values are within range or sequence breaks
            #a = self.maxbound(muvals)
            #b = self.minbound(muvals)
            a=muvals>1
            #b = self.minbound(muvals)
            b=muvals<-1
            # Applying first "above 1" corrections if any boolean values are true for max bound
            k=k+1
        #once corrections are made, return array of mu values
        return muvals

    '''
    # Function that corrects mu values by rules of reflective boundaries (-1,1)
    def mucor(self,muvals):
        a=muvals>1
        b=muvals<-1
        while a.any()==True or b.any()==True:
            muvals[b]= -1+abs(muvals[b]+1)
            muvals[a]= 1-abs(muvals[a]-1)
            a=muvals>1
            b=muvals<-1
        #once corrections are made, return array of mu values
        return muvals

    def mucor_faster(self,muvals):
        mu_toobig=muvals>=1
        mu_toosmall=muvals<=-1
        #try correct the correctable mu values
        muvals[mu_toobig]= 1-muvals[mu_toobig]%1
        muvals[mu_toosmall]= -1-muvals[mu_toosmall]%-1
        return muvals

    #takes in the requested simulation, and outputs the particle simulation array
    def simulate_transport(self):
        '''
        number of alpha_vals, mean free path pairs and energies being simulated
        '''

        #number of meanfreepath pairs
        n_pairs = np.shape(self.mfp0_vals)[0]
        #number of alpha values considered
        n_alph = len(self.alpha_vals)
        #how many energy channels are we considering?
        n_ener = len(self.ee)

        sim_tup = (n_alph,n_pairs,n_ener,self.Np)

        '''
        building paramater arrays for the simulation
        '''
        # To define the mean free path dependent on distance we need to find the momentum of the lowest energy considered
        #finding minimum energy
        lowest_ee = np.min(self.ee)
        #finding minimum velocity [in au/day]
        lowest_vel = self.energy_vel(lowest_ee)
        #finding minimum momementum
        p0=self.rel_momentum(lowest_vel)
        ## Initialising the particle velocities
        #recall, ee holds the energy channels as floats
        v = self.energy_vel(self.ee)

        #finding an array of the relativistic momentums, given the particle velocities...
        ## Corresponding momentums for each energy channel
        p = self.rel_momentum(v)

        '''
        initialising and vectorising simulation parameters
        '''

        #reformatting arrays for vector computation
        #reformatting velocities, momentums, mean free path respectively
        vels = np.zeros(sim_tup)
        moms = np.zeros(sim_tup)
        #place v and p into formatted arrays
        for e in range(n_ener):
            vels[:,:,e,:] = v[e]
            moms[:,:,e,:] = p[e]

        #normalising the momentum w.r.t momentum of lowest energy channel.
        mom = moms/p0

        #initialising an array to hold the mean_free_paths
        #by convention, first entry on last axis is mfp_n, second is mfp_p
        mfp_ar = np.zeros(sim_tup+(2,))
        # dt_vals will be an intermediate array to help initialise the full timestep array
        #it will hold the timestep for each lambda_parallel,oplus, energy channel combination
        #it is constant across alpha
        dt_vals=np.zeros((n_pairs,n_ener))
        #for each mean_freepath, compute the corresponding  the corresponding timestep
        for l in range(0,n_pairs):
            #extracting the two values of the mean free path
            L_n= self.mfp0_vals[l,0]
            L_p = self.mfp0_vals[l,1]
            #set all the elements in the [l,:,:] entries to these respective values
            mfp_ar[:,l,:,:,0]=L_n
            mfp_ar[:,l,:,:,1]=L_p
            # here we will take minimum mean free path of the set to define the stepsize
            L_min = min(L_n,L_p)
            #finding the diffusive timescale for the L_min v combination
            dt_vals[l,:]=self.finddt(L_min,v)

        #finding the minimum timestep in seconds
        max_dt_seconds = np.max(dt_vals)*86400

        #ignore for now
        if self.requested_t_binwidth<max_dt_seconds:
            raise SystemError('The maximum timesteps in seconds are: '+ str(max_dt_seconds)+' but the requested temporal resolution is: '+str(self.requested_t_binwidth)+'. Increase the requested temporal resolution! Timesteps are too large in some or all of the energies simulated.')

        #full array initialising for vectorising computations
        dt = np.zeros(sim_tup)
        for n in range(self.Np):
            dt[:,:,:,n]=dt_vals

        #initialising the alpha vector format array
        alphas = np.zeros(sim_tup)
        for alph in range(n_alph):
            alphas[alph,:,:,:] = self.alpha_vals[alph]

        '''
        setting up the primary simulation arrays and related variables
        '''
        #we need to make sure the smallest timestep makes it to t_end
        #number of timesteps for each dt
        n_timesteps = self.t_end/dt

        #what is the maximum number of timesteps? i.e the most timesteps needed such that
        #the combination with the smallest timestep makes it to t_end
        max_steps = int(np.max(n_timesteps)+1)

        #in the last axis, 0 is the z vals, 1 is the mu vals
        #sim_zmu will hold the position,z, and pitch angle, mu, of each particles in all the simulations in all energy channels
        sim_zmu = np.zeros(sim_tup+(max_steps+1,2))

        ## All particles start at z=0.05
        sim_zmu[:,:,:,:,0,0] = self.z_init
        #print(self.z_init)

        #picking the initial mu distribution
        if self.mu_IC_set =='uniform+':
            mu_init = np.random.uniform(0,1,sim_tup)

        if self.mu_IC_set =='uniform+-':
            mu_init = np.random.uniform(-1,1,sim_tup)

        if self.mu_IC_set == 'forward_beamed':
            mu_init = np.random.uniform(-1,1,sim_tup)*1e-4+0.999

        #placing initial mu distribution into the main simulation array
        sim_zmu[...,0,1] = mu_init[:,:,:,:]

        # Construct a ballistic particle that will be UNAFFECTED by scattering to test arrival time
        sim_test = np.zeros((sim_tup[0:-1])+(max_steps+1,))
        #independent of mu naturally
        sim_test[:,:,:,0]=self.z_init

        #raise SystemExit

        #array to keep track of time for each simulation combination
        t = np.zeros(sim_tup)

        '''
        Accounting for non-instantateous injection!
        '''
        #setting the injection boundaries
        if self.inj_set=='instantaneous':
            self.inj_range = [0,self.t_end/10000]

        if self.inj_set=='constant':
            self.inj_range=[0,self.t_end]

        if self.inj_set=='custom':
            inj_range=[0,self.custom_end]

        #hold particles at z=init, at each timestep 'release' N particles according to inj function
        #seperate injection functions for mfp,ee combinations (since dt varies for these parameters)
        inj_function = np.zeros((sim_tup[0:-1])+(max_steps+1,))
        t_inj = np.zeros((sim_tup[0:-1])+(max_steps+1,))
        #size of the time array is max_steps+1
        size = max_steps+1

        #extracting the injection boundaries
        t1=self.inj_range[0]
        t2=self.inj_range[1]
        #constructing each injection function, for every l and e combination
        #these are the variables which affect timestep size
        for l in range(n_pairs):
            for e in range(n_ener):
                #pulling out the specific timestep for that combination
                dt_spec = dt[0,l,e,0]
                #construct the time arrays(for plotting) and the injection function array
                t_inj[:,l,e],inj_function[:,l,e]=self.const_inj_function(size,dt_spec, t1, t2)

        #at tau=0 no particles are in the simulation
        #particles_insim will hold how many particles have been injected into the sim each timestep, initially zero
        particles_insim = 0*inj_function[:,:,:,0]

        '''
        selecting the chosen form of D_mumu and mean free path
        '''

        sim_funcs=SIM_funcs(self.D_mumu_set,self.mfp_const,self.h_val)
        diffusion = sim_funcs.return_D_mumu_funcs()[0]
        ddiffusion=sim_funcs.return_D_mumu_funcs()[1]
        meanfreepath_func = sim_funcs.return_mfp_func()

        #if consider focusing...
        if self.consider_focusing==True:
            B=1
        if self.consider_focusing==False:
            B=0

        '''
        Main simulation loop
        -for speed, define the local variables for functions before the main loop
        '''

        # t must also now be an array
        print("Running simulation for "+str(self.Np)+" particles.")
        particles_insim = 0*inj_function[:,:,:,0]
        #tau=0

        '''
        de-selfing some of the parameters to be used in the loop
        '''
        #scalar
        t_end = self.t_end
        #function
        return_boole_asym = self.return_boole_asym
        #scalar
        kappa=self.kappa
        #function
        asym_diffusion=self.asym_diffusion
        #function
        mucor=self.mucor_faster

        '''
        main simulation loop
        '''
        tau=0
        #so incremement tau then use tau-1 elements to define tau
        for n in range(1,max_steps+1):
        #while (np.min(t) < t_end):
            #timekeeping
            if tau%10==0:
                print(str(np.round(100*tau/max_steps+1,2))+'%')
                #print(np.min(t)*1440)

            #construct the boolean array and inject particles into the sim using inj_function
            boole,particles_insim = return_boole_asym(particles_insim, inj_function, tau,sim_tup)
            #incremeent by one timestep
            tau=tau+1
            # Increment time by one timestep (t and dt both multdim arrays)
            t=t+dt
            #pull out a random variable from a normal distribution centred at the origin variance 1
            W = np.random.normal(0,1,sim_tup)

            #l_n is applied for particles with mu<0
            #l_p will be applied to particles with mu>0
            # finding mean free path for mu<0
            l_n = meanfreepath_func(mom,sim_zmu[:,:,:,:,tau-1,0],mfp_ar[:,:,:,:,0],alphas,kappa)
            #finding the meanfreepath for mu>0
            l_p = meanfreepath_func(mom,sim_zmu[:,:,:,:,tau-1,0],mfp_ar[:,:,:,:,1],alphas,kappa)

            #define new focusing length
            L_z = sim_zmu[:,:,:,:,tau-1,0]/2

            ## Finding the (now asymmetric) diffusion coefficients (splits into negative and positive particles and applies diffusion formulae with the respective mfps)
            D,dD=asym_diffusion(diffusion,ddiffusion,sim_zmu[:,:,:,:,tau-1,1],vels,l_n,l_p)

            #simple ballisitc current dist+vels*dt
            sim_test[:,:,:,tau] = sim_test[:,:,:,tau-1]+vels[:,:,:,0]*dt[:,:,:,0]

            #computing the stochastic recurcions

            #advance particles using boole. If index of particle<sum of injected then boole =1 and particle z advances
            sim_zmu[:,:,:,:,tau,0] = sim_zmu[:,:,:,:,tau-1,0]+ boole*sim_zmu[:,:,:,:,tau-1,1]*vels*dt
            #sim_zmu[:,:,:,:,tau,0] = sim_zmu[:,:,:,:,tau-1,0]+ vels*dt

            #pitch angle is unaffected by the injection and always varies for all particles
            sim_zmu[:,:,:,:,tau,1] =  sim_zmu[:,:,:,:,tau-1,1] + dt*(dD+B*(vels*(1-sim_zmu[:,:,:,:,tau-1,1]**2))/(2*L_z))+np.sqrt(2*D*dt)*W
            #correct the zmu_values in order to keep within range using the mucor function
            sim_zmu[:,:,:,:,tau,1] = mucor(sim_zmu[:,:,:,:,tau,1])

        #after simulating, collect some values needed for sorting and place in a dictionary
        carry_over = [v,dt_vals,max_steps,sim_funcs]
        carry_over_labels = ['velocities[AU/day]','dt_vals[days]','max_steps','sim_funcs']
        carry_over=funcs.build_dict(carry_over_labels,carry_over)

        #rather than unpacking as part of the function, numpy save the carry over array
        data_path=funcs.folder_functions().return_datapath()
        np.save(os.path.join(data_path,"carry_over"),carry_over,allow_pickle=True)
        np.save(os.path.join(data_path,"sim_zmu"),sim_zmu)

        #save the parameters that can be saved (prior to sorting!)
        print('Saving relevant variables.')
        data_path=funcs.folder_functions().return_datapath()
        for alph in range(n_alph):
            alpha = self.alpha_vals[alph]
            for l in range(n_pairs):
                l_n = self.mfp0_vals[l,0]
                l_p = self.mfp0_vals[l,1]
                fname = funcs.file_name_asym(alpha,l_n,l_p,self.kappa)
                #saving t_inj and (normalised) injection function
                np.save(os.path.join(data_path,"t_inj_"+fname),t_inj[alph,l])
                np.save(os.path.join(data_path,"inj_function_"+fname),inj_function[alph,l]/self.Np)

                #save the injection status and injection locations to remove the injection bin for that run if necessary
                np.save(os.path.join(data_path,"inj_set_"+fname),self.inj_set)

                #save the initial_z
                np.save(os.path.join(data_path,"z_init_"+fname),self.z_init)

                #save the electron energies
                np.save(os.path.join(data_path,"ee_"+fname),self.ee)

                #save whether or not constant mean free path was used (to plot the mean free path function)
                np.save(os.path.join(data_path,"mfp_const_"+fname),self.mfp_const)

        print('Simulation complete.')
        #return the simulation array and the variables to carry over for sorting
        #return sim_zmu,carry_over
        return sim_zmu


from pyspark.sql import SparkSession
import pyspark.sql.functions as F

spark = (SparkSession
         .builder
         .appName("Analyzing the vocabulary of Pride and Prejudice.")
         .getOrCreate())

sc = spark.sparkContext

sc.setLogLevel("ERROR")

# Ex. 3.3
count = (
    spark.read.text("data/gutenberg_books/*.txt")
    .select(F.split(F.col("value"), " ").alias("line"))
    .select(F.explode(F.col("line")).alias("word"))
    .select(F.lower(F.col("word")).alias("word_lower"))
    .select(F.regexp_extract(F.col("word_lower"), "[a-z]*", 0).alias("word"))
    .where(F.col("word") != "")
    .groupby(F.col("word"))
    .count()
    .count()
)
print(count)

# Ex. 3.4
once = (
    spark.read.text("data/gutenberg_books/*.txt")
    .select(F.split(F.col("value"), " ").alias("line"))
    .select(F.explode(F.col("line")).alias("word"))
    .select(F.lower(F.col("word")).alias("word_lower"))
    .select(F.regexp_extract(F.col("word_lower"), "[a-z]*", 0).alias("word"))
    .where(F.col("word") != "")
    .groupby(F.col("word"))
    .count()
    .filter(F.col("count") == 1)
)
once.show(5)

# Ex. 3.5
first_letters = (
    spark.read.text("data/gutenberg_books/1342-0.txt")
    .select(F.split(F.col("value"), " ").alias("line"))
    .select(F.explode(F.col("line")).alias("word"))
    .select(F.lower(F.col("word")).alias("word_lower"))
    .select(F.regexp_extract(F.col("word_lower"), "[a-z]*", 0).alias("word"))
    .where(F.col("word") != "")
    .select(F.substring(F.col("word"), 1, 1).alias("first_letter"))
    .groupby(F.col("first_letter"))
    .count()
    .orderBy(F.col("count"), ascending=False)
)

first_letters.show(5)


from django.shortcuts import render
from django.http import JsonResponse, HttpResponseRedirect
from django.core.paginator import Paginator
from django.views.decorators.csrf import csrf_exempt
from .models import Product, ProductVariation
from datetime import datetime, timedelta
import pandas as pd
import random
from openpyxl import load_workbook

def redirectToUrl(request):
    return HttpResponseRedirect("/excel")

def index(request):
    result = []

    # Retrieve all products from the database
    allProducts = Product.objects.all()

    # Create a paginator with 3 items per page and get the requested page number
    paginator = Paginator(allProducts, 3)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    # Loop through each product on the requested page and retrieve its variations
    for product in page_obj:

        variation = Product.objects.get(name=product.name).variations.all()

        # Add the product and its variations to a dictionary and append it to the result list
        product_variance = {
            "item": product,
            "variation": variation,
        }
        result.append(product_variance)

    # Create a context dictionary with the result list and the page object
    context = {
        "data": result,
        'page_obj': page_obj,
    }

    # Render the homepage template with the context dictionary
    return render(request, 'excelperser/homePage.html', context=context)

@csrf_exempt
def addProduct(request):

    # Check if the request method is POST and if a file was uploaded
    if request.method == 'POST' and request.FILES.get('file'):

        file = request.FILES['file']

        # Check if the file type and size are valid
        if file.content_type not in ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']:
            return JsonResponse({'error': 'Invalid file type'})
        if file.size > 2 * 1024 * 1024:
            return JsonResponse({'error': 'File size exceeded'})

        try:

            # Load the workbook from the uploaded file and retrieve the first worksheet
            productFile = load_workbook(filename=file)
            sheet_name = productFile.sheetnames[0]
            dataInFile = productFile[sheet_name]

            # Loop through each row in the worksheet and add the products and variations to the database
            ok = False

            for line in dataInFile:

                # Skip the first row (header row)
                if not ok:
                    ok = True
                    continue

                # Get the product name, variation text, and stock from the current row
                name, variation_text, stock = line[0].value, line[1].value, line[2].value

                # Check if the product already exists in the database
                products = Product.objects.filter(name=name)

                if products:
                    # If the product exists, check if the variation already exists
                    variation = ProductVariation.objects.filter(
                        product_id=products[0].id, variation_text=variation_text)

                    if variation:
                        # If the variation already exists, update its stock
                        variation[0].stock += stock

                        utc_now = datetime.utcnow()
                        india_offset = timedelta(hours=5, minutes=30)
                        variation[0].last_updated = utc_now + india_offset
                        products[0].last_updated = (utc_now + india_offset)

                        products[0].save()
                        variation[0].save()
                    else:
                        # If the variation doesn't exist, create a new one
                        newVariation = ProductVariation(
                            product_id=products[0].id, variation_text=variation_text, stock=stock)
                        newVariation.save()

                else:

                    # If the product doesn't exist, create a new one and a new variation

                    newProduct = Product(
                        name=name, lowest_price=random.randint(10000, 99999))
                    newProduct.save()

                    newVariation = ProductVariation(
                        product_id=newProduct.id, variation_text=variation_text, stock=stock)
                    newVariation.save()

            return JsonResponse({'success': True})

        except Exception as e:
            return JsonResponse({'error': str(e)})

    else:
        return JsonResponse({'error': 'Invalid request'})


import sys
import psycopg2
import psycopg2.pool
import yaml
import argparse
import yaml.scanner
from threading import Thread
from betmaster.redis import RedisQueue
from betmaster.utils import check_positive, check_conf, get_configuration

NAMESPACE = 'betmaster'
DSN = 'dbname={database} user={user} password={password} host={host}'

def parse_args(args):
    parser = argparse.ArgumentParser()
    parser.add_argument('--workers', '-w',
                        help='Quantity of workers to be launched in current session',
                        type=check_positive,
                        default=1)
    parser.add_argument('--conf-path',
                        help='Path to the db configuration',
                        type=check_conf,
                        required=True)

    return vars(parser.parse_args(args))

class WorkersPool:
    """Initialize pool of workers that will listen redis queue for the event url then download and parse html page
    find arbitrage odds and save results into database"""

    def __init__(self, count, conn_pool):
        self.count = count
        self.conn_pool = conn_pool

        self.workers = []
        self.threads = []

    def start_pool(self):
        for i in range(self.count):
            worker = Worker(
                name='Worker #{}'.format(i),
                conn_pool=self.conn_pool)
            self.workers.append(worker)

            t = Thread(target=worker.run)
            t.start()
            self.threads.append(t)

    def close_pool(self):
        for w in self.workers:
            w.stop(force=False)

        for t in self.threads:
            t.join()

class Worker:
    """
    Worker
    MSG Example (raw and approx):
    - type: dict
    - format: pickle
    structure
    url: [url]
    metadata: [data]
    """

    STOP_WORD = "STOP"

    def __init__(self, name, conn_pool):
        self.name = name
        self.conn = RedisQueue(name=NAMESPACE, host='0.0.0.0')
        self.db_conn = conn_pool.getconn()

    def stop(self, force=False):
        if force:
            self.conn.lput('message', 'STOP')
        else:
            self.conn.put('message', 'STOP')

    def run(self):
        # listen to queue
        while True:
            msg = self.conn.get('message')
            if msg == self.STOP_WORD:
                break
            try:
                # do some stuff here
                deserialized_msg = self._deserialize_msg(msg)
                self._process_message(deserialized_msg)
                pass
            except:
                pass

    def _deserialize_msg(self, msg):
        """"""
        return pickle.loads(msg)

    def _process_message(self, msg: dict):
        """"""

def main():
    """
    Workers pool initialization script
    """
    args = parse_args(sys.argv[1:])
    redis_conf = get_configuration(args['conf_path'], 'redis')
    redis_conn = RedisQueue(name=args.get('db_key'), **redis_conf)

    # configure at postgres config
    max_connections = 50
    if args['workers'] > max_connections:
        raise ValueError(f'To much workers use from 1 to {max_connections}')
    try:
        # database configuration
        db_conf = get_configuration(args['conf_path'], 'database')
        conn_pool = psycopg2.pool.ThreadedConnectionPool(
            minconn=1,
            maxconn=max_connections,
            dsn=DSN.format(**db_conf['user']))
    except (FileNotFoundError,
            yaml.parser.ParserError,
            yaml.scanner.ScannerError,
            psycopg2.Error) as e:
        print(e)
        sys.exit()

    ths = []
    try:
        for i in range(args['workers']):
            worker = Worker(
                name=f'Worker #{i}',
                conn_pool=conn_pool)
            t = Thread(target=worker.run, )
            t.start()
            ths.append(t)
        for t in ths:
            t.join()
    except KeyboardInterrupt:
        for _ in range(args['workers']):
            redis_conn.lput('message', 'STOP')
    finally:
        conn_pool.closeall()

if __name__ == '__main__':
    main()


#first_sanic
from sanic import Sanic
from sanic.response import json

app = Sanic(name = "first_api")

@app.route("/")
async def test(request):
    return json({"hello" : "Sir"})

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8000)


# remove 1st, 4th and 5th element in the list
def remove_items(list_):
    try:
        del list_[4]
        del list_[3]
        del list_[0]
    except IndexError:
        return
    sorted_list = list_.sort()
    return sorted_list

userInput = []
item = ''
# ask the user to enter elements and create list
print('Enter at least 5 items which will be added to the list. To end the process write \"q\":')
while item != 'q':
    item = input()
    if item == ' ':
        continue
    elif item != 'exit':
        print('Next item')
        userInput.append(item)
# count list's length
input_len = len(userInput)
print('Your list has ' + str(input_len) + ' elements and contains: ' + str(userInput))
# check if the list has a proper length and if so, use the function and remove elements
if input_len < 5:
    print('Your list is too short to remove elements')
else:
    remove_items(userInput)
    print('Your list after removing operation:' + str(userInput))