# -*- coding: utf-8 -*-

# train_mnist.pyを改造したモノ
#　https://github.com/chainer/chainer/blob/master/examples/mnist/train_mnist.py
'''
やること
- fetch Dataset
    - ImageDataset(chainer.dataset.DatasetMixIn的なクラス)
- define model
    - to abstract model, use Links (& Functions+ addlink)
- evaluate Loss function
    - lossfunc => mean_squared_error(平均二乗誤差x,tの数値が必要？)
- fix paramater
    - After data acquisition through the input in 1 epoch, ruturn params
    - and restart learning
        - need activater
        - use iterater? what is it?
- sketch inner activation
    - matplotlib?
-
-
-
-

'''

from __future__ import print_function

try:
    import matplotlib
    matplotlib.use('Agg')
except ImportError:
    pass

from PIL import Image
import numpy as np
import argparse
import random
import math
import glob
import sys
import os

#os.environ["CHAINER_TYPE_CHECK"] = "0"

import chainer
import chainer.links as L
import chainer.functions as F

from chainer import cuda
from chainer import link
from chainer import Chain
from chainer import utils
from chainer import report
from chainer import datasets
from chainer import Function
from chainer import reporter
from chainer import training
from chainer import Variable
from chainer import iterators
from chainer import optimizers
from chainer import serializers
from chainer.training import extensions
from chainer.datasets import tuple_dataset
from chainer.functions.loss import mean_squared_error
#from chainer.functions.evaluation import accuracy

class Accuracy(chainer.Function):

    def __init__(self, ignore_label=None):
        self.ignore_label = ignore_label

    def forward(self, inputs):
        xp = cuda.get_array_module(*inputs)# numpy or cupy を返すらしい？
        y, t = inputs
        # 多次元numpy配列x, tを一次元に落とし込む
        # np.reshape: http://messefor.hatenablog.com/entry/2017/02/13/225156
        y_d1 = y.reshape(-1,)
        t_d1 = t.reshape(-1,)
        # 数字が一致する部分が、画像データの入出力域が合致している部分
        #acc = np.sum(y_d1 == t_d1, dtype=np.float32) / y_d1.shape[0].astype(np.float32)
        acc = np.sum(y_d1 == t_d1, dtype=np.float32) / float(y_d1.shape[0])

        # y_d1.shape[0]はndarrayではなくint?
            #if acc > 1.0 :
             #   print('program failed!')
              #  exit()
        return xp.asarray(acc),

def moeAccuracy(y, t, ignore_label=None):
    return Accuracy(ignore_label=ignore_label)(y, t)
# ------------------------ modelの定義 ------------------------------
class Downscaling(chainer.Chain):
    def __init__(self, ch_in, ch_out):
        w = math.sqrt(2)
        super(Downscaling, self).__init__(
        # strideをx2にすればデータサイズはそれに比例して早く小さくなる
            downscaling = L.Convolution2D(ch_in, ch_out, ksize=2, stride=2, pad=0, initialW=w)
        )
    def __call__(self, x):
        h = self.downscaling(x)

        return h

class Upscaling(chainer.Chain):
    # 知見: ニューラルネットワークにおけるDeconvolutionというのは、
    # transposed convolution = 転置畳み込みと言うほうがわかりやすく、元となる特徴マップを拡大してから畳み込むことを指す
    def __init__(self, ch_in, ch_out):
        w = math.sqrt(2)
        super(Upscaling, self).__init__(
            upscaling = L.Deconvolution2D(ch_in, ch_out, ksize=2, stride=2, pad=0, initialW=w)
        )
    def __call__(self, x):
        h = self.upscaling(x)

        return h
'''
class Merging(chainer.chain):

    def __init__(self, ch_in, ch_out):
        # 調整中
        #merging =

    def __call__(self, x, ch_in, ch_out):
        h = self.merging(x, test=not train)

        return h
'''
class Block(chainer.Chain):
        # Convolution2D(入力ch数[画像の x, y のサイズや総ピクセル数ではない], 出力ch数[フィルターの個数],
        # フィルタの大きさ, strideの大きさ, padの大きさ, weight=w)
    def __init__(self, ch_in=32, ch_out=32):
        w = math.sqrt(2)
        super(Block, self).__init__(
            bn1=L.BatchNormalization(ch_in),
            conv1=L.Convolution2D(ch_out, ch_out, ksize=3, stride=1, pad=1, initialW=w),
            bn2=L.BatchNormalization(ch_out),
            conv2=L.Convolution2D(ch_out, ch_out, ksize=3, stride=1, pad=1, initialW=w),
        )

    def __call__(self, x): # データを受け取った際のforward計算を書く
        # bn1-relu1-conv1-bn2-relu2-dropout-conv2
        # 広さの係数10で28層のWide ResNetにDropout率30~40%程度適用すると高い精度
        # https://deepage.net/deep_learning/2016/11/30/resnet.html#batch-normalizationの位置

        h = F.relu(self.bn1(x))
        h = F.relu(self.bn2(self.conv1(h)))
        h = F.dropout(h, ratio=0.35) # 30%-40%ぐらいがいいらしい
        h = self.conv2(h)

        output = h + x
        return output

# Neural net architecture
# ニューラルネットの構造
# https://github.com/mitmul/chainer-cifar10/blob/master/models/ResNet.py
class MoeNet(chainer.Chain):

    def __init__(self, block_class, down_class, up_class, ch_in=3, ch_out=3):
        super(MoeNet, self).__init__()

        links = [('res001', block_class(ch_in, ch_out)),
                 ('res002', block_class(ch_in, ch_out)),
                 ('res003', block_class(ch_in, ch_out)),
                 ('res004', block_class(ch_in, ch_out)),
                 ('down01', down_class(ch_in, ch_out * 2)), #datasizeを縦横1/2に 代わりにch数を増やす
                 ('res101', block_class(ch_in * 2, ch_out * 2)),
                 ('res102', block_class(ch_in * 2, ch_out * 2)),
                 ('res103', block_class(ch_in * 2, ch_out * 2)),
                 ('res104', block_class(ch_in * 2, ch_out * 2)),
                 ('res105', block_class(ch_in * 2, ch_out * 2)),
                 ('res106', block_class(ch_in * 2, ch_out * 2)),
                 ('down02', down_class(ch_in * 2, ch_out * 4)), #datasizeを縦横1/2に 代わりにch数を増やす
                 ('res201', block_class(ch_in * 4, ch_out * 4)),
                 ('res202', block_class(ch_in * 4, ch_out * 4)),
                 ('res203', block_class(ch_in * 4, ch_out * 4)),
                 ('res204', block_class(ch_in * 4, ch_out * 4)),
                 ('res205', block_class(ch_in * 4, ch_out * 4)),
                 ('res206', block_class(ch_in * 4, ch_out * 4)),
                 ('res207', block_class(ch_in * 4, ch_out * 4)),
                 ('res208', block_class(ch_in * 4, ch_out * 4)),
                 ('res209', block_class(ch_in * 4, ch_out * 4)),
                 ('dwns03', down_class(ch_in * 4, ch_out * 8)), #datasizeを縦横1/2に 代わりにch数を増やす
                 ('res301', block_class(ch_in * 8, ch_out * 8)),
                 ('res302', block_class(ch_in * 8, ch_out * 8)),
                 ('res303', block_class(ch_in * 8, ch_out * 8)),
                 ('res304', block_class(ch_in * 8, ch_out * 8)),
                 ('res305', block_class(ch_in * 8, ch_out * 8)),
                 ('res306', block_class(ch_in * 8, ch_out * 8)),
                 ('res307', block_class(ch_in * 8, ch_out * 8)),
                 ('res308', block_class(ch_in * 8, ch_out * 8)),
                 ('res309', block_class(ch_in * 8, ch_out * 8)),
                 ('res310', block_class(ch_in * 8, ch_out * 8)),
                 ('res311', block_class(ch_in * 8, ch_out * 8)),
                 ('res312', block_class(ch_in * 8, ch_out * 8)),
                 ('up_s01', up_class(ch_in * 8, ch_out * 4)), #datasizeを縦横x2に
                 ('res401', block_class(ch_in * 4, ch_out * 4)),
                 ('res402', block_class(ch_in * 4, ch_out * 4)),
                 ('res403', block_class(ch_in * 4, ch_out * 4)),
                 ('res404', block_class(ch_in * 4, ch_out * 4)),
                 ('res405', block_class(ch_in * 4, ch_out * 4)),
                 ('res406', block_class(ch_in * 4, ch_out * 4)),
                 ('res407', block_class(ch_in * 4, ch_out * 4)),
                 ('res408', block_class(ch_in * 4, ch_out * 4)),
                 ('res409', block_class(ch_in * 4, ch_out * 4)),
                 # '_merg1', Merging(ch_in * 4, ch_out * 4))　=> skipされてきた値を統合
                 ('up_s02', up_class(ch_in * 4, ch_out * 2)), #datasizeを縦横x2に
                 ('res501', block_class(ch_in * 2, ch_out * 2)),
                 ('res502', block_class(ch_in * 2, ch_out * 2)),
                 ('res503', block_class(ch_in * 2, ch_out * 2)),
                 ('res504', block_class(ch_in * 2, ch_out * 2)),
                 ('res505', block_class(ch_in * 2, ch_out * 2)),
                 ('res506', block_class(ch_in * 2, ch_out * 2)),
                 # '_merg2', Merging(ch_in * 2, ch_out * 2))
                 ('up_s03', up_class(ch_in * 2, ch_out)), #datasizeを縦横x2に
                 ('res601', block_class(ch_in, ch_out)),
                 ('res602', block_class(ch_in, ch_out)),
                 ('res603', block_class(ch_in, ch_out)),
                 ('res604', block_class(ch_in, ch_out)),
                 # '_merg3', Merging(ch_in, ch_out))
                 # flat
                 ('res701', block_class(ch_in, ch_out)),
                 ('res702', block_class(ch_in, ch_out)),
                 ('res703', block_class(ch_in, ch_out)),
                 # output
                 ('res801', block_class(ch_in, ch_out))]
        for link in links:
            if not link[0].startswith('_'):
                self.add_link(*link)

        self.forward = links
        self.train = True

    def __call__(self, x, t): # tはどこから持ってくるの？

        for name, f in self.forward: # linksから関数を一つずつ実行
            x = f(x)

        if self.train:
            self.loss = F.mean_squared_error(x, t)
            self.accuracy = moeAccuracy(x, t)
            return self.loss
        else:
            return x

        return x
# ------------------------- datasetの用意 ----------------------------------

# datasetを用意する
#　参考:　"Chainerで画像を読み込む際のTips"
#　http://qiita.com/ysasaki6023/items/fa2fe9c2336677821583
# 参考:　"chainerの独自datasetの作り方"
#　http://mizti.hatenablog.com/entry/chainer_dataset
# データセット内のデータ数を返す__len__メソッド
# 引数として渡されるiに対応したデータもしくはデータとラベルの組を返すget_exampleメソッド
# train = chainer.datasets.ImageDataset(paths)を使えば自前のデータセットが使える
# tuple_dataset.TupleDataset(train_x,train_y)だとどうなるの？
# pathsには学習データとする画像のパスのリストを入れる（numpy配列でも可）
# リサイズの必要性？？
    # データの画素数がMxNとする
    # M,N が奇数の時、データの大きさをM+1 x N+1にしたい
    # 横と下からconcatすればいいはず

# カレントディレクトリ下を探してファイル名を読み込みそれらをリストにしてそのリストのペアを返すメソッド
def fileFetch():

    x_imgNames = glob.glob('./dataset/senga_t_data/*.jpg')
    t_imgNames = glob.glob('./dataset/t_data/*.jpg')

    nameList = [x_imgNames, t_imgNames] # 入力&教師データ名が収められたlist
    return nameList

# 画像のファイル名を与えるとpillowで読み込んでnp.array変換して返すメソッド
def get_image(filename, croppedSize=128):
    image = Image.open(filename) # ここで初めて読み込み
    # cropしとかないとメモリエラーで動かなかった
    #  crop処理を施す場合
    new_w = croppedSize
    new_h = croppedSize
    # リサイズと一緒に画質の設定ができる　ANTIALIASは最高品質
    image = image.resize((new_w, new_h), Image.ANTIALIAS)

    # PIL->np.array変換
    imgAry = np.asarray(image).transpose(2,0,1).astype(np.float32)/255.

    return imgAry

def makeDataset():
    # 「引数として渡されるiに対応したデータもしくはデータとラベルの組を返すget_exampleメソッド」
    # がchainerの自作データベースを利用するメソッド；dataset.DatasetMixinに必要となる
    # self._pairsは入力&教師データの名称のペアが収められたlist
    fileList = fileFetch()
    x_images_list = []
    t_images_list = []
    for j in fileList[0]:
        x_imgAry = get_image(j)
        x_images_list.append(x_imgAry)
    for k in fileList[1]:
        t_imgAry = get_image(k)
        t_images_list.append(t_imgAry)

    return x_images_list, t_images_list
# ----------------------- datasetの用意 終了 --------------------------------

#　ハイパーパラメータの調整
# main(バッチサイズ, エポック数, snap.pngを保存するタイミング,
#      GPUの可否, 結果を保存するフォルダ指定, res='', 一度の学習で取り出すデータ数)
def main(modelName='myModel', bs=2, ep=10   , frq=-1, gpuID=-1, rF='resultFolder', res='', un=2):

    parser = argparse.ArgumentParser(description='Chainer : {}'.format(modelName))
    parser.add_argument('--batchsize', '-b', type=int, default=bs,
                        help='Number of images in each mini-batch')
    parser.add_argument('--epoch', '-e', type=int, default=ep,
                        help='Number of sweeps over the dataset to train')
    parser.add_argument('--frequency', '-f', type=int, default=frq,
                        help='Frequency of taking a snapshot')
    parser.add_argument('--gpu', '-g', type=int, default=gpuID,
                        help='GPU ID (negative value indicates CPU)')
    parser.add_argument('--out', '-o', default=rF,
                        help='Directory to output the resultFolder')
    parser.add_argument('--resume', '-r', default=res,
                        help='Resume the training from snapshot')
    parser.add_argument('--unit', '-u', type=int, default=un,
                        help='Number of units')
    args = parser.parse_args()

    print('GPU: {}'.format(args.gpu))
    print('# unit: {}'.format(args.unit))
    print('# Minibatch-size: {}'.format(args.batchsize))
    print('# epoch: {}'.format(args.epoch))
    print('')

    # Set up a neural network to train
    # Classifier reports mean_squared_error loss and accuracy at every
    # iteration, which will be used by the PrintReport extension below.
    # 参考　http://qiita.com/icoxfog417/items/96ecaff323434c8d677b
    #model = L.Classifier(MoeNet(Block, Downscaling, Upscaling), lossfun=mean_squared_error)
    model = MoeNet(Block, Downscaling, Upscaling)

    if args.gpu >= 0:
        # Make a specified GPU current
        chainer.cuda.get_device_from_id(args.gpu).use()
        model.to_gpu()  # Copy the model to the GPU

    # Setup an optimizer
    optimizer = chainer.optimizers.Adam()
    optimizer.setup(model)

# --------------------------------------------------------------------------
# イテレータにデータを渡す

    #dataset = ImageDataset() # dataset = (入力データ, 教師データ)の配列
    # -----------------------------------------------------------------------
    # train_x は、(1000枚, 3色,32,32)のfloat32 => つまり変換した後の画像の集まりnumpy配列
    # train_y は、(1000, )のint32　＝＞　ラベル　今回は不要
    #　画像群とラベル群のペアを渡している

    #dataset = tuple_dataset.TupleDataset(makeDataset()) # list of list を渡していた…

    x, t = makeDataset()
    # Load the dataset
    train = tuple_dataset.TupleDataset(x, t)
    test = tuple_dataset.TupleDataset(x, t)
# -----------------------------------------------------------------------

    train_iter = chainer.iterators.SerialIterator(train, args.batchsize, repeat=True, shuffle=True)
    test_iter = chainer.iterators.SerialIterator(test, args.batchsize, repeat=False, shuffle=True)
# ---------------------------------------------------------------------------
    # Set up a trainer
    updater = training.StandardUpdater(train_iter, optimizer, device=args.gpu)
    trainer = training.Trainer(updater, (args.epoch, 'epoch'), out=args.out)

    # Evaluate the model with the test dataset for each epoch
    trainer.extend(extensions.Evaluator(test_iter, model, device=args.gpu))

    # Dump a computational graph from 'loss' variable at the first iteration
    # The "main" refers to the target link of the "main" optimizer.
    trainer.extend(extensions.dump_graph('main/loss'))

    # Take a snapshot for each specified epoch
    frequency = args.epoch if args.frequency == -1 else max(1, args.frequency)
    trainer.extend(extensions.snapshot(), trigger=(frequency, 'epoch'))

    # Write a log of evaluation statistics for each epoch
    trainer.extend(extensions.LogReport())

    # Save two plot images to the result dir
    if extensions.PlotReport.available():
        trainer.extend(
            extensions.PlotReport(['main/loss', 'validation/main/loss'],
                                  'epoch', file_name='loss.png'))
        trainer.extend(
            extensions.PlotReport(
                ['main/accuracy', 'validation/main/accuracy'],
                'epoch', file_name='accuracy.png'))

    # Print selected entries of the log to stdout
    # Here "main" refers to the target link of the "main" optimizer again, and
    # "validation" refers to the default name of the Evaluator extension.
    # Entries other than 'epoch' are reported by the Classifier link, called by
    # either the updater or the evaluator.
    trainer.extend(extensions.PrintReport(
        ['epoch', 'main/loss', 'validation/main/loss',
         'main/accuracy', 'validation/main/accuracy', 'elapsed_time']))

    # Print a progress bar to stdout
    trainer.extend(extensions.ProgressBar())

    if args.resume:
        # Resume from a snapshot
        chainer.serializers.load_npz(args.resume, trainer)

    # Run the training
    trainer.run()

if __name__ == '__main__':
    main()

print('\nLearning process finished!!\n')


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
    File name: solution.py
    Author: Alexander Popp
    Date created: 5/20/2018
    Date last modified: 8/7/2018
    Python version: 3.6.5
    Description:
        Problem #33: Birthday Dictionaries from http://www.practicepython.org
        For detailed description of the problem see the accompanying
        file named 'problem.txt' or refer to the aformentioned website.
"""

# Get user input
def get_input(dictionary):
    while True:
        name = input("Who's birthday do you want to look up? ")
        if name.title() in dictionary:
            break
        else:
            print("Unrecognised input.\nPlease try again...")
    return name.title()

# Main function
def main():
    dictionary = {
        "Ernest Rutherford": [8, 30, 1871],
        "Werner Heisenberg": [12, 5, 1901],
        "Erwin Schroedinger": [8, 12, 1887],
        "Max Planck": [4, 23, 1858]
    }
    print("Welcome to the birthday dictionary. We know the birthdays of:")
    for item in dictionary:
        print(item)
    name = get_input(dictionary)
    print("{}'s birthday is {}/{}/{}.".format(name, dictionary[name][0], dictionary[name][1], dictionary[name][2]))

# Run program
if __name__ == "__main__":
    main()


import base64
import json
import requests
import re
import os
from typing import Dict, Optional
from data import Data, JobState, JsonPayload
from _logging import get_logger
from googleapiclient.discovery import build

ml = build('ml', 'v1')
GCP_PROJECT = os.environ.get('GCP_PROJECT')

def check_job_state(data: Data) -> Optional[JobState]:

    if isinstance(data.textPayload, str):
        if "completed successfully" in data.textPayload:
            return JobState.SUCCEEDED
        elif "failed" in data.textPayload:
            return JobState.FAILED
        elif "cancelled" in data.textPayload:
            return JobState.CANCELLED

    elif isinstance(data.jsonPayload, JsonPayload):
        if "queued" in data.jsonPayload.message:
            return JobState.QUEUED

    else:
        return None

def get_job_json(data):
    logger = get_logger()
    projectName = data.resource.labels.project_id
    projectId = 'projects/{}'.format(projectName)
    jobName = data.resource.labels.job_id
    jobId = '{}/jobs/{}'.format(projectId, jobName)
    request = ml.projects().jobs().get(name=jobId)
    response = None
    try:
        response = request.execute()
    except Exception as err:
        # Something went wrong. Handle the exception in an appropriate
        #  way for your application.
        raise err
    if response is None:
        raise Exception(f'Got no response for {jobId}')
    logger.info(f'Response: {json.dumps(response)}')
    return response

def get_slack_user_name(email: str) -> str:
    bot_token = os.environ.get('SLACK_BOT_TOKEN')
    response = requests.get(f'https://slack.com/api/users.lookupByEmail?email={email}', headers= {'Authorization': f'Bearer {bot_token}'})

    if response.status_code != 200:
        raise ValueError(
            'Request to slack returned an error %s, the response is:\n%s'
            % (response.status_code, response.text)
        )
    print(f'getting slack name {response.json()}')
    slack_user_name = response.json()['user']['name']
    return slack_user_name

def get_message(message: Dict) -> str:
    global GCP_PROJECT
    slack_message_template = "{slack_user_name} => JOB *{job_id}* state is: `{job_state}`{details}\n{job_link} "
    email = message.get('email')
    slack_user_name = ''
    if email:
        slack_user_name = f'@{get_slack_user_name(email)}'
    details = message.get('job_error_message')
    if details:
        details = f'\n> `{details}`\n'
    else:
        details = ''
    job_link = f'https://console.cloud.google.com/ai-platform/jobs/{message["job_id"]}/charts/cpu?project={GCP_PROJECT}'
    return slack_message_template.format(slack_user_name=slack_user_name, job_id=message['job_id'], job_state=message['job_state'], details=details, job_link=job_link)

def send_message(message: Dict) -> None:
    # Set the webhook_url to the one provided by Slack when you create the webhook at https://my.slack.com/services/new/incoming-webhook/
    webhook_url = os.environ.get('SLACK_WEBHOOK_URI')
    channel_name = os.environ.get('SLACK_CHANNEL_NAME')
    response = requests.post(
        webhook_url, data=json.dumps({
            'parse': 'full',
            'link_names': 1,
            'channel': channel_name,
            'text': get_message(message)
        }),
        headers={'Content-Type': 'application/json'}
    )
    if response.status_code != 200:
        raise ValueError(
            'Request to slack returned an error %s, the response is:\n%s'
            % (response.status_code, response.text)
        )

def extract_email_from_job(job):
    args = job['trainingInput']['args']
    for arg in args:
        result = re.search('--email(?:=| )(.+)', arg)
        if result:
            return result.group(1)
    return None

def main(event, context):
    """Triggered from a message on a Cloud Pub/Sub topic.
    Args:
         event (dict): Event payload.
         context (google.cloud.functions.Context): Metadata for the event.
    """
    logger = get_logger()
    pubsub_message = base64.b64decode(event['data']).decode('utf-8')
    logger.info(f'Event: {json.dumps(event)}')
    event_data = json.loads(pubsub_message)
    data = Data(**event_data)
    logger.info(f'data: {json.dumps(event_data)}')
    job = get_job_json(data)
    job_state = check_job_state(data)
    if not job_state:
        logger.info('Job state is none, not sending a message')
        return
    email = extract_email_from_job(job)
    message = {'email': email, 'job_id': job['jobId'], 'job_error_message': job.get('errorMessage'), 'job_state': job_state}
    send_message(message)

# main({"@type": "type.googleapis.com/google.pubsub.v1.PubsubMessage", "attributes": {"logging.googleapis.com/timestamp": "2021-05-23T23:57:10.343201317Z"}, "data": "eyJpbnNlcnRJZCI6IjEweDJhcmtjdGM1IiwibGFiZWxzIjp7Im1sLmdvb2dsZWFwaXMuY29tL2VuZHBvaW50IjoiIn0sImxvZ05hbWUiOiJwcm9qZWN0cy9zd3ZsLXNhbmRib3gvbG9ncy9tbC5nb29nbGVhcGlzLmNvbSUyRnRlc3RfZHVyYXRpb25zX3BhcmFsbGVsXzEiLCJyZWNlaXZlVGltZXN0YW1wIjoiMjAyMS0wNS0yM1QyMzo1NzoxMS4xMzE3OTIyMjFaIiwicmVzb3VyY2UiOnsibGFiZWxzIjp7ImpvYl9pZCI6InRlc3RfZHVyYXRpb25zX3BhcmFsbGVsXzEiLCJwcm9qZWN0X2lkIjoic3d2bC1zYW5kYm94IiwidGFza19uYW1lIjoic2VydmljZSJ9LCJ0eXBlIjoibWxfam9iIn0sInNldmVyaXR5IjoiSU5GTyIsInRleHRQYXlsb2FkIjoiV2FpdGluZyBmb3IgdHJhaW5pbmcgcHJvZ3JhbSB0byBzdGFydC4iLCJ0aW1lc3RhbXAiOiIyMDIxLTA1LTIzVDIzOjU3OjEwLjM0MzIwMTMxN1oifQ=="}, None)


import csv
import yaml

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from pubg_python import PUBG, Shard
from datetime import datetime

config = yaml.safe_load(open('config.yml'))

API_KEY = config['API_KEY']

def convert_timestamp(s):
  """"""
  # return datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ")
  return datetime.strptime(s, "%Y-%m-%dT%H:%M:%S.%fZ")

def get_player_ids(names, verbose=False):
  """return player ids from usernames"""

  players = api.players().filter(player_names=names)

  if verbose:
    for player in players:
      print('{}: {}'.format(player.name, player.id))

  return players

def participant_names(roster):
  return [participant.name for participant in roster.participants]

def get_winners(rosters):
  for i, roster in enumerate(rosters):
    if roster.won == 'true':
      return i, participant_names(roster)

def print_match_history():
  player_names = ['eponymoose']
  # player_names = ['Stalkyard']

  players = api.players().filter(player_names=player_names)
  player = players[0]

  print("name: {}\nid: {}\n".format(player.name, player.id))

  matches = player.matches

  match_ids = [match.id for match in matches]

  matches = api.matches().filter(match_ids=match_ids)

  for i, match_id in enumerate(match_ids):
    match = api.matches().get(match_id)
    print("{}: {}; {}; {}; {}".format(
      i, match.id, datetime.strptime(match.created_at, "%Y-%m-%dT%H:%M:%SZ"), match.game_mode, match.map))

    rosters = match.rosters

    for roster in rosters:
      if any([participant.name in player_names for participant in roster.participants]):
        print([participant.name for participant in roster.participants])

        for participant in roster.participants:
          print("\t{}: kills={}; death_type={}; kill_place={}".format(
            participant.name, participant.kills, participant.death_type, participant.kill_place))
  #             print("winners(s): {}".format(roster.won))
    try:
      roster_index, winning_participants = get_winners(rosters)
      print("winners(s) [{}]: {}\n".format(roster_index, winning_participants))

    except TypeError:
      print('\nEXCEPTION! None type returned get_winners()\n')
      continue

  print('end')

def write_match_kill_details():

  non_player_kills = [
    "Damage_BlueZone",
    "Damage_Drown",
    "Damage_Explosion_RedZone",
    "Damage_Instant_Fall",
    "Damage_VehicleCrashHit"]

  player_names = ['eponymoose']
  players = api.players().filter(player_names=player_names)
  player = players[0]

  print("name: {}\nid: {}\n".format(player.name, player.id))

  matches = player.matches
  match_ids = [match.id for match in matches]

  match_id = match_ids[0]
  # match_id = "2a0346f6-2493-4deb-beb3-151af50ecf19"  # squad/erangel
  # match_id = "1deb2118-557e-4945-a8e1-81ae70bf62e3"
  # match_id = "42f94823-1e69-423e-983a-02f0973c9534"  # duo/sanhok

  match = api.matches().get(match_id)
  asset = match.assets[0]
  telemetry = api.telemetry(asset.url)

  player_kill_events = telemetry.events_from_type('LogPlayerKill')

  # print(player_kill_events)

  with open('c:/workspace/pubg-analytics/output/pubg_kill_events_{}.csv'.format(match.id), 'w', newline='') as f:
    writer = csv.writer(f, delimiter=',')
    writer.writerow(["killer", "killer_team_id", "victim", "victim_team_id"])
    for i, event in enumerate(player_kill_events):

      # TODO: add in logic for suicides
      killer_team = event.killer.team_id

      if event.damage_type_category in non_player_kills:
        killer_name = event.damage_type_category
        killer_team = 0
      else:
        if event.killer.name == "":
          killer_name = event.damage_type_category + "_MISSING_KILLER"
        else:
          killer_name = event.killer.name

      writer.writerow([killer_name, event.killer.team_id, event.victim.name, event.victim.team_id])

if __name__ in '__main__':

  api = PUBG(API_KEY, Shard.PC_OC)
  names = ['eponymoose', 'Stalkyard', 'Ritalin', 'yakabox']

  # get_player_ids(names, verbose=True)

  write_match_kill_details()


#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
Created on Mon Apr 17 22:27:34 2017

@author: bladestone
"""
from flask_apscheduler import APScheduler
from flask import Flask
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
import time,json
import urllib2
from flask import request
import traceback
import logging
logging.basicConfig()
scheduler=None

class Config(object):
    # JOBS = [
    #         {
    #            'id':'job1',
    #            'func':'flask-ap:test_data',
    #            'args': 'x',
    #            'trigger': {
    #                 'type': 'cron',
    #                 'day_of_week':"mon-fri",
    #                 'hour':'0-23',
    #                 'minute':'0-59',
    #                 'second': '*/5'
    #             }

    #          }
    #     ]
    SCHEDULER_API_ENABLED = True
    SCHEDULER_JOBSTORES = {
        'default': SQLAlchemyJobStore(url='sqlite:////var/www/jobs.sqlite')
    }

app = Flask(__name__, static_url_path='')

def get(URL):
    response = urllib2.urlopen(URL) #调用urllib2向服务器发送get请求
    return json.loads(response.read()) #获取服务器返回的页面信息

def post(URL,values):
    headers = {'Content-Type': 'application/json'}
    data = json.dumps(values)    #适用urllib对数据进行格式化编码
    req = urllib2.Request(url=URL, headers=headers, data=data)    #生成页面请求的完整数据
    response = urllib2.urlopen(req)     #发送页面请求
    return json.loads(response.read())    #获取服务器返回的页面信息
def task(d):
    print("work param:",d)
    r = get(d)
    print("work res:",r)

def jobfromparm(**jobargs):
    id = str(time.time())
    print('add job: ',id)
    job = scheduler.add_job(func=task,id=id, **jobargs)
    return 'sucess'

@app.route('/pause')
def pausejob():
    scheduler.pause_job('job1')
    return "Success!"

@app.route('/')
def index():
    return "杜萌你好!"

@app.route('/resume')
def resumejob():
    scheduler.resume_job('job1')
    return "Success!"

@app.route('/job', methods=['GET', 'POST'])
def job():
    try:
        if request.method=='POST':
            data = request.get_json(force=True)
            job = jobfromparm(**data)
            return json.dumps({'res':'sucess'})
        elif request.method=='GET':
            res = {'res':[]}
            for job in scheduler.get_jobs():
                t = {}
                t['id'] = job.id
                t['args'] = job.args
                t['trigger'] = str(job.trigger)
                res['res'].append(t)
            return json.dumps(res)
    except:
        traceback.print_exc()

@app.route('/job/<id>', methods=['GET', 'PUT', 'DELETE'])
def job_id(id):
    if request.method=='PUT':
        pass
        return 'sucess'
    elif request.method=='DELETE':
        scheduler.delete_job(id)
        return json.dumps({'res':'sucess'})
    elif request.method=='GET':
        job = scheduler.get_job(id)
        res = {'id':job.id,'args':job.args}
        return json.dumps(res)

if __name__ == '__main__':
    scheduler = APScheduler()
    print("Let us run out of the loop")
    app.config.from_object(Config())

    # it is also possible to enable the API directly
    # scheduler.api_enabled = True
    scheduler.init_app(app)
    scheduler.start()
    # scheduler.add_job('job3', test_data,trigger='cron',second='*/5',args=['z'])
    app.run(host='0.0.0.0',debug=True,threaded=False)


from django.conf.urls import patterns, include, url
from django.contrib import admin

urlpatterns = patterns('',
    # Examples:

    # url(r'^blog/', include('blog.urls')),
    # url(r'^view', 'Obrazki_django.views.home', name='home'),
    url(r'^$' ,       include('img_bro.urls')), # kiedy nie ma nic w pasku poza localhostem

    url(r'admin/', include(admin.site.urls)),
    url(r'', include('img_bro.urls')),
)


class SwitchBoard():
    '''A class to represent a switch board, which contains electrical
    switches like LightSwitch
    '''

    def __init__(self, number_of_switches):
        '''
        Create a switchboard with numer_of_switches, with that many switches
        switched to off

        REQ: number_of_switches >= 0

        >>>s1 = SwitchBoard(10)
        '''
        self._list_of_switches = []
        self._number_of_switches = number_of_switches
        for i in range(number_of_switches):
            self._list_of_switches.insert(i, LightSwitch("off"))

    def __str__(self):
        '''(SwitchBoard) --> str
        Return a string of what we want to print when we call to print
        a Switchboard object

        >>>s1 = SwitchBoard(12)
        >>>print(s1)
        The following switches are on:
        '''
        insert_counter = 0
        str_of_on = ""
        for i in range(len(self._list_of_switches)):
            if(self._list_of_switches[i]._power_state):
                str_of_on += str(i) + " "
        str_to_return = "The following switches are on: " + str_of_on
        return str_to_return

    def which_switch(self):
        '''(SwitchBoard) --> list of int
        Creates a list which contains the index values of which switches are on
        in the SwitchBoard
        '''
        self._switches_on = []
        insert_counter = 0
        for i in range(len(self._list_of_switches)):
            if(self._list_of_switches[i]._power_state):
                self._switches_on.insert(insert_counter, i)
                insert_counter += 1
        return self._switches_on

    def flip(self, switchplace):
        '''(SwitchBoard, int) --> None

        REQ: switchplace <= len(self._list_of_switches)

        Flip the state of the Switch at switchplace
        '''
        if(switchplace > (len(self._list_of_switches) - 1)):
            return
        elif(self._list_of_switches[switchplace]._power_state):
            self._list_of_switches[switchplace]._power_state = False
        else:
            self._list_of_switches[switchplace]._power_state = True

    def flip_every(self, switch_increment):
        '''(SwitchBoard, int) --> None

        REQ: switch_increment > 0 and
             switch_increment < len(self._list_of_switches)

        Flip the state of every switch, incrementing at switch_increment
        '''
        if(switch_increment <= 0):
            return
        i = 0
        while(i < len(self._list_of_switches)):
            self.flip(i)
            i += switch_increment

    def reset(self):
        '''(SwitchBoard) --> None
        Make all switches in the SwitchBoard false
        '''
        for i in range(len(self._list_of_switches)):
            self._list_of_switches[i]._power_state = False

class LightSwitch():
    '''A class to represent a light switch, or any other electrical switch'''

    def __init__(self, power):
        '''(LightSwitch, str) --> None
        Creates a lightswitch with power; on or off

        REQ: power == "on" or power == "off"

        >>>l1 = LightSwitch("on")

        >>>l1 = LightSwitch("off")
        '''
        power = power.lower()
        if(power == "on"):
            self._power_state = True
        elif(power == "off"):
            self._power_state = False

    def __str__(self):
        '''(LightSwitch) --> Str
        Return a string that prints out the current power state of the
        LightSwitch

        >>>l1 = LightSwitch("on")
        >>>l1
        I am on

        >>>l1 = LightSwitch("off")
        >>>l1
        I am off
        '''
        if(self._power_state):
            return "I am on"
        else:
            return "I am off"

    def turn_on(self):
        '''(LightSwitch) --> None
        Turn the LightSwitch's power state to on

        >>>l1 = LightSwitch("off")
        >>>l1.turn_on()
        >>>l1
        I am on
        '''
        self._power_state = True

    def turn_off(self):
        '''(LightSwitch) --> None
        Turn the LightSwitch's power state to off

        >>>l1 = LightSwitch("on")
        >>>l1.turn_off()
        >>>l1
        I am off
        '''
        self._power_state = False

    def flip(self):
        '''(LightSwitch) --> None
        Turn the LightSwitch; if it's off, turns it on... if it's on
        turns it off

        >>>l1 = LightSwitch("on")
        >>>l1.flip()
        >>>l1
        I am off

        >>>l1 = LightSwitch("off")
        >>>l1.flip()
        >>>l1
        I am on
        '''
        if(self._power_state):
            self._power_state = False
        else:
            self._power_state = True


import psutil
import time
import opentracing
import sys
import requests
import argparse
import logging

# log everything with no format, because these messages will be formatted
# and printed by the controller
logging.basicConfig(format='%(message)s', level=logging.DEBUG)

MEMORY_PERIOD = 1  # report memory use every 5 seconds
CONTROLLER_PORT = 8023
NUM_SATELLITES = 8
MAX_BUFFERED_SPANS = 10000
REPORTING_PERIOD = 200  # ms
SPANS_PER_LOOP = 6

def do_work(units):
    i = 1.12563
    for i in range(0, units):
        i *= i

def send_result(result):
    requests.get(f'http://localhost:{CONTROLLER_PORT}/result', params=result)

class Monitor:
    """ Special timer to measure process time and time spent as a result of
    this process' system calls.

    Records 2 * 10^-5 seconds when we immediately run start() then stop(), so
    tests should be at ms scale to dwarf this contribution.
    """
    def __init__(self):
        self.process = psutil.Process()

    def get_memory(self):
        """ Returns the size of process virtual memory """
        return self.process.memory_info()[0]

    def start(self):
        user, system, _, _ = self.process.cpu_times()
        self.start_cpu_time = user + system
        self.start_clock_time = time.time()
        self.get_cpu()

    def get_cpu(self):
        """ Gets CPU %, calculated since last call to split. """
        return self.process.cpu_percent(interval=None)

    def stop(self):
        user, system, _, _ = self.process.cpu_times()
        return (user + system - self.start_cpu_time,
                time.time() - self.start_clock_time)

def build_tracer(command, tracer_name, port):
    if command['Trace'] and tracer_name == "vanilla":
        logging.info("We're using the python tracer.")
        import lightstep
        return lightstep.Tracer(
            component_name='isaac_service',
            collector_port=port,
            collector_host='localhost',
            collector_encryption='none',
            use_http=True,
            access_token='developer',
            # these are much more aggressive than the defaults
            # but are common in production
            periodic_flush_seconds=REPORTING_PERIOD / 1000,
            max_span_records=MAX_BUFFERED_SPANS,
        )
    elif command['Trace'] and tracer_name == "cpp":
        logging.info("We're using the python-cpp tracer.")
        import lightstep_native
        return lightstep_native.Tracer(
            component_name='isaac_service',
            access_token='developer',
            use_stream_recorder=True,
            collector_plaintext=True,
            satellite_endpoints=[{'host': 'localhost', 'port': p}
                                 for p in range(port, port + NUM_SATELLITES)],
            max_buffered_spans=MAX_BUFFERED_SPANS,
            reporting_period=REPORTING_PERIOD,
        )

    logging.info("We're using a NoOp tracer.")
    return opentracing.Tracer()

def generate_spans(tracer, units_work, number_spans, scope=None):
    assert number_spans >= 1

    # since python-cpp tracer doesn't allow child_of=None
    child_of_kwargs = {'child_of': scope.span} if scope else {}

    with tracer.start_active_span(
            operation_name='make_some_request',
            **child_of_kwargs) as client_scope:

        client_scope.span.set_tag('http.url', 'http://somerequesturl.com')
        client_scope.span.set_tag('http.method', "POST")
        client_scope.span.set_tag('span.kind', 'client')
        do_work(units_work)
        number_spans -= 1
        if number_spans == 0:
            return

        with tracer.start_active_span(
                operation_name='handle_some_request') as server_scope:
            server_scope.span.set_tag('http.url', 'http://somerequesturl.com')
            server_scope.span.set_tag('span.kind', 'server')
            server_scope.span.log_kv({
                'event': 'cache_miss',
                'message': 'some cache missed :('
            })

            do_work(units_work)
            number_spans -= 1
            if number_spans == 0:
                return

            with tracer.start_active_span(
                    operation_name='database_write') as db_scope:
                db_scope.span.set_tag('db.user', 'test_user')
                db_scope.span.set_tag('db.type', 'sql')
                db_scope.span.set_tag(
                    'db_statement',
                    "UPDATE ls_employees SET email = 'isaac@lightstep.com' " +
                    "WHERE employeeNumber = 27;")

                # pretend that an error happened
                db_scope.span.set_tag('error', True)
                db_scope.span.log_kv({
                    'event': 'error',
                    'stack': """File \"example.py\", line 7, in <module>
                                caller()
                                File \"example.py\", line 5, in caller
                                callee()
                                File \"example.py\", line 2, in callee
                                raise Exception(\"Yikes\")"""})

                do_work(units_work)
                number_spans -= 1
                if number_spans == 0:
                    return

            generate_spans(tracer, units_work,
                           number_spans, scope=server_scope)

def perform_work(command, tracer_name, port):
    logging.info("About to run this test: {}".format(command))
    logging.info("Connecting to satellite on port {}".format(port))

    # if exit is set to true, end the program
    if command['Exit']:
        send_result({})
        logging.info("sent exit response, now exiting...")
        sys.exit()

    tracer = build_tracer(command, tracer_name, port)

    sleep_debt = 0
    spans_sent = 0

    last_memory_save = time.time()
    memory_list = []
    cpu_list = []

    monitor = Monitor()
    monitor.start()

    while spans_sent < command['Repeat']:
        spans_to_send = min(command['Repeat'] - spans_sent, SPANS_PER_LOOP)
        generate_spans(tracer, command['Work'], spans_to_send)
        spans_sent += spans_to_send
        sleep_debt += command['Sleep'] * spans_to_send

        if sleep_debt > command['SleepInterval']:
            sleep_debt -= command['SleepInterval']
            # 10^-9 nanoseconds / second
            time.sleep(command['SleepInterval'] * 10**-9)

        if time.time() > last_memory_save + MEMORY_PERIOD:
            memory_list.append(monitor.get_memory())
            # saves CPU percentage as fraction since last call
            cpu_list.append(monitor.get_cpu() / 100)
            last_memory_save = time.time()

    memory_list.append(monitor.get_memory())

    # don't include flush in time measurement
    if command['Trace'] and not command['NoFlush']:
        logging.info("Flushing spans.")
        tracer.flush()

    cpu_time, clock_time = monitor.stop()

    result = {
        'ProgramTime': cpu_time,
        'ClockTime': clock_time,
        'SpansSent': spans_sent,
        'MemoryList': memory_list,
        'CPUList': cpu_list,
    }

    logging.info("Sending result to controller:")
    logging.info(result)
    send_result(result)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='Start a client to test a LightStep tracer.')

    parser.add_argument(
        'port',
        type=int,
        help='Which port to connect to the satellite on.')

    parser.add_argument(
        'tracer',
        type=str,
        choices=["vanilla", "cpp"],
        help='Which LightStep tracer to use.')

    args = parser.parse_args()

    while True:
        r = requests.get(f'http://localhost:{CONTROLLER_PORT}/control')
        perform_work(r.json(), args.tracer, args.port)


#!/usr/bin/env python

"""
KEGG enrichment parser Scripts.
Author: Keigo IDE
mail: ide_0109@outlook.jp
"""

import argparse
import sys
from collections import defaultdict
from collections import Counter

def create_kegg_dict(kegg_file):
    '''
    keyword argunemt:
        kegg_file: Kegg_files were downloaded from KEGG web server (ex. ko00001.keg)
    return:
        kegg dictionary objects(input: kegg id, output: Category, Gene, Annotation)
    '''
    input_files = open(kegg_file, 'r')
    kegg = input_files.readlines()

    d = defaultdict(dict)

    for i in kegg:
        if i[0] in {"#", "!"}:
            continue
        elif i[0] == "A":
            Category_tmp = i.split("<b>")
            Category = Category_tmp[1]
            Category = Category.rstrip(Category[-5:])
        elif i[0] == "B":
            continue
        elif i[0] == "C":
            Pathway_tmp = i.split()
            del Pathway_tmp[0:2]
            Pathway_tmp = Pathway_tmp.pop()
            Pathway = " ".join(Pathway_tmp)
        elif i[0] == "D":
            Annotation_tmp = i.split()
            Kegg_id = Annotation_tmp[1]
            del Annotation_tmp[0:2]
            Annotation_tmp.pop(len(Annotation_tmp)-1)
            Annotation_tmp2 = " ".join(Annotation_tmp)
            Annotation_tmp3 = Annotation_tmp2.split(";")
            d[Kegg_id]["Category"] = Category
            d[Kegg_id]["Gene"] = Annotation_tmp3[0]
            d[Kegg_id]["Annotation"] = Annotation_tmp3[1]

    return d


from .config import (COOKIE_NAME, COOKIE_REMEMBER_ME, COOKIE_DURATION,
                     COOKIE_SECURE, COOKIE_HTTPONLY, LOGIN_REQUIRED_MESSAGE, LOGIN_REQUIRED_ROUTE,
                     LOGIN_PROHIBITED_MESSAGE, LOGIN_PROHIBITED_ROUTE, DISABLE_RUNTIME_WARNING)

def UNAUTHORIZED(req, resp, *_, **__):
    if LOGIN_REQUIRED_ROUTE:
        resp.headers.update({"Location": LOGIN_REQUIRED_ROUTE})
    resp.text = LOGIN_REQUIRED_MESSAGE
    resp.status_code = 401

def AUTHORIZED(req, resp, *_, **__):
    if LOGIN_PROHIBITED_ROUTE:
        resp.headers.update({"Location": LOGIN_PROHIBITED_ROUTE})
    resp.text = LOGIN_PROHIBITED_MESSAGE
    resp.status_code = 403


import pandas as pd
import numpy as np
from random import randint
import matplotlib.pyplot as plt

#code init
iterations = 50
ants = 15
twt = 240

#datastructure
graph = []
ph = []
num_node = 0
nodes = []

#param
alpha=0.5
beta=0.5
dens=0.25

#vehicals path
veh1 = []
veh2 = []
veh3 = []
all_st = {}

def read_data():
	global graph
	global ph
	global num_node
	global nodes

	#reading time matrix from csv file
	dt = pd.read_csv('ip3.csv')
	graph = dt.to_numpy()
	num_node = len(graph)
	temp = []

	#initiallization of
	for i in range(num_node):
		ph.append([1 for i in range(num_node)])

	#initiallization of all nodes
	nodes = [ i for i in range(num_node) ]

def start_ant(nvis,dpot):
	global graph
	global ph
	global num_node
	global nodes

	# init, cp(current position) is dpot.
	cp=dpot
	path = []
	path.append(cp)
	# This loop makes ant to visit each&every vertex. By the time visiting the vertex, it will remove the vertex from nvis(not visited list).
	while len(nvis)!=0:
		#count the probabilities of non visited vertex.
		probabilities = list(map(lambda x: ( ( ( (ph[cp][x])**alpha)*((1/graph[cp][x])**beta))  ) , nvis))
		probabilities = probabilities/np.sum(probabilities)

		# counting next vertex in the bases of heigest probability.
		cp=nvis[0]
		mm=probabilities[0]
		for i in range(len(probabilities)):
			if probabilities[i] >mm:
				mm=probabilities[i]
				cp=nvis[i]
		# appending next vertex in path and removing from the list of non visited vertex.
		path.append(cp)
		nvis.remove(cp)
	#returning the path of individual ant.
	return path

def update_feromone(dpot,best_solution,shortest_time):
	# for all the edge, decresing the level of feromone.
	for i in range(num_node):
		for j in range(num_node):
			ph[i][j] -= (1-dens)*ph[i][j]
			# if the feromone level become 0 then it will not appropriate for the probability count.
			# So, I've taken 0.0000000001 insted of 0.
			if ph[i][j]<=0:
				ph[i][j]=(10**(-10))

	# cp is current position
	# starting from dpot which is 0 by default.
	cp = dpot

	#end of the path is also dpot(0). so, i'm appending mnly.
	best_solution[1].append(dpot)
	#path = [1,2,3,4,0]
	# 0-1
	# 1-2
	# 2-3
	# 3-4
	# 4-0

	# taking each edges in best path and updating feromone level.
	for x in best_solution[1]:
		if cp != x:
			#Q=1,l=graph[cp][x]
			ph[cp][x] += 1/graph[cp][x] + (ants/6)*(1/shortest_time[0])
			ph[x][cp] = ph[cp][x]
			cp=x

def total_traveltime(path,dpot):
	# this function counts the summation of the path.
	x=dpot
	travel_time = 0
	for y in path:
		travel_time+=graph[x][y]
		x=y
	travel_time+=graph[x][dpot]
	return travel_time

def get_best_solution(solution):
	# this function returns path which has min length.
	bs=solution[0]
	for soln in solution:
		if bs[0]>soln[0]:
			bs=soln
	return bs

def opt_2(path):
	#making 2 path. temp_path is old path. "path" is the path where all the 2-opt changes gonna happen.
	temp_path = path.copy()

	#temp_path,path

	# path <- 2-opt

	# path = [2,3,4,5,2,3,0]
	# selecting rendomly node from the path and removing that node.
	rnd_node = np.random.choice(path[:-1])
	path.remove(rnd_node)

	#inserting the selected node randomaly.
	path.insert( randint(0, len(path[:-1])) ,rnd_node)

	#path = [ 2,5,3,4,2,3,0]
	# return temp_path
	#If the new path has less cost than old one, update the  path by returning new one.
	if total_traveltime(temp_path,0) > total_traveltime(path,0):
		return path
	else:
		return temp_path

def select_nodes(path):
	#1--3-4-5-6
	# 3 = 66
	# 1 = 50
	inds = []
	cp=0
	# path = 0-1-2 = 0-2
	# time(0,1) + time(1,2) - time(0,2)
	# ans = [ (-50,2) , ( -100 , 1 )  ]
	for i in range(0,len(path)-1):
		change = graph[path[cp]][path[i]]+graph[path[i]][ path[i+1] ]-graph[path[cp]][path[i+1]]
		inds.append( (-1*change, path[i] ) )
		cp=i
	inds.sort()
	#ans = [ (-100,1) , (-50,2) ]
	return inds

def start_spreading_ants(nvis,shortest_time,veh_type,itr,limit):
	global graph
	global ph
	global num_node
	global nodes

	global veh1
	global veh2
	global veh3
	global all_st

	#solution will store all the paths which are coverd by 13 ants.
	solution = []

	for i in range(ants):
		#nvis is list of not visited nodes.
		nnvis = nvis.copy()
		#selecting randome starting point.
		dpot = np.random.choice(nnvis)
		nnvis.remove(dpot)
		#ant will start from the mentioned dpot.
		path = start_ant(nnvis,dpot)
		if len(path)>2:
			path = opt_2(path)
		solution.append( (total_traveltime(path,0),path) )

	# "get_best_solution" will return shortest path coverd among all the ants.
	best_solution = get_best_solution(solution)

	# "opt_2" will apply 2-opt method on best solution.
	if( len(best_solution[1])>1 ):
		opt_best_solution = opt_2(best_solution[1])
		# upedating the best solution.
		#todo:
		best_solution = ( total_traveltime(opt_best_solution,0) , opt_best_solution )

	# print("best",best_solution)
	ID = 240-best_solution[0]
	# if the idle time is positive and pass the given condition then only we can apply idle time optimization
	if itr>limit and ID>0:
		if veh_type==2:
			from_veh_type = 1
			inds = []

			# if the idle time is greater then twt/4, then only vehicle can adopt the node from othervehivle
			# this is minimum cindition

			while twt/4 <= ID:
				# select node will return the list of node of from_veh_type_type
				# this list of node is sorted inorder to get the node which decrease the traveling time most
				inds = select_nodes(all_st[from_veh_type][1])
				if( len(inds)<=3 ):
					break
				# inds = [ (-100,1) , (-50,2) ]
				#lock is use to terminate the while loop. if the vehicle is not able to adopt any node from other vehicle
				lock = True

				for ind in inds:
					#ind = (-100,1)
					#slp = second last position
					#lp = last position
					# for exaample path : 1-2-3-4-5-6 then slp=5, lp=6
					slp = best_solution[1][-2]
					lp = best_solution[1][-1]

					#checking that after adding one node, the total time of the path is less then 240 or not
					if graph[slp][ind[1]]+graph[ind[1]][lp]-graph[slp][lp]+best_solution[0] < twt:
						#lock is false because we found one node which is adopted by the vehicle
						lock=False
						#removing and updating the node from the solution of from vehicle
						all_st[from_veh_type][1].remove(ind[1])
						all_st[from_veh_type]=(total_traveltime(all_st[from_veh_type][1],0),all_st[from_veh_type][1])

						#appending the new node in the vehicle's path, and updating the best solution of this vehicle.
						veh2.append(ind[1])
						all_st[2][1].remove(0)
						all_st[2][1].append(ind[1])
						all_st[2][1].append(0)
						all_st[2]=(total_traveltime(all_st[2][1],0) , all_st[2][1] )

						#after adding new node, updating the best solution.
						shortest_time=all_st[2]
						best_solution=all_st[2]
						veh1.remove(ind[1])
						# counting IDLE time again, if the idle time is more than twt/4, then again we will adopt one more node.
						ID = 240-best_solution[0]
						break
				# if vehicle not able to adopt any node then we will break the current while loop
				if lock:
					break
		elif veh_type==3:
			inds = []
			# checking basic condition for single node adoption.
			while twt/4 <=ID:
				#lock is use to terminate the while loop. if the vehicle is not able to adopt any node from other vehicle
				lock = True

				# vehicle 3 can adopt node for either vehicle1 or vehicle2
				# counting idle time for both vehicles,
				ID1 = 240 - all_st[1][0]
				ID2 = 240 - all_st[2][0]
				from_veh_type = -1

				#which ever vehicle has higher value we will adopt node from that vehicle.
				if ID1>ID2 and len(veh2)>3:
					from_veh_type=2
				elif ID1<ID2 and len(veh1)>3:
					from_veh_type=1
				else:
					break

				# selectiong node from selected vehicle
				# select node will return the list of node of from_veh_type_type
				# this list of node is sorted inorder to get the node which decrease the traveling time most
				inds = select_nodes(all_st[from_veh_type][1])

				#iterate through all the nodes and chech the conditions.
				for ind in inds:
					#slp = second last position
					#lp = last position
					# for exaample path : 1-2-3-4-5-6 then slp=5, lp=6
					slp = best_solution[1][-2]
					lp = best_solution[1][-1]

					#checking that after adding one node, the total time of the path is less then 240 or not
					if graph[slp][ind[1]]+graph[ind[1]][lp]-graph[slp][lp]+best_solution[0] < twt:
						#lock is false because we found one node which is adopted by the vehicle
						lock=False
						#removing and updating the node from the solution of from vehicle
						all_st[from_veh_type][1].remove(ind[1])
						all_st[from_veh_type]=(total_traveltime(all_st[from_veh_type][1],0),all_st[from_veh_type][1])

						#appending the new node in the vehicle's path, and updating the best solution of this vehicle.
						veh3.append(ind[1])
						all_st[3][1].remove(0)
						all_st[3][1].append(ind[1])
						all_st[3][1].append(0)
						all_st[3]=(total_traveltime(all_st[3][1],0) , all_st[3][1] )
						#after adding new node, updating the best solution.
						shortest_time=all_st[3]
						best_solution=all_st[3]
						#removing the node from from_veh_type_type vehicle
						if from_veh_type==1:
							if ind[1] in veh1:
								veh1.remove(ind[1])
						else:
							if ind[1] in veh2:
								veh2.remove(ind[1])
						# counting IDLE time again, if the idle time is more than twt/4, then again we will adopt one more node.
						ID = 240-best_solution[0]
						break
				# if vehicle not able to adopt any node then we will break the current while loop
				if lock:
					break

	#updating the shortest time
	if shortest_time[0] > best_solution[0]:
		shortest_time=best_solution

	#This will update the feromone level.
	update_feromone(0,best_solution,shortest_time)
	return shortest_time

def main():
	global alpha
	global beta
	global dens
	global iterations

	global veh1
	global veh2
	global veh3
	global all_st

	# # init the path of all vehicles
	# veh1 = [1, 4, 6, 9, 10, 12]
	# veh2 = [8,11,2,13,5]
	# veh3 = [3,7]

	#output graph datastructure = x,veh1,veh2,veh3

	#printing the value of parameters of the algo
	print("alpha:",alpha, " | beta:", beta, " | density",dens, " | Iterations: ",iterations, " | ants:",ants)

	# # code for n number of iteration
	# limit = randint(4,8)

	vehs_type1 = [[1,4,6,9,10,12],[55,92,20,33,18],[72,51,79,41,39],[98,16,17,76,56],[21,84,52,99,28],[15,93,27,73,24],[53,59,68,82,25,14],[50,38,75,91,97],[90,85,83,74,29],[70,64,54,46,66,81]]
	vehs_type2 = [[45,48,77,86],[8,11,13,2,5],[26,30,43,96],[31,40,58,62],[34,47,95,63],[36,49,60,65,67],[37,44,61],[69,71,78,80]]
	vehs_type3 = [[42,32,23],[19,100,89],[57,88,94],[87,22,35],[3,7]]

	for comb in range(0,10):
		"""
			0, (0,0,0)
			1, (1,1,1)
			.
			.
			.
			5, (5,5,0)
			.
			.
			.
			9, (9,1,4)
		"""
		veh1 = vehs_type1[ comb%10 ]
		veh2 = vehs_type2[ comb%8 ]
		veh3 = vehs_type3[ comb%5 ]
		limit = randint(4,8)
		plt.clf()
		output_graph = [ [] , [] , [] , [] ]

		# for n number of iterations, spreading ants in the graph.
		all_st[1] = (10**200,[])
		all_st[2] = (10**200,[])
		all_st[3] = (10**200,[])

		for itr in range(iterations):
			read_data()

			# iterations=itr

			for ii in range(itr):
				# this will start spreading ants in the graph.This will return shortest time of all the previous iterations
				all_st[1]= start_spreading_ants(veh1,all_st[1],1,ii,limit)
				all_st[1] = ( total_traveltime( all_st[1][1] , 0 ) , all_st[1][1] )

			for ii in range(itr):
				# this will start spreading ants in the graph.This will return shortest time of all the previous iterations
				all_st[2] = start_spreading_ants(veh2,all_st[2],2,ii,limit)
				all_st[2] = ( total_traveltime( all_st[2][1] , 0) , all_st[2][1] )

			for ii in range(itr):
				# this will start spreading ants in the graph.This will return shortest time of all the previous iterations
				all_st[3] = start_spreading_ants(veh3,all_st[3],3,ii,limit)
				all_st[3] = ( total_traveltime( all_st[3][1] , 0) , all_st[3][1] )

			#printing result, shortest time of all the vehicals.
			if itr!=0:
				print(itr,all_st)
				output_graph[0].append(itr)
				output_graph[1].append(all_st[1][0])
				output_graph[2].append(all_st[2][0])
				output_graph[3].append(all_st[3][0])

		plt.plot(output_graph[0] , output_graph[1], label="Vehicle 1"  )
		plt.plot(output_graph[0] , output_graph[2], label="Vehicle 2"  )
		plt.plot(output_graph[0] , output_graph[3], label="Vehicle 3"  )
		ttl = "Elist Combinations : " + str(comb+1)
		plt.title( ttl)
		plt.legend()
		plt.show()
		plt.close()

if __name__ == '__main__':
	main()


import numpy as np

from openmdao.api import ExplicitComponent
from lsdo_cubesat.utils.utils import get_array_indices

class VectorBodyComp(ExplicitComponent):
    """
    Transform from body to inertial frame.
    """
    def initialize(self):
        self.options.declare('num_times', types=int)

    def setup(self):
        num_times = self.options['num_times']

        self.add_input('r_b2g_I',
                       np.zeros((3, num_times)),
                       units='km',
                       desc='Position vector from satellite to ground station '
                       'in Earth-centered inertial frame over time')

        self.add_input(
            'rot_mtx_i_b_3x3xn',
            np.zeros((3, 3, num_times)),
            units=None,
            desc='Rotation matrix from body-fixed frame to Earth-centered'
            'inertial frame over time')

        self.add_output(
            'r_b2g_B',
            np.zeros((3, num_times)),
            units='km',
            desc='Position vector from satellite to ground station '
            'in body-fixed frame over time')

        ones_3 = np.ones(3, int)
        mtx_indices = get_array_indices(*(3, 3, num_times))
        vec_indices = get_array_indices(*(3, num_times))

        rows = np.einsum('in,j->ijn', vec_indices, ones_3).flatten()
        cols = mtx_indices.flatten()
        self.declare_partials('r_b2g_B',
                              'rot_mtx_i_b_3x3xn',
                              rows=rows,
                              cols=cols)

        rows = np.einsum('in,j->ijn', vec_indices, ones_3).flatten()
        cols = np.einsum('jn,i->ijn', vec_indices, ones_3).flatten()
        self.declare_partials('r_b2g_B', 'r_b2g_I', rows=rows, cols=cols)

    def compute(self, inputs, outputs):
        num_times = self.options['num_times']

        rot = inputs['rot_mtx_i_b_3x3xn']

        outputs['r_b2g_B'] = np.einsum('ijn,jn->in',
                                       inputs['rot_mtx_i_b_3x3xn'],
                                       inputs['r_b2g_I'])

        # np.savetxt("rundata/rot_mtx_i_b_3x3xn.csv", rot, header="r_b2g_I")

    def compute_partials(self, inputs, partials):
        num_times = self.options['num_times']

        partials['r_b2g_B',
                 'rot_mtx_i_b_3x3xn'] = np.einsum('jn,i->ijn',
                                                  inputs['r_b2g_I'],
                                                  np.ones(3)).flatten()
        partials['r_b2g_B', 'r_b2g_I'] = inputs['rot_mtx_i_b_3x3xn'].flatten()

if __name__ == '__main__':
    from openmdao.api import Problem, IndepVarComp

    num_times = 4

    prob = Problem()

    comp = IndepVarComp()
    comp.add_output('r_b2g_I', val=10 * np.random.random((3, num_times)))
    comp.add_output('rot_mtx_i_b_3x3xn',
                    val=10 * np.random.random((3, 3, num_times)))
    prob.model.add_subsystem('inputs_comp', comp, promotes=['*'])

    comp = VectorBodyComp(num_times=num_times, )
    prob.model.add_subsystem('comp', comp, promotes=['*'])

    prob.setup()
    prob.run_model()
    prob.model.list_outputs()
    prob.check_partials(compact_print=True)


class a:
  def __init__(self,a=None,b=None,c=None):
    print("This is a consturcto overloading")
t1=a()
t2=a(10)
t1=a(10,20,30)
print()

print("class b")
class b:
  def __init__(self,*a):
    print("This is a class b consturcto overloading")
t1=b()
t2=b(10)
t1=b(10,20,30)