#!/usr/bin/python3
import argparse
import logging

import slackclient
import json
import datetime

class UserMap:
    def __init__(self, user_id_to_name):
        self._user_id_to_name = user_id_to_name

    def get_username(self, message):
        if message.get("user"):
            return self._user_id_to_name[message["user"]]
        if message.get("bot_id"):
            return message["bot_id"]
        raise Exception("unknown username: %s" % message)

class APIWrapper:
    def __init__(self, token):
        self._slackclient = slackclient.SlackClient(token)

    def get_messages(self, channel_name):
        """ get all messages from channel """
        channel_id = self._channel_name_to_channel_id(channel_name)
        msgs = []
        while True:
            args = dict(count=1000, channel=channel_id)
            if msgs:
                args["latest"] = msgs[-1]["ts"]
            resp = self._api_call("channels.history", **args)
            msgs += resp["messages"]
            if resp["is_limited"] or not resp["has_more"]:
                break
        return msgs

    def get_user_map(self):
        users = self._api_call("users.list")
        user_map_data = {u["id"]: u["name"] for u in users["members"]}
        return UserMap(user_map_data)

    def _channel_name_to_channel_id(self, channel_name):
        channels = self._api_call("channels.list")
        for c in channels["channels"]:
            if c.get("name") == channel_name:
                return c.get("id")
        raise KeyError("Channel %s not found in %s" % (channel_name, channels))

    def _api_call(self, *a, **kw):
        resp = self._slackclient.api_call(*a, **kw)
        if not resp["ok"]:
            raise Exception("not ok")
        return resp

def nice_ts(tsarg):
    """ prettify timestamp string with microseconds precision
        NOTE: timezones may not always work correctly
    """
    ts, msec = map(int, tsarg.split("."))
    d = datetime.datetime.fromtimestamp(ts)
    d = d.replace(microsecond=msec)
    return d.strftime("%Y-%m-%d %H:%M:%S.%f")

def prettify_text_for_csv(text):
    if "\n" in text:
        text = "\n" + text
    # standard CSV escape character is "
    text = text.replace("\"", "\"\"")
    text = text.replace("\t", "\"\t")
    return text

def make_csv_line(msg):
    """ prefix multiline message with \n, for better reading comfort
        and escape characters, so that CSV can be parsed again
    """
    text = prettify_text_for_csv(msg.get("text", ""))
    return "\t".join([msg["datetime"], msg["username"], text])

def get_pretty_messages(client, channel):
    msgs = client.get_messages(channel)
    user_map = client.get_user_map()

    for m in msgs:
        try:
            m["datetime"] = nice_ts(m["ts"])
            m["username"] = user_map.get_username(m)
            m["csv_line"] = make_csv_line(m)
        except Exception:
            logging.exception("Error with message %s" % m)
    return msgs

def run():
    p = argparse.ArgumentParser(description="Dump slack channel archive in full JSON and human-readable CSV")
    p.add_argument("--channel", default="konfa")
    p.add_argument("-s", "--secret-file", default="secret.txt",
                   help="Get it from https://api.slack.com/custom-integrations/legacy-tokens")
    p.add_argument("--csv", default="output.csv", help="Output csv path")
    p.add_argument("--json", default="output.json", help="Output json path")
    args = p.parse_args()

    client = APIWrapper(open(args.secret_file, "r").read().strip())
    msgs = get_pretty_messages(client, args.channel)
    with open(args.json, "w") as jsonfile:
        json.dump(msgs, jsonfile, indent=4)
    with open(args.csv, "w") as csvfile:
        for l in msgs:
            # noinspection PyTypeChecker
            print(l["csv_line"], file=csvfile)

if __name__ == "__main__":
    run()


"""Creates an image from a numpy array of floating point depth data.

Taken from https://github.com/ahundt/robotics_setup/blob/master/datasets/google_brain_robot_data/depth_image_encoding.py

Examples:

  depth_array is a 2D numpy array of floating point depth data in meters.

  depth_rgb = FloatArrayToRgbImage(depth_array)
  depth_rgb is a PIL Image object containing the same data as 24-bit
  integers encoded in the RGB bytes.
  depth_rgb.save('image_file.png') - to save to a file.

  depth_array2 = ImageToFloatArray(depth_rgb)
  depth_array2 is a 2D numpy array containing the same data as
  depth_array up to the precision of the RGB image (1/256 mm).

  depth_gray = FloatArrayToGrayImage(depth_array)
  depth_gray is a PIL Image object containing the same data rounded to
  8-bit integers.
  depth_gray.save('image_file.jpg', quality=95) - to save to a file.

  depth_array3 = ImageToFloatArray(depth_gray)
  depth_array3 is a 2D numpy array containing the same data as
  depth_array up to the precision of the grayscale image (1 cm).

The image conversions first scale and round the values and then pack
them into the desired type in a numpy array before converting the
array to a PIL Image object.  The Image can be saved in any format.
We are using PNG for RGB and high quality JPEG for grayscale images.

You can use different numeric types (e.g. np.uint16, np.int32), but
not all combinations of numeric type and image format are supported by
PIL or standard image viewers.

"""

import numpy as np
from PIL import Image

def ClipFloatValues(float_array, min_value, max_value):
  """Clips values to the range [min_value, max_value].

  First checks if any values are out of range and prints a message.
  Then clips all values to the given range.

  Args:
    float_array: 2D array of floating point values to be clipped.
    min_value: Minimum value of clip range.
    max_value: Maximum value of clip range.

  Returns:
    The clipped array.

  """
  if float_array.min() < min_value or float_array.max() > max_value:
    float_array = np.clip(float_array, min_value, max_value)
  return float_array

DEFAULT_RGB_SCALE_FACTOR = 256000.0

def float_array_to_rgb_image(float_array,
                             scale_factor=DEFAULT_RGB_SCALE_FACTOR,
                             drop_blue=False):
  """Convert a floating point array of values to an RGB image.

  Convert floating point values to a fixed point representation where
  the RGB bytes represent a 24-bit integer.
  R is the high order byte.
  B is the low order byte.
  The precision of the depth image is 1/256 mm.

  Floating point values are scaled so that the integer values cover
  the representable range of depths.

  This image representation should only use lossless compression.

  Args:
    float_array: Input array of floating point depth values in meters.
    scale_factor: Scale value applied to all float values.
    drop_blue: Zero out the blue channel to improve compression, results in 1mm
      precision depth values.

  Returns:
    24-bit RGB PIL Image object representing depth values.
  """
  # Scale the floating point array.
  scaled_array = np.floor(float_array * scale_factor + 0.5)
  # Convert the array to integer type and clip to representable range.
  min_inttype = 0
  max_inttype = 2**24 - 1
  scaled_array = ClipFloatValues(scaled_array, min_inttype, max_inttype)
  int_array = scaled_array.astype(np.uint32)
  # Calculate:
  #   r = (f / 256) / 256  high byte
  #   g = (f / 256) % 256  middle byte
  #   b = f % 256          low byte
  rg = np.divide(int_array, 256)
  r = np.divide(rg, 256)
  g = np.mod(rg, 256)
  image_shape = int_array.shape
  rgb_array = np.zeros((image_shape[0], image_shape[1], 3), dtype=np.uint8)
  rgb_array[..., 0] = r
  rgb_array[..., 1] = g
  if not drop_blue:
    # Calculate the blue channel and add it to the array.
    b = np.mod(int_array, 256)
    rgb_array[..., 2] = b
  image_mode = 'RGB'
  image = Image.fromarray(rgb_array, mode=image_mode)
  return image

DEFAULT_GRAY_SCALE_FACTOR = {np.uint8: 100.0,
                             np.uint16: 1000.0,
                             np.int32: DEFAULT_RGB_SCALE_FACTOR}

def float_array_to_grayscale_image(float_array, scale_factor=None, image_dtype=np.uint8):
  """Convert a floating point array of values to an RGB image.

  Convert floating point values to a fixed point representation with
  the given bit depth.

  The precision of the depth image with default scale_factor is:
    uint8: 1cm, with a range of [0, 2.55m]
    uint16: 1mm, with a range of [0, 65.5m]
    int32: 1/256mm, with a range of [0, 8388m]

  Right now, PIL turns uint16 images into a very strange format and
  does not decode int32 images properly.  Only uint8 works correctly.

  Args:
    float_array: Input array of floating point depth values in meters.
    scale_factor: Scale value applied to all float values.
    image_dtype: Image datatype, which controls the bit depth of the grayscale
      image.

  Returns:
    Grayscale PIL Image object representing depth values.

  """
  # Ensure that we have a valid numeric type for the image.
  if image_dtype == np.uint16:
    image_mode = 'I;16'
  elif image_dtype == np.int32:
    image_mode = 'I'
  else:
    image_dtype = np.uint8
    image_mode = 'L'
  if scale_factor is None:
    scale_factor = DEFAULT_GRAY_SCALE_FACTOR[image_dtype]
  # Scale the floating point array.
  scaled_array = np.floor(float_array * scale_factor + 0.5)
  # Convert the array to integer type and clip to representable range.
  min_dtype = np.iinfo(image_dtype).min
  max_dtype = np.iinfo(image_dtype).max
  scaled_array = ClipFloatValues(scaled_array, min_dtype, max_dtype)

  image_array = scaled_array.astype(image_dtype)
  image = Image.fromarray(image_array, mode=image_mode)
  return image

def image_to_float_array(image, scale_factor=None):
  """Recovers the depth values from an image.

  Reverses the depth to image conversion performed by FloatArrayToRgbImage or
  FloatArrayToGrayImage.

  The image is treated as an array of fixed point depth values.  Each
  value is converted to float and scaled by the inverse of the factor
  that was used to generate the Image object from depth values.  If
  scale_factor is specified, it should be the same value that was
  specified in the original conversion.

  The result of this function should be equal to the original input
  within the precision of the conversion.

  Args:
    image: Depth image output of FloatArrayTo[Format]Image.
    scale_factor: Fixed point scale factor.

  Returns:
    A 2D floating point numpy array representing a depth image.

  """
  image_array = np.array(image)
  image_dtype = image_array.dtype
  image_shape = image_array.shape

  channels = image_shape[2] if len(image_shape) > 2 else 1
  assert 2 <= len(image_shape) <= 3
  if channels == 3:
    # RGB image needs to be converted to 24 bit integer.
    float_array = np.sum(image_array * [65536, 256, 1], axis=2)
    if scale_factor is None:
      scale_factor = DEFAULT_RGB_SCALE_FACTOR
  else:
    if scale_factor is None:
      scale_factor = DEFAULT_GRAY_SCALE_FACTOR[image_dtype.type]
    float_array = image_array.astype(np.float32)
  scaled_array = float_array / scale_factor
  return scaled_array

def task_file_to_task_class(task_file):
  import importlib
  name = task_file.replace('.py', '')
  class_name = ''.join([w[0].upper() + w[1:] for w in name.split('_')])
  mod = importlib.import_module("rlbench.tasks.%s" % name)
  mod = importlib.reload(mod)
  task_class = getattr(mod, class_name)
  return task_class

def rgb_handles_to_mask(rgb_coded_handles):
  # rgb_coded_handles should be (w, h, c)
  # Handle encoded as : handle = R + G * 256 + B * 256 * 256
  rgb_coded_handles *= 255  # takes rgb range to 0 -> 255
  rgb_coded_handles.astype(int)
  return (rgb_coded_handles[:, :, 0] +
          rgb_coded_handles[:, :, 1] * 256 +
          rgb_coded_handles[:, :, 2] * 256 * 256)


'''

                            Online Python Compiler.
                Code, Compile, Run and Debug python program online.
Write your code in this editor and press "Run" button to execute it.

'''
def kbig(nums, k):
    max_num=max(nums)
    for i in range(k):
        n=max(nums)
        nums.remove(int(n))
    print(n)


import os

#os.environ['LD_LIBRARY_PATH'] += ':/usr/local/cuda-11.1/bin64:/usr/local/cuda-11.2/bin64'

import numpy as np
import torch
import torch.multiprocessing as mp
import torch_geometric.datasets as GeoData
from modelnet40 import ModelNet40
from torch.utils.data import DataLoader, Sampler
import torch_geometric.transforms as T
from torch.nn.parallel import DistributedDataParallel
from torch.utils.data.distributed import DistributedSampler
from config import OptInit
from architecture import ClassificationGraphNN, ClassificationGraphNN2
from utils.ckpt_util import load_pretrained_models, load_pretrained_optimizer, save_checkpoint
from utils.metrics import AverageMeter
import logging
from tqdm import tqdm
from parallel_wrapper import launch
import comm
import wandb
from sklearn.metrics import accuracy_score, confusion_matrix
from gcn_lib.dense import pairwise_distance
import random

def seed_worker(worker_id):
    worker_seed = torch.initial_seed() % 2**32
    np.random.seed(worker_seed)
    random.seed(worker_seed)

def dist2distloss(feats1,feats2):
    f1 = feats1.transpose(2, 1).squeeze(-1)
    f2 = feats2.transpose(2, 1).squeeze(-1)
    d1 = pairwise_distance(f1)/f1.shape[2]
    d2 = pairwise_distance(f2)/f2.shape[2]
    crit = torch.nn.MSELoss(reduction='sum')
    return crit(d1,d2)

def stressloss(feats1,feats2):
    f1 = feats1.transpose(2, 1).squeeze(-1)
    f2 = feats2.transpose(2, 1).squeeze(-1)
    d1 = torch.sqrt(pairwise_distance(f1)/f1.shape[2] + 1e-6)
    d2 = torch.sqrt(pairwise_distance(f2)/f2.shape[2] + 1e-6)
    crit = torch.nn.MSELoss(reduction='sum')
    return crit(d1,d2)

def scaledstressloss(feats1,feats2):
    f1 = feats1.transpose(2, 1).squeeze(-1)
    f2 = feats2.transpose(2, 1).squeeze(-1)
    d1squared = pairwise_distance(f1)
    d2squared = pairwise_distance(f2)
    #We add 1 to avoid problems with squared root gradients, this doesn't affect as we compute the difference
    #d1 = torch.sqrt(d1squared/f1.shape[2] + 1)
    #d2 = torch.sqrt(d2squared/f2.shape[2] + 1)
    d1 = torch.sqrt(d1squared + 1)
    d2 = torch.sqrt(d2squared + 1)
    crit = torch.nn.MSELoss(reduction='none')
    #print(d1.shape, ((d1squared.view(f1.shape[0],-1)).sum(1, keepdim=True).unsqueeze(-1)).shape)
    #Shapes are B,N,N and B,1,1
    scaled_se = crit(d1,d2)/((d1squared.view(f1.shape[0],-1)).sum(1, keepdim=True).unsqueeze(-1))
    #print(scaled_se.shape)
    flat_scaled_se = scaled_se.view(f1.shape[0],-1)
    #print(flat_scaled_se.shape)
    return flat_scaled_se.sum(dim=1).sum(dim=0)

def train(model, train_loader, optimizer, criterion, opt, cur_rank):
    model.train()
    total_loss = 0
    total_d2d_loss = 0
    total_ce_loss = 0

    targets = []
    preds = []
    with tqdm(train_loader) as tqdm_loader:
        for i, (data,label) in enumerate(tqdm_loader):
            opt.iter += 1
            desc = 'Epoch:{}  Iter:{}  [{}/{}]'\
                .format(opt.epoch, opt.iter, i + 1, len(train_loader))
            tqdm_loader.set_description(desc)

            inputs = data.transpose(2, 1).unsqueeze(3).to(opt.device)
            gt = label.to(opt.device)
            # ------------------ zero, output, loss
            optimizer.zero_grad()
            out, graph_feats = model(inputs)
            #Cros Entropy
            loss = criterion(out, gt)
            total_ce_loss += loss.item()

            #L2 regularization of Graph features
            l2_crit = torch.nn.L1Loss(reduction='sum')
            reg_loss = 0
            for name, param in model.named_parameters():
                if name[:16] == 'module.graph_mlp':
                    zero = torch.zeros_like(param)
                    reg_loss += l2_crit(param,zero)
            factor_l2 = opt.graph_l2reg
            #Divergence of distance matrices
            factor_dist2dist = opt.d2d_weight
            d2d_loss = scaledstressloss(inputs.to(opt.device), graph_feats)
            total_d2d_loss += d2d_loss.item()

            #Update loss
            loss += factor_l2 * reg_loss + factor_dist2dist*d2d_loss
            total_loss+=loss.item()
            # ------------------ optimization
            loss.backward()
            optimizer.step()

            target_np = gt.cpu().numpy()
            pred = out.max(dim=1)[1]
            pred_np = pred.cpu().numpy()

            targets += list(target_np.ravel())
            preds += list(pred_np.ravel())

    acc = accuracy_score(targets, preds)

    return total_loss, total_d2d_loss, total_ce_loss, acc

def test(model, loader, criterion, opt, cur_rank):
    Is = np.empty((len(loader), opt.n_classes))
    Us = np.empty((len(loader), opt.n_classes))
    total_loss = 0
    total_d2d_loss = 0
    total_ce_loss = 0

    targets = []
    preds = []

    model.eval()
    with torch.no_grad():
        for i, (data, label) in enumerate(tqdm(loader)):
            inputs = data.transpose(2, 1).unsqueeze(3).to(opt.device)
            gt = label.to(opt.device)

            out, graph_feats = model(inputs)
            loss = criterion(out, gt.to(opt.device))
            total_ce_loss += loss.item()

            #Divergence of distance matrices
            factor_dist2dist = opt.d2d_weight
            d2d_loss = scaledstressloss(inputs.to(opt.device), graph_feats)
            total_d2d_loss += d2d_loss.item()

            #Update loss
            loss += factor_dist2dist*d2d_loss
            total_loss+=loss.item()
            pred = out.max(dim=1)[1]

            target_np = gt.cpu().numpy()
            pred_np = pred.cpu().numpy()

            targets += list(target_np.ravel())
            preds += list(pred_np.ravel())

    acc = accuracy_score(targets, preds)

    logging.info('TEST Epoch: [{}]\t Acc: {:.4f}\t'.format(opt.epoch, acc))
    return targets, preds, total_loss, total_d2d_loss, total_ce_loss, acc

def epochs(opt):
    logging.info('===> Creating dataloader ...')
    #train_dataset = GeoData.ModelNet(opt.data_dir, name = '40', train = True, pre_transform=T.NormalizeScale())
    #train_sampler = DistributedSampler(train_dataset, shuffle=True, seed=opt.seed)
    #train_loader = DenseDataLoader(train_dataset, batch_size=opt.batch_size, shuffle=False, sampler = train_sampler, num_workers=opt.n_gpus)
    #test_dataset = GeoData.ModelNet(opt.data_dir, name = '40', train=False, pre_transform=T.NormalizeScale())
    #test_sampler = DistributedSampler(test_dataset, shuffle=False, seed=opt.seed)
    #test_loader = DenseDataLoader(test_dataset, batch_size=opt.batch_size, shuffle=False, sampler = test_sampler, num_workers=opt.n_gpus)

    random.seed(opt.seed)
    np.random.seed(opt.seed)
    torch.manual_seed(opt.seed)

    train_dataset = ModelNet40(1024, 'train')
    train_generator = torch.Generator()
    train_generator.manual_seed(opt.seed)
    if opt.n_gpus > 1:
        train_sampler = DistributedSampler(train_dataset, shuffle=True, seed=opt.seed)
        train_loader = DataLoader(train_dataset, batch_size=opt.batch_size, shuffle=False, generator= train_generator, sampler = train_sampler, num_workers=opt.n_gpus, drop_last=False,worker_init_fn=seed_worker)
    else:
        train_loader = DataLoader(train_dataset, batch_size=opt.batch_size, shuffle=True, generator=train_generator, num_workers=4, drop_last=False,worker_init_fn=seed_worker)

    test_dataset = ModelNet40(1024, 'test')
    test_generator = torch.Generator()
    test_generator.manual_seed(opt.seed)
    if opt.n_gpus > 1:
        test_sampler = DistributedSampler(test_dataset, shuffle=False, seed=opt.seed)
        test_loader = DataLoader(test_dataset, batch_size=opt.batch_size, shuffle=False, generator = test_generator, sampler = test_sampler, num_workers=opt.n_gpus, drop_last=False,worker_init_fn=seed_worker)
    else:
        test_loader = DataLoader(test_dataset, batch_size=opt.batch_size, shuffle=False, generator=test_generator, num_workers=4, drop_last=False,worker_init_fn=seed_worker)

    LABELS = [
    'airplane', 'bathtub', 'bed', 'bench', 'bookshelf', 'bottle', 'bowl', 'car',
    'chair', 'cone', 'cup', 'curtain', 'desk', 'door', 'dresser', 'flower_pot',
    'glass_box', 'guitar', 'keyboard', 'lamp', 'laptop', 'mantel', 'monitor',
    'night_stand', 'person', 'piano', 'plant', 'radio', 'range_hood', 'sink',
    'sofa', 'stairs', 'stool', 'table', 'tent', 'toilet', 'tv_stand', 'vase',
    'wardrobe', 'xbox']

    opt.n_classes = 40

    cur_rank = comm.get_local_rank()

    #torch.use_deterministic_algorithms(True)

    logging.info('===> Loading the network ...')
    if opt.n_gpus > 1:
        model = DistributedDataParallel(ClassificationGraphNN(opt).to(cur_rank),device_ids=[cur_rank], output_device=cur_rank,broadcast_buffers=False).to(cur_rank)
    else:
        model = ClassificationGraphNN(opt).to(cur_rank)
    logging.info('===> loading pre-trained ...')
    model, opt.best_value, opt.epoch = load_pretrained_models(model, opt.pretrained_model, opt.phase)
    logging.info(model)
    if comm.is_main_process():
        wandb.init(project="MODELNET40")
        wandb.run.name = opt.exp_name
        wandb.watch(model,log_freq=100,log="all")

    logging.info('===> Init the optimizer ...')
    criterion = torch.nn.CrossEntropyLoss().to(cur_rank)
    optimizer = torch.optim.Adam(model.parameters(), lr=opt.lr, weight_decay = opt.decay)

    scheduler = torch.optim.lr_scheduler.StepLR(optimizer, opt.lr_adjust_freq, opt.lr_decay_rate)
    optimizer, scheduler, opt.lr = load_pretrained_optimizer(opt.pretrained_model, optimizer, scheduler, opt.lr)

    logging.info('===> start training ...')
    epochs_frozen = 0
    freeze_graph = True
    for _ in range(opt.epoch, opt.total_epochs):
        '''
        filtered_parameters = []
        if epochs_frozen == 5:
            freeze_graph = not freeze_graph
            epochs_frozen = 0
        for name, param in model.named_parameters():
            #filter(lambda t: ( t[0][:16] == 'module.graph_mlp') or (not bool(opt.epoch%2) and t[0][:16] != 'module.graph_mlp'), model.parameters())
            if (freeze_graph and name[:16] == 'module.graph_mlp') or (not freeze_graph and name[:16] != 'module.graph_mlp'):
                print(name)
                filtered_parameters.append(param)
        optimizer = torch.optim.Adam(filtered_parameters)
        '''

        opt.epoch += 1
        if opt.n_gpus > 1:
            train_sampler.set_epoch(opt.epoch)
            test_sampler.set_epoch(opt.epoch)
        logging.info('Epoch:{}'.format(opt.epoch))
        train_loss, train_d2d_loss, train_ce_loss, train_acc = train(model, train_loader, optimizer, criterion, opt, cur_rank)
        if opt.epoch % opt.eval_freq == 0 and opt.eval_freq != -1:
            test_targets, test_preds, test_loss, test_d2d_loss, test_ce_loss, test_acc = test(model, test_loader, criterion, opt, cur_rank)
        scheduler.step()
        if comm.is_main_process():
            # ------------------ save checkpoints
            # min or max. based on the metrics
            is_best = (test_acc < opt.best_value)
            opt.best_value = max(test_acc, opt.best_value)
            model_cpu = {k: v.cpu() for k, v in model.state_dict().items()}
            save_checkpoint({
                'epoch': opt.epoch,
                'state_dict': model_cpu,
                'optimizer_state_dict': optimizer.state_dict(),
                'scheduler_state_dict': scheduler.state_dict(),
                'best_value': opt.best_value,
            }, is_best, opt.ckpt_dir, opt.exp_name)
            matrix = confusion_matrix(test_targets, test_preds)
            per_class_acc = matrix.diagonal()/matrix.sum(axis=1)
            wandb_dict = {'Train/loss': train_loss,
                       'Val/loss': test_loss,
                       'Train/Accuracy':train_acc,
                       'Val/Accuracy':test_acc,
                       'Train/d2d_loss':train_d2d_loss,
                       'Val/d2d_loss':test_d2d_loss,
                       'Train/ce_loss':train_ce_loss,
                       'Val/ce_loss':test_ce_loss,
                       'lr':scheduler.get_last_lr()[0]}
            for i, c in enumerate(LABELS):
                wandb_dict[f'Test_acc/{c}'] = per_class_acc[i]
            wandb_dict[f'Test_acc/MEAN'] = sum(per_class_acc)/opt.n_classes
            # ------------------ tensorboard log
            wandb.log(wandb_dict, step=opt.epoch)

        logging.info('Saving the final model.Finish!')
        epochs_frozen += 1

def main():
    opt = OptInit().get_args()
    '''
    This wrapper taken from detectron2 (https://github.com/facebookresearch/detectron2/blob/main/detectron2/engine/launch.py),
    creates n_gpus processes and launches epochs function on each of them.
    '''
    launch(
        epochs,
        num_gpus_per_machine=opt.n_gpus,
        num_machines=1,
        machine_rank=0,
        dist_url='auto',
        args=(opt,)
    )
    #epochs(opt)

if __name__ == '__main__':
    main()


import logging
import os
import yaml
import appdirs

from mail_sender_daemon import app, APP_NAME

logger = logging.getLogger(APP_NAME)

os.environ["XDG_CONFIG_DIRS"] = "/etc"

CONFIG_DIRS = (
    appdirs.user_config_dir(APP_NAME),
    appdirs.site_config_dir(APP_NAME),
    os.path.abspath(os.path.join(app.root_path, "../")),
)
CONFIG_FILENAME = "config.yml"

def build_app_config(custom_path=None):
    """
    Get config file and load it with yaml

    :returns: loaded config in yaml, as a dict object
    """
    if custom_path:
        config_path = custom_path
    else:
        for d in CONFIG_DIRS:
            config_path = os.path.join(d, CONFIG_FILENAME)
            if os.path.isfile(config_path):
                break
    try:
        with open(config_path, "r") as config_file:
            return yaml.safe_load(config_file)
    except FileNotFoundError as e:
        logger.debug(e)
        if custom_path:
            logger.error(
                "Configuration file {} not found.".format(custom_path)
            )
        else:
            logger.error(
                "No configuration file can be found.\n"
                "Please create a config.yml in one of these directories:\n"
                "\t{}".format("\n\t".join(CONFIG_DIRS))
            )
        raise


import sys

from discord.ext.commands import Cog, command, check
from discord.utils import find
from typing import List
from bot.settings import CHANNEL_ID, FIELDS, TOPICS, STAGE_3_MODULES, PRONOUNS, SERVER_2020, SERVER_2022_CHANNEL_ID
from bot.cogs.name import Name

def is_in_guild(guild_id):
    async def predicate(ctx):
        return ctx.guild and ctx.guild.id == guild_id

    return check(predicate)

def is_in_channel():
    async def predicate(ctx):
        member = ctx.message.author
        channel = member.guild.get_channel(
            CHANNEL_ID
        ) if member.guild.id == SERVER_2020 else member.guild.get_channel(
            SERVER_2022_CHANNEL_ID)
        return channel.id == ctx.message.channel.id

    return check(predicate)

class RoleChooser(Cog, name="Choose Roles"):
    """List of commands to set roles for various topics and modules"""
    def __init__(self, bot):
        self.bot = bot

    def _common(self, list1, list2):
        return list(set(list1) & set(list2))

    async def change_role(self, ctx, rolename: str, role_type: str,
                          pos_roles: List[str], max_num: int):
        member = ctx.author
        name = member.nick or member.name

        if not rolename:
            await ctx.send(
                f"You forgot to provide a {role_type} name after the command, {name}!"
            )
            return

        if rolename.lower() not in pos_roles:
            await ctx.send(f"Role change failed, {name}."
                           "You are only allowed the roles below\n"
                           "```\n" + '\n'.join(pos_roles) + "\n```")
            return

        author_roles = [
            role.name.lower() for role in ctx.author.roles
            if role.name != "@everyone"
        ]
        common_roles = self._common(author_roles, pos_roles)

        if rolename.lower() in common_roles:
            await ctx.send(f"You already have that role, {name}!")
            return

        role = find(
            lambda r: r.name.lower() == rolename.lower(),
            member.guild.roles,
        )

        if common_roles:
            role_objs = [
                find(
                    lambda r: r.name.lower() == cr_name,
                    member.guild.roles,
                ) for cr_name in common_roles
            ]
            if len(role_objs) >= max_num:
                await member.remove_roles(*role_objs)

        await member.add_roles(role)
        await ctx.send(f"Successfully assigned to {role.name}, {name}!")

    @command(help="Select your field", usage=f"[{'|'.join(FIELDS)}]")
    @is_in_channel()
    async def field(self, ctx, *, rolename=None):
        await self.change_role(ctx,
                               rolename,
                               "field",
                               pos_roles=FIELDS,
                               max_num=1)

    @command(help="Select your CSC2034 topic", usage=f"[{'|'.join(TOPICS)}]")
    @is_in_guild(SERVER_2020)
    @is_in_channel()
    async def topic(self, ctx, *, rolename=None):
        await self.change_role(ctx,
                               rolename,
                               "topics",
                               pos_roles=TOPICS,
                               max_num=1)

    @command(help="Select your Stage 3 modules",
             usage='\n'.join(STAGE_3_MODULES))
    @is_in_guild(SERVER_2020)
    @is_in_channel()
    async def stage3(self, ctx, *, rolename=None):
        await self.change_role(
            ctx,
            rolename,
            "Stage 3 Module",
            pos_roles=[x.split(' ')[0] for x in STAGE_3_MODULES],
            max_num=4)

    @command(help="Preferred Pronouns", usage='\n'.join(PRONOUNS))
    @is_in_channel()
    async def pronoun(self, ctx, *, rolename=None):
        await self.change_role(ctx,
                               rolename,
                               "Preferred Pronouns",
                               pos_roles=PRONOUNS,
                               max_num=1)
        member = ctx.author
        old_nick = member.nick
        if old_nick is None:
            old_nick = member.name
        old_pronoun = None
        for pronoun in PRONOUNS:
            if pronoun in old_nick:
                old_pronoun = pronoun
        if old_pronoun is None:
            new_nick = f"{old_nick} ({rolename})"
        else:
            new_nick = old_nick.replace(old_pronoun, rolename)
        print(new_nick)
        await member.edit(nick=new_nick)

def setup(bot):
    bot.add_cog(RoleChooser(bot))


import torch, torch.nn as nn, torch.nn.functional as F, numpy as np

'''

Two implementations, chosen at bottom of file.

functorch based PNP solver.
Requires a decent initial estimate.

Actually opencv solvePnP is not very good unless you use the iterative method with an initial estimate,
which is about as good as my NLLS solver. IIRC solvePnP use Lu OI algorithm though, which converges fast, probably
unlike the NLLS solve.
Without useExtrinsicGuess, I figure solvePnP either does OI with a bad initial scene plane, or attempts to first use an algebraic
method like EPNP and simply fails.

'''

def log_R(R):
    t = np.arccos((np.trace(R) - 1) * .5)
    d = np.linalg.norm((R[2,1]-R[1,2], R[0,1]-R[1,0], R[0,2]-R[2,0]))
    if d < 1e-12: return np.zeros(3)
    return np.array((R[2,1]-R[1,2], R[0,2]-R[2,0], R[1,0]-R[0,1])) * t / d
def q_exp(r):
    l2 = r@r
    if l2 < 1e-15:
        return np.array((1,0,0,0.))
    l = np.sqrt(l2)
    # a = l * np.pi * .5
    a = l * .5
    c,s = np.cos(a), np.sin(a)
    # return np.array((0,1,0,0))
    return np.array((c,*((s/l)*r)))

def q_to_matrix1(q):
    # r,i,j,k = q[0], q[1], q[2], q[3]
    # return torch.stack((
    r,i,j,k = q[0:1], q[1:2], q[2:3], q[3:4]
    return torch.cat((
        1-2*(j*j+k*k), 2*(i*j-k*r), 2*(i*k+j*r),
        2*(i*j+k*r), 1-2*(i*i+k*k), 2*(j*k-i*r),
        2*(i*k-j*r), 2*(j*k+i*r), 1-2*(i*i+j*j))).view(3,3)

def mapProject2(pose, pts, fxy, wh):
    q,t = pose[...,:4], pose[...,4:]
    tpts = (pts-t.view(-1,3)) @ q_to_matrix1(q) # Transposing R twice: R.T.T = R
    ppts = (tpts[...,:2] / tpts[...,2:])
    # ppts[...,1] *= -1
    return ppts * fxy + wh*.5

def get_functorch_jac_2():
    from functorch import jacfwd, vmap
    from functorch.compile import aot_function, memory_efficient_fusion, ts_compile

    # Each camera projects the SAME number of points
    m2 = vmap(mapProject2, (0,0,0,0))
    d_m2 = vmap(jacfwd(mapProject2, (0,1)), (0,0,0,0))

    return m2, d_m2

# Actually this is not very good.
def recover_camera_opencv(wh, fxy, obspts, worldpts,
                   initialEye=torch.FloatTensor((0,1,-2)),
                   initialQ=torch.FloatTensor((1,0,0,0))):

    rvec0 = log_R(q_to_matrix1(initialQ))
    tvec0 = -(q_to_matrix1(initialQ) @ initialEye).cpu().numpy()

    import cv2
    Ps = []
    for i in range(len(obspts)):
        opts = worldpts[i].cpu().numpy()
        ipts = obspts[i].cpu().numpy()
        K = np.array((
            fxy[0], 0, wh[0]*.5,
            0, fxy[1], wh[1]*.5,
            0,0,1)).reshape(3,3)
        print(opts.shape, ipts.shape, K.shape)
        if 0:
            stat,rvec,tvec = cv2.solvePnP(opts,ipts,K,None)
        else:
            stat,rvec,tvec = cv2.solvePnP(opts,ipts,K,None, np.copy(rvec0),np.copy(tvec0), useExtrinsicGuess=True)
        assert(stat)
        P = np.eye(4)
        # print('K',K)
        rod = cv2.Rodrigues(rvec)
        print('tvec',tvec.squeeze())
        print('rvec',rvec)
        print('R',rod[0])
        # P[:3,:3] = rod[0]
        # P[:3,3] = tvec.squeeze()
        P = np.zeros(7)
        if 1:
            # Must invert
            P[:4] = q_exp(rvec.squeeze()) * (1,-1,-1,-1)
            P[4:] = -(rod[0].T @ tvec.squeeze())
        else:
            P[:4] = q_exp(rvec.squeeze())# * (1,-1,-1,-1)
            P[4:] = tvec.squeeze()
        # print('R_',q_to_matrix1(torch.from_numpy(P[:4])))
        Ps.append(P)
    return torch.from_numpy(np.stack(Ps))

def recover_camera_functorch(wh, fxy, obspts, worldpts,
                   initialEye=torch.FloatTensor((0,1,-2)),
                   initialQ=torch.FloatTensor((1,0,0,0)),
            ):

    B,N,three = worldpts.size()
    x = torch.cat((initialQ,initialEye), -1).view(1,7).repeat(B,1)
    x[...,:4] = nn.functional.normalize(x[...,:4], dim=-1)
    wh = wh.view(1,2).repeat(B,1)
    fxy = fxy.view(1,2).repeat(B,1)

    Nstate = 7
    Nobs = N * 2

    prior0 = torch.eye(7).unsqueeze_(0)
    prior0[:,:4,:4] *= 1e4
    prior0[:,4:,4:] *= 1e2
    prior = prior0.clone()

    F, dF = get_functorch_jac_2()

    # print('obs\n',obspts)

    for i in range(32):
        pred = F(x, worldpts, fxy, wh)
        Js = dF(x, worldpts, fxy, wh)

        # print('pred\n',pred)
        res = pred - obspts # [B,N,2]
        rmse = res.pow(2).sum(2).mean(1).sqrt() # [B]
        print(f' - step {i} rmse {rmse}')

        # print(pred.shape,[JJ.shape for JJ in Js])
        if 0:
            J = Js[0].sum(1) # sum out 'N', the observation dim. to get a [B,2,7] tensor.

            # grad = (J.mT @ res.mT).sum(2) # [B,2,7] x [B,N,2] -> [B,7]
            grad = (J.mT @ res.permute(0,2,1)).sum(2) # [B,2,7] x [B,N,2] -> [B,7]

            # JtJ = J.mT @ J # [B,7,7]
            JtJ = J.permute(0,2,1) @ J # [B,7,7]
        else:
            J = Js[0] # [B,N,2,7]
            # print('j',J.shape, 'res',res.shape)
            # print((J.mT @ res.permute(0,2,1).unsqueeze(-2)).shape)
            # grad = (J.mT @ res.permute(0,2,1)).sum(1)
            # print(torch.bmm(J.view(-1,2,7).mT, res.view(-1,2,1))[...,0]
            # print(J.shape, res.shape)
            grad = torch.bmm(J.reshape(-1,2,7).mT, res.reshape(-1,2,1))[...,0].reshape(B,N,7).sum(1)
            JtJ = (J.permute(0,1,3,2) @ J).sum(1) # [B,7,7]
            # print(J.shape,grad.shape,JtJ.shape)

        # print('JtJ:\n',JtJ)
        # print('grad:',grad)
        if 1:
            Hess = JtJ + prior
            P = Hess.inverse()
            # print('P:\n',P)

            bad = (P.diagonal(dim1=1,dim2=2) <= 0)
            if (bad).any():
                print(P.diagonal(dim1=1,dim2=2))
                print(' - WARNING: non-pos-definite covariance.')
                # prior = prior*2

                # continue
                # P[bad.flatten(1).any(1)] = 0
                # exit()

            # print(P.shape,grad.shape)
            x = x - (P @ grad.unsqueeze(-1))[...,0]
        else:
            Hess = JtJ[...,4:,4:] + prior[...,4:,4:]
            P = Hess.inverse()
            # print('P',P.shape)
            x[...,4:] = x[...,4:] - (P @ grad[...,4:].unsqueeze(-1))[...,0]

        x[...,:4] = nn.functional.normalize(x[...,:4], dim=-1)
        # x[...,:4] = torch.FloatTensor((1,0,0,0)).view(1,4)
        # print('q',x[0,:4], 't',x[0,4:])
    print('q',x[0,:4], 't',x[0,4:])

    return x

# Set implementation
# recover_camera = recover_camera_opencv
recover_camera = recover_camera_functorch

if __name__ == '__main__':
    wh = torch.FloatTensor((512,512.))
    uv = np.tan(np.deg2rad(50)/2)*2
    fxy = wh/uv
    worldpts = torch.randn(1,10,3) + torch.FloatTensor((0,1,8)).view(1,1,3)

    # def mapProject2(pose, pts, fxy, wh):
    # obspts = (worldpts * 1)[:,:,:2] * fxy + wh*.5
    pose0 = torch.FloatTensor((1,0,.1,-.02, 0,2.1,-1.02)).view(7)
    pose0[...,:4] = nn.functional.normalize(pose0[...,:4], dim=-1)
    obspts = mapProject2(pose0, worldpts, fxy, wh)

    recover_camera(wh, fxy, obspts, worldpts)
    # exit()


from functools import reduce
from operator import xor

from migen import *

from litex.soc.interconnect import stream

from usb3_pipe.common import COM

# Scrambler Unit (Appendix B) ----------------------------------------------------------------------

@ResetInserter()
@CEInserter()
class ScramblerUnit(Module):
    """Scrambler Unit

    This module generates the scrambled datas for the USB3.0 link (X^16 + X^5 + X^4 + X^3 + 1 polynom).
    """
    def __init__(self, reset=0xffff):
        self.value = Signal(32)

        # # #

        new = Signal(16)
        cur = Signal(16, reset=reset)

        self.comb += [
            new[0].eq(cur[0]  ^ cur[6] ^ cur[8]  ^ cur[10]),
            new[1].eq(cur[1]  ^ cur[7] ^ cur[9]  ^ cur[11]),
            new[2].eq(cur[2]  ^ cur[8] ^ cur[10] ^ cur[12]),
            new[3].eq(cur[3]  ^ cur[6] ^ cur[8]  ^ cur[9]  ^ cur[10] ^ cur[11] ^ cur[13]),
            new[4].eq(cur[4]  ^ cur[6] ^ cur[7]  ^ cur[8]  ^ cur[9]  ^ cur[11] ^ cur[12] ^ cur[14]),
            new[5].eq(cur[5]  ^ cur[6] ^ cur[7]  ^ cur[9]  ^ cur[12] ^ cur[13] ^ cur[15]),
            new[6].eq(cur[0]  ^ cur[6] ^ cur[7]  ^ cur[8]  ^ cur[10] ^ cur[13] ^ cur[14]),
            new[7].eq(cur[1]  ^ cur[7] ^ cur[8]  ^ cur[9]  ^ cur[11] ^ cur[14] ^ cur[15]),
            new[8].eq(cur[0]  ^ cur[2] ^ cur[8]  ^ cur[9]  ^ cur[10] ^ cur[12] ^ cur[15]),
            new[9].eq(cur[1]  ^ cur[3] ^ cur[9]  ^ cur[10] ^ cur[11] ^ cur[13]),
            new[10].eq(cur[0] ^ cur[2] ^ cur[4]  ^ cur[10] ^ cur[11] ^ cur[12] ^ cur[14]),
            new[11].eq(cur[1] ^ cur[3] ^ cur[5]  ^ cur[11] ^ cur[12] ^ cur[13] ^ cur[15]),
            new[12].eq(cur[2] ^ cur[4] ^ cur[6]  ^ cur[12] ^ cur[13] ^ cur[14]),
            new[13].eq(cur[3] ^ cur[5] ^ cur[7]  ^ cur[13] ^ cur[14] ^ cur[15]),
            new[14].eq(cur[4] ^ cur[6] ^ cur[8]  ^ cur[14] ^ cur[15]),
            new[15].eq(cur[5] ^ cur[7] ^ cur[9]  ^ cur[15]),

            self.value[0].eq(cur[15]),
            self.value[1].eq(cur[14]),
            self.value[2].eq(cur[13]),
            self.value[3].eq(cur[12]),
            self.value[4].eq(cur[11]),
            self.value[5].eq(cur[10]),
            self.value[6].eq(cur[9]),
            self.value[7].eq(cur[8]),
            self.value[8].eq(cur[7]),
            self.value[9].eq(cur[6]),
            self.value[10].eq(cur[5]),
            self.value[11].eq(cur[4]  ^ cur[15]),
            self.value[12].eq(cur[3]  ^ cur[14] ^ cur[15]),
            self.value[13].eq(cur[2]  ^ cur[13] ^ cur[14] ^ cur[15]),
            self.value[14].eq(cur[1]  ^ cur[12] ^ cur[13] ^ cur[14]),
            self.value[15].eq(cur[0]  ^ cur[11] ^ cur[12] ^ cur[13]),
            self.value[16].eq(cur[10] ^ cur[11] ^ cur[12] ^ cur[15]),
            self.value[17].eq(cur[9]  ^ cur[10] ^ cur[11] ^ cur[14]),
            self.value[18].eq(cur[8]  ^ cur[9]  ^ cur[10] ^ cur[13]),
            self.value[19].eq(cur[7]  ^ cur[8]  ^ cur[9]  ^ cur[12]),
            self.value[20].eq(cur[6]  ^ cur[7]  ^ cur[8]  ^ cur[11]),
            self.value[21].eq(cur[5]  ^ cur[6]  ^ cur[7]  ^ cur[10]),
            self.value[22].eq(cur[4]  ^ cur[5]  ^ cur[6]  ^ cur[9]  ^ cur[15]),
            self.value[23].eq(cur[3]  ^ cur[4]  ^ cur[5]  ^ cur[8]  ^ cur[14]),
            self.value[24].eq(cur[2]  ^ cur[3]  ^ cur[4]  ^ cur[7]  ^ cur[13] ^ cur[15]),
            self.value[25].eq(cur[1]  ^ cur[2]  ^ cur[3]  ^ cur[6]  ^ cur[12] ^ cur[14]),
            self.value[26].eq(cur[0]  ^ cur[1]  ^ cur[2]  ^ cur[5]  ^ cur[11] ^ cur[13] ^ cur[15]),
            self.value[27].eq(cur[0]  ^ cur[1]  ^ cur[4]  ^ cur[10] ^ cur[12] ^ cur[14]),
            self.value[28].eq(cur[0]  ^ cur[3]  ^ cur[9]  ^ cur[11] ^ cur[13]),
            self.value[29].eq(cur[2]  ^ cur[8]  ^ cur[10] ^ cur[12]),
            self.value[30].eq(cur[1]  ^ cur[7]  ^ cur[9]  ^ cur[11]),
            self.value[31].eq(cur[0]  ^ cur[6]  ^ cur[8]  ^ cur[10]),
        ]
        self.sync += cur.eq(new)

# Scrambler (Appendix B) ---------------------------------------------------------------------------

class Scrambler(Module):
    """Scrambler

    This module scrambles the TX data/ctrl stream. K codes shall not be scrambled.
    """
    def __init__(self, reset=0x7dbd):
        self.enable = Signal(reset=1)
        self.sink   =   sink = stream.Endpoint([("data", 32), ("ctrl", 4)])
        self.source = source = stream.Endpoint([("data", 32), ("ctrl", 4)])

        # # #

        self.submodules.unit = unit = ScramblerUnit(reset=reset)
        self.comb += unit.ce.eq(sink.valid & sink.ready)
        self.comb += sink.connect(source)
        for i in range(4):
            self.comb += [
                If(~self.enable | sink.ctrl[i], # K codes shall not be scrambled.
                    source.data[8*i:8*(i+1)].eq(sink.data[8*i:8*(i+1)])
                ).Else(
                    source.data[8*i:8*(i+1)].eq(sink.data[8*i:8*(i+1)] ^ unit.value[8*i:8*(i+1)])
                )
            ]

# Descrambler (Scrambler + Auto-Synchronization) (Appendix B) --------------------------------------

class Descrambler(Module):
    """Descrambler

    This module descrambles the RX data/ctrl stream. K codes shall not be scrambled. The descrambler
    automatically synchronizes itself to the incoming stream and resets the scrambler unit when COM
    characters are seen.
    """
    def __init__(self, reset=0xffff):
        self.enable = Signal(reset=1)
        self.sink   =   sink = stream.Endpoint([("data", 32), ("ctrl", 4)])
        self.source = source = stream.Endpoint([("data", 32), ("ctrl", 4)])

        # # #

        scrambler = Scrambler(reset=reset)
        self.submodules += scrambler
        self.comb += scrambler.enable.eq(self.enable)

        # Synchronize on COM
        for i in range(4):
            self.comb += [
                If(sink.valid &
                   sink.ready &
                   (sink.data[8*i:8*(i+1)] == COM.value) &
                   sink.ctrl[i],
                   scrambler.unit.reset.eq(1)
                )
            ]

        # Descramble data
        self.comb += [
            sink.connect(scrambler.sink),
            scrambler.source.connect(source)
        ]


from typing import Dict, List

from torch import Tensor, nn

from modules.modeling.dynamic_blocks.base_dynamic_block import BaseDynamicBlock
from modules.modeling.ops import (
    DynamicQConvNormActivation, DynamicQSE4ResNet
)
from modules.modeling.blocks import (
    FusedMBConvResBlock, FusedMBConvSEResBlock
)
from modules.modeling.common.utils import make_divisible, get_activation

class _DynamicFusedMBConvBlock(BaseDynamicBlock):

    def __init__(self, max_cin: int, width_list: List[int], kernel_list: List[int], stride: int, expand_list: List[float], use_se: bool, activation=nn.ReLU, inplace=True, force_residual=False) -> None:
        super().__init__(max_cin, width_list, kernel_list, stride, expand_list, activation)
        self.use_se = use_se
        self.force_residual = force_residual

        self.fused_conv = DynamicQConvNormActivation(max_in_channels=self.max_cin, max_out_channels=self.max_hidden_size, kernel_size_list=kernel_list, stride=stride, activation_layer=self.activation_layer, inplace=inplace)

        if self.use_se:
            self.se = DynamicQSE4ResNet(max_cin=self.max_hidden_size, max_mid=DynamicQSE4ResNet.get_mid_channels(self.max_cin))

        self.point_conv = DynamicQConvNormActivation(max_in_channels=self.max_hidden_size, max_out_channels=self.max_width, kernel_size_list=[1], stride=1, activation_layer=None)

        self.force_residual = force_residual
        if self.force_residual:
            self.downsample = DynamicQConvNormActivation(
                max_in_channels=self.max_cin, max_out_channels=self.max_width,
                kernel_size_list=[1], stride=stride, activation_layer=None
            )

    def forward(self, x: Tensor) -> Tensor:
        cin =  x.shape[1]
        if self.use_res_connect(cin):
            x0 = x
        elif self.force_residual:
            x0 = self.downsample(x)

        active_hidden_size = self.get_active_hidden_size(cin)

        x = self.fused_conv.forward(x, out_channels=active_hidden_size)

        if self.use_se:
            self.se.active_mid_channels = DynamicQSE4ResNet.get_mid_channels(cin)
            x = self.se(x)
        x = self.point_conv(x)

        if self.use_res_connect(cin) or self.force_residual:
            x = x0 + x
        return x

    def use_res_connect(self, cin):
        return cin == self.active_width and self.stride == 1

    @property
    def max_hidden_size(self):
        return make_divisible(self.max_expand_ratio * self.max_cin)

    def get_active_hidden_size(self, cin: int) -> int:
        return make_divisible(self.active_expand_ratio * cin)

    @property
    def active_kernel_size(self) -> int:
        return self.fused_conv.active_kernel_size

    @active_kernel_size.setter
    def active_kernel_size(self, kernel_size: int):
        self.fused_conv.active_kernel_size = kernel_size

    @property
    def active_width(self) -> int:
        return self.point_conv.active_out_channels

    @active_width.setter
    def active_width(self, width: int):
        self.point_conv.active_out_channels = width
        if self.force_residual:
            self.downsample.active_out_channels = width

    @property
    def active_expand_ratio(self) -> float:
        return self._active_expand_ratio

    @active_expand_ratio.setter
    def active_expand_ratio(self, expand_ratio: float):
        self._active_expand_ratio = expand_ratio

    def zero_last_gamma(self):
        if self.force_residual:
            self.point_conv.norm.weight.data.zero_()

class DynamicFusedMBConvResBlock(_DynamicFusedMBConvBlock):

    def __init__(self, max_cin: int, width_list: List[int], kernel_list: List[int], stride: int, expand_list: List[float], activation=nn.ReLU, inplace=True) -> None:
        super().__init__(max_cin, width_list, kernel_list, stride, expand_list, use_se=False, activation=activation, inplace=inplace, force_residual=True)

    def get_active_block(self, cin: int, retain_weights=True) -> FusedMBConvResBlock:
        block = FusedMBConvResBlock.build_from_config(self.get_active_block_config(cin))
        if retain_weights:
            hidden_size = self.get_active_hidden_size(cin)
            block.fused_conv.load_state_dict(self.fused_conv.active_state_dict(cin, cout=hidden_size))
            block.point_conv.load_state_dict(self.point_conv.active_state_dict(hidden_size))
            if hasattr(block, 'downsample'):
                block.downsample.load_state_dict(self.downsample.active_state_dict(cin))
        return block

    def get_active_tf_block(self, cin: int):
        from modules.modeling.blocks.tf_blocks import FusedMBConvResBlock as FusedMBConvResBlock_TF
        return FusedMBConvResBlock_TF.build_from_config(self.get_active_block_config(cin))

class DynamicFusedMBConvSEResBlock(_DynamicFusedMBConvBlock):

    def __init__(self, max_cin: int, width_list: List[int], kernel_list: List[int], stride: int, expand_list: List[float], activation=nn.ReLU, inplace=True) -> None:
        super().__init__(max_cin, width_list, kernel_list, stride, expand_list, use_se=True, activation=activation, inplace=inplace, force_residual=True)

    def get_active_block(self, cin: int, retain_weights=True) -> FusedMBConvSEResBlock:
        block = FusedMBConvSEResBlock.build_from_config(self.get_active_block_config(cin))
        if retain_weights:
            hidden_size = self.get_active_hidden_size(cin)
            block.fused_conv.load_state_dict(self.fused_conv.active_state_dict(cin, cout=hidden_size))
            self.se.active_mid_channels = self.se.get_mid_channels(cin)
            block.se.load_state_dict(self.se.active_state_dict(hidden_size))
            block.point_conv.load_state_dict(self.point_conv.active_state_dict(hidden_size))
            if hasattr(block, 'downsample'):
                block.downsample.load_state_dict(self.downsample.active_state_dict(cin))
        return block

    def get_active_tf_block(self, cin: int):
        from modules.modeling.blocks.tf_blocks import FusedMBConvSEResBlock as FusedMBConvSEResBlock_TF
        return FusedMBConvSEResBlock_TF.build_from_config(self.get_active_block_config(cin))


# -*- coding: utf-8 -*-
"""
Created on Fri Feb  7 09:52:33 2020

@author: chadd
"""

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

led_pins = [18, 19, 20, 21, 24, 26, 27]
but_pin = 23

GPIO.setup(led_pins, GPIO.OUT)
GPIO.output(led_pins, False)
GPIO.setup(but_pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

run = True

while run == True:
    for pin in led_pins:
        GPIO.output(pin, True)

        #delay and check button press function
            #break if you detect a button press

    GPIO.output(pin,True)
    time.sleep(0.4)
    GPIO.output(pin, False)
    time.sleep(0.4)
    GPIO.output(pin,True)
    time.sleep(0.4)
    GPIO.output(pin, False)
    time.sleep(0.4)
    GPIO.output(pin,True)
    time.sleep(0.4)

    # same delay and check button press function while waiting for like 3 seconds
        # run == False if button press


###################################################################
#
#           MM     MM
#           MMM   MMM
#           MMMM MMMM
#           MM MMM MM
#           MM  M  MM
#           MM     MM
#          MMMM   MMMM     AaronMing 2020
#
#       贪食蛇，游戏控制单元
#
###################################################################

from pybricks.hubs import EV3Brick
from pybricks.parameters import Port, Stop, Direction, Button, Color
from pybricks.tools import wait, StopWatch, DataLog
from pybricks.media.ev3dev import SoundFile, ImageFile
from pybricks.media.ev3dev import Font  # 引入字体类

from uMSGround import MSGround
from uMSnake import *
import time

# 调用主机
ev3 = EV3Brick()

class MSControl:
    # 构造函数
    def __init__(self, ASnake, AFood):
        self.ASnake = ASnake  # 蛇
        self.AFood = AFood
        self.ALevel = 1  # 当前等级
        self.TopScore = 0  # 最高分
        self.LoadTopScore()
        ev3.speaker.set_speech_options(language=None, voice="f2", speed=180, pitch=None)
        ev3.speaker.set_volume(5, which="Beep")
        chinese_font = Font(size=12, lang="zh-cn")
        big_font = Font(size=12, bold=True)
        ev3.screen.set_font(chinese_font)

    # 读取最高分数
    def LoadTopScore(self):
        # 打开保存最高分的文件
        FTopScore = open("score.txt", "r")
        score = FTopScore.readline()  # 读取第一行
        self.TopScore = int(score)  # 把自己当前的最高分设置为从文件读取的最高分

    # 将最高分数写入文件
    def WriteTopScore(self):
        FTopScore = open("score.txt", "w")
        FTopScore.write(str(self.TopScore))  # 把自己当前的最高分设置为从文件读取的最高分

    # 根据当前数据设置最高分，如果超过最高分，则刷新最高分
    def _RefreshTopScore(self):
        score = self.ASnake.GetLength()
        if score > self.TopScore:
            self.TopScore = score
            self.WriteTopScore()
            ev3.speaker.say("New high score! Congratulations!")

    # 显示最高分
    def ShowBest(self):
        self.LoadTopScore()
        ev3.screen.draw_line(
            4, 5, 4 + self.TopScore // 2, 5, width=3, color=Color.BLACK
        )

    # 显示积分
    def ShowScore(self):
        ev3.screen.draw_line(
            4, 9, 4 + self.ASnake.GetLength() // 2, 9, width=3, color=Color.BLACK
        )

    # 显示游戏信息
    def ShowGameInfo(self):
        ev3.screen.print(
            "=============================\n"
            + "   MM     MM\n"
            + "   MMM   MMM\n"
            + "   MMMM MMMM\n"
            + "   MM MMM MM  AaronMing 2020\n"
            + "   MM  M  MM   MSnake  V0.0.0\n"
            + "   MM     MM     《贪食蛇》\n"
            + "  MMMM   MMMM\n"
            + "============================="
        )

    # 显示启动页面并等待开始
    def ShowWelcomAndWait(self):
        ev3.screen.print(
            "\n"
            + "   上方第一条线：最高分数\n\n"
            + "   上方第二条线：当前分数\n\n\n"
            + "   当前最高分数："
            + str(self.TopScore)
            + "\n"
            + "\n"
            + "        按右键继续..."
        )
        while not Button.RIGHT in ev3.buttons.pressed():
            time.sleep(0.01)

    # 计算蛇的等级
    def _CalLevel(self):
        SLen = self.ASnake.GetLength()
        # 如果长度大于200，则长度为200
        if SLen > 90:
            SLen = 90
        self.ALevel = (SLen // 10) + 1

    # 计算等待的计数次数
    def _CalWaitTag(self):
        if self.ALevel == 1:
            Result = 160
        elif self.ALevel == 2:
            Result = 150
        elif self.ALevel == 3:
            Result = 140
        elif self.ALevel == 4:
            Result = 130
        elif self.ALevel == 5:
            Result = 120
        elif self.ALevel == 6:
            Result = 110
        elif self.ALevel == 7:
            Result = 100
        elif self.ALevel == 8:
            Result = 90
        elif self.ALevel == 9:
            Result = 80
        elif self.ALevel == 10:
            Result = 70
        return Result

    # 开始游戏
    def StartGame(self):
        ev3.screen.clear()
        self.ASnake.GetGround().RedrawGround()
        self.ASnake.Reset()
        self.ASnake.Drawbody()
        self.ShowBest()
        self.ShowScore()

        # 播放开始游戏的声音
        ev3.speaker.say("Go Go Go!")
        # 避免程序在sleep时实去响应，定义此参数，等待计数
        waitTag = 0
        AWaitCnt = self._CalWaitTag()

        # 取得蛇的方向，
        ADir = self.ASnake.GetDirect()
        while True:
            # 根据按键确认方向
            if Button.RIGHT in ev3.buttons.pressed():
                ADir = MSDirec_Right
            elif Button.DOWN in ev3.buttons.pressed():
                ADir = MSDirec_Down
            elif Button.LEFT in ev3.buttons.pressed():
                ADir = MSDirec_Left
            elif Button.UP in ev3.buttons.pressed():
                ADir = MSDirec_Up

            if waitTag == AWaitCnt:
                # if waitTag == 70:
                # 根据最后的输入确定改变蛇的方向
                self.ASnake.SetDirect(ADir)
                # 如果蛇头吃掉了一个食物
                if self.AFood.EatAFood(self.ASnake.GetHeadLoc()):
                    AGrow = True
                    self.ShowScore()
                else:
                    AGrow = False

                self._CalLevel()
                AWaitCnt = self._CalWaitTag()

                # 如果移动失败了，说明游戏结束了
                if not self.ASnake.Move(AGrow):
                    ev3.speaker.say("Game over! ")
                    break
                    # 重置等待计数
                self.AFood.AddFood()
                self.AFood.DrawAllFood()
                waitTag = 0
            else:
                waitTag += 1

            time.sleep(0.001)

    # 显示游戏结果并等待
    def ShowResult(self):
        ev3.screen.print(
            "\n\n"
            + "   最高分："
            + str(self.TopScore)
            + "\n\n"
            + "   您的得分："
            + str(self.ASnake.GetLength())
            + "\n\n\n"
            + "\n"
            + "        按右键继续..."
        )

    # 开始运行
    def Run(self):
        RunGame = True  # 定义游戏是否继续运行
        ev3.screen.clear()  # 清理屏幕
        self.ShowGameInfo()  # 显示游戏信息
        time.sleep(1)
        ev3.screen.clear()  # 清理屏幕
        self.ShowWelcomAndWait()
        while RunGame:
            self.StartGame()
            ev3.screen.clear()  # 清理屏幕
            self.ShowResult()
            self._RefreshTopScore()
            while not Button.RIGHT in ev3.buttons.pressed():
                time.sleep(0.01)


# Задание 2
import hashlib

def get_md5(file):
    with open(file, 'r', encoding='utf-8-sig') as doc:
        for _ in doc:
            line_hash = hashlib.md5(doc.readline().encode('utf-8-sig')).hexdigest()
            yield line_hash

if __name__ == '__main__':
    # Используем result.txt, полученный в main.py
    for line in get_md5('result.txt'):
        print(line)


#!/usr/bin/python3
from requests import get

def top_ten(subreddit):
    url = "https://api.reddit.com/r/{}?sort=hot&limit=10".format(subreddit)
    user_agent = "application/x-www-form-urlencoded"
    response = get(url, headers={'User-Agent': user_agent})

    if response.status_code == 200:
        data = response.json()
        top = data.get('data').get('children')
        for new in top:
            title = new.get('data').get('title')
            print(title)
    else:
        print('None')


from ..models import History

def get_history_by_patient_id(patient_pk):
    # Try to get the history for the given patient_pk
    history, created = History.objects.get_or_create(patient_id=patient_pk)

    # If created is True, it means a new history object was created
    if created:
        # You can initialize default values for the history object here
        history.state = 'New Patient'
        history.observation = ''
        history.save()

    return history

def get_history_by_id(history_pk):
    return History.objects.get(pk=history_pk)

def update_history(form, history_pk, patient_id):
    form.instance.pk = history_pk
    form.instance.patient_id = patient_id
    history = form.save()
    history.save()
    return history


import glob
import os
import platform
import re
import shutil
import subprocess
import sys

import setuptools
from setuptools.command.build_ext import build_ext

cur_dir = os.path.dirname(os.path.abspath(__file__))

def is_windows():
    return platform.system() == "Windows"

def cmake_extension(name, *args, **kwargs) -> setuptools.Extension:
    kwargs["language"] = "c++"
    sources = []
    return setuptools.Extension(name, sources, *args, **kwargs)

class BuildExtension(build_ext):
    def build_extension(self, ext: setuptools.extension.Extension):
        build_dir = self.build_temp
        os.makedirs(build_dir, exist_ok=True)

        os.makedirs(self.build_lib, exist_ok=True)

        cmake_args = os.environ.get("KALDILM_CMAKE_ARGS", "")
        make_args = os.environ.get("KALDILM_MAKE_ARGS", "")
        system_make_args = os.environ.get("MAKEFLAGS", "")

        if cmake_args == "":
            cmake_args = "-DCMAKE_BUILD_TYPE=Release"

        if make_args == "" and system_make_args == "":
            print("For fast compilation, run:")
            print('export KALDILM_MAKE_ARGS="-j"; python setup.py install')
            make_args = " -j4 "
            print("Setting make_args to '-j4'")

        if "PYTHON_EXECUTABLE" not in cmake_args:
            print(f"Setting PYTHON_EXECUTABLE to {sys.executable}")
            cmake_args += f" -DPYTHON_EXECUTABLE={sys.executable}"

        if not is_windows():
            ret = os.system(
                f"cd {build_dir}; cmake {cmake_args} {cur_dir}; make -j _kaldilm"
            )
            if ret != 0:
                raise Exception(
                    "\nBuild kaldilm failed. Please check the error message.\n"
                    "You can ask for help by creating an issue on GitHub.\n"
                    "\nClick:\n    https://github.com/csukuangfj/kaldilm/issues/new\n"
                )
            lib_so = glob.glob(f"{build_dir}/lib/*.so*")
            for so in lib_so:
                print(f"Copying {so} to {self.build_lib}/")
                shutil.copy(f"{so}", f"{self.build_lib}/")

            # macos
            # also need to copy *fst*.dylib
            lib_so = glob.glob(f"{build_dir}/lib/*.dylib*")
            for so in lib_so:
                print(f"Copying {so} to {self.build_lib}/")
                shutil.copy(f"{so}", f"{self.build_lib}/")
            return
        # for windows

        build_cmd = f"""
            cmake {cmake_args} -B {self.build_temp} -S {cur_dir}
            cmake --build {self.build_temp} --target _kaldilm --config Release -- -m
        """
        print(f"build command is:\n{build_cmd}")

        ret = os.system(f"cmake {cmake_args} -B {self.build_temp} -S {cur_dir}")
        if ret != 0:
            raise Exception("Failed to build kaldilm")
        ret = os.system(
            f"cmake --build {self.build_temp} --target _kaldilm --config Release -- -m"
        )
        if ret != 0:
            raise Exception("Failed to build kaldilm")

        # bin/Release/_kaldilm.cp38-win_amd64.pyd
        lib_so = glob.glob(f"{self.build_temp}/**/*.pyd", recursive=True)
        for so in lib_so:
            print(f"Copying {so} to {self.build_lib}/")
            shutil.copy(f"{so}", f"{self.build_lib}/")

        # lib/Release/{_kaldilm, openfst}.lib
        lib_so = glob.glob(f"{self.build_temp}/**/*.lib", recursive=True)
        for so in lib_so:
            print(f"Copying {so} to {self.build_lib}/")
            shutil.copy(f"{so}", f"{self.build_lib}/")

def read_long_description():
    with open("README.md", encoding="utf8") as f:
        readme = f.read()
    return readme

def get_package_version():
    with open("CMakeLists.txt") as f:
        content = f.read()

    latest_version = re.search(r"set\(kaldilm_VERSION (.*)\)", content).group(1)
    latest_version = latest_version.strip('"')
    return latest_version

package_name = "kaldilm"

setuptools.setup(
    name=package_name,
    version=get_package_version(),
    author="Fangjun Kuang",
    author_email="csukuangfj@gmail.com",
    package_dir={
        package_name: "kaldilm/python/kaldilm",
    },
    packages=[package_name],
    url="https://github.com/csukuangfj/kaldilm",
    long_description=read_long_description(),
    long_description_content_type="text/markdown",
    ext_modules=[cmake_extension("_kaldilm")],
    cmdclass={"build_ext": BuildExtension},
    zip_safe=False,
    classifiers=[
        "Programming Language :: C++",
        "Programming Language :: Python",
        "Topic :: Scientific/Engineering :: Artificial Intelligence",
    ],
    license="Apache licensed, as found in the LICENSE file",
)


from urllib.request import urlretrieve, URLError

uri_fmt = 'https://portalstoragewuprod.azureedge.net/vision/{}/{}.jpg'
file_fmt = '{}_{}.jpg'

for service in ['Analysis', 'Thumbnail']:
    for ix in range(1, 40):
        uri = uri_fmt.format(service, ix)
        img = file_fmt.format(service, ix)
        try:
            urlretrieve(uri, img)
            print('Downloaded {} to {}'.format(uri, img))
        except URLError as e:
            print('Image {} failed to download: {}'.format(uri, e))


import discord
from discord.ext import commands
from Helpers import EmbedHelper as embed
import urbandictionary as ud

class CMD_UrbanDictionary:
    def __init__ (self, client):
        self.client = client

    @commands.command(pass_context = True)
    async def urban (self, ctx, *searchItem):
        author = ctx.message.author
        channel = ctx.message.channel

        search = ""
        for word in searchItem:
            search += word
            search += " "

        if search == "":
          await embed.SpecifyErrorEmbed(self.client, channel)
        else:
          try:
            search = search.replace('[', '')
            search = search.replace(']', '')

            definitions = ud.define(search)

            definition = definitions[0]

            definition.word = definition.word.replace('[', '')
            definition.word = definition.word.replace(']', '')
            definition.definition = definition.definition.replace('[', '')
            definition.definition = definition.definition.replace(']', '')
            definition.example = definition.example.replace('[', '')
            definition.example = definition.example.replace(']', '')

            await embed.UrbanEmbed(self.client, definition.word, definition.definition, definition.example, definition.upvotes, definition.downvotes, channel)
          except:
            await embed.UnknownErrorEmbed(self.client, channel)

def setup (client):
    client.add_cog(CMD_UrbanDictionary(client))


import argparse
import os
import torch
import torch.distributed as dist

from maskrcnn_benchmark.solver import make_lr_scheduler
from maskrcnn_benchmark.solver import make_optimizer
from maskrcnn_benchmark.utils.checkpoint import DetectronCheckpointer
from maskrcnn_benchmark.utils.collect_env import collect_env_info
from maskrcnn_benchmark.utils.comm import synchronize, get_rank
from maskrcnn_benchmark.utils.logger import setup_logger
from maskrcnn_benchmark.utils.miscellaneous import mkdir, save_config

from siammot.configs.defaults import cfg
from siammot.data.build_train_data_loader import build_train_data_loader
from siammot.modelling.rcnn import build_siammot
from siammot.engine.trainer import do_train
from siammot.utils.get_model_name import get_model_name
from siammot.engine.tensorboard_writer import TensorboardWriter

try:
    from apex import amp
except ImportError:
    raise ImportError('Use APEX for multi-precision via apex.amp')

parser = argparse.ArgumentParser(description="PyTorch SiamMOT Training")
parser.add_argument("--config-file", default="", metavar="FILE", help="path to config file", type=str)
parser.add_argument("--train-dir", default="", help="training folder where training artifacts are dumped", type=str)
parser.add_argument("--model-suffix", default="", help="model suffix to differentiate different runs", type=str)
parser.add_argument("--local_rank", type=int, default=0)

def train(cfg, train_dir, local_rank, distributed, logger):

    # build model
    model = build_siammot(cfg)
    device = torch.device(cfg.MODEL.DEVICE)
    model.to(device)

    optimizer = make_optimizer(cfg, model)
    scheduler = make_lr_scheduler(cfg, optimizer)

    # Initialize mixed-precision training
    use_mixed_precision = cfg.DTYPE == "float16"
    amp_opt_level = 'O1' if use_mixed_precision else 'O0'
    model, optimizer = amp.initialize(model, optimizer, opt_level=amp_opt_level)

    if distributed:
        model = torch.nn.parallel.DistributedDataParallel(
            model, device_ids=[local_rank], output_device=local_rank,
            broadcast_buffers=False, find_unused_parameters=True
        )

    arguments = {}
    arguments["iteration"] = 0

    save_to_disk = get_rank() == 0
    checkpointer = DetectronCheckpointer(cfg, model, optimizer,
                                         scheduler, train_dir, save_to_disk
                                         )
    extra_checkpoint_data = checkpointer.load(cfg.MODEL.WEIGHT)
    arguments.update(extra_checkpoint_data)

    data_loader = build_train_data_loader(
        cfg,
        is_distributed=distributed,
        start_iter=arguments["iteration"],
    )

    checkpoint_period = cfg.SOLVER.CHECKPOINT_PERIOD

    tensorboard_writer = TensorboardWriter(cfg, train_dir)

    do_train(model, data_loader, optimizer, scheduler,
             checkpointer, device, checkpoint_period, arguments,
             logger, tensorboard_writer
             )

    return model

def setup_env_and_logger(args, cfg):
    num_gpus = int(os.environ["WORLD_SIZE"]) if "WORLD_SIZE" in os.environ else 1
    args.distributed = num_gpus > 1

    if args.distributed:
        torch.cuda.set_device(args.local_rank)
        torch.distributed.init_process_group(backend="nccl", init_method="env://")
        synchronize()

    model_name = get_model_name(cfg, args.model_suffix)
    train_dir = os.path.join(args.train_dir, model_name)
    if train_dir:
        mkdir(train_dir)

    logger = setup_logger("siammot", train_dir, get_rank())
    logger.info("Using {} GPUs".format(num_gpus))
    logger.info(args)

    logger.info("Collecting env info (might take some time)")
    logger.info("\n" + collect_env_info())

    logger.info("Loaded configuration file {}".format(args.config_file))
    with open(args.config_file, "r") as cf:
        config_str = "\n" + cf.read()
        logger.info(config_str)
    logger.info("Running with config:\n{}".format(cfg))

    output_config_path = os.path.join(train_dir, 'config.yml')
    logger.info("Saving config into: {}".format(output_config_path))
    save_config(cfg, output_config_path)

    return train_dir, logger

def main():
    args = parser.parse_args()

    cfg.merge_from_file(args.config_file)
    cfg.freeze()

    train_dir, logger = setup_env_and_logger(args, cfg)

    train(cfg, train_dir, args.local_rank, args.distributed, logger)

if __name__ == "__main__":
    main()


from PIL import Image
import numpy as np

def distance(x, y, ox, oy):
    return np.sqrt((x-ox)**2 + (y-oy)**2)

def sin(x):
    return np.sin(x)

def zdistance(x, y, origin, factor):
    return round(distance(x, y, origin[0], origin[1])) % factor

def colorSin(freq, o, x, y, factor, num):
    return np.floor((128 + 127 * sin(freq * np.pi*2 * zdistance(x,y,o, factor)/factor))/num)

def createImg(dim, factor, waves, colorSplit, originSplit):
    w, h = dim, dim
    data = np.zeros((w, h, 3), dtype=np.uint8)

    waves = sorted(waves)
    factor = min(waves)*dim/(2*factor)
    waveOrigins = [(dim/2, dim/2)] * len(waves)
    if originSplit == True:
        if len(waves) == 2:
            waveOrigins = [(dim/3, dim/2), (2*dim/3, dim/2)]
        if len(waves) == 3:
            waveOrigins = [(dim/3, dim/2), (2*dim/3, dim/3), (2*dim/3, 2*dim/3)]
        if len(waves) == 4:
            waveOrigins = [(dim/3, dim/3), (dim/3, 2*dim/3), (2*dim/3, dim/3), (2*dim/3, 2*dim/3)]

    colorCount = 2
    waveCount = 0
    for wave in waves:
        for x in range(0, w):
            for y in range(0, h):
                if colorSplit:
                    data[x,y][colorCount] += colorSin(wave, waveOrigins[waveCount], x, y, factor, 1)
                    data[x,y][colorCount] %= 256
                else:
                    v = colorSin(wave, waveOrigins[waveCount], x, y, factor, len(waves))
                    data[x,y][0] += v
                    data[x,y][1] += v
                    data[x,y][2] += v
        waveCount = waveCount+1
        colorCount = (colorCount+1)%3

    return data

def saveImage(dim, factor, waves, filename, colorSplit = False, originSplit = False):
    data = createImg(dim, factor, waves, colorSplit, originSplit)
    img = Image.fromarray(data, 'RGB')
    img.save(filename+'.png')

def showImage(dim, factor, waves, colorSplit = False, originSplit = False):
    data = createImg(dim, factor, waves, colorSplit, originSplit)
    img = Image.fromarray(data, 'RGB')
    img.show()

intervalRatios = [1, 16/15, 9/8, 6/5, 5/4, 4/3, 7/5, 3/2, 8/5, 5/3, 9/5, 15/8, 2]
intervalNames = ["U", "mi2", "M2", "mi3", "M3", "P4", "T", "P5", "mi6", "M6", "mi7", "M7", "O"]

def tetImages(dim, factor, base, colorDif = False, originDif = False):
    for i in range(0, 13):
        saveImage(dim, factor,[base, base*intervalRatios[i]], intervalNames[i], colorDif, originDif)

def chordImages(dim, factor, base, colorDif = False, originDif = False):
    saveImage(dim, factor, [base, base*intervalRatios[4], base*intervalRatios[7]], "major", colorDif, originDif)
    saveImage(dim, factor, [base, base*intervalRatios[3], base*intervalRatios[7]], "minor", colorDif, originDif)
    saveImage(dim, factor, [base, base*intervalRatios[5], base*intervalRatios[7]], "sus4", colorDif, originDif)
    saveImage(dim, factor, [base, base*intervalRatios[2], base*intervalRatios[7]], "sus2", colorDif, originDif)
    saveImage(dim, factor, [base, base*intervalRatios[1], base*intervalRatios[7]], "phyrgian", colorDif, originDif)
    saveImage(dim, factor, [base, base*intervalRatios[6], base*intervalRatios[7]], "tritone", colorDif, originDif)

def arrayFromImage(filename):
    im = Image.open(filename)
    return np.array(im)

def intervalAnalysis(filename):
    count = 0
    arr = arrayFromImage(filename)
    for x in range(0, arr.shape[0]):
        for y in range(0, arr.shape[1]):
            if( np.abs(int(arr[x,y][2]) - int(arr[x,y][0])) < 5): #Purple or Black
                count = count + 1
            if( int(arr[x,y][0]) > 0 and int(arr[x,y][2])/int(arr[x,y][0]) < 0.1): #Red
                count = count + 1
            if( int(arr[x,y][2]) > 0 and int(arr[x,y][0])/int(arr[x,y][2]) < 0.1): #Blue
                count = count - 0
    return count

tetImages(512, 1, 200, True, False)

#chordImages(512, 1, 200, True, False)

#intervalsAnalysisArray = [intervalAnalysis(intervalNames[0]+".png"),intervalAnalysis(intervalNames[1]+".png"),intervalAnalysis(intervalNames[2]+".png"),intervalAnalysis(intervalNames[3]+".png"),intervalAnalysis(intervalNames[4]+".png"),intervalAnalysis(intervalNames[5]+".png"),intervalAnalysis(intervalNames[6]+".png"),intervalAnalysis(intervalNames[7]+".png"),intervalAnalysis(intervalNames[8]+".png"),intervalAnalysis(intervalNames[9]+".png"),intervalAnalysis(intervalNames[10]+".png"),intervalAnalysis(intervalNames[11]+".png"),intervalAnalysis(intervalNames[12]+".png")]
#print(intervalsAnalysisArray)

#showImage(512, 1, [200, 300], originSplit= False, colorSplit=True)


from contextlib import nullcontext
from typing import List

from absl import logging
import tensorflow as tf
from monolith.agent_service.agent_service_pb2 import ServerType
from monolith.agent_service.backends import SyncBackend
from monolith.utils import get_libops_path
from monolith.native_training.runtime.ops import gen_monolith_ops
from monolith.native_training import utils
from monolith.native_training.model_export.export_context import is_exporting_standalone
from monolith.native_training.runtime.parameter_sync import \
  parameter_sync_pb2

gen_distributed_serving_ops = gen_monolith_ops

def remote_predict(input_tensor_alias,
                   input_tensors,
                   output_tensor_alias,
                   model_name,
                   task,
                   old_model_name,
                   model_version=-1,
                   fail_op_on_rpc_error=True,
                   max_rpc_deadline_millis=30,
                   output_types=None,
                   name=None,
                   signature_name='serving_default'):
  """Runs a predict in remote process through rpc.
  Args:
    input_tensor_alias: input tensor alias for Predict
    input_tensors: input tensors for Predict
    output_tensor_alias: output tensor alias for Predict
    task: Parameter Server index
    model_name: model_name that the Predict is running on
    model_version: the model version for the Predict call. If unset, the highest
      version available for serving will be targeted.
    max_rpc_deadline_millis: rpc deadline in millis
    output_types: output types for Predict
    name: name for the op in the graph
    signature_name: the signature def for remote graph inference
  Returns:
    output_tensors as a result of the Predict.
  Raises ValueError if model_name value is missing.
  """
  if model_name is None:
    raise ValueError('model_name must be specified.')
  return (gen_distributed_serving_ops.tf_serving_remote_predict(
      input_tensor_alias,
      input_tensors,
      output_tensor_alias,
      model_name=model_name,
      old_model_name=old_model_name,
      task=task,
      model_version=model_version,
      fail_op_on_rpc_error=fail_op_on_rpc_error,
      max_rpc_deadline_millis=max_rpc_deadline_millis,
      signature_name=signature_name,
      output_types=output_types,
      name=name))[2]

def create_parameter_sync_clients(ps_num: int,) -> List[tf.Tensor]:
  logging.info("Create parameter sync clients.")
  if ps_num == 0:
    return [parameter_sync_client_from_config()]

  sync_clients = list()
  for i in range(ps_num):
    ps_device_name = utils.ps_device(i)
    with nullcontext() if is_exporting_standalone() else tf.device(
        ps_device_name):
      sync_clients.append(parameter_sync_client_from_config(name_suffix=str(i)))
  return sync_clients

def parameter_sync_client_from_config(
    config: parameter_sync_pb2.ClientConfig = None,
    name_suffix: str = "") -> tf.Tensor:
  return gen_distributed_serving_ops.MonolithParameterSyncClient(
      config=config.SerializeToString() if config else '',
      shared_name="MonolithSyncClient_" + name_suffix)

def refresh_sync_config(sync_backend: SyncBackend, ps_index: int) -> bytes:
  saved_model, online_ps_replicas = sync_backend.get_sync_targets(
      f"ps_{ps_index}")
  config = parameter_sync_pb2.ClientConfig()
  if isinstance(online_ps_replicas, list):
    config.targets.extend(online_ps_replicas)
  elif isinstance(online_ps_replicas, dict):
    for addr, target_extra_info in online_ps_replicas.items():
      config.targets.append(addr)
      config.targets_extra_info.append(target_extra_info)
  config.model_name = saved_model
  config.signature_name = "hashtable_assign"
  config.timeout_in_ms = 3000
  return config.SerializeToString()

def create_dummy_sync_client() -> tf.Tensor:
  return gen_distributed_serving_ops.MonolithDummySyncClient(
      shared_name="MonolithDummySyncClient")

def create_dummy_sync_server(address: str) -> tf.Tensor:
  return gen_distributed_serving_ops.MonolithDummySyncServer(address=address)

class ParameterSyncClient(object):

  def __init__(self, client: tf.Tensor):
    self._client = client

  def create_sync_op(self, config_str: tf.Tensor):
    return gen_distributed_serving_ops.monolith_parameter_sync(
        self._client, config_str)

  def as_op(self):
    return tf.group(self._client)

  @property
  def handle(self):
    return self._client

class DummySyncServer(object):

  def __init__(self, address: str):
    self._server = create_dummy_sync_server(address)

  def shutdown(self):
    return gen_distributed_serving_ops.monolith_dummy_sync_server_shutdown(
        self._server)

  def get_port(self):
    return gen_distributed_serving_ops.monolith_dummy_sync_server_get_port(
        self._server)

  def as_op(self):
    return tf.group(self._server)

  @property
  def handle(self):
    return self._server


from collections import defaultdict
import math

def solution(fees, records):
    answer = []

    record_dict = defaultdict(list)
    car_num = defaultdict(list)

    for element in records:
        now_time, now_car, now_statue = element.split()

        car_num[now_car] = [0, 0]

        convert_time = int(now_time.split(":")[0]) * 60 + int(now_time.split(":")[1])

        if now_statue == "IN":
            record_dict[now_car].append(convert_time)
        else:
            record_dict[now_car].append(convert_time)

    for key in record_dict.keys():
        if len(record_dict[key]) % 2 != 0:
            record_dict[key].append(1439)

        for i in range(0, len(record_dict[key]), 2):
            sum_time = record_dict[key][i + 1] - record_dict[key][i]
            car_num[key][0] += sum_time

    for key in car_num.keys():
        if car_num[key][0] <= fees[0]:
            car_num[key][1] = fees[1]
        else:
            now_fee = fees[1]
            last_time = math.ceil((car_num[key][0] - fees[0]) / fees[2])
            now_fee += last_time * fees[3]
            car_num[key][1] = now_fee

    unsorted_arr = []

    for key in car_num.keys():
        unsorted_arr.append([int(key), car_num[key][1]])

    unsorted_arr.sort()

    for element in unsorted_arr:
        answer.append(element[1])

    return answer

if __name__ == "__main__":
    print(solution([180, 5000, 10, 600],
                   ["05:34 5961 IN", "06:00 0000 IN", "06:34 0000 OUT", "07:59 5961 OUT", "07:59 0148 IN",
                    "18:59 0000 IN", "19:09 0148 OUT", "22:59 5961 IN", "23:00 5961 OUT"]), [14600, 34400, 5000])
    print(solution([120, 0, 60, 591],
                   ["16:00 3961 IN", "16:00 0202 IN", "18:00 3961 OUT", "18:00 0202 OUT", "23:58 3961 IN"]), [0, 591])
    print(solution([1, 461, 1, 10], ["00:00 1234 IN"]), [14841])


# coding=utf-8
import pandas as pd
from sklearn.cross_validation import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold, KFold
from sklearn.metrics import roc_auc_score, precision_recall_curve, roc_curve, average_precision_score
import numpy as np
import gc
from datetime import datetime
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import MinMaxScaler,StandardScaler

valid_data = pd.read_csv("../result/submission_5x-LGB0598965_seed_1024.txt")
print(valid_data.count())
valid_data = valid_data.rename(columns={'prob':'prob1'})
valid2 = pd.read_csv("../result/submission_5x-LGB0600478_seed_1024.txt")
valid2 = valid2.rename(columns={'prob':'prob2'})
valid3 = pd.read_csv("../result/submission_5x-LGB0605474_seed_1024.txt")
valid3 = valid3.rename(columns={'prob':'prob3'})
valid4 = pd.read_csv("../result/submission_5x-LGB0609101_seed_1024.txt")
valid4 = valid4.rename(columns={'prob':'prob4'})
valid5 = pd.read_csv("../result/submission_5x-XGB0596604_seed_1024.txt")
valid5 = valid5.rename(columns={'prob':'prob5'})
valid6 = pd.read_csv("../result/submission_5x-XGB0605969_seed_1024.txt")
valid6 = valid6.rename(columns={'prob':'prob6'})
valid7 = pd.read_csv("../result/submission_5x-XGB0607207_seed_1024.txt")
valid7 =valid7.rename(columns={'prob':'prob7'})

valid_data = pd.merge(valid_data,valid2,how='left',on='id')
valid_data = pd.merge(valid_data,valid3,how='left',on='id')
valid_data = pd.merge(valid_data,valid4,how='left',on='id')
valid_data = pd.merge(valid_data,valid5,how='left',on='id')
valid_data = pd.merge(valid_data,valid6,how='left',on='id')
valid_data = pd.merge(valid_data,valid7,how='left',on='id')

print(valid_data.head())
valid_data['prob'] = (valid_data['prob1']+valid_data['prob2']+
                      valid_data['prob3']+valid_data['prob4']+
                      valid_data['prob5']+valid_data['prob6']+
                      valid_data['prob7'])/7
print(valid_data.count())
valid_data = valid_data[['id','prob']]

# valid_data.to_csv("../result/sub_final.txt",index=False)

params = [
    {'boosting_type': 'gbdt',
     'objective': 'binary',
     'metric': {'auc'},
     'learning_rate': 0.1,
     'max_depth': 10,
     'num_leaves': 40,
     'feature_fraction': 0.3,
     'bagging_freq': 3,
     # 'min_split_gain': 0.2,
     'min_child_weight': 12,
     'reg_alpha': 4,
     'reg_lambda':4 ,
     # 'is_unbalance':True
     # 'verbose': 1},
     },
    {
        'booster': 'gbtree',
        'objective': 'binary:logistic',
        'eta': 0.1,
        # 'max_depth': 10,
        'subsample': 0.5,
        # 'min_child_weight': 5,
        'colsample_bytree': 0.6,
        # 'scale_pos_weight': 0.1,
        'eval_metric': 'auc',
        'alpha':2,
        'lambda': 5,
        'nthread':4
    }

]
############################################################
import lightgbm as lgb
import xgboost as xgb
from  sklearn.linear_model import LogisticRegression
feature = [x for x in train_data.columns if x not in ('label','id')]
print(feature)
valid_data = train_data[train_data['label']==-1]
train_data = train_data[train_data['label']!=-1]
# valid_X = valid_data[feature]
# valid_Y = valid_data['label']
# X = train_data[feature]
y = train_data['label']

# sc = StandardScaler()
# train_data = sc.fit_transform(train_data[[x for x in train_data.columns if x not in ('symbol','label')]])

folds = StratifiedKFold(n_splits=5, shuffle=True, random_state=1024)
# oof_preds = np.zeros(train_data.shape[0])
# sub_preds = np.zeros(valid_data.shape[0])
# feature_importance_df = pd.DataFrame()
# for n_fold, (trn_idx, val_idx) in enumerate(folds.split(train_data, y)):
#     X_train, y_train = train_data[feature].iloc[trn_idx], y.iloc[trn_idx]
#     X_test, y_test = train_data[feature].iloc[val_idx], y.iloc[val_idx]
#
#     lgb_train = lgb.Dataset(X_train, y_train)
#     del X_train, y_train,
#     lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train)
#
#     clf = lgb.train(params[0],
#                     lgb_train,
#                     num_boost_round=20000,
#                     valid_sets=[lgb_eval],
#                     early_stopping_rounds=200,
#                     verbose_eval=100)
#
#     oof_preds[val_idx] = clf.predict(X_test, num_iteration=clf.best_iteration)
#
#     sub = pd.Series(clf.predict(valid_data[feature], num_iteration=clf.best_iteration)).rank(pct=True).values
#     sub_preds += sub / (folds.n_splits)
#
#     fold_importance_df = pd.DataFrame()
#     fold_importance_df["feature"] = clf.feature_name()
#     fold_importance_df["importance"] = clf.feature_importance()
#     fold_importance_df["fold"] = n_fold + 1
#     feature_importance_df = pd.concat([feature_importance_df, fold_importance_df], axis=0)
#
#     print('Fold %2d AUC : %.6f' % (n_fold + 1, roc_auc_score(y_test, oof_preds[val_idx])))
#     del X_test, y_test
#     gc.collect()
# print('Full AUC score %.6f' % roc_auc_score(y, oof_preds))
# oof_preds1 = oof_preds
# sub_preds1 = sub_preds
# ################################
oof_preds = np.zeros(train_data.shape[0])
sub_preds = np.zeros(valid_data.shape[0])
for n_fold, (trn_idx, val_idx) in enumerate(folds.split(train_data, y)):
    X_train, y_train = train_data[feature].iloc[trn_idx], y.iloc[trn_idx]
    X_test, y_test = train_data[feature].iloc[val_idx], y.iloc[val_idx]
    xgb_train = xgb.DMatrix(X_train,y_train)
    # lgb_train = lgb.Dataset(X_train, y_train)
    del X_train, y_train,
    xgb_eval = xgb.DMatrix(X_test,y_test)
    watchlist = [(xgb_train,'train'),(xgb_eval,'val')]

    # lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train)

    # clf = lgb.train(params[0],
    #                 lgb_train,
    #                 num_boost_round=20000,
    #                 valid_sets=[lgb_eval],
    #                 early_stopping_rounds=200,
    #                 verbose_eval=100)
    clf = xgb.train(params[1],xgb_train,num_boost_round=10000,evals=watchlist,early_stopping_rounds=100)
    # print(clf.predict(X_test).head())
    test = xgb.DMatrix(X_test)
    oof_preds[val_idx] = clf.predict(test,ntree_limit=clf.best_iteration)

    valid = xgb.DMatrix(valid_data[feature])
    sub = pd.Series(clf.predict(valid,ntree_limit=clf.best_iteration)).rank(pct=True).values
    sub_preds += sub / (folds.n_splits)
########################################################################
    # print(clf.feature_importance)
    # fold_importance_df = pd.DataFrame()
    # fold_importance_df["feature"] = clf.feature_name()
    # fold_importance_df["importance"] = clf.feature_importance()
    # fold_importance_df["fold"] = n_fold + 1
    # feature_importance_df = pd.concat([feature_importance_df, fold_importance_df], axis=0)

    print('Fold %2d AUC : %.6f' % (n_fold + 1, roc_auc_score(y_test, oof_preds[val_idx])))
    del X_test, y_test
    gc.collect()
print('Full AUC score %.6f' % roc_auc_score(y, oof_preds))
# oof_preds1 = (oof_preds1+oof_preds)/2
# sub_preds = (sub_preds+sub_preds1)/2
# print('Full AUC score final %.6f' % roc_auc_score(y, oof_preds1))

res = valid_data[['id']]
res['prob']=sub_preds

res_t = train_data[['id']]
res_t['prob'] = oof_preds

# In[ ]:

score = str(round(roc_auc_score(y, oof_preds), 6)).replace('.', '')
sub_file = '../result/submission_5x-XGB' + score + "_seed_" + str(1024) + '.txt'
sub_t_file = '../result/submission_t_5x-XGB' + score + "_seed_" + str(1024) + '.txt'
res.to_csv(sub_file, index=False)
res_t.to_csv(sub_t_file,index=False)

# In[ ]:

folds_idx = [(trn_idx, val_idx) for trn_idx, val_idx in folds.split(train_data, y)]
# display_importances(feature_importance_df_=feature_importance_df)

# In[ ]:

display_roc_curve(y_=y, oof_preds_=oof_preds, folds_idx_=folds_idx)


from __future__ import annotations

from typing import TYPE_CHECKING, Optional, List, Union, Any

from discord import Message
from pygame import Surface

from UI.Game import ActivePlayerView, InactivePlayerView

if TYPE_CHECKING:
    from Classes import DeadBot, SubnauticaPlayer, ResourceCard, EquipmentCard, CreatureCard
################################################################################

__all__ = ("SubnauticaPlayerHand",)

################################################################################
class SubnauticaPlayerHand:

    __slots__ = (
        "_player",
        "_resources",
        "_equipment",
        "_creatures",
        "_hand_msg",
        "_hand_view",
        "_hand_renderer",
        "_resource_count",
    )

################################################################################
    def __init__(self, player: SubnauticaPlayer):

        self._player: SubnauticaPlayer = player

        self._resources: List[ResourceCard] = []
        self._equipment: List[EquipmentCard] = []
        self._creatures: List[CreatureCard] = []

        self._hand_msg: Optional[Message] = None
        self._hand_view: Optional[Union[ActivePlayerView, InactivePlayerView]] = None
        self._hand_renderer: PlayerHandRenderer = PlayerHandRenderer(self)

        self._resource_count: int = 0

################################################################################
    def __iadd__(self, other: Any) -> SubnauticaPlayerHand:

        if other.__class__.__name__ not in ("ResourceCard", "EquipmentCard", "CreatureCard",):
            raise TypeError(
                f"unsupported operand type(s) for +=: 'SubnauticaPlayerHand' "
                f"and '{other.__class__.__name__}'"
            )

        if other.__class__.__name__ == "ResourceCard":
            self.add_resource(other)
            self._resource_count += 1
        elif other.__class__.__name__ == "EquipmentCard":
            self.add_equipment(other)
        else:
            self.add_creature(other)

        return self

################################################################################
    def __isub__(self, other: Any) -> SubnauticaPlayerHand:

        if other.__class__.__name__ not in ("ResourceCard", "EquipmentCard",):
            raise TypeError(
                f"unsupported operand type(s) for +=: 'SubnauticaPlayerHand' "
                f"and '{other.__class__.__name__}'"
            )

        if other.__class__.__name__ == "ResourceCard":
            self.resources.remove(other)
        else:
            self.equipment.remove(other)

        return self

################################################################################
    @property
    def resources(self) -> List[ResourceCard]:

        return self._resources

################################################################################
    @property
    def equipment(self) -> List[EquipmentCard]:

        return self._equipment

################################################################################
    @property
    def creatures(self) -> List[CreatureCard]:

        return self._creatures

################################################################################
    @property
    def message(self) -> Optional[Message]:

        return self._hand_msg

################################################################################
    @property
    def view(self) -> Union[ActivePlayerView, InactivePlayerView]:

        return self._hand_view

################################################################################
    @property
    def image(self) -> Optional[str]:

        return self._hand_img

################################################################################
    def add_resource(self, card: ResourceCard) -> None:

        self.resources.append(card)

################################################################################
    def add_equipment(self, card: EquipmentCard) -> None:

        self.equipment.append(card)

################################################################################
    def add_creature(self, card: CreatureCard) -> None:

        self.creatures.append(card)

################################################################################
class PlayerHandRenderer:

    __slots__ = (
        "_parent",
        "_surface",
    )

################################################################################
    def __init__(self, parent: SubnauticaPlayerHand):

        self._parent: SubnauticaPlayerHand = parent
        self._surface: Surface = Surface((1024, 768))

################################################################################
    @property
    def bot(self) -> DeadBot:

        return self._parent._player.bot

################################################################################
    def render(self) -> None:

        pass

################################################################################