#
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
#
# 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 os
import sys
import time
import ctypes
import argparse
import numpy as np
import tensorrt as trt

import pycuda.driver as cuda
import pycuda.autoinit

from image_batcher import ImageBatcher
from visualize import visualize_detections

class TensorRTInfer:
    """
    Implements inference for the EfficientDet TensorRT engine.
    """

    def __init__(self, engine_path):
        """
        :param engine_path: The path to the serialized engine to load from disk.
        """
        # Load TRT engine
        self.logger = trt.Logger(trt.Logger.ERROR)
        trt.init_libnvinfer_plugins(self.logger, namespace="")
        with open(engine_path, "rb") as f, trt.Runtime(self.logger) as runtime:
            self.engine = runtime.deserialize_cuda_engine(f.read())
        self.context = self.engine.create_execution_context()
        assert self.engine
        assert self.context

        # Setup I/O bindings
        self.inputs = []
        self.outputs = []
        self.allocations = []
        for i in range(self.engine.num_bindings):
            is_input = False
            if self.engine.binding_is_input(i):
                is_input = True
            name = self.engine.get_binding_name(i)
            dtype = np.dtype(trt.nptype(self.engine.get_binding_dtype(i)))
            shape = self.context.get_binding_shape(i)
            if is_input and shape[0] < 0:
                assert self.engine.num_optimization_profiles > 0
                profile_shape = self.engine.get_profile_shape(0, name)
                assert len(profile_shape) == 3  # min,opt,max
                # Set the *max* profile as binding shape
                self.context.set_binding_shape(i, profile_shape[2])
                shape = self.context.get_binding_shape(i)
            if is_input:
                self.batch_size = shape[0]
            size = dtype.itemsize
            for s in shape:
                size *= s
            allocation = cuda.mem_alloc(size)
            host_allocation = None if is_input else np.zeros(shape, dtype)
            binding = {
                'index': i,
                'name': name,
                'dtype': dtype,
                'shape': list(shape),
                'allocation': allocation,
                'host_allocation': host_allocation,
            }
            self.allocations.append(allocation)
            if self.engine.binding_is_input(i):
                self.inputs.append(binding)
            else:
                self.outputs.append(binding)
            print("{} '{}' with shape {} and dtype {}".format(
                "Input" if is_input else "Output",
                binding['name'], binding['shape'], binding['dtype']))

        assert self.batch_size > 0
        assert len(self.inputs) > 0
        assert len(self.outputs) > 0
        assert len(self.allocations) > 0

    def input_spec(self):
        """
        Get the specs for the input tensor of the network. Useful to prepare memory allocations.
        :return: Two items, the shape of the input tensor and its (numpy) datatype.
        """
        return self.inputs[0]['shape'], self.inputs[0]['dtype']

    def output_spec(self):
        """
        Get the specs for the output tensors of the network. Useful to prepare memory allocations.
        :return: A list with two items per element, the shape and (numpy) datatype of each output tensor.
        """
        specs = []
        for o in self.outputs:
            specs.append((o['shape'], o['dtype']))
        return specs

    def infer(self, batch):
        """
        Execute inference on a batch of images.
        :param batch: A numpy array holding the image batch.
        :return A list of outputs as numpy arrays.
        """
        # Copy I/O and Execute
        cuda.memcpy_htod(self.inputs[0]['allocation'], batch)
        self.context.execute_v2(self.allocations)
        for o in range(len(self.outputs)):
            cuda.memcpy_dtoh(self.outputs[o]['host_allocation'], self.outputs[o]['allocation'])
        return [o['host_allocation'] for o in self.outputs]

    def process(self, batch, scales=None, nms_threshold=None):
        """
        Execute inference on a batch of images. The images should already be batched and preprocessed, as prepared by
        the ImageBatcher class. Memory copying to and from the GPU device will be performed here.
        :param batch: A numpy array holding the image batch.
        :param scales: The image resize scales for each image in this batch. Default: No scale postprocessing applied.
        :return: A nested list for each image in the batch and each detection in the list.
        """
        # Run inference
        outputs = self.infer(batch)

        # Process the results
        nums = outputs[0]
        boxes = outputs[1]
        scores = outputs[2]
        classes = outputs[3]
        detections = []
        normalized = (np.max(boxes) < 2.0)
        for i in range(self.batch_size):
            detections.append([])
            for n in range(int(nums[i])):
                scale = self.inputs[0]['shape'][2] if normalized else 1.0
                if scales and i < len(scales):
                    scale /= scales[i]
                if nms_threshold and scores[i][n] < nms_threshold:
                    continue
                detections[i].append({
                    'ymin': boxes[i][n][0] * scale,
                    'xmin': boxes[i][n][1] * scale,
                    'ymax': boxes[i][n][2] * scale,
                    'xmax': boxes[i][n][3] * scale,
                    'score': scores[i][n],
                    'class': int(classes[i][n]),
                })
        return detections

def main(args):
    if args.output:
        output_dir = os.path.realpath(args.output)
        os.makedirs(output_dir, exist_ok=True)

    labels = []
    if args.labels:
        with open(args.labels) as f:
            for i, label in enumerate(f):
                labels.append(label.strip())

    trt_infer = TensorRTInfer(args.engine)
    if args.input:
        print("Inferring data in {}".format(args.input))
        batcher = ImageBatcher(args.input, *trt_infer.input_spec())
        for batch, images, scales in batcher.get_batch():
            print("Processing Image {} / {}".format(batcher.image_index, batcher.num_images), end="\r")
            detections = trt_infer.process(batch, scales, args.nms_threshold)
            if args.output:
                for i in range(len(images)):
                    basename = os.path.splitext(os.path.basename(images[i]))[0]
                    # Image Visualizations
                    output_path = os.path.join(output_dir, "{}.png".format(basename))
                    visualize_detections(images[i], output_path, detections[i], labels)
                    # Text Results
                    output_results = ""
                    for d in detections[i]:
                        line = [d['xmin'], d['ymin'], d['xmax'], d['ymax'], d['score'], d['class']]
                        output_results += "\t".join([str(f) for f in line]) + "\n"
                    with open(os.path.join(output_dir, "{}.txt".format(basename)), "w") as f:
                        f.write(output_results)
    else:
        print("No input provided, running in benchmark mode")
        spec = trt_infer.input_spec()
        batch = 255 * np.random.rand(*spec[0]).astype(spec[1])
        iterations = 200
        times = []
        for i in range(20):  # GPU warmup iterations
            trt_infer.infer(batch)
        for i in range(iterations):
            start = time.time()
            trt_infer.infer(batch)
            times.append(time.time() - start)
            print("Iteration {} / {}".format(i + 1, iterations), end="\r")
        print("Benchmark results include time for H2D and D2H memory copies")
        print("Average Latency: {:.3f} ms".format(
            1000 * np.average(times)))
        print("Average Throughput: {:.1f} ips".format(
            trt_infer.batch_size / np.average(times)))

    print()
    print("Finished Processing")

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-e", "--engine", default=None, required=True,
                        help="The serialized TensorRT engine")
    parser.add_argument("-i", "--input", default=None,
                        help="Path to the image or directory to process")
    parser.add_argument("-o", "--output", default=None,
                        help="Directory where to save the visualization results")
    parser.add_argument("-l", "--labels", default="./labels_coco.txt",
                        help="File to use for reading the class labels from, default: ./labels_coco.txt")
    parser.add_argument("-t", "--nms_threshold", type=float,
                        help="Override the score threshold for the NMS operation, if higher than the built-in threshold")
    args = parser.parse_args()
    main(args)


import os
import sys

os.environ['OMP_NUM_THREADS'] = '1'
import argparse
import paddle
from env import MultipleEnvironments
from model import Model
import multiprocessing as _mp
from utils import eval, print_arguments
from paddle.distribution import Categorical
import paddle.nn.functional as F
import numpy as np

def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--world",            type=int,   default=1,    help='游戏的世界')
    parser.add_argument("--stage",            type=int,   default=1,    help='游戏的阶段')
    parser.add_argument("--action_type",      type=str,   default="simple", help='游戏的动作类型')
    parser.add_argument('--lr',               type=float, default=1e-4, help='模型的学习率')
    parser.add_argument('--gamma',            type=float, default=0.9,  help='奖励折扣率')
    parser.add_argument('--tau',              type=float, default=1.0,  help='GAE参数')
    parser.add_argument('--beta',             type=float, default=0.01, help='熵权')
    parser.add_argument('--epsilon',          type=float, default=0.2,  help='剪切替代目标参数')
    parser.add_argument('--batch_size',       type=int,   default=16,   help='训练数据的批量大小')
    parser.add_argument('--num_epochs',       type=int,   default=10,   help='每次采样训练多少轮')
    parser.add_argument("--num_local_steps",  type=int,   default=512,  help='每次采样的次数')
    parser.add_argument("--num_processes",    type=int,   default=16,   help='使用多少条线程启动游戏')
    parser.add_argument("--saved_path",       type=str,   default="models", help='保存模型的路径')
    parser.add_argument("--show_play",        type=bool,  default=False, help='是否显示评估游戏的界面，终端无法使用')
    args = parser.parse_args()
    return args

# 训练模型
def train(args):
    # 使用 GPU训练
    if paddle.is_compiled_with_cuda():
        paddle.set_device("gpu:0")
    # 创建多进程的游戏环境
    envs = MultipleEnvironments(args.world, args.stage, args.action_type, args.num_processes)
    # 固定初始化状态
    paddle.seed(123)
    # 创建模型
    model = Model(envs.num_states, envs.num_actions)
    # 创建保存模型的文件夹
    if not os.path.isdir(args.saved_path):
        os.makedirs(args.saved_path)
    paddle.save(model.state_dict(), "{}/model_{}_{}.pdparams".format(args.saved_path, args.world, args.stage))
    # 为游戏评估单独开一个进程
    mp = _mp.get_context("spawn")
    process = mp.Process(target=eval, args=(args, envs.num_states, envs.num_actions))
    process.start()
    # 创建优化方法
    clip_grad = paddle.nn.ClipGradByNorm(clip_norm=0.5)
    optimizer = paddle.optimizer.Adam(parameters=model.parameters(), learning_rate=args.lr, grad_clip=clip_grad)
    # 刚开始给每个进程的游戏执行初始化
    [agent_conn.send(("reset", None)) for agent_conn in envs.agent_conns]
    # 获取游戏初始的界面
    curr_states = [agent_conn.recv() for agent_conn in envs.agent_conns]
    curr_states = paddle.to_tensor(np.concatenate(curr_states, 0), dtype='float32')
    curr_episode = 0
    while curr_episode < 400:
        curr_episode += 1
        old_log_policies, actions, values, states, rewards, dones = [], [], [], [], [], []
        for _ in range(args.num_local_steps):
            states.append(curr_states)
            # 执行预测
            logits, value = model(curr_states)
            # 计算每个动作的概率值
            policy = F.softmax(logits)
            # 根据每个标签的概率随机生成符合概率的标签
            old_m = Categorical(policy)
            action = old_m.sample([1]).squeeze()
            # 记录预测数据
            actions.append(action)
            values.append(value.squeeze())
            # 计算类别的概率的对数
            old_log_policy = old_m.log_prob(paddle.unsqueeze(action, axis=1))
            old_log_policy = paddle.squeeze(old_log_policy)
            old_log_policies.append(old_log_policy)
            # 向各个进程游戏发送动作
            [agent_conn.send(("step", int(act[0]))) for agent_conn, act in zip(envs.agent_conns, action)]
            # 将多进程的游戏数据打包
            state, reward, done, info = zip(*[agent_conn.recv() for agent_conn in envs.agent_conns])
            # 进行数据转换
            state = paddle.to_tensor(np.concatenate(state, 0), dtype='float32')
            # 转换为tensor数据
            reward = paddle.to_tensor(reward, dtype='float32')
            done = paddle.to_tensor(done, dtype='float32')
            # 记录预测数据
            rewards.append(reward)
            dones.append(done)
            curr_states = state
        # 根据上面最后的图像预测
        _, next_value, = model(curr_states)
        next_value = next_value.squeeze()
        old_log_policies = paddle.concat(old_log_policies).detach().squeeze()
        actions = paddle.concat(actions).squeeze()
        values = paddle.concat(values).squeeze().detach()
        states = paddle.concat(states).squeeze()

        gae = 0.0
        R = []
        for value, reward, done in list(zip(values, rewards, dones))[::-1]:
            gae = gae * args.gamma * args.tau
            gae = gae + reward + args.gamma * next_value.detach() * (1.0 - done) - value.detach()
            next_value = value
            R.append(gae + value)
        R = R[::-1]
        R = paddle.concat(R).detach()
        advantages = R - values
        for i in range(args.num_epochs):
            indice = paddle.randperm(args.num_local_steps * args.num_processes)
            for j in range(args.batch_size):
                batch_indices = indice[
                                int(j * (args.num_local_steps * args.num_processes / args.batch_size)): int((j + 1) * (
                                        args.num_local_steps * args.num_processes / args.batch_size))]
                # 根据拿到的图像执行预测
                logits, value = model(paddle.gather(states, batch_indices))
                # 计算每个动作的概率值
                new_policy = F.softmax(logits)
                # 计算类别的概率的对数
                new_m = Categorical(new_policy)
                new_log_policy = new_m.log_prob(paddle.unsqueeze(paddle.gather(actions, batch_indices), axis=1))
                new_log_policy = paddle.squeeze(new_log_policy)
                # 计算actor损失
                ratio = paddle.exp(new_log_policy - paddle.gather(old_log_policies, batch_indices))
                advantage = paddle.gather(advantages, batch_indices)
                actor_loss = paddle.clip(ratio, 1.0 - args.epsilon, 1.0 + args.epsilon) * advantage
                actor_loss = paddle.concat([paddle.unsqueeze(ratio * advantage, axis=0), paddle.unsqueeze(actor_loss, axis=0)])
                actor_loss = -paddle.mean(paddle.min(actor_loss, axis=0))
                # 计算critic损失
                critic_loss = F.smooth_l1_loss(paddle.gather(R, batch_indices), value.squeeze())
                entropy_loss = paddle.mean(new_m.entropy())
                # 计算全部损失
                total_loss = actor_loss + critic_loss - args.beta * entropy_loss
                # 计算梯度
                total_loss.backward()
                optimizer.step()
                optimizer.clear_grad()
            paddle.save(model.state_dict(), "{}/model_{}_{}.pdparams".format(args.saved_path, args.world, args.stage))
        print("Episode: {}. Total loss: {:.4f}".format(curr_episode, total_loss.numpy()[0]))
        if os.path.exists("{}/model_{}_{}_finish.pdparams".format(args.saved_path, args.world, args.stage)):
            process.kill()
            envs.close()
            print('顺利通关，world=%d, stage=%d' % (args.world, args.stage))
            break
    process.kill()
    envs.close()

if __name__ == "__main__":
    args = get_args()
    print_arguments(args)
    train(args)
    print('训练结束\n\n')


import numpy as np
import random
from time import time, sleep
import h5py
import torch
import torch.nn as nn
import torch.optim as optimizer
import glob
import os
#from scipy.stats import rankdata
from lstm import Model, initialize
from Optim import ScheduledOptim

# import _pickle as cPickle

# np.set_printoptions(threshold=np.nan)

def start(config):
    model = Model(config)
    model = model.to(config.device)

    #optim = optimizer.SGD(model.parameters(), lr=2e-4, momentum=0.9, weight_decay=config.c)
    #lr_scheduler = torch.optim.lr_scheduler.StepLR(optim, step_size=200, gamma=0.1)  # 20M iters
    optim = ScheduledOptim(
        optimizer.Adam(
            filter(lambda p: p.requires_grad, model.parameters()), lr=config.lr,
            betas=(0.9, 0.98), eps=1e-09),
        config.hidden_dim, 2000)

    list_of_files = glob.glob(config.model_path + '/*')
    latest_file = None
    if list_of_files:
        latest_file = max(list_of_files, key=os.path.getctime)
    model_ckpt = latest_file
    # model_ckpt = config.model_path + '/model-454.pth'
    print(model_ckpt)
    if model_ckpt:
        checkpoint = torch.load(model_ckpt)
        model.load_state_dict(checkpoint['state_dict'])
        optim.optimizer.load_state_dict(checkpoint['optimizer'])
        start_iter = model_ckpt.split('-')[-1].split('.')[0]
        start_iter = int(start_iter)
    else:
        model.apply(initialize)
        start_iter = 0

    count = 0

    for iter in range(start_iter, config.total_iterations):
        print('iteration: %s' % iter)
        #if (iter + 1) % 100000 == 0:
        #    lr_scheduler.step()
        start_time = time()
        optim.update_learning_rate(iter)

        # reads the randomly sampled (s,pi,z)'s from the buffer
        # ~ 0.1s
        # TODO: if error, set a lock
        # translate, _ = cPickle.load(open('save/vocab_cotra.pkl', 'rb'))

        with h5py.File("buffer", "r") as f:
            cur_row = int(f['/cur_row'][0])
            s_buffer = f['/s']
            pi_buffer = f['/pi']
            z_buffer = f['/z']
            s_tmp = []
            pi_tmp = []
            z_tmp = []
            df = cur_row - count

            '''x = np.bincount(s_buffer[:,1].astype(int)) / 500000
            for i in range(len(x)):
                if x[i] > 0.01:
                    print(i, x[i], translate[i])
            break'''

            if count == 0:
                count = cur_row
                t_inf = time()
            if count != 0 and df >= 1000:
                print('time required for 32 self-play games: ', 32 * (time() - t_inf) / df)
                t_inf = time()
                count = cur_row
            if cur_row >= config.buffer_size:
                r = np.sort(
                    np.random.choice(list(range(0, config.buffer_size)), (config.batch_size // 2), replace=False))
            else:
                r = np.sort(
                    np.random.choice(list(range(0, cur_row)), (config.batch_size // 2), replace=False))
            tmp = []
            # randomly sample rows 8 times for a dramatic speedup.
            num_segments = 8
            for i in range(num_segments):
                tmp.append(
                    r[(config.batch_size // 2) // num_segments * i:(config.batch_size // 2) // num_segments * (i + 1)])
            for i in range(num_segments):
                s_tmp.append(s_buffer[tmp[i], :config.max_length])
                pi_tmp.append(pi_buffer[tmp[i], :config.max_length, ...])
                z_tmp.append(z_buffer[tmp[i], ...])
        s = np.concatenate(s_tmp, 0)
        pi = np.concatenate(pi_tmp, 0)
        z = np.concatenate(z_tmp, 0)
        # print('io time: ',time() - start_time)

        # decompresses sampled pi's
        # takes about 0.005s
        new_pi = np.zeros(((config.batch_size // 2), config.max_length, config.vocab_size))
        for i in range((config.batch_size // 2)):
            for j in range(config.max_length):
                if pi[i, j, 0] == -1:  # meaning the terminal state; pi=0
                    new_pi[i, j, :] = 0
                elif pi[i, j, 0] == -2 or sum(pi[i, j, :]) == 0:  # meaning the padding; place -1 padding
                    new_pi[i, j, :] = -1
                else:
                    # Beware that np.bincount's bin is [0,1,...min_length-1]
                    new_pi[i, j, :] = np.bincount(pi[i, j, :].astype(int),
                                                  minlength=config.vocab_size) / config.simulation_num_per_move
        pi = new_pi

        # creating a mask for loss function and preparing a minibatch
        def generate_mask(array):
            new_array = np.zeros_like(array)
            for i in range(len(array)):
                for j in range(len(array[i])):
                    if j == len(array[i]) - 1:
                        new_array[i, :] = 1
                    elif array[i, j] == config.period_token:
                        new_array[i, :j + 1] = 1
                        break
                    elif array[i, j] == config.blank_token:
                        new_array[i, :j] = 1
                        break
            return new_array

        def pi_mask(array):
            array = array[:, 1:]
            array = np.pad(array, ((0, 0), (0, 1)), 'constant')
            return generate_mask(array)

        # pi_tmp isn't modified here, since the mask will be modified appropriately

        _, pi_mask = pi_mask(s)
        z_mask = generate_mask(s)
        z_batch = np.concatenate(
            [np.ones([(config.batch_size // 2), config.max_length]) * (-1),
             np.ones([(config.batch_size // 2), config.max_length])])
        def convert(x):
            return torch.tensor(x.astype(np.float32), device=config.device)

        t2 = time()

        # gradient update
        model.train()

        cache = []
        for i in range(config.depth // config.unit_depth):
            cache += [torch.zeros(config.batch_size, config.hidden_dim,device=config.device),
                       torch.zeros(config.batch_size, config.hidden_dim,device=config.device)]
        s_batch = convert(np.array(s)).long()
        policy, v, cache = model(s_batch, tuple(cache))

        def loss_policy(y_true, y_pred):
            return torch.sum(-y_true * torch.log(y_pred + 1.0e-8), 2)

        def loss_value(y_true, y_pred):
            return (y_true - y_pred) ** 2

        pi_mask = convert(pi_mask)
        z_mask = convert(z_mask)
        z = convert(z)
        pi = convert(pi)
        loss = torch.mean(torch.sum(loss_policy(pi, policy) * pi_mask +
                                    loss_value(z, v) * z_mask
                                    , 1) / torch.sum(z_mask, 1))
        loss.backward()
        gn = nn.utils.clip_grad_norm(model.parameters(), config.clip)
        print(gn)
        optim.step()
        optim.zero_grad()
        print("grad update: %s seconds" % (time() - t2))
        print("iteration: %s seconds" % (time() - start_time))

        checkpoint = {'state_dict': model.state_dict(),
                      'optimizer': optim.optimizer.state_dict()}
        sleep(config.training_sleep_time)
        torch.save(checkpoint, config.model_path + '/model' + '-' + str(iter + 1) + '.pth')


# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.

# custom service file

# model_handler.py

"""
ModelHandler defines a base model handler.
"""
import logging
import data_transformer
import keras
import sys
import numpy as np
import defs
import mxnet as mx

class ModelHandler(object):
    """
    A base Model handler implementation.
    """

    def __init__(self):
        self.error = None
        self._context = None
        self._batch_size = 0
        self.initialized = False
        self.mod = None

    def initialize(self, context):
        """
        Initialize model. This will be called during model loading time
        :param context: Initial context contains model server system properties.
        :return:
        """
        self._context = context
        self._batch_size = context.system_properties["batch_size"]
        self.initialized = True

        sym, arg_params, aux_params = mx.model.load_checkpoint(prefix='./prog', epoch=0)
        self.mod = mx.mod.Module(symbol=sym,
                            data_names=['/dropout_1_input1'],
                            context=mx.cpu(),
                            label_names=None)
        self.mod.bind(for_training=False,
                 data_shapes=[('/dropout_1_input1', (1, 2048, 70), 'float32', 'NTC')],
                 label_shapes=self.mod._label_shapes)

        self.mod.set_params(arg_params, aux_params)

    def preprocess(self, batch):
        """
        Transform raw input into model input data.
        :param batch: list of raw requests, should match batch size
        :return: list of preprocessed model input data
        """
        assert self._batch_size == len(batch), "Invalid input batch size: {}".format(len(batch))
        #with open('tmp_file','wb') as f:
        #     f.write(batch[0].get('body'))
        #return mx.nd.array(data_transformer.file_to_vec('tmp_file', file_vector_size=defs.file_chars_trunc_limit))
        return mx.nd.array(data_transformer.file_to_vec(batch[0].get('body'), file_vector_size=defs.file_chars_trunc_limit))

    def inference(self, model_input):
        """
        Internal inference methods
        :param model_input: transformed model input data
        :return: list of inference output in NDArray
        """
        return self.mod.predict(model_input)

    def postprocess(self, inference_output):
        """
        Return predict result in batch.
        :param inference_output: list of inference output
        :return: list of predict results
        """
        y = inference_output
        results = []
        for i in range(0, len(defs.langs)):
            results.append("{} - {}:     {}%".format(' ' if (y[0][i] < 0.5) else '*', defs.langs[i],
                                                     (100 * y[0][i])).strip('<NDArray 1 @cpu(0)>%'))
        return [results]

    def handle(self, data, context):
        """
        Custom service entry point function.
        :param data: list of objects, raw input from request
        :param context: model server context
        :return: list of outputs to be send back to client
        """

        try:
            data = self.preprocess(data)
            data = self.inference(data)
            data = self.postprocess(data)
            print("after", data)
            return data
        except Exception as e:
            logging.error(e, exc_info=True)
            request_processor = context.request_processor
            request_processor.report_status(500, "Unknown inference error")
            return [str(e)] * self._batch_size


"""
  Similarity Database Module.
  Classes:
    - Database

  Author: @captain-pool
"""
import os

import faiss
import numpy as np
import _pickle as pickle

class Database:
  """
    Database for storing Vectors and searching them by
    similarity.
  """
  def __init__(self, db_path, vector_dim):
    """
      Creates Database Instance.
      Args:
        db_path (str): Path to database storage folder
        vector_dim (int): Dimension of the vectors
    """
    name = os.path.basename(db_path)
    path = os.path.normpath(db_path)
    if not os.path.exists(path) or not os.path.isdir(path):
      os.makedirs(path)
    self._index_file = os.path.join(path, "%s.index" % name)
    self._payload_path = os.path.join(path, "%s.payload" % name)
    self._inv_payload_path = os.path.join(path, "%s.invpayload" % name)
    self._vector_dim = vector_dim

  def __repr__(self):
    if hasattr(self, "_payload"):
      result = []
      result.append("Index \t| Path \t| Vector")
      result.append("-" * (len("Index t| Path | Vector") + 2*8))
      for idx, data in enumerate(self._payload):
        result.append(f"{idx} \t| {data} \t| <float32 vector representation>")
      return "\n".join(result)
    return "Datbase not yet opened"

  def open(self):
    """
      Opens the database for reading and writing
    """
    if os.path.exists(self._index_file) and os.path.exists(self._payload_path):
      self._index = faiss.read_index(self._index_file)
      with open(self._payload_path, "rb") as f:
        self._payload = np.load(f)
      with open(self._inv_payload_path, "rb") as f:
        self._inv_payload = pickle.load(f)
      assert self._index.ntotal == len(self._payload),\
             "Number of Rows doesn't match"
      return
    print("No database found. Initializing a new one")
    self._index = faiss.IndexFlatL2(self._vector_dim)
    self._payload = np.asarray([], dtype=str)
    self._inv_payload = dict()

  def nearest(self, vector, num_closest=1):
    """
      Searches for the most similar items and returns them.
      Args:
        vector: a `np.float32` context vector of shape <= 2
        num_closest (default: 1): a `np.int32` variable
                                  to denote the number of
                                  closest matches to return
      Returns:
        A list of strings containing the similar items
    """
    if len(vector.shape) < 2:
      vector = vector[np.newaxis, :]
    _, index = self._index.search(vector, num_closest)
    payload_paths = self._payload[tuple(index)]
    return payload_paths.tolist()

  def insert(self, string, vector):
    """
      Inserts new item-vector pair to the database
      Args:
        string (str): The string item to store
        vector: a `np.float32` context vector for
                storing with the key
      Returns:
        `True` if insertion was successful `False` if
        insertion fails.
    """
    if not string in self._payload:
      if len(vector.shape) < 2:
        vector = vector[np.newaxis, :]
      self._index.add(vector)
      self._payload = np.append(self._payload, string)
      self._inv_payload[string] = len(self._payload) - 1
      return True
    return False

  def search_vector(self, key):
    """
      Inverse Search for searching vectors for a given key.
      Args:
        key (str): key to be searched
      Returns:
        A `np.float32` context vector associated with the key
    """
    index = self._inv_payload.get(key, None)
    if index is not None:
      return self._index.reconstruct(index)
    return np.zeros(self._vector_dim, dtype=np.float32)

  def remove(self, index):
    """
      Removes items at a given index / indices.
      Args:
        index (int / list(int)): index / indices of the items to be removed
      Returns:
        `True` if the deletion was successful, `False` if not.
    """
    if self._payload.size:
      index = np.asarray(index)
      if index.ndim < 1:
        index = index[np.newaxis, :]
      keys = self._payload[index]
      self._payload = np.delete(self._payload, index)
      self._index.remove_ids(index)
      for key in keys.tolist():
        self._inv_payload.pop(key)
      return True
    return False
  def remove_by_key(self, key):
    """
      Removes item by a given key
      Args:
        key (str): key to be removed
      Returns:
        `True` if deletion was successful else returns `False`
    """
    index = self._inv_payload.get(key, None)
    if index is not None:
      return self.remove(index)
    return False

  def write(self):
    """
      Commits the Changes to disk
    """
    faiss.write_index(self._index, self._index_file)
    with open(self._payload_path, "wb") as f:
      np.save(f, self._payload)
    with open(self._inv_payload_path, "wb") as f:
      pickle.dump(self._inv_payload, f)


"""Module defining the skip-thoughts model."""

import re
import time

import numpy as np
import tensorflow as tf
from tensorflow.contrib import seq2seq

class SkipThoughts:
  """Skip-thoughts model.

  Instantiating this class builds the computational graph Note that this model
  expects input sequences with the following reserved special token ids:
    0: padding token,
    1: out-of-vocabulary token,
    2: start-of-string token,
    3: end-of-string token.

  Input sequences are expected to already be padded and have the end-of-string
  token added (necessary for labels, optional for inputs; regard it as a
  hyperparameter to the model). The start-of-string token is added
  automatically as part of the computational graph during training."""

  def __init__(self, w2v_model, train=None, vocabulary_size=20000,
    batch_size=16, output_size=512, max_sequence_length=40, learning_rate=1e-3,
    max_grad_norm=10., concat=False, optimizer=None, softmax_samples=0,
    train_special_embeddings=False, train_word_embeddings=False,
    time_major=True, cuda=False):
    """Build the computational graph.

    Args:
      w2v_model: a word2vec model instance.

    Keyword args:
      train: either None (default), or `iterator.get_next()` where `iterator`
             is an instance of `tf.data.Iterator` that yields 3-tuples in the
             order bw_label, input, fw_label.

      TODO: complete documentation
    """

    # Internally used attributes
    self._w2v_model = w2v_model
    self._vocabulary_size = vocabulary_size
    self._batch_size = batch_size
    self._output_size = output_size
    self._max_sequence_length = max_sequence_length
    self._max_grad_norm = max_grad_norm
    self._concat = concat
    self._softmax_samples = softmax_samples
    self._time_major = time_major
    self._cuda = cuda
    self._embedding_size = w2v_model.vector_size

    self.learning_rate = tf.get_variable(
      "learning_rate", shape=[], trainable=False,
      initializer=tf.initializers.constant(learning_rate))

    self.global_step = tf.get_variable(
      "global_step", shape=[], trainable=False,
      initializer=tf.initializers.zeros())

    # Embedding matrices. The special embeddings are initialized with a mean 0
    # and variance 1 random uniform distribution.
    special_embeddings = tf.get_variable(
      "special_embeddings", shape=[4, self._embedding_size],
      initializer=tf.initializers.random_uniform(-np.sqrt(3), np.sqrt(3)),
      trainable=train_special_embeddings)

    word_embeddings = tf.get_variable(
      "word_embeddings", shape=[vocabulary_size, self._embedding_size],
      initializer=tf.initializers.constant(w2v_model.syn0[:vocabulary_size]),
      trainable=train_word_embeddings)

    self._embeddings = tf.concat([special_embeddings, word_embeddings], 0)

    # Softmax layer
    self._output_layer = tf.layers.Dense(vocabulary_size, name="output_layer")
    # Call this to be able to obtain the layer's weights at any given moment.
    self._output_layer.build(output_size)

    # Training
    if train is not None:

      # Unpack iterator ops
      bw_labels, train_inputs, fw_labels = tf.unstack(train, num=3)

      # Encoder
      self._get_thought = self._thought(train_inputs)

      # Forward and backward decoders
      fw_logits = self._decoder(self._get_thought, fw_labels)
      bw_logits = self._decoder(self._get_thought, bw_labels)

      # Loss
      self.loss = self._loss(fw_logits, fw_labels) + \
                  self._loss(bw_logits, bw_labels)

      # Optimizer with gradient clipping
      tvars = tf.trainable_variables()
      grads, _ = tf.clip_by_global_norm(
        tf.gradients(self.loss, tvars), self._max_grad_norm)
      if optimizer is None:
        optimizer = tf.train.AdamOptimizer
      self.train_op = optimizer(self.learning_rate).apply_gradients(
        zip(grads, tvars), global_step=self.global_step)

    # Inference
    else:
      shape = [None, max_sequence_length]
      if time_major:
        shape = [max_sequence_length, None]
      self._inputs = tf.placeholder(
        tf.int64, shape=shape, name="inference_inputs")
      self._get_thought = self._thought(self._inputs)

  def _get_embeddings(self, query):
    """Internally used for embedding lookup."""
    return tf.nn.embedding_lookup(self._embeddings, query)

  def _thought(self, inputs):
    """Internally used to run the model agnostic to input feeding method."""
    encoder_in = self._get_embeddings(inputs)

    if self._cuda:
      rnn = tf.contrib.cudnn_rnn.CudnnGRU(
        1, self._output_size, direction='bidirectional')
      rnn_output = tf.unstack(rnn(encoder_in)[1][0])

    else:
      fw_cell = tf.contrib.cudnn_rnn.CudnnCompatibleGRUCell(self._output_size)
      bw_cell = tf.contrib.cudnn_rnn.CudnnCompatibleGRUCell(self._output_size)
      sequence_length = tf.reduce_sum(
        tf.sign(inputs), reduction_indices=int(not self._time_major))
      rnn_output = tf.nn.bidirectional_dynamic_rnn(
        fw_cell, bw_cell, encoder_in, sequence_length=sequence_length,
        dtype=tf.float32, time_major=self._time_major)[1]

    if self._concat:
      return tf.concat(rnn_output, 0)
    return sum(rnn_output)

  def _decoder(self, thought, labels):
    """Internally used to build a decoder RNN."""

    # Labels are shifted to the right by adding a start-of-string token.
    if self._time_major:
      sos_tokens = tf.constant([[2] * self._batch_size], dtype=tf.int64)
      shifted_labels = tf.concat([sos_tokens, labels[:-1]], 0)
    else:
      sos_tokens = tf.constant([[2]] * self._batch_size, dtype=tf.int64)
      shifted_labels = tf.concat([sos_tokens, labels[:,:-1]], 1)

    decoder_in = self._get_embeddings(shifted_labels)

    if self._cuda:
      decoder_out = tf.contrib.cudnn_rnn.CudnnGRU(
        1, self._output_size, direction='unidirectional')(decoder_in)[0]

    else:
      rnn_cell = tf.contrib.cudnn_rnn.CudnnCompatibleGRUCell(self._output_size)
      max_seq_lengths = tf.constant(
        [self._max_sequence_length] * self._batch_size)
      helper = seq2seq.TrainingHelper(
        decoder_in, max_seq_lengths, time_major=self._time_major)
      decoder = seq2seq.BasicDecoder(rnn_cell, helper, thought)
      decoder_out = seq2seq.dynamic_decode(
        decoder, output_time_major=self._time_major)[0].rnn_output

    return decoder_out

  def _loss(self, rnn_outputs, labels):
    """Get a properly masked loss for the given logits and labels."""
    if not self._softmax_samples:
      mask = tf.cast(tf.sign(labels), tf.float32)
      logits = self._output_layer(rnn_outputs)
      return seq2seq.sequence_loss(logits, labels, mask)

    # Sampled softmax for improved performance.
    rnn_outputs = tf.reshape(rnn_outputs, [-1, self._output_size])
    labels = tf.reshape(labels, [-1])
    mask = tf.cast(tf.sign(labels), tf.float32)

    weights, biases = self._output_layer.trainable_weights
    losses = tf.nn.sampled_softmax_loss(
      tf.transpose(weights), biases, tf.expand_dims(labels, axis=1),
      rnn_outputs, self._softmax_samples, self._vocabulary_size)

    return tf.reduce_mean(mask * losses)  # Hadamard product

  def _sequence(self, sentence, clean=True, eos_token=True):
    """Interally used to convert strings to integer sequences."""

    # First the sentences are cleaned to reduce out-of-vocabulary cases.
    if clean:
      sentence = re.sub(r"[^A-Za-z0-9 ']", " ", sentence)
      sentence = re.sub(r"[ ]+", " ", sentence).strip()

    words = sentence.split()
    seq = []

    # Compensate for start-of-string and end-of-string tokens.
    for word in words[:self._max_sequence_length - 2]:
      id_to_append = 1  # unknown word (id: 1)
      if word in self._w2v_model:
        # Add 4 to compensate for the special seq2seq tokens.
        word_id = self._w2v_model.vocab[word].index + 4
        if word_id < self._vocabulary_size:
          id_to_append = word_id
      seq.append(id_to_append)
    if eos_token:
      seq.append(3)  # end-of-string (id: 3)
    while len(seq) < self._max_sequence_length:
      seq.append(0)  # padding (id: 0)
    return seq

  def restore(self, save_dir, verbose=True):
    """Attempt to restore the model's weights from the given directory.

    Returns True or False depending on success."""
    sess = tf.get_default_session()
    saver = tf.train.Saver(max_to_keep=1)
    ckpt = tf.train.get_checkpoint_state(save_dir)
    if not ckpt:
      if verbose:
        print("Failed to restore model at {}.".format(save_dir))
      return False
    if verbose:
      print("Restoring model...")
    start = time.time()
    saver.restore(sess, ckpt.model_checkpoint_path)
    duration = time.time() - start
    if verbose:
      print(
        "Restored model at step", sess.run(self.global_step),
        "({:0.4f}s).".format(duration))
    return True

  def encode(self, sentences):
    """Run the encoder op on a list of sentences (sentence strings)."""
    sess = tf.get_default_session()
    sequences = np.array(list(map(self._sequence, sentences)))
    if self._time_major:
      sequences = sequences.T
    return sess.run(self._get_thought, feed_dict={self._inputs: sequences})


import maml_rl.envs
import gym
import numpy as np
import torch

from maml_rl.metalearner import MetaLearner
from maml_rl.policies import CategoricalMLPPolicy, NormalMLPPolicy
from maml_rl.baseline import LinearFeatureBaseline
from maml_rl.sampler import BatchSampler

from tensorboardX import SummaryWriter

def total_rewards(episodes_rewards, aggregation=torch.mean):

    rewards = torch.mean(torch.stack([aggregation(torch.sum(rewards, dim=0))
        for rewards in episodes_rewards], dim=0))
    return rewards.item()

def main(args):
    continuous_actions = (args.env_name in ['AntVelEnv-v1', 'AntDirEnv-v1',
        'HalfCheetahVelEnv-v1', 'HalfCheetahDirEnv-v1', '2DNavigation-v0'])

    save_folder = os.path.join('tmp', args.output_folder)
    if not os.path.exists(save_folder):
        os.makedirs(save_folder)

    sampler = BatchSampler(args.env_name, batch_size=args.fast_batch_size,
        num_workers=args.num_workers)
    if continuous_actions:
        policy = NormalMLPPolicy(
            int(np.prod(sampler.envs.observation_space.shape)),
            int(np.prod(sampler.envs.action_space.shape)),
            hidden_sizes=(args.hidden_size,) * args.num_layers)
    else:
        policy = CategoricalMLPPolicy(
            int(np.prod(sampler.envs.observation_space.shape)),
            sampler.envs.action_space.n,
            hidden_sizes=(args.hidden_size,) * args.num_layers)
    baseline = LinearFeatureBaseline(
        int(np.prod(sampler.envs.observation_space.shape)))

    # Load model
    with open(args.model, 'rb') as f:
        state_dict = torch.load(f)
        policy.load_state_dict(state_dict)

    metalearner = MetaLearner(sampler, policy, baseline, gamma=args.gamma,
        fast_lr=args.fast_lr, tau=args.tau, device=args.device)

    args.meta_batch_size = 81
    # velocities = np.linspace(-1., 3., num=args.meta_batch_size)
    # tasks = [{'velocity': velocity} for velocity in velocities]
    tasks = [{'direction': direction} for direction in [-1, 1]]

    for batch in range(args.num_batches):
        episodes = metalearner.sample(tasks)
        train_returns = [ep.rewards.sum(0).cpu().numpy() for ep, _ in episodes]
        valid_returns = [ep.rewards.sum(0).cpu().numpy() for _, ep in episodes]

        with open(os.path.join(save_folder, '{0}.npz'.format(batch)), 'wb') as f:
            np.savez(f, train=train_returns, valid=valid_returns)
        print('Batch {0}'.format(batch))

if __name__ == '__main__':
    import argparse
    import os
    import multiprocessing as mp

    parser = argparse.ArgumentParser(description='MAML')

    # General
    parser.add_argument('--env-name', type=str,
        help='name of the environment')
    parser.add_argument('--gamma', type=float, default=0.95,
        help='value of the discount factor gamma')
    parser.add_argument('--tau', type=float, default=1.0,
        help='value of the discount factor for GAE')
    parser.add_argument('--model', type=str,
        help='path to the model checkpoint')

    # Policy network (relu activation function)
    parser.add_argument('--hidden-size', type=int, default=100,
        help='number of hidden units per layer')
    parser.add_argument('--num-layers', type=int, default=2,
        help='number of hidden layers')

    # Task-specific
    parser.add_argument('--fast-batch-size', type=int, default=20,
        help='batch size for each individual task')
    parser.add_argument('--fast-lr', type=float, default=0.5,
        help='learning rate for the 1-step gradient update of MAML')

    # Evaluation
    parser.add_argument('--num-batches', type=int, default=200,
        help='number of batches')

    # Miscellaneous
    parser.add_argument('--output-folder', type=str, default='maml',
        help='name of the output folder')
    parser.add_argument('--num-workers', type=int, default=mp.cpu_count() - 1,
        help='number of workers for trajectories sampling')
    parser.add_argument('--device', type=str, default='cpu',
        help='set the device (cpu or cuda)')

    args = parser.parse_args()

    # Device
    args.device = torch.device(args.device
        if torch.cuda.is_available() else 'cpu')
    # Slurm
    if 'SLURM_JOB_ID' in os.environ:
        args.output_folder += '-{0}'.format(os.environ['SLURM_JOB_ID'])

    main(args)


import os
from tensorboard_logger import configure, log_value
import torch
import torch.autograd as autograd
from torch.autograd import Variable
import torch.utils.data as torchdata
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
import tqdm
import utils
import torch.optim as optim
import pdb
from data_loader import OpenI
from PIL import Image
from xray_utils import transform_xray, get_model
import cv2
import numpy as np
import torch.backends.cudnn as cudnn
cudnn.benchmark = True
from torch.optim.lr_scheduler import StepLR

import argparse
parser = argparse.ArgumentParser(description='Radiograph_Pretraining')
parser.add_argument('--lr', type=float, default=1e-4, help='learning rate')
parser.add_argument('--wd', type=float, default=0.0, help='weight decay')
parser.add_argument('--cv_dir', default='cv/', help='checkpoint directory (models and logs are saved here)')
parser.add_argument('--batch_size', type=int, default=32, help='batch size')
parser.add_argument('--epoch_step', type=int, default=10000, help='epochs after which lr is decayed')
parser.add_argument('--max_epochs', type=int, default=10000, help='total epochs to run')
parser.add_argument('--parallel', action ='store_true', default=False, help='use multiple GPUs for training')
args = parser.parse_args()

if not os.path.exists(args.cv_dir):
    os.system('mkdir ' + args.cv_dir)
utils.save_args(__file__, args)

def train(epoch, counter):

    rnet.train()
    losses = []
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    for batch_idx, (inputs, targets) in tqdm.tqdm(enumerate(trainloader), total=len(trainloader)):

        inputs, targets = inputs.to(device), targets.to(device)
        preds = rnet.forward(inputs)

        loss = criterion(preds, targets, torch.ones((inputs.size(0))).cuda())
        if batch_idx % 50 == 0:
            log_value('train_loss_iteration', loss, counter)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        losses.append(loss.cpu())
        counter += 1

    loss = torch.stack(losses).mean()
    log_str = 'E: %d | L: %.3f'%(epoch, loss)
    print(log_str)

    log_value('train_loss_epoch', loss, epoch)

def test(epoch):

    rnet.eval()
    losses = []
    for batch_idx, (inputs, targets) in tqdm.tqdm(enumerate(devloader), total=len(devloader)):
        with torch.no_grad():
            inputs, targets = Variable(inputs), Variable(targets).cuda()
            if not args.parallel:
                inputs = inputs.cuda()

            v_inputs = Variable(inputs.data)

            preds = rnet.forward(v_inputs)

            loss = criterion(preds, targets, torch.ones((inputs.size(0))).cuda())

            losses.append(loss.cpu())

    loss = torch.stack(losses).mean()
    log_str = 'TS: %d | L: %.3f'%(epoch, loss)
    print(log_str)

    log_value('test_loss', loss, epoch)

    # save the model parameters
    rnet_state_dict = rnet.module.state_dict() if args.parallel else rnet.state_dict()

    state = {
      'state_dict': rnet_state_dict,
      'epoch': epoch,
    }
    torch.save(state, args.cv_dir+'/ckpt_E_%d'%(epoch))
#--------------------------------------------------------------------------------------------------------#
train_set = OpenI('train', 'data', transform_xray())
dev_set = OpenI('dev', 'data', transform_xray(), doc2vec_file="report2vec.model")
test_set = OpenI('test', 'data', transform_xray(), doc2vec_file="report2vec.model")
trainloader = torchdata.DataLoader(train_set, batch_size=args.batch_size, shuffle=True, num_workers=16)
devloader = torchdata.DataLoader(dev_set, batch_size=args.batch_size, shuffle=False, num_workers=4)
testloader = torchdata.DataLoader(test_set, batch_size=args.batch_size, shuffle=False, num_workers=4)

rnet = get_model(50)
if args.parallel:
    rnet = nn.DataParallel(rnet)
rnet.cuda()

start_epoch = 0
counter = 0
criterion = nn.CosineEmbeddingLoss()
optimizer = optim.Adam(rnet.parameters(), lr=args.lr)
scheduler = StepLR(optimizer, 1, gamma=args.wd, last_epoch=-1)
configure(args.cv_dir+'/log', flush_secs=5)
for epoch in range(start_epoch, start_epoch+args.max_epochs+1):
    train(epoch, counter)
    if epoch % 1 == 0:
        torch.cuda.empty_cache()
        test(epoch)
    scheduler.step()


#!/usr/bin/env python
#-*- coding=utf-8 -*-

from __future__ import division
from __future__ import print_function

import os
import math
import random
import colorsys
try:
    import ConfigParser as configparser
except ImportError:
    import configparser
import cv2
import numpy as np
import tensorflow as tf
# from tensorflow.python import debug as tf_debug

from utils.utils import make_unique_section_file
from utils.utils import get_padding_num
from utils.utils import print_conv_layer_params
from utils.utils import print_pooling_layer_params
from utils.utils import print_dropout_layer_params
from utils.utils import print_upsample_layer_params
from utils.utils import print_route_params
from utils.utils import print_fc_layer_params
from utils.utils import print_shortcut_params
from utils.utils import print_v3_detection_layer_params
from utils.utils import timer_wrapper
from yolo_utils import *
# from yolo_utils import select_boxes_by_classes_prob
# from yolo_utils import non_max_suppression
# from yolo_utils import read_classes_names

_LEAKY_RATIO = .1
_BATCH_NORM_DECAY = .9
_BATCH_NORM_EPSILON = 1e-05
_WEIGHT_HEADER_LEN = 5

import sys

class Yolov3(object):
    def __init__(self, flags):
        self.cfg_parser = configparser.ConfigParser()
        self.sections = None
        self.params = {}
        self.configs = {}
        # layer important values: input, output
        self.vals = {}
        self.verbose = True
        self.flags = flags

        self.classes_names = read_classes_names(self.flags.names)

        # gpu_options = tf.GPUOptions(allow_growth=True)
        # self.sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
        self.sess = tf.Session()

        # Parse cfg file
        self._parse_config(self.flags.cfg)

        # Construct network and load weight
        self.input, self.encoding, self.processed_image= self._build_network()

        # Post process encoding
        scores, boxes, classes = self._build_detector(self.encoding)
        # print(scores)
        # print(boxes)
        # print(classes)

        # Define detect function
        self.detect_func = lambda image: self.sess.run(
            [scores, boxes, classes], feed_dict={self.input: image})

        # Get summary writer
        if self.flags.summary:
            writer = tf.summary.FileWriter(self.flags.summary, self.sess.graph)
        # self.sess = tf_debug.LocalCLIDebugWrapperSession(self.sess)
    def __del__(self):
        del self.cfg_parser
        del self.sections
        del self.params
        del self.configs
        del self.flags
        self.sess.close()
    def _parse_config(self, cfg_path):
        if self.verbose:
            print("\nParsing config file {}...\n-----------------------------------------".format(cfg_path))
        if not os.path.exists(cfg_path):
            raise IOError("{} doesn't exists.".format(cfg_path))
        # Get cfg file with unique section name
        uni_cfg_path, self.sections = make_unique_section_file(cfg_path)
        # Read cfg file
        self.cfg_parser.read(uni_cfg_path)

        # Get input image info
        try:
            # self.img_height = self.cfg_parser.getint(self.sections[0], "height")
            # self.img_width = self.cfg_parser.getint(self.sections[0], "width")

            # yolov3 doesn't use fc layer, different size of input can be feeded.
            self.img_size = self.flags.img_size
            self.img_channels = self.cfg_parser.getint(self.sections[0], "channels")
        except Exception as e:
            raise ValueError(e)

        # Get output feature map info
        # try:
        #     self.classes = self.cfg_parser.getint(self.sections[-1], "classes")
        #     self.box_nums = self.cfg_parser.getint(self.sections[-1], "num")
        #     self.use_softmax = self.cfg_parser.getboolean(self.sections[-1], 'softmax')
        # except Exception as e:
        #     raise ValueError(e)

        for index, section in enumerate(self.sections[1:]):
            if section.startswith("convolutional"):
                activation = self.cfg_parser.get(section, 'activation')
                filters, size, stride, padding = map(
                    lambda x: self.cfg_parser.getint(section, x),
                    ['filters', 'size', 'stride', 'pad']
                )
                try:
                    batch_norm = self.cfg_parser.getint(section, 'batch_normalize')
                except:
                    batch_norm = 0
                self.configs[section] = {
                    'filters': filters, 'size': size, 'stride': stride, 'padding': padding,
                    'bn': batch_norm, 'activation': activation}

            if section.startswith("local"):
                size, stride, padding, filters = map(
                    lambda x: self.cfg_parser.getint(section, x),
                    ['size', 'stride', 'pad', 'filters']
                )
                activation = self.cfg_parser.get(section, 'activation')

                self.configs[section] = {
                    'filters': filters, 'size': size, 'stride': stride, 'padding': padding,
                    'activation': activation}

            if "pool" in section:
                size, stride = map(
                    lambda x: self.cfg_parser.getint(section, x),
                    ['size', 'stride'])
                if 'maxpool' in section:
                    pooling_type = 'max'
                else:
                    pooling_type = 'avg'

                self.configs[section] = {
                    'size': size, 'stride': stride, "type": pooling_type}

            if "dropout" in section:
                prob = self.cfg_parser.getfloat(section, 'probability')
                self.configs[section] = {
                    'prob': prob}

            if "connected" in section:
                n_out = self.cfg_parser.getint(section, 'output')
                activation = self.cfg_parser.get(section, 'activation')

                self.configs[section] = {
                    'out': n_out, 'activation': activation}

            if section.startswith('route'):
                from_layer = self.cfg_parser.get(section, 'layers')
                if ',' in from_layer:
                    from_layer = from_layer.strip().split(', ')
                    # from_layer = [int(val) for val in from_layer]
                    # from_layer = map(lambda x: x if x>0 else (index+x))
                    from_layer = [int(val) if int(val)>0 else (index+int(val)) for val in from_layer]
                else:
                    from_layer = int(from_layer) if int(from_layer) > 0 else (int(from_layer)+index)
                self.configs[section] = {'from_layer': from_layer}

            if section.startswith('shortcut'):
                from_layer = self.cfg_parser.getint(section, 'from')
                from_layer = from_layer if 0 < from_layer else from_layer+index

                activation = self.cfg_parser.get(section, 'activation')

                self.configs[section] = {'from_layer': from_layer, 'activation': activation}

            if section.startswith('upsample'):
                stride = self.cfg_parser.getint(section, 'stride')
                self.configs[section] = {'stride': stride}

            if section.startswith('yolo'):
                classes = self.cfg_parser.getint(section, 'classes')
                box_nums = self.cfg_parser.getint(section, 'num')

                masks = self.cfg_parser.get(section, 'mask').strip().split(',')
                masks = [int(mask) for mask in masks]

                anchors = self.cfg_parser.get(self.sections[-1], 'anchors').strip().split(",  ")
                anchors = [[float(val.split(',')[0]), float(val.split(',')[1])] for val in anchors]

                self.classes = classes

                self.configs[section] = {
                    'classes': classes, 'box_nums': len(masks),
                    'mask': masks, 'anchors': anchors}

            if self.verbose:
                print("{} - {}: {}".format(index, section, self.configs[section]))
    def _activation(self, inputs, activation):
        return activation_func(inputs, activation, leaky_ratio=_LEAKY_RATIO)
    def _create_bn_layer(
        self,
        inputs,
        momentum=0.9,
        eps=1e-5,
        is_training=False,
        name=None):
        '''
        Create batch normalization layer
        '''
        return create_bn_layer(
            inputs,
            momentum=momentum,
            eps=eps,
            is_training=is_training,
            name=name)
    def _create_convolution_layer(
        self,
        inputs,
        filters, f_h, f_w,
        stride,
        padding=None,
        batch_norm=1,
        activation='leaky',
        is_training=False,
        filter_initializer=tf.variance_scaling_initializer(),
        use_bias=False,
        bias_initializer=tf.variance_scaling_initializer(),
        name = None):
        '''
        Create a convolution layer.
        Arguments:
        Returns:
        '''
        output, param = create_convolution_layer(
            inputs,
            filters, f_h, f_w,
            stride,
            padding=padding,
            batch_norm=batch_norm,
            momentum=_BATCH_NORM_DECAY,
            eps=_BATCH_NORM_EPSILON,
            activation=activation,
            is_training=is_training,
            filter_initializer=filter_initializer,
            use_bias=use_bias,
            bias_initializer=bias_initializer,
            name=name
        )
        self.params[name] = param
        self.vals[name] = {"input": inputs, "output": output}

        if self.verbose:
            padding = 'SAME' if 1 == padding and 1 == stride else 'VALID'
            print_conv_layer_params(
                self.params[name]['weight_shape'], stride, padding, batch_norm, activation,
                inputs.shape.as_list(), output.shape.as_list(), name=name)
        return output
    def _create_pooling_layer(
        self,
        inputs,
        p_h, p_w,
        pooling_type,
        stride,
        padding="VALID",
        name=None):
        '''
        Pooling layer
        '''

        padding = 'SAME' if None == padding and 1 == stride else 'VALID'

        output = create_pooling_layer(
            inputs,
            p_h, p_w,
            pooling_type,
            stride,
            padding=padding,
            name=name)

        self.vals[name] = {"input": inputs, "output": output}

        if self.verbose:
            print_pooling_layer_params(
                [p_h, p_w], stride, padding, pooling_type,
                inputs.shape.as_list(), output.shape.as_list(), name=name)
        return output
    def _create_flatten_layer(self, inputs, transpose=[0, 3, 1, 2]):
        inputs = tf.transpose(inputs, transpose)
        output = create_flatten_layer(inputs, name="flatten")

        self.vals[name] = {"input": inputs, "output": output}

        return output
    def _create_fully_connectd_layer(
        self,
        inputs,
        n_out,
        activation='leaky',
        weight_initializer=tf.variance_scaling_initializer(),
        use_bias=True,
        bias_initializer=tf.variance_scaling_initializer(),
        name=None):
        '''
        Fully-Connected layer.
        '''
        inputs = self._create_flatten_layer(inputs)
        output, param = create_fully_connectd_layer(
            inputs,
            n_out,
            activation=activation,
            activation_fn=None,
            weight_initializer=weight_initializer,
            use_bias=use_bias,
            bias_initializer=bias_initializer,
            name=name)

        self.params[name] = param
        self.vals[name] = {"input": inputs, "output": output}

        if self.verbose:
            print_fc_layer_params(
                param['weight_shape'], activation,
                inputs.shape.as_list(), output.shape.as_list(), name=name)

        return output
    def _create_upsample_layer(self, inputs, config, name=None):
        try:
            stride = config['stride']
        except Exception as e:
            raise Exception(e)

        output = create_upsample_layer(inputs, stride, name=name)

        self.vals[name] = {'inputs': inputs, 'output': output}

        if self.verbose:
            print_upsample_layer_params(
                stride,
                inputs.shape.as_list(), output.shape.as_list(),
                name=name)

        return output
    def _create_route_layer(self, config, name=None):
        routes = config['from_layer']
        get_layer_name = lambda x: self.sections[1:][x]

        if isinstance(routes, int):
            layer_names = get_layer_name(routes)
            output = self.vals[layer_names]['output']
        elif isinstance(routes, list):
            layer_names = [get_layer_name(layer) for layer in routes]
            output = reduce(
                lambda x,y: tf.concat(
                    [self.vals[x]['output'], self.vals[y]['output']], axis=-1),
                layer_names)
        else:
            raise TypeError("Need from_layer of type int or list, got {}".format(type(routes)))

        if self.verbose:
            print_route_params(
                routes, layer_names,
                output.shape.as_list(), name=name)

        return output
    def _create_shortcut_layer(self, inputs, config, name=None):
        try:
            from_layer = config['from_layer']
            activation = config['activation']
        except Exception as e:
            raise KeyError(e)

        layer_name = self.sections[1:][from_layer]

        output = create_shortcut_layer(
            inputs,
            self.vals[layer_name]['output'],
            activation=activation,
            name=name)

        self.vals[name] = {'inputs': inputs, 'output': output}

        if self.verbose:
            print_shortcut_params(
                from_layer, activation,
                inputs.shape.as_list(), output.shape.as_list(),
                name=name)
        return output
    def _create_detection_layer(self, inputs, config, img_size=(448,448), name=None):
        # Get anchors by mask
        mask = config['mask']
        anchors = config['anchors']
        anchors = [m for i,m in enumerate(anchors) if i in mask]
        classes = config['classes']

        output = create_v3_detection_layer(inputs, classes, anchors, img_size=img_size, name=name)
        self.vals[name] = {'inputs': inputs, 'output': output}

        if self.verbose:
            print_v3_detection_layer_params(
                inputs.shape.as_list(), output.shape.as_list(),
                name=name)

        return output
    def _gather_detections(self, name='gather_detections'):
        detection_list = []
        with tf.name_scope(name):
            for section in self.sections[1:]:
                if section.startswith('yolo'):
                    detection_list.append(self.vals[section]['output'])
            if detection_list:
                if 1 == len(detection_list):
                    detections = detection_list[0]
                else:
                    detections = reduce(
                        lambda det1, det2: tf.concat([det1, det2], axis=1),
                        detection_list)
            else:
                detections = None

        return detections
    def _load_model(self, inputs):
        if self.verbose:
            print("\nConstructing network...\n-----------------------------------------")
        output = inputs

        # Exclude net layer for route index align
        # Create model by config file
        for index, section in enumerate(self.sections[1:]):
            if section.startswith("convolutional"):
                output = self._create_convolution_layer(
                    output,
                    self.configs[section]['filters'],
                    self.configs[section]['size'],
                    self.configs[section]['size'],
                    self.configs[section]['stride'],
                    self.configs[section]['padding'],
                    bool(self.configs[section]['bn']),
                    self.configs[section]['activation'],
                    use_bias=not self.configs[section]['bn'],
                    is_training=self.flags.train,
                    name=section)
                # print("output shape: {}".format(output.shape))
            if "pool" in section:
                output = self._create_pooling_layer(
                    output,
                    self.configs[section]['size'],
                    self.configs[section]['size'],
                    self.configs[section]['type'],
                    self.configs[section]['stride'],
                    padding=None,
                    name=section)
                # print("output shape: {}".format(output.shape))
            if section.startswith("dropout"):
                output = self._create_dropout_layer(
                    output,
                    self.configs[section]['prob'],
                    is_training=self.flags.train,
                    seed=None,
                    name=section)
                # print("output shape: {}".format(output.shape))
            if section.startswith("connected"):
                output = self._create_fully_connectd_layer(
                    output,
                    self.configs[section]['out'],
                    activation=self.configs[section]['activation'],
                    name=section)
                # print("output shape: {}".format(output.shape))
            if section.startswith("upsample"):
                output = self._create_upsample_layer(output, self.configs[section], name=section)
            if section.startswith('route'):
                output = self._create_route_layer(self.configs[section], name=section)
            if section.startswith('shortcut'):
                output = self._create_shortcut_layer(output, self.configs[section], name=section)
            if section.startswith('yolo'):
                _ = self._create_detection_layer(
                    output, self.configs[section],
                    img_size=(self.flags.img_size, self.flags.img_size),
                    name=section)
        # Gather output from different scale branch
        gathered = self._gather_detections()
        if gathered is not None:
            output = gathered

        return output
    def _load_conv_weight(self, section, config, ptr, weights):
        # shape of kernel
        f_h, f_w, prev_c, filters = self.params[section]['weight_shape']
        # kernel variable size
        num = f_h * f_w * prev_c * filters

        assign_ops = []
        with tf.variable_scope(section, reuse=True):
            if config['bn']:
                beta = tf.get_variable("batch_normalization/beta")
                # assign_ops.append(tf.assign(beta, weights[ptr:ptr + filters]))
                assign_ops.append(beta.assign(weights[ptr:ptr+filters]))
                ptr += filters

                gamma = tf.get_variable("batch_normalization/gamma")
                assign_ops.append(gamma.assign(weights[ptr:ptr + filters]))
                ptr += filters

                mean = tf.get_variable("batch_normalization/moving_mean")
                assign_ops.append(mean.assign(weights[ptr:ptr + filters]))
                ptr += filters

                var = tf.get_variable("batch_normalization/moving_variance")
                assign_ops.append(var.assign(weights[ptr:ptr + filters]))
                ptr += filters

                kernel = tf.get_variable("conv2d/kernel")
                # DaekNet weight shape [f, c, h, w], tensorflow [h, w, c, f]
                kernel_shape = self.params[section]['weight_shape']
                kernel_data = weights[ptr:ptr + num].reshape(
                    kernel_shape[3], kernel_shape[2], kernel_shape[0], kernel_shape[1])
                kernel_data = np.transpose(kernel_data, [2, 3, 1, 0])
                assign_ops.append(kernel.assign(kernel_data))

                ptr += num
            else:
                bias = tf.get_variable("conv2d/bias")
                assign_ops.append(bias.assign(weights[ptr:ptr + filters]))
                ptr += filters

                kernel = tf.get_variable("conv2d/kernel")
                kernel_shape = self.params[section]['weight_shape']
                kernel_data = weights[ptr:ptr + num].reshape(
                    kernel_shape[3], kernel_shape[2], kernel_shape[0], kernel_shape[1])
                kernel_data = np.transpose(kernel_data, [2, 3, 1, 0])
                assign_ops.append(kernel.assign(kernel_data))
                ptr += num

        return ptr, assign_ops
    def _load_local_conv_weight(self, section, config, ptr, weights):
        f_h, f_w, prev_c, filters = self.params[section]['weight_shape']
        _, o_h, o_w, o_c = self.params[section]['output_shape']

        # local conv locations
        n_locs = o_h * o_w
        # kernel size
        size = f_h * f_w * prev_c * filters * n_locs

        assign_ops = []
        with tf.variable_scope(section, reuse=True):
            # bias = tf.get_variable("locally_connected2d/bias")
            n_bias = o_h * o_w * o_c
            bias = tf.Variable("locally_connected2d/bias")
            assign_ops.append(bias.assign(weights[ptr:ptr + n_bias].tostring()))
            ptr += n_bias

            kernel_data = weights[ptr:ptr + size].reshape(
                [o_h*o_w, filters, prev_c, f_h, f_w])
            kernel_data = np.transpose(kernel_data, [0, 3, 4, 2, 1])

            # weight_data = [kernel_data.tostring(), np.zeros([o_h, o_w, filters]).tostring()]
            kernel = tf.Variable("locally_connected2d/kernel")
            assign_ops.append(kernel.assign(kernel_data.tostring()))
            ptr += size

        self.sess.run(assign_ops)
        return ptr, assign_ops
    def _load_fc_weight(self, section, config, ptr, weights):
        n_in, n_out = self.params[section]['weight_shape']

        assign_ops = []
        with tf.variable_scope(section, reuse=True):
            bias = tf.get_variable("fully_connected/biases")
            assign_ops.append(bias.assign(weights[ptr:ptr + n_out]))
            ptr += n_out

            weight = tf.get_variable("fully_connected/weights")
            weight_data = weights[ptr:ptr + n_out*n_in].reshape([n_out, n_in])
            weight_data = np.transpose(weight_data, [1, 0])

            assign_ops.append(weight.assign(weight_data))
            ptr += n_out * n_in

        self.sess.run(assign_ops)
        return ptr, assign_ops
    def _load_ckpt(self):
        pass
    def _load_pb(self):
        pass
    def _load_weight(self, header_len=4):
        if not os.path.exists(self.flags.weight):
            raise IOError("{} doesn't exist.".format(self.flags.weight))

        if self.verbose:
            print("\nLoading weights...\n-----------------------------------------")

        with open(self.flags.weight, 'rb') as f:
            # different from v1,v2, v3 header's length is 5
            self.header = np.fromfile(f, dtype=np.int32, count=header_len)
            self.seen = self.header[3]

            weights = np.fromfile(f, dtype=np.float32)
            ptr = 0
            assign_op_list = []

            # load weight doesn't run out of weight file, have no idea about remaining data.
            for section in self.sections:
                prev_ptr = ptr
                if section.startswith("convolutional"):
                    config = self.configs[section]
                    ptr, assign_ops = self._load_conv_weight(section, config, ptr, weights)
                    assign_op_list.insert(-1, assign_ops)

                if section.startswith("local"):
                    config = self.configs[section]
                    ptr, assign_ops = self._load_local_conv_weight(section, config, ptr, weights)
                    assign_op_list.insert(-1, assign_ops)

                if section.startswith("connected"):
                    config = self.configs[section]
                    ptr, assign_ops = self._load_fc_weight(section, config, ptr, weights)
                    assign_op_list.insert(-1, assign_ops)

                if self.verbose:
                    print("layer:{} load {} float data  total:{}/{}".format(
                        format(section, '<20s'),
                        format(ptr-prev_ptr, '<10d'),
                        ptr+header_len,
                        weights.shape[-1]+header_len))
            self.sess.run(assign_op_list)
    def _load_model_weight(self):
        if self.flags.weight:
            self._load_weight(_WEIGHT_HEADER_LEN)
        elif self.flags.ckpt:
            self._load_ckpt()
        elif self.flags.pb:
            self._load_pb()
        else:
            raise TypeError("Please provide model weight file.")
    @timer_wrapper
    def _inference(self, image):
        if not isinstance(image, np.ndarray):
            raise TypeError("Need np.ndarray, got {} of type {}.".format(image, type(image)))
        return self.detect_func(image[np.newaxis])
    def _pre_process_input(self, inputs):
        with tf.name_scope('pre_process'):
            image = tf.to_float(inputs) / 255.0
            image = tf.image.resize_images(
                image, tf.constant([self.img_size, self.img_size], dtype=tf.int32))
        return image
    def _build_network(self):
        # Input placeholder
        inputs = tf.placeholder(
            tf.float32,
            shape=[None, None, None, self.img_channels],
            name="inputs")

        # pre-processed image data
        processed_input = self._pre_process_input(inputs)

        # Builde network
        output = self._load_model(processed_input)
        self._load_model_weight()

        return inputs, output, processed_input
    def _build_detector(self, encoding):
        with tf.name_scope("post_process"):
            boxes, box_confidences, class_probs = tf.split(
                encoding, [4, 1, self.classes],
                axis=-1,
                name='detections')

            # select those boxes whose class confidence is larger than threshold
            class_scores, boxes, box_classes = select_boxes_by_classes_prob(
                box_confidences, class_probs, boxes,
                threshold=self.flags.score_thresh)
            # Do nms, get final results
            scores, boxes, classes = non_max_suppression(
                class_scores, boxes, box_classes,
                max_detect_count=self.flags.max_count,
                iou_threshold=self.flags.iou_thresh)

            return scores, boxes, classes
    def show_results(
            self,
            image,
            scores, boxes, classes,
            show=True,
            text_record=None,
            output_file="detected.jpg"):
        """Show the detection boxes

        """

        # Get color map
        hsv_tuples = [(x/float(len(self.classes_names)), 1., 1.)  for x in range(len(self.classes_names))]
        colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples))
        colors = list(
            map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)),
            colors))
        random.seed(23333)
        # random.seed(9527)
        random.shuffle(colors)
        random.seed(None)

        img_cp = image.copy()
        if text_record:
            if not os.path.exists(os.path.split(text_record)[0]):
                os.makedirs(os.path.split(text_record)[0])
            f = open(text_record, "w")

        detect_count = scores.shape[0]
        for i in range(detect_count):
            box = boxes[i]
            class_name = self.classes_names[classes[i]]
            score = scores[i]

            x, y, w, h = box.astype(np.int32)

            result_string = "Class name: {} [x, y, w, h]=[{}, {}, {}, {}], score={}".format(
                format(class_name, '<10s'),
                format(x, '<3d'),
                format(y, '<3d'),
                format(w, '<3d'),
                format(h, '<3d'),
                format(score, '<5.4f'))

            if self.verbose:
                print(result_string)
            if text_record:
                f.write("{}\n".format(result_string))
            if show or output_file:
                # cv2.rectangle(img_cp, (x - w//2, y - h//2), (x + w//2, y + h//2), (0, 255, 0), 2)
                cv2.rectangle(img_cp, (x - w//2, y - h//2), (x + w//2, y + h//2), colors[classes[i]], 2)

                cv2.rectangle(img_cp, (x - w//2, y - h//2 + 20), (x + w//2, y - h//2), colors[classes[i]], -1)
                cv2.putText(img_cp,
                            "{}:{}".format(class_name, format(score, '.4f')),
                            (x - w//2 + 5, y - h//2 + 15),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1)
                if show:
                    cv2.imwrite(output_file, img_cp)
                if output_file:
                    cv2.imwrite(output_file, img_cp)
        if text_record:
            f.close()
    def detect_from_image_file(self, image_file):
        image = cv2.imread(image_file)
        image_RGB = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

        if self.verbose:
            print("\nDetecting {}...\n-----------------------------------------".format(image_file))
            print("Detected result:")
        scores, boxes, classes = self._inference(image_RGB)

        img_h, img_w, _ = image.shape

        boxes[:,0] *= (1.0 * img_w)
        boxes[:,1] *= (1.0 * img_h)
        boxes[:,2] *= (1.0 * img_w)
        boxes[:,3] *= (1.0 * img_h)

        if self.flags.text_record:
            if self.flags.output_dir:
                text_record = os.path.join(self.flags.output_dir, self.flags.text_record)
            else:
                text_record = self.flags.text_record
        else:
            text_record = None

        if self.flags.output_dir:
            output_file = os.path.join(self.flags.output_dir, "detected.jpg")
        self.show_results(
            image,
            scores, boxes, classes,
            show=True,
            text_record=text_record,
            output_file=output_file)


import numpy as np
from helper import *

def stateDecoder(playerInfo, gameMap, visiblePlayers):
    vecteur = []
    vecteur.append(playerInfo.Position.x)
    vecteur.append(playerInfo.Position.y)
    for i in range(len(gameMap.tiles)-1):
        for j in range(len(gameMap.tiles[i]) - 1):
            vecteur.append(gameMap.tiles[i][j].TileContent.value)

    if(len(visiblePlayers) > 2):
        for j in range(3):
            vecteur.append(visiblePlayers[j].Health)
            vecteur.append(visiblePlayers[j].Position.x)
            vecteur.append(visiblePlayers[j].Position.y)
            vecteur.append(visiblePlayers[j].TotalResources)
            vecteur.append(visiblePlayers[j].AttackPower)
    elif (len(visiblePlayers) == 0):
        for l in range(15):
            vecteur.append(0)
    elif(len(visiblePlayers) == 1):
        for k in range(1):
            vecteur.append(visiblePlayers[k].Health)
            vecteur.append(visiblePlayers[k].Position.x)
            vecteur.append(visiblePlayers[k].Position.y)
            vecteur.append(visiblePlayers[k].TotalResources)
            vecteur.append(visiblePlayers[k].AttackPower)
        for n in range(10):
            vecteur.append(0)

    elif(len(visiblePlayers) == 2):
        for k in range(2):
            vecteur.append(visiblePlayers[k].Health)
            vecteur.append(visiblePlayers[k].Position.x)
            vecteur.append(visiblePlayers[k].Position.y)
            vecteur.append(visiblePlayers[k].TotalResources)
            vecteur.append(visiblePlayers[k].AttackPower)
        for n in range(5):
            vecteur.append(0)
    return vecteur

def decide_action(priority, gameMap, visiblePlayers, playerInfo):
        directionEnemy = Point()
        directionCollect = Point()
        posPlayer = playerInfo.Position
        tileHaut = Point(posPlayer.x, posPlayer.y - 1)
        tileDroite = Point(posPlayer.x + 1, posPlayer.y)
        tileBas = Point(posPlayer.x, posPlayer.y + 1)
        tileGauche = Point(posPlayer.x - 1, posPlayer.y)
        canAttack = False

        for i in range(len(visiblePlayers)-1):
            posEnemy = Point(visiblePlayers[i].Position.x, visiblePlayers[i].Position.y)
            if posPlayer.x - posEnemy.x == 1:
                directionEnemy.x = -1
                canAttack = True
            elif posPlayer.x - posEnemy.x == -1:
                directionEnemy.x = 1
                canAttack = True
            elif posPlayer.y - posEnemy.y == 1:
                directionEnemy.y = -1
                canAttack = True
            elif posPlayer.y - posEnemy.y == -1:
                directionEnemy.y = 1
                canAttack = True

        attackWall = False
        wallDir = Point()
        if (gameMap.getTileAt(tileHaut) == 1):
            attackWall = True
            wallDir.y = -1
        elif (gameMap.getTileAt(tileBas) == 1):
            attackWall = True
            wallDir.y = 1
        elif (gameMap.getTileAt(tileGauche) == 1):
            attackWall = True
            wallDir.x = -1
        elif (gameMap.getTileAt(tileDroite) == 1):
            attackWall = True
            wallDir.x = 1

        canCollect = False
        if gameMap.getTileAt(tileHaut) == 4:
            directionCollect.y = -1
            canCollect = True
        elif gameMap.getTileAt(tileDroite) == 4:
            directionCollect.x = 1
            canCollect = True
        elif gameMap.getTileAt(tileBas) == 4:
            directionCollect.y = 1
            canCollect = True
        elif gameMap.getTileAt(tileGauche) == 4:
            directionCollect.x = -1
            canCollect = True

        if priority == 0:
            return create_move_action(Point(-1,0))
        elif priority == 1:
            return create_move_action(Point(1,0))
        elif priority == 2:
            return create_move_action(Point(0,1))
        elif priority == 3:
            return create_move_action(Point(0,-1))
        elif priority == 4:
            if (canAttack):
                return create_attack_action(directionEnemy)
            elif (attackWall):
                print("WALL BREAKER --------------------------")
                return create_empty_action(wallDir)
            else:
                return create_empty_action()
        elif priority == 5:
            if (canCollect):
                print("Collection --------------------------")
                return create_collect_action(directionCollect)
            else:
                return create_empty_action()


#!/usr/bin/env python
import yaml
import sys
import argparse
import numpy
import math
from os.path import join

import rospy
import rosnode
import roslib
roslib.load_manifest('reflex_gripper_rr_bridge')

from reflex_gripper.reflex_sf_hand import ReflexSFHand
import reflex_gripper_msgs.msg as MSG
import reflex_gripper_msgs.srv as SRV
from std_srvs.srv import Empty
import RobotRaconteur as RR

gripper_servicedef="""
#Service to provide simple interface to the Right Hand Robotics Gripper Hands
service ReflexGripper_Interface

option version 0.4

object Gripper

property double[] joint_positions
property double[] raw_angles
property double[] joint_velocities
property double[] joint_torques

function void setControlMode(uint8 mode)
function void setJointCommand(double[] command)
function void setPositionModeSpeed(double speed)
function void calibrate()

#Functions for position mode presets
function void setGripShape(string shape)
function void closeGrip()
function void openGrip()
function void tightenGrip()
function void loosenGrip()
function void tightenFinger(string finger)
function void loosenFinger(string finger)
function void zeroHand()

end object
"""

class Gripper_impl(object):
	def __init__(self, name):
		print "Initializing Node..."

		self._name = name
		rospy.init_node('reflex_%s_RRService'%(name))

		print "Connecting to the ROS Service for the Hand..."
		self._default_pub = rospy.Publisher('reflex_%s/command'%(name), MSG.Command, queue_size=10)
		self._pos_pub = rospy.Publisher('/reflex_%s/command_position'%(name), MSG.PoseCommand, queue_size=10)
		self._vel_pub = rospy.Publisher('/reflex_%s/command_velocity'%(name), MSG.VelocityCommand, queue_size=10)
		self._force_pub = rospy.Publisher('/reflex_%s/command_motor_force'%(name), MSG.ForceCommand, queue_size=10)

		self._set_speed_service = rospy.ServiceProxy('/reflex_%s/set_speeds'%(name), SRV.SetSpeed)
		self._cal_service = rospy.ServiceProxy('/reflex_%s/zero_fingers'%name, Empty)

		rospy.Subscriber('/reflex_%s/hand_state'%(name), MSG.Hand, self._joint_state_cb)

		print "Initializing Hand ..."

		self._joint_positions = [0]*4
		self._raw_angles = [0]*4
		self._joint_velocities = [0]*4
		self._joint_torques = [0]*4
		self._joint_command = [0]*8
		self._position_mode_speed = [4.5]*4
		self._valid_finger_names = {'f1' : 'f1',
									'f2' : 'f2',
									'f3' : 'f3',
									'preshape' : 'preshape',
									'p' : 'preshape'}
		self._finger_positions = dict(zip(['f1','f2','f3','preshape'], range(0,4)))

		_30_DEG = math.radians(30)
		_45_DEG = math.radians(45)
		_60_DEG = math.radians(60)
		_90_DEG = math.radians(90)
		_120_DEG = math.radians(120)
		_135_DEG = math.radians(135)
		_180_DEG = math.radians(180)

		self._PINCH_GRIP = [_90_DEG,_90_DEG, 0.0, _90_DEG]
		self._CYLINDER_GRIP = [0.0, 0.0, 0.0, 0.0]
		self._SPHERICAL_GRIP = [_60_DEG,_60_DEG,_60_DEG,_60_DEG]

		self._CYLINDER_CLOSED = [_180_DEG, _180_DEG, _180_DEG, 0.0]
		self._PINCH_CLOSED = [_120_DEG,_120_DEG, 0.0, _90_DEG]
		self._SPHERICAL_CLOSED = [_120_DEG, _120_DEG, _135_DEG, _60_DEG]

		self._valid_shape_names = {'cylinder' : 'cylinder',
									'c' : 'cylinder',
									'sphere' : 'sphere',
									's' : 'sphere',
									'pinch' : 'pinch',
									'p' : 'pinch'}
		self._grip_shape = 'cylinder'

		self._MODE_DEFAULT  = 0
		self._MODE_POSITION = 1
		self._MODE_VELOCITY = 2
		self._MODE_TORQUE   = 3
		self._mode = self._MODE_DEFAULT

		#initial joint command is current position
		self.setJointCommand(self._joint_positions + self._joint_velocities)

	@property
	def joint_positions(self):
	    return self._joint_positions

	@property
	def raw_angles(self):
	    return self._raw_angles

	@property
	def joint_velocities(self):
	    return self._joint_velocities

	@property
	def joint_torques(self):
		return self._joint_torques

	def setControlMode(self, mode):
		if mode != self._MODE_DEFAULT and \
				mode != self._MODE_POSITION and \
				mode != self._MODE_VELOCITY and \
				mode != self._MODE_TORQUE:
			return

		self._mode = mode

		if mode == self._MODE_DEFAULT:
			self.setJointCommand(self._joint_positions + self._joint_velocities)
		elif mode == self._MODE_POSITION:
			self._set_speed_service(*self._position_mode_speed)
			self.setJointCommand(self._joint_positions)
		elif mode == self._MODE_VELOCITY:
			self.setJointCommand([0]*4)
		elif mode == self._MODE_TORQUE:
			self.setJointCommand([0]*4)

	def setJointCommand(self, command):
		prev_command = self._joint_command
		self._joint_command = command
		if (self._mode == self._MODE_DEFAULT):
				if len(command)!=8:
					raise RuntimeError("Current control mode expects 8 inputs")
					self._joint_command = old_command
					return

				msg = MSG.Command()
				msg.pose = MSG.PoseCommand(*self._joint_command[0:4])
				msg.velocity = MSG.VelocityCommand(*self._joint_command[4:8])
				self._default_pub.publish(msg)
		else:
			if len(command) != 4:
				raise RuntimeError("Current control mode expects 4 inputs")
				self._joint_command = prev_command
				return

			if (self._mode == self._MODE_POSITION):
				msg = MSG.PoseCommand(*self._joint_command)
				self._pos_pub.publish(msg)
			elif (self._mode == self._MODE_VELOCITY):
				msg = MSG.VelocityCommand(*self._joint_command)
				self._vel_pub.publish(msg)
			elif (self._mode == self._MODE_TORQUE):
				msg = MSG.ForceCommand(*self._joint_command)
				self._force_pub.publish(msg)

	def setPositionModeSpeed(self, speed):
		if speed < 0.0:
			speed = 0.0
		self._position_mode_speed=[speed]*4

	def setGripShape(self, shape):
		if self._check_pos_mode():
			shape = shape.lower()
			if not shape in self._valid_shape_names.keys():
				raise RuntimeError("Not a valid grip shape")
				return

			if self._valid_shape_names[shape] == 'cylinder':
				self.setJointCommand(self._CYLINDER_GRIP)
			elif self._valid_shape_names[shape] == 'sphere':
				self.setJointCommand(self._SPHERICAL_GRIP)
			elif self._valid_shape_names[shape] == 'pinch':
				self.setJointCommand(self._PINCH_GRIP)

			self._grip_shape = self._valid_shape_names[shape]

	def closeGrip(self):
		if self._check_pos_mode():
			if self._grip_shape == 'cylinder':
				self.setJointCommand(self._CYLINDER_CLOSED)
			elif self._grip_shape == 'sphere':
				self.setJointCommand(self._SPHERICAL_CLOSED)
			elif self._grip_shape == 'pinch':
				self.setJointCommand(self._PINCH_CLOSED)

	def openGrip(self):
		if self._check_pos_mode():
			self.setGripShape(self._grip_shape)

	def tightenGrip(self):
		if self._check_pos_mode():
			command = [0]*4
			# only tighten fingers, not preshape
			for i in range(0,3):
				command[i] = self._joint_positions[i] + 0.05
			command[3] = self._joint_positions[3]
			self.setJointCommand(command)

	def loosenGrip(self):
		if self._check_pos_mode():
			command = [0]*4
			# only loosen fingers, not preshape
			for i in range(0,3):
				command[i] = self._joint_positions[i] - 0.05
			command[3] = self._joint_positions[3]
			self.setJointCommand(command)

	def tightenFinger(self, finger):
		if self._check_pos_mode():
			finger = finger.lower()
			if not finger in self._valid_finger_names.keys():
				raise RuntimeError("'%s' is not a valid finger"%finger)
				return
			else:
				finger = self._valid_finger_names[finger]
				command = self._joint_positions
				command[self._finger_positions[finger]] += 0.05
				self.setJointCommand(command)

	def loosenFinger(self, finger):
		if self._check_pos_mode():
			finger = finger.lower()
			if not finger in self._valid_finger_names.keys():
				raise RuntimeError("'%s' is not a valid finger"%finger)
				return
			else:
				finger = self._valid_finger_names[finger]
				command = self._joint_positions
				command[self._finger_positions[finger]] -= 0.05
				self.setJointCommand(command)

	def zeroHand(self):
		self.setControlMode(self._MODE_POSITION)
		self.setJointCommand([0]*4)
		self._grip_shape = 'cylinder'

	def calibrate(self):
		self.zeroHand()
		self._cal_service()

	#---------------------------
	#--- Private Functions -----
	#---------------------------
	def close(self):
		self.zeroHand()

	def readJointPositions(self,data):
		for i in range(0,4):
			self._joint_positions[i] = data.motor[i].joint_angle

	def readRawAngles(self,data):
		for i in range(0,4):
			self._raw_angles[i] = data.motor[i].raw_angle

	def readJointVelocities(self,data):
		for i in range(0,4):
			self._joint_velocities[i] = data.motor[i].velocity

	def readJointTorques(self,data):
		for i in range(0,4):
			self._joint_torques[i] = data.motor[i].load

	def _joint_state_cb(self,data):
		self.readJointPositions(data)
		self.readRawAngles(data)
		self.readJointVelocities(data)
		self.readJointTorques(data)

	def _check_pos_mode(self):
		if self._mode != self._MODE_POSITION:
			raise RuntimeError("Must be in position mode to use this funciton")
			return False
		else:
			return True

def main(argv):
	print "REFLEX GRIPPER RR BRIDGE"
	print "========================"
	# Parse command line arguments
	parser = argparse.ArgumentParser(
		description='Initialize a Gripper Hand')
	parser.add_argument('--port', type=int, default=0,
		help='TCP port to host service on' +\
		'(will auto-generate if not specified)')
	parser.add_argument('name', help='The desired name for the gripper.' +\
		'Must match name given to start gripper services(e.g. left)')

	args = parser.parse_args(argv)
	# Check for valid name
	name = args.name
	if not "/reflex_%s"%(name) in rosnode.get_node_names():
		print "The name '%s' is not valid. The gripper services may not "%(name) +\
		"be started yet."
		raw_input("Press ENTER to close")
		return -1

	# Enable numpy
	RR.RobotRaconteurNode.s.UseNumPy = True

	# Set the node name
	RR.RobotRaconteurNode.s.NodeName = "ReflexGripperServer.%s"%name

	# Initialize the object
	gripper_obj = Gripper_impl(name)

	# Create transport, register it, and start the server
	print "Registering Transport..."
	t = RR.TcpTransport()
	t.EnableNodeAnnounce(RR.IPNodeDiscoveryFlags_NODE_LOCAL |
						 RR.IPNodeDiscoveryFlags_LINK_LOCAL |
						 RR.IPNodeDiscoveryFlags_SITE_LOCAL)

	RR.RobotRaconteurNode.s.RegisterTransport(t)

	t.StartServer(args.port)
	port = args.port
	if (port == 0):
		port = t.GetListenPort()

	# Register the service type and the service
	print "Starting Service..."
	RR.RobotRaconteurNode.s.RegisterServiceType(gripper_servicedef)
	RR.RobotRaconteurNode.s.RegisterService("Gripper",
						  "ReflexGripper_Interface.Gripper",
						  				  gripper_obj)

	print "Service started, connect via"
	print "tcp://localhost:%s/ReflexGripperServer.%s/Gripper"%(port, name)

	raw_input("press ENTER to quit ... \r\n")

	gripper_obj.close()

	# This must be here to prevent segfault
	RR.RobotRaconteurNode.s.Shutdown()

if __name__ == '__main__':
	main(sys.argv[1:])