import pandas
import os, sys
from datetime import datetime
import numpy as np
import gmplot
from geopy.geocoders import Nominatim
from string import digits
from math import sin, cos, sqrt, atan2, radians, asin

gmap = gmplot.GoogleMapPlotter(35.14, -85.17, 11)

path = os.path.dirname(sys.argv[0])
folderpath = '/'.join(path.split('/')[0:-1]) + '/'
R = 6373.0  # Radius of the globe

start = datetime.now()

# MAIN Calldata 2018 + 2017 #
calldata = pandas.read_excel(folderpath + "Road Diet/Brainerd18.xlsx")

roadwaydata = pandas.read_excel(folderpath + "Excel & CSV Sheets/Roadways_with_Roadnames.xlsx")

def save_excel_file(save_file_name, sheet, data_file_name):
    writer = pandas.ExcelWriter(save_file_name, engine='xlsxwriter', date_format='mmm d yyyy')
    data_file_name.to_excel(writer, sheet_name=sheet)
    workbook = writer.book
    worksheet = writer.sheets[sheet]
    writer.save()

#          Mapping the Calls and their AADT Stations           #

# for i, value in enumerate(calldata.values[0:1000]):
#     lat = calldata.Latitude.values[i]
#     long = calldata.Longitude.values[i]
#     gmap.marker(lat, long, '#FF0000', title=calldata.index.values[i])  # Places a red marker for call

#     roadlat = calldata.Road_Lat.values[i]
#     roadlong = calldata.Road_Long.values[i]
#     gmap.marker(roadlat, roadlong, 'b', title=calldata.index.values[i])

calldata["Road_Station"] = pandas.Series(index=calldata.index)
calldata["AADT"] = pandas.Series(index=calldata.index)
calldata["Road_Lat"] = pandas.Series(index=calldata.index)
calldata["Road_Long"] = pandas.Series(index=calldata.index)
calldata.Road_Station = calldata.Road_Station.astype(str)
calldata.AADT = calldata.AADT.astype(float)
calldata.Road_Lat = calldata.Road_Lat.astype(float)
calldata.Road_Long = calldata.Road_Long.astype(float)

def get_AADT_no_road(j):
    matchlist = []
    minilist = []
    print(j)
    for p,value in enumerate(roadwaydata.values):
        matchlist.append(roadwaydata.StationNumber.values[p])
        lat1 = radians(roadwaydata.Latitude.values[p])
        lon1 = radians(roadwaydata.Longitude.values[p])
        lat2 = radians(calldata.Latitude.values[j])
        lon2 = radians(calldata.Longitude.values[j])

        dlon = lon2 - lon1
        dlat = lat2 - lat1

        a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
        c = 2 * atan2(sqrt(a), sqrt(1 - a))

        distance = R * c

        minilist.append(round(distance,2))

    minindex = minilist.index(min(minilist))

    match = matchlist[minindex]
    calldata.Road_Station.values[j] = match
    calldata.AADT.values[j] = \
    roadwaydata.loc[roadwaydata['StationNumber'] == match, 'AADT_10_Year_Average'].iloc[0]
    calldata.Road_Lat.values[j] = \
        roadwaydata.loc[roadwaydata['StationNumber'] == match, 'Latitude'].iloc[0]
    calldata.Road_Long.values[j] = \
        roadwaydata.loc[roadwaydata['StationNumber'] == match, 'Longitude'].iloc[0]

def get_AADT(j):
    calldata.Address = calldata.Address.astype(str)
    matchlist = []
    latcoords = []
    longcoords = []
    minilist = []
    road = calldata.Address.values[j]
    # print("Call Road",road)
    road = road.lstrip(digits)
    road = road.split("/")[0]
    lat = calldata.Latitude.values[j]
    long = calldata.Longitude.values[j]
    index = 0
    try:
        print(j)
        for i, value in enumerate(roadwaydata.values):
            aadtroad = roadwaydata.Road.values[i]
            aadtroad = aadtroad.lstrip(digits)
            if road in aadtroad:
                print("AADT Road",aadtroad)
                print("Match found!",road, ":", aadtroad)
                # print("Match")
                matchlist.append(roadwaydata.StationNumber.values[i])
                latcoords.append(roadwaydata.Latitude.values[i])
                longcoords.append(roadwaydata.Longitude.values[i])
                print(matchlist)

        for p in range(0, len(matchlist)):
            lat1 = radians(latcoords[p])
            lon1 = radians(longcoords[p])
            lat2 = radians(lat)
            lon2 = radians(long)

            dlon = lon2 - lon1
            dlat = lat2 - lat1

            a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
            c = 2 * atan2(sqrt(a), sqrt(1 - a))

            distance = R * c

            minilist.append(distance)

        minindex = minilist.index(min(minilist))
        match = matchlist[minindex]
        calldata.Road_Station.values[j] = match
        calldata.AADT.values[j] = \
        roadwaydata.loc[roadwaydata['StationNumber'] == match, 'AADT_10_Year_Average'].iloc[0]
        calldata.Road_Lat.values[j] = \
            roadwaydata.loc[roadwaydata['StationNumber'] == match, 'Latitude'].iloc[0]
        calldata.Road_Long.values[j] = \
            roadwaydata.loc[roadwaydata['StationNumber'] == match, 'Longitude'].iloc[0]

    except:
        get_AADT_no_road(j)

# #Finding addresses for the AADT stations.
def find_address(i):
    calldata.Address = calldata.Address.astype(str)
    # empty_test = pandas.isnull(calldata.Address.values[i])
    # if empty_test is True:
    latlong = calldata.Latitude.values[i], calldata.Longitude.values[i]
    print(i)
    try:
        geolocator = Nominatim()
        location = geolocator.reverse(latlong)
        location = str(location).split(",")
        road = str(location[0:2])
        calldata.Address.values[i] = road
    except:
        calldata.Address.values[i] = "Address not found"
    else:
        pass

for k, info in enumerate(calldata.values):
    if calldata.Latitude.values[k] > 40:
        calldata.Latitude.values[k] = (calldata.Latitude.values[k] / 1000000)
        calldata.Longitude.values[k] = (calldata.Longitude.values[k] / -1000000)
for i, info in enumerate(calldata.values):
    find_address(i)

save_excel_file(folderpath + "Road Diet/Brainerd18.xlsx", "Brainerd18", calldata)


import re
from collections import OrderedDict
from datetime import datetime
import moment

# Regex list of lowercase months with characters after the first three made optional
MONTH_NAMES = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august',
  'september', 'october', 'november', 'december']
MONTHS = [m[:3]+"(?:"+m[3:]+")?" if len(m) > 3 else m[:3] for m in MONTH_NAMES]
# Regex list of lowercase weekdays with characters after the first three made optional
DAY_NAMES = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']
WEEKDAYS = [d[:3]+"(?:"+d[3:]+")?" for d in DAY_NAMES]

# Acceptable format tokens mapped to what they should match in the date string
# Ordered so that larger configurations are matched first
DATE_TOKENS = OrderedDict([
  ("HH",      r"(?P<H>\d{1,2})"),          # 24 hr
  ("H",       r"(?P<H>\d{1,2})"),
  ("hh",      r"(?P<h>\d{1,2})"),          # 12 hr
  ("h",       r"(?P<h>\d{1,2})"),
  ("mm",      r"(?P<m>\d{1,2})"),          # min
  ("m",       r"(?P<m>\d{1,2})"),
  ("A",       r"(?P<A>[ap]m?)"),           # am/pm
  ("a",       r"(?P<A>[ap]m?)"),
  ("ss",      r"(?P<s>\d{1,2})"),          # sec
  ("s",       r"(?P<s>\d{1,2})"),
  ("SSSSSS",  r"(?P<S>\d{1,6})"),          # fractional second
  ("SSSSS",   r"(?P<S>\d{1,6})"),
  ("SSSS",    r"(?P<S>\d{1,6})"),
  ("SSS",     r"(?P<S>\d{1,6})"),
  ("SS",      r"(?P<S>\d{1,6})"),
  ("S",       r"(?P<S>\d{1,6})"),
  ("YYYY",    r"(?P<YY>\d{4}|\d{2})"),     # 4 or 2 digit year
  ("YY",      r"(?P<YY>\d{2})"),           # 2 digit year
  ("MMMM",    r"(?P<MMM>" + ("|".join(MONTHS)) + ")"),  # month name, abbr or not
  ("MMM",     r"(?P<MMM>" + ("|".join(MONTHS)) + ")"),
  ("MM",      r"(?P<M>\d{1,2})"),          # month num
  ("M",       r"(?P<M>\d{1,2})"),
  ("DD",      r"(?P<D>\d{1,2})"),          # day num
  ("Do",      r"(?P<D>\d{1,2})(st|nd|rd|th)"),
  ("D",       r"(?P<D>\d{1,2})"),
  ("dddd",    r"(" + ("|".join(WEEKDAYS)) + ")"),  # day name, abbr or not (ignored)
  ("ddd",     r"(" + ("|".join(WEEKDAYS)) + ")")
])
DATE_TOKENS_REGEX = re.compile("("+("|".join(DATE_TOKENS))+")")

# List of separators to replace and match any standard date/time separators
SEP = r"[\s/.\-:,]*"
SEP_REGEX = re.compile(SEP)

# Maps date parse format to compile regex
FORMAT_CACHE = {}

# Parses date_string using parse_format in the style of moment.js
# See: http://momentjs.com/docs/#/parsing
# Supports the following tokens:
# H HH      0..23 24        hour time
# h hh      1..12 12        hour time used with a A.
# a A       am pm           Post or ante meridiem
# m mm      0..59           Minutes
# s ss      0..59           Seconds
# S SS SSS  0..999          Fractional seconds
# YYYY      2014            4 or 2 digit year
# YY        14              2 digit year
# M MM      1..12           Month number
# MMM MMMM  Jan..December   Month name in locale set by moment.locale()
# D DD      1..31           Day of month
# Do        1st..31st       Day of month with ordinal
def parse(date_string, parse_format, zonelabel='UTC', override_current_date=None):
  """Parse a date string via a moment.js style parse format and a timezone string.
     Supported tokens are documented above. Returns seconds since epoch"""

  if parse_format in FORMAT_CACHE:
    # Check if parse_format has been cache, and retrieve if so
    parser = FORMAT_CACHE[parse_format]
  else:
    # e.g. "MM-YY" -> "(?P<mm>\d{1,2})-(?P<yy>\d{2})"
    # Note that DATE_TOKENS is ordered so that the longer letter chains are recognized first
    tokens = DATE_TOKENS_REGEX.split(parse_format)
    tokens = [DATE_TOKENS[t] if t in DATE_TOKENS else SEP_REGEX.sub(SEP, t) for t in tokens]

    # Compile new token string ignoring case (for month names)
    parser = re.compile(''.join(tokens), re.I)
    FORMAT_CACHE[parse_format] = parser

  match = parser.match(date_string)

  # Throw error if matching failed
  if match is None:
    raise Exception("Failed to parse %s with %s" % (date_string, parse_format))

  # Create datetime from the results of parsing
  current_date = override_current_date or moment.CURRENT_DATE
  m = match.groupdict()
  dt = datetime(
    year=getYear(m, current_date.year),
    month=getMonth(m, current_date.month),
    day=int(m['D']) if ('D' in m) else current_date.day,
    hour=getHour(m),
    minute=int(m['m']) if ('m' in m) else 0,
    second=int(m['s']) if ('s' in m) else 0,
    microsecond=getMicrosecond(m)
  )

  # Parses the datetime with the given timezone to return the seconds since EPOCH
  return moment.tz(dt, zonelabel).timestamp_s()

def getYear(match_dict, current_year):
  if 'YYYY' in match_dict:
    return int(match_dict['YYYY'])
  elif 'YY' in match_dict:
    match = match_dict['YY']
    if len(match) == 2:
      # Must guess on the century, choose so the result is closest to the current year
      # The first year that could be meant by YY is the current year - 50.
      first = current_year - 50
      # We are seeking k such that 100k + YY is between first and first + 100.
      # first <= 100k + YY  < first + 100
      # 0 <= 100k + YY - first < 100
      # The value inside the comparison operators is precisely (YY - first) % 100.
      # So we can calculate the century 100k as (YY - first) % 100 - (YY - first).
      return first + (int(match) - first) % 100
    else:
      return int(match)
  else:
    return current_year

def getMonth(match_dict, current_month):
  if 'M' in match_dict:
    return int(match_dict['M'])
  elif 'MMM' in match_dict:
    return lazy_index(MONTHS, match_dict['MMM'][:3].lower()) + 1
  else:
    return current_month

def getHour(match_dict):
  if 'H' in match_dict:
    return int(match_dict['H'])
  elif 'h' in match_dict:
    hr = int(match_dict['h']) % 12
    merid = 12 if 'A' in match_dict and match_dict['A'][0] == "p" else 0
    return hr + merid
  else:
    return 0

def getMicrosecond(match_dict):
  if 'S' in match_dict:
    match = match_dict['S']
    return int(match + ("0"*(6-len(match))) if len(match) < 6 else match[:6])
  else:
    return 0

# Gets the index of the first string from iter that starts with startswith
def lazy_index(l, startswith, missing=None):
  for i, token in enumerate(l):
    if token[:len(startswith)] == startswith:
      return i
  return missing


import csv
import os
import warnings
from collections import defaultdict

import imagesize
import numpy as np
import skimage.io as io
from iopath.common.file_io import PathManager as PathManagerBase
from PIL import Image
from tqdm import tqdm

PathManager = PathManagerBase()

# https://en.wikipedia.org/wiki/YUV#SDTV_with_BT.601
_M_RGB2YUV = [[0.299, 0.587, 0.114], [-0.14713, -0.28886, 0.436], [0.615, -0.51499, -0.10001]]
_M_YUV2RGB = [[1.0, 0.0, 1.13983], [1.0, -0.39465, -0.58060], [1.0, 2.03211, 0.0]]

# https://www.exiv2.org/tags.html
_EXIF_ORIENT = 274  # exif 'Orientation' tag

def convert_PIL_to_numpy(image, format):
    """
    Convert PIL image to numpy array of target format.

    Args:
        image (PIL.Image): a PIL image
        format (str): the format of output image

    Returns:
        (np.ndarray): also see `read_image`
    """
    if format is not None:
        # PIL only supports RGB, so convert to RGB and flip channels over below
        conversion_format = format
        if format in ["BGR", "YUV-BT.601"]:
            conversion_format = "RGB"
        image = image.convert(conversion_format)
    image = np.asarray(image)
    # PIL squeezes out the channel dimension for "L", so make it HWC
    if format == "L":
        image = np.expand_dims(image, -1)

    # handle formats not supported by PIL
    elif format == "BGR":
        # flip channels if needed
        image = image[:, :, ::-1]
    elif format == "YUV-BT.601":
        image = image / 255.0
        image = np.dot(image, np.array(_M_RGB2YUV).T)

    return image

def convert_image_to_rgb(image, format):
    """
    Convert an image from given format to RGB.

    Args:
        image (np.ndarray or Tensor): an HWC image
        format (str): the format of input image, also see `read_image`

    Returns:
        (np.ndarray): (H,W,3) RGB image in 0-255 range, can be either float or uint8
    """
    if isinstance(image, torch.Tensor):
        image = image.cpu().numpy()
    if format == "BGR":
        image = image[:, :, [2, 1, 0]]
    elif format == "YUV-BT.601":
        image = np.dot(image, np.array(_M_YUV2RGB).T)
        image = image * 255.0
    else:
        if format == "L":
            image = image[:, :, 0]
        image = image.astype(np.uint8)
        image = np.asarray(Image.fromarray(image, mode=format).convert("RGB"))
    return image

def _apply_exif_orientation(image):
    """
    Applies the exif orientation correctly.

    This code exists per the bug:
      https://github.com/python-pillow/Pillow/issues/3973
    with the function `ImageOps.exif_transpose`. The Pillow source raises errors with
    various methods, especially `tobytes`

    Function based on:
      https://github.com/wkentaro/labelme/blob/v4.5.4/labelme/utils/image.py#L59
      https://github.com/python-pillow/Pillow/blob/7.1.2/src/PIL/ImageOps.py#L527

    Args:
        image (PIL.Image): a PIL image

    Returns:
        (PIL.Image): the PIL image with exif orientation applied, if applicable
    """
    if not hasattr(image, "getexif"):
        return image

    try:
        exif = image.getexif()
    except Exception:  # https://github.com/facebookresearch/detectron2/issues/1885
        exif = None

    if exif is None:
        return image

    orientation = exif.get(_EXIF_ORIENT)

    method = {
        2: Image.FLIP_LEFT_RIGHT,
        3: Image.ROTATE_180,
        4: Image.FLIP_TOP_BOTTOM,
        5: Image.TRANSPOSE,
        6: Image.ROTATE_270,
        7: Image.TRANSVERSE,
        8: Image.ROTATE_90,
    }.get(orientation)

    if method is not None:
        return image.transpose(method)
    return image

def read_image(file_name, format=None):
    """
    Read an image into the given format.
    Will apply rotation and flipping if the image has such exif information.

    Args:
        file_name (str): image file path
        format (str): one of the supported image modes in PIL, or "BGR" or "YUV-BT.601".

    Returns:
        image (np.ndarray):
            an HWC image in the given format, which is 0-255, uint8 for
            supported image modes in PIL or "BGR"; float (0-1 for Y) for YUV-BT.601.
    """
    with PathManager.open(file_name, "rb") as f:
        image = Image.open(f)

        # work around this bug: https://github.com/python-pillow/Pillow/issues/3973
        image = _apply_exif_orientation(image)
        return convert_PIL_to_numpy(image, format)

def csvread(file):
    if file:
        with open(file, "r", encoding="utf-8") as f:
            csv_f = csv.reader(f)
            data = []
            for row in csv_f:
                data.append(row)
    else:
        data = None

    return data

def csvwrite(data, file):
    with open(file, "w", encoding="utf-8") as f:
        writer = csv.writer(f)
        for d in data:
            writer.writerow(d)

def _url_to_license(licenses, mode="http"):
    # create dict with license urls as
    # mode is either http or https

    # create dict
    licenses_by_url = {}

    for license in licenses:
        # Get URL
        if mode == "https":
            url = "https:" + license["url"][5:]
        else:
            url = license["url"]
        # Add to dict
        licenses_by_url[url] = license

    return licenses_by_url

def _list_to_dict(list_data):

    dict_data = []
    columns = list_data.pop(0)
    for i in range(len(list_data)):
        dict_data.append({columns[j]: list_data[i][j] for j in range(len(columns))})

    return dict_data

def convert_category_annotations(orginal_category_info):

    categories = []
    num_categories = len(orginal_category_info)
    for i in range(num_categories):
        cat = {}
        cat["id"] = i + 1
        cat["name"] = orginal_category_info[i][1]
        cat["freebase_id"] = orginal_category_info[i][0]

        categories.append(cat)

    return categories

def convert_image_annotations(
    original_image_metadata,
    original_image_annotations,
    original_image_sizes,
    image_dir,
    categories,
    licenses,
    apply_exif,
    origin_info=False,
):

    original_image_metadata_dict = _list_to_dict(original_image_metadata)
    original_image_annotations_dict = _list_to_dict(original_image_annotations)

    cats_by_freebase_id = {cat["freebase_id"]: cat for cat in categories}

    if original_image_sizes:
        image_size_dict = {x[0]: [int(x[1]), int(x[2])] for x in original_image_sizes[1:]}
    else:
        image_size_dict = {}

    # Get dict with license urls
    licenses_by_url_http = _url_to_license(licenses, mode="http")
    licenses_by_url_https = _url_to_license(licenses, mode="https")

    # convert original image annotations to dicts
    pos_img_lvl_anns = defaultdict(list)
    neg_img_lvl_anns = defaultdict(list)
    for ann in original_image_annotations_dict[1:]:
        cat_of_ann = cats_by_freebase_id[ann["LabelName"]]["id"]
        if int(ann["Confidence"]) == 1:
            pos_img_lvl_anns[ann["ImageID"]].append(cat_of_ann)
        elif int(ann["Confidence"]) == 0:
            neg_img_lvl_anns[ann["ImageID"]].append(cat_of_ann)

    # Create list
    images = []

    # loop through entries skipping title line
    num_images = len(original_image_metadata_dict)
    for i in tqdm(range(num_images), mininterval=0.5):
        # Select image ID as key
        key = original_image_metadata_dict[i]["ImageID"]

        # Copy information
        img = {}
        img["id"] = key
        img["file_name"] = key + ".jpg"
        img["neg_category_ids"] = neg_img_lvl_anns.get(key, [])
        img["pos_category_ids"] = pos_img_lvl_anns.get(key, [])
        if origin_info:
            img["original_url"] = original_image_metadata_dict[i]["OriginalURL"]
            license_url = original_image_metadata_dict[i]["License"]
            # Look up license id
            try:
                img["license"] = licenses_by_url_https[license_url]["id"]
            except:
                img["license"] = licenses_by_url_http[license_url]["id"]

        # Extract height and width
        image_size = image_size_dict.get(key, None)
        if image_size is not None:
            img["width"], img["height"] = image_size
        else:
            filename = os.path.join(image_dir, img["file_name"])
            img["width"], img["height"] = imagesize.get(filename)
        if apply_exif:
            filename = os.path.join(image_dir, img["file_name"])
            image = read_image(filename, format="BGR")
            if image.shape[1] != img["width"] or image.shape[0] != img["height"]:
                print("before exif correction: ", img)
                img["width"], img["height"] = image.shape[1], image.shape[0]
                print("after exif correction: ", img)

        # Add to list of images
        images.append(img)

    return images

def convert_instance_annotations(original_annotations, images, categories, start_index=0):

    original_annotations_dict = _list_to_dict(original_annotations)

    imgs = {img["id"]: img for img in images}
    cats = {cat["id"]: cat for cat in categories}
    cats_by_freebase_id = {cat["freebase_id"]: cat for cat in categories}

    annotations = []

    annotated_attributes = [
        attr
        for attr in ["IsOccluded", "IsTruncated", "IsGroupOf", "IsDepiction", "IsInside"]
        if attr in original_annotations[0]
    ]

    num_instances = len(original_annotations_dict)
    for i in tqdm(range(num_instances), mininterval=0.5):
        # set individual instance id
        # use start_index to separate indices between dataset splits
        key = i + start_index
        csv_line = i
        ann = {}
        ann["id"] = key
        image_id = original_annotations_dict[csv_line]["ImageID"]
        ann["image_id"] = image_id
        ann["freebase_id"] = original_annotations_dict[csv_line]["LabelName"]
        ann["category_id"] = cats_by_freebase_id[ann["freebase_id"]]["id"]
        ann["iscrowd"] = False

        xmin = float(original_annotations_dict[csv_line]["XMin"]) * imgs[image_id]["width"]
        ymin = float(original_annotations_dict[csv_line]["YMin"]) * imgs[image_id]["height"]
        xmax = float(original_annotations_dict[csv_line]["XMax"]) * imgs[image_id]["width"]
        ymax = float(original_annotations_dict[csv_line]["YMax"]) * imgs[image_id]["height"]
        dx = xmax - xmin
        dy = ymax - ymin
        ann["bbox"] = [round(a, 2) for a in [xmin, ymin, dx, dy]]
        ann["area"] = round(dx * dy, 2)

        for attribute in annotated_attributes:
            ann[attribute.lower()] = int(original_annotations_dict[csv_line][attribute])

        annotations.append(ann)

    return annotations

def _id_to_rgb(array):
    B = array // 256 ** 2
    rest = array % 256 ** 2
    G = rest // 256
    R = rest % 256
    return np.stack([R, G, B], axis=-1).astype("uint8")

def _get_mask_file(segment, mask_dir):
    name = "{}_{}_{}.png".format(
        segment["ImageID"], segment["LabelName"].replace("/", ""), segment["BoxID"]
    )
    return os.path.join(mask_dir, name)

def _combine_small_on_top(masks):
    combined = np.zeros(shape=masks[0].shape, dtype="uint32")
    sizes = [np.sum(m != 0) for m in masks]
    for idx in np.argsort(sizes)[::-1]:
        mask = masks[idx]
        combined[mask != 0] = mask[mask != 0]
    return combined

def _greedy_combine(masks):
    combined = np.zeros(shape=masks[0].shape, dtype="uint32")
    for maks in maksk:
        combined[mask != 0] = mask[mask != 0]
    return combined

def convert_segmentation_annotations(
    original_segmentations,
    images,
    categories,
    original_mask_dir,
    segmentation_out_dir,
    start_index=0,
):

    original_segmentations_dict = _list_to_dict(original_segmentations)

    if not os.path.isdir(segmentation_out_dir):
        os.mkdir(segmentation_out_dir)

    image_ids = list(np.unique([ann["ImageID"] for ann in original_segmentations_dict]))
    filtered_images = [img for img in images if img["id"] in image_ids]

    imgs = {img["id"]: img for img in filtered_images}
    cats = {cat["id"]: cat for cat in categories}
    cats_by_freebase_id = {cat["freebase_id"]: cat for cat in categories}

    for i in range(len(original_segmentations_dict)):
        original_segmentations_dict[i]["SegmentID"] = i + 1

    img_segment_map = defaultdict(list)
    for segment in original_segmentations_dict:
        img_segment_map[segment["ImageID"]].append(segment)

    annotations = []
    segment_index = 0 + start_index
    for img in tqdm(filtered_images, mininterval=0.5):
        ann = dict()
        ann["file_name"] = img["file_name"]
        ann["image_id"] = img["id"]
        ann["segments_info"] = []
        masks = []
        for segment in img_segment_map[img["id"]]:
            # collect mask
            mask_file = _get_mask_file(segment, original_mask_dir)
            mask = io.imread(mask_file)  # load png
            # exclude empty masks
            if np.max(mask) == 0:
                continue
            mask = mask // 255  # set to [0,1]
            mask = mask * segment["SegmentID"]
            masks.append(mask)

            # collect segment info
            segment_info = {}
            # Compute bbox coordinates
            xmin = float(segment["BoxXMin"]) * img["width"]
            ymin = float(segment["BoxYMin"]) * img["height"]
            xmax = float(segment["BoxXMax"]) * img["width"]
            ymax = float(segment["BoxYMax"]) * img["height"]
            dx = xmax - xmin
            dy = ymax - ymin
            # Fill in annotations
            segment_info["bbox"] = [round(a, 2) for a in [xmin, ymin, dx, dy]]
            segment_info["area"] = round(dx * dy, 2)
            segment_info["category_id"] = (cats_by_freebase_id[segment["LabelName"]],)
            segment_info["id"] = segment_index
            segment_index += 1
            # append
            ann["segments_info"].append(segment_info)

        # combined_binary_mask = sum(masks)
        # Looks like many masks overlap
        # currently managed by greedy combining
        combined_binary_mask = _combine_small_on_top(masks)
        # check if masks overlap. If they do we have a problem
        ids_in_mask = len(np.unique(combined_binary_mask[combined_binary_mask != 0]))
        num_segments = len(img_segment_map[img["id"]])
        if ids_in_mask != num_segments:
            print("Overlapping masks in image {}".format(ann["image_id"]))
            values_in_output = np.unique(combined_binary_mask[combined_binary_mask != 0])
            ids_in_segments = [segment["SegmentID"] for segment in img_segment_map[img["id"]]]
            not_in_segments = [x for x in values_in_output if x not in ids_in_segments]
            not_in_values = [x for x in ids_in_segments if x not in values_in_output]
            print("Not in segments: {}".format(not_in_segments))
            print("Not in pixel values: {}".format(not_in_values))
            # don't include the annotation into the output
            continue

        combined_rgb_mask = _id_to_rgb(combined_binary_mask)
        out_file = os.path.join(segmentation_out_dir, "{}.png".format(ann["image_id"]))
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            io.imsave(out_file, combined_rgb_mask)

        annotations.append(ann)

    return annotations

def filter_images(images, annotations):
    image_ids = list(np.unique([ann["image_id"] for ann in annotations]))
    filtered_images = [img for img in images if img["id"] in image_ids]
    return filtered_images


from flask import Flask
from flask_restful import Resource, Api
from flask import abort, request
from game import Game, GameError
from utils import game_json_encoder_factory

app = Flask("BlackJack")
app.json_encoder = game_json_encoder_factory()
api = Api(app)

game = Game()

class GameAPI(Resource):

    def get(self):
        return {'hello': 'world'}

    def post(self):
        pass

class PlayerAddApi(Resource):

    def post(self):
        payload = request.get_json()
        name = payload.get('name', None)
        if not name:
            abort(400, "Field is missing")
        try:
            return game.add_player(name)
        except GameError as e:
            abort(e.status_code, e.error_msg)

class GameStatusAPI(Resource):

    def get(self):
        return game.infos()

class PlayerChoiceAPI(Resource):

    def post(self, id):
        payload = request.get_json()
        token, choice = [payload.get(x, None) for x in ('token', 'choice')]
        if id is None or not token:
            abort(400, "Field is missing")
        try:
            return game.make_choice(id, token, choice)
        except GameError as e:
            abort(e.status_code, e.error_msg)

class PlayerReadyAPI(Resource):

    def post(self, id):
        payload = request.get_json()
        token = payload.get('token')
        if id is None or not token:
            abort(400, "Field is missing")
        try:
            return game.set_ready(id, token)
        except GameError as e:
            abort(e.status_code, e.error_msg)

class GameRestartAPI(Resource):

    def post(self):
        try:
            return game.restart()
        except GameError as e:
            abort(e.status_code, e.error_msg)

api.add_resource(PlayerAddApi, '/player/add')
api.add_resource(GameStatusAPI, '/game/status')
api.add_resource(GameRestartAPI, '/game/restart')
api.add_resource(PlayerChoiceAPI, '/player/<int:id>/choice')
api.add_resource(PlayerReadyAPI, '/player/<int:id>/ready')

if __name__ == "__main__":
    app.run()


# (C) Frank Rene Schaefer
import quex.output.core.state_machine_coder       as     state_machine_coder
import quex.output.core.state_router              as     state_router_generator
from   quex.output.core.variable_db               import variable_db
from   quex.engine.analyzer.door_id_address_label import DoorID, \
                                                         DialDB
import quex.output.core.reload_state              as     reload_state_coder
import quex.engine.analyzer.engine_supply_factory as     engine
from   quex.engine.analyzer.terminal.core         import Terminal
import quex.engine.analyzer.core                  as     analyzer_generator

from   quex.engine.misc.tools import typed

from   quex.constants  import E_IncidenceIDs, E_R
from   quex.blackboard import setup as Setup, \
                              Lng

# MAIN:      sm --> analyzer
#            sm_txt --> code_analyzer
#            terminal_txt --> code_terminals
#
# PRE_SM:    pre_sm --> analyzer
#            pre_sm_txt --> code_analyzer
#            terminal = begin of core
#
# BIPD_SM-s: bipd_sm -> analyzer
#            bipd_sm_txt -> code_analyzer
#            termina = terminal for which BIPD operated
#
# COUNT_SM:  count_db --> count_sm
#            analyzer = get_analyzer
#            modify analyzer
#            terminal = exit_door_id
#
def do_main(CoreSmList, ReloadStateForward, dial_db):
    """Main pattern matching state machine (forward).
    ---------------------------------------------------------------------------
    Micro actions are: line/column number counting, position set/reset,
    last acceptance setting/reset, lexeme start pointer set/reset, setting
    terminating zero for lexeme/reset, setting last character.

            DropOut     --> FAILURE
            BLC         --> ReloadStateForward
            EndOfStream --> END_OF_STREAM

    Variables (potentially) required:

            position, PositionRegisterN, last_acceptance, input.
    """
    txt, analyzer = __do_state_machine(CoreSmList, engine.Class_FORWARD(), dial_db,
                                       ReloadStateForward)

    # Treat the external reload state the same way as if it was generated
    # along the process.
    analyzer.reload_state_extern_f = False

    return txt, analyzer

def do_pre_context(PreContextSmToBeReversedList, PreContextSmIdList, dial_db):
    """Pre-context detecting state machine (backward).
    ---------------------------------------------------------------------------
    Micro actions are: pre-context fullfilled_f

            DropOut     --> Begin of 'main' state machine.
            BLC         --> ReloadStateBackward
            EndOfStream --> 'error'

    Variables (potentially) required:

            pre_context_fulfilled_f[N] --> Array of flags for pre-context
                                           indication.
    RETURNS: [0] generated code text
             [1] reload state BACKWARD, to be generated later.
    """

    if not PreContextSmToBeReversedList: return [], None

    analyzer_txt, \
    analyzer      = __do_state_machine(PreContextSmToBeReversedList, engine.BACKWARD_PRE_CONTEXT,
                                       dial_db, ReverseF=True)

    epilog_txt    = _get_pre_context_epilog_definition(dial_db)

    txt = analyzer_txt
    txt.extend(epilog_txt)

    for sm_id in PreContextSmIdList:
        variable_db.require("pre_context_%i_fulfilled_f", Index = sm_id)

    return txt, analyzer

def do_backward_read_position_detectors(BipdDb, dial_db):
    """RETURNS: [0] Code for BIPD analyzer
                [1] map: acceptance_id --> DoorID of entry into BIPD

    The 'bipd_entry_door_id_db' is used by 'do_main()' later.
    """
    result = []
    for incidence_id, bipd_sm in BipdDb.iteritems():
        txt, analyzer = __do_state_machine(bipd_sm,
                                           engine.Class_BACKWARD_INPUT_POSITION(incidence_id),
                                           dial_db,
                                           ReverseF=True)
        result.extend(txt)
    return result

def do_reload_procedure(TheAnalyzer):
    """Lazy (delayed) code generation of the forward and backward reloaders.
    Any state who needs reload may 'register' in a reloader. This registering may
    happen after the code generation of forward or backward state machine.
    """
    # Variables that tell where to go after reload success and reload failure
    if   TheAnalyzer is None:                             return []
    elif not TheAnalyzer.engine_type.subject_to_reload(): return []
    elif TheAnalyzer.reload_state is None:                return []
    elif TheAnalyzer.reload_state_extern_f:               return []

    variable_db.require("target_state_else_index")  # upon reload failure
    variable_db.require("target_state_index")       # upon reload success

    return reload_state_coder.do(TheAnalyzer.reload_state)

def require_position_registers(TheAnalyzer):
    """Require an array to store input positions. This has later to be
    implemented as 'variables'. Position registers are exclusively used
    for post-context restore. No other engine than FORWARD would require
    those.
    """
    if not TheAnalyzer.engine_type.is_FORWARD():
        return

    if TheAnalyzer.position_register_map is None:
        position_register_n = 0
    else:
        position_register_n = len(set(TheAnalyzer.position_register_map.itervalues()))

    if position_register_n != 0:
        initial_array  = "{ " + ("0, " * (position_register_n - 1) + "0") + "}"
    else:
        # Implement a dummy array (except that there is no reload)
        initial_array = "(void*)0"

    previous = variable_db.get().get("position")
    if previous is not None:
        if previous.element_n > position_register_n:
            return

    if position_register_n or TheAnalyzer.engine_type.subject_to_reload():
        variable_db.require_array("position", ElementN = position_register_n,
                                  Initial = initial_array)
        variable_db.require("PositionRegisterN",
                            Initial = "(size_t)%i" % position_register_n)

@typed(dial_db=DialDB)
def do_state_router(dial_db):
    routed_address_set = dial_db.routed_address_set()
    # If there is only one address subject to state routing, then the
    # state router needs to be implemented.
    #if len(routed_address_set) == 0:
    #    return []

    # Add the address of 'terminal_end_of_file()' if it is not there, already.
    # (It should not be there, if we are working on a fixed chunk, as in 'counting'.
    #  When counting is webbed into analysis:: assert address_eof in routed_address_set)
    if False:
        address_eof = DoorID.incidence(E_IncidenceIDs.END_OF_STREAM, dial_db).related_address
        routed_address_set.add(address_eof)
        dial_db.mark_address_as_gotoed(address_eof)

    routed_state_info_list = state_router_generator.get_info(routed_address_set, dial_db)
    return state_router_generator.do(routed_state_info_list, dial_db)

def do_variable_definitions():
    # Following function refers to the global 'variable_db'
    return Lng.VARIABLE_DEFINITIONS(variable_db)

def __do_state_machine(SmOrSmList, EngineType, dial_db, ReloadStateForward=None, ReverseF=False):
    """Generates code for state machine 'sm' and the 'EngineType'.

    RETURNS: list of strings
    """
    assert type(SmOrSmList) == list or len(SmOrSmList.get_orphaned_state_index_list()) == 0

    # -- Analyze state machine --> optimized version
    analyzer = analyzer_generator.do(SmOrSmList, EngineType,
                                     ReloadStateExtern = ReloadStateForward,
                                     dial_db           = dial_db,
                                     ReverseF          = ReverseF)

    txt = []
    # -- [optional] comment state machine transitions
    if Setup.comment_state_machine_f:
        if type(SmOrSmList) != list: SmOrSmList = [ SmOrSmList ]
        for sm in SmOrSmList:
            Lng.COMMENT_STATE_MACHINE(txt, sm)

    # -- Generate code for analyzer
    txt.extend(
        do_analyzer(analyzer)
    )

    return txt, analyzer

def do_analyzer_list(analyzer_list):
    """RETURNS: String containing source code for the 'loop'.

       -- The source code for the (looping) state machine.
       -- The terminals which contain counting actions.

    Also, it requests variable definitions as they are required.
    """
    # FSM Ids MUST be unique (LEAVE THIS ASSERT IN PLACE!)
    assert len(set(a.state_machine_id for a in analyzer_list)) == len(analyzer_list)
    if not analyzer_list: return []

    txt = []
    subject_to_reload_f = False
    for analyzer in analyzer_list:
        txt.extend(
            do_analyzer(analyzer)
        )
        subject_to_reload_f |= analyzer.engine_type.subject_to_reload()

    if subject_to_reload_f:
        txt.extend(
            do_reload_procedure(analyzer_list[0])
        )

    return txt

def do_analyzer(analyzer):

    # Variable to store the current input
    variable_db.require("input")
    if analyzer.last_acceptance_variable_required():
        variable_db.require("last_acceptance")

    require_position_registers(analyzer)

    code = state_machine_coder.do(analyzer)
    Lng.REPLACE_INDENT(code)

    return code

@typed(TerminalList=[Terminal])
def do_terminals(TerminalList, TheAnalyzer, dial_db):
    return Lng.TERMINAL_CODE(TerminalList, TheAnalyzer, dial_db)

def do_reentry_preparation(PreContextSmIdList, OnAfterMatchCode, dial_db):
    return Lng.REENTRY_PREPARATION(PreContextSmIdList, OnAfterMatchCode, dial_db)

_increment_actions_for_utf8 = [
     1, "if     ( ((*iterator) & 0x80) == 0 ) { iterator += 1; } /* 1byte character */\n",
     1, "/* NOT ( ((*iterator) & 0x40) == 0 ) { iterator += 2; }    2byte character */\n",
     1, "else if( ((*iterator) & 0x20) == 0 ) { iterator += 2; } /* 2byte character */\n",
     1, "else if( ((*iterator) & 0x10) == 0 ) { iterator += 3; } /* 3byte character */\n",
     1, "else if( ((*iterator) & 0x08) == 0 ) { iterator += 4; } /* 4byte character */\n",
     1, "else if( ((*iterator) & 0x04) == 0 ) { iterator += 5; } /* 5byte character */\n",
     1, "else if( ((*iterator) & 0x02) == 0 ) { iterator += 6; } /* 6byte character */\n",
     1, "else if( ((*iterator) & 0x01) == 0 ) { iterator += 7; } /* 7byte character */\n",
     1, "else                                 { iterator += 1; } /* default 1       */\n",
]

_increment_actions_for_utf16 = [
     1, "if( *iterator >= 0xD800 && *iterator < 0xE000 ) { iterator += 2; }\n",
     1, "else                                            { iterator += 1; }\n",
]

def _get_pre_context_epilog_definition(dial_db):
    backup_position = Lng.REGISTER_NAME(E_R.BackupStreamPositionOfLexemeStartP)

    txt = [
        Lng.LABEL(DoorID.global_end_of_pre_context_check(dial_db)),
        #-------------------
        Lng.IF(backup_position, "!=", "((QUEX_TYPE_STREAM_POSITION)-1)"),
            # "QUEX_NAME(Buffer_print_content)(&me->buffer);\n",
            # "std::cout << std::endl;\n",
            Lng.IF("false", "==", Lng.BUFFER_SEEK(backup_position)),
                Lng.RAISE_ERROR_FLAG("E_Error_File_SeekFailed"),
                Lng.RETURN,
            Lng.END_IF,
            Lng.LEXEME_START_SET(PositionStorage=None), # use '_read_p'
            # "std::cout << \"lexst \" << me->buffer._lexeme_start_p[0] << std::endl;",
            # "std::cout << \"readp \" << me->buffer._read_p[0] << std::endl;",
            # "QUEX_NAME(Buffer_print_content)(&me->buffer);\n",
            # "std::cout << std::endl;\n",
            Lng.ASSIGN(backup_position, "((QUEX_TYPE_STREAM_POSITION)-1)"),
        Lng.ELSE_FOLLOWS,
            #-----------------------
            # -- set the input stream back to the real current position.
            #    during backward lexing the analyzer went backwards, so it needs to be reset.
            Lng.INPUT_P_TO_LEXEME_START(),
        Lng.END_IF,
    ]

    return [ "%s\n" % line for line in txt ]


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

import os
import sys
import dbus
import re

try:
    from Tkinter import *
    from FileDialog import *
except:
    from tkinter import *

class Player:
    def __init__(self, name, serviceName = None, objectPath = None, interface = None):
        self.name = name

        self.serviceName = serviceName
        self.objectPath = objectPath
        self.interface = interface

        self.dbusObject = None
        self.player = None
        self.connected = False

    def connect(self, serviceName = None, objectPath = None, interface = None):
        if serviceName:
            self.serviceName = serviceName
        if objectPath:
            self.objectPath = objectPath
        if interface:
            self.interface = interface

        self.sesBus = dbus.SessionBus()
        self.dbusObject = self.sesBus.get_object(self.serviceName, self.objectPath)
        self.player = dbus.Interface(self.dbusObject, dbus_interface = self.interface)

        if self.dbusObject and self.player:
            self.connected = True
        else:
            self.connected = False

    def playFrom(self, posByMSec):
        ''' Seek to position given by posByMSec '''
        if not self.connected:
            return

        self.player.PositionSet(posByMSec)
        # If playing : rewind to the beginning of current track, else : start playing.
        # self.player.Play()

    def getPostion(self):
        ''' return position current playing '''
        if not self.connected:
            return -1

        return self.player.PositionGet()

    def getState(self):
        ''' '''
        if not self.connected:
            return

        return self.player.GetStatus()

    def play(self):
        ''' '''
        if not self.connected:
            return

        self.player.Play()

    def pause(self):
        ''' '''
        if not self.connected:
            return

        self.player.Pause()

class TotemPlayer(Player):
    def __init__(self):
        Player.__init__(self, "Totem", "org.mpris.Totem", "/Player", "org.freedesktop.MediaPlayer")

class MarkerList:
    ''' # [ [ timeInSec, timeInHuman, Stars ], ... ] '''

    def __init__(self):
        self.dirty = False
        self.clear()

    def isDirty(self):
        return self.dirty

    def clear(self):
        self.dirty = True
        self.allines = []

    def saveMarkers(self, path):
        content = [ "%s --> 00:00:00,000\n" % l[1] for l in self.allines ]
        fp = open(path, "wt+")
        if not fp:
            return
        fp.writelines(content)
        fp.close()
        self.dirty = False

    def loadMarkers(self, path):
        f = open(path, "rt")
        if not f:
            return

        pat = r"(\d*):(\d*):(\d*),(\d*) --> \d*:\d*:\d*,\d*"
        for line in f.readlines():
            m = re.search(pat, line)
            if not m:
                continue
            hh = int(m.group(1))
            mm = int(m.group(2))
            ss = int(m.group(3))
            ms = int(m.group(4))
            self.insertMarker(hh * 1000 * 3600 + mm * 1000 * 60 + ss * 1000 + ms)
        f.close()
        self.dirty = False

    def insertMarker(self, time):
        ''' If OK, return index, dup: return -1 '''
        index = 0
        for l in self.allines:
            if l[0] > time:
                break
            if l[0] == time:
                return -1
            index += 1
        if index >= 0:
            sec = time / 1000
            msec = time % 1000
            self.allines.insert(index, [time, "%02d:%02d:%02d,%d" %
                (sec / 3600, (sec / 60) % 60, sec % 60, msec)])
        self.dirty = True
        return index

    def deleteMarker(self, index):
        del self.allines[index]
        self.dirty = True

    def findMarker(self, time):
        ''' Find the marker nearest to time '''
        index = 0
        for l in self.allines:
            if l[0] >= time:
                break
            index += 1
        if index > 0:
            return index - 1
        return 0

class MarkerDialog:
    def __init__(self, player, markers):
        self.saved_path = None
        self.player = player
        self.markers = markers

        self.root = Tk()
        self.root.option_add("*Font", "Courier")
        self.root.geometry("240x600")
        self.root.title("Markers")

        self.lb = Listbox(self.root)
        self.sl = Scrollbar(self.root)
        self.sl.pack(side = RIGHT, fill = Y)
        self.lb['yscrollcommand'] = self.sl.set

        self.lb.bind("<Double-Button-1>", self.do_dbclick)
        self.lb.bind("<Return>", self.do_dbclick)
        self.lb.bind("<KeyPress>", self.do_keypress)
        self.lb.bind("<KeyRelease>", self.do_keyrelease)

        #self.root.bind("<Double-Button-1>", self.do_dbclick)
        #self.root.bind("<Return>", self.do_dbclick)
        #self.root.bind("<KeyPress>", self.do_keypress)
        #self.root.bind("<KeyRelease>", self.do_keyrelease)

        self.fillMarkers(self.markers.allines)
        self.lb.focus_set()

    def fillMarkers(self, lines):
        index = 0
        for l in lines:
            self.lb.insert(index, l[1])
            index += 1
        self.lb.pack(expand=1, fill=BOTH)
        self.sl['command'] = self.lb.yview

    def updateTitle(self):
        path = self.saved_path and os.path.basename(self.saved_path) or "[Markers]"
        title = self.markers.isDirty() and "* %s" % path or path
        self.root.title(title)

    def do_dbclick(self, *event):
        try:
            index = int(self.lb.curselection()[0])
            intTime = self.markers.allines[index][0]
            strTime = self.markers.allines[index][1]
            self.player.playFrom(intTime)
        except:
            return

    def do_keyrelease(self, *event):
        pass

    def get_list_selected(self, ):
        try:
            return int(self.lb.curselection()[0])
        except:
            return -1

    def navi_focus(self, *event):
        cursel = self.get_list_selected()
        if cursel < 0:
            return

        if event[0].keysym == "j":
            new_index = cursel + 1
        elif event[0].keysym == "k":
            new_index = cursel - 1
        elif event[0].keysym == "0":
            new_index = 0
        elif event[0].keysym == "G":
            new_index = self.lb.size() - 1

        self.sel_item(new_index)

    def sel_item(self, index):
        if index >= self.lb.size():
            index = self.lb.size() - 1
        if index < 0:
            index = 0

        self.lb.select_clear(0, END)
        self.lb.select_set(index)
        self.lb.activate(index)
        self.lb.see(index)

    def do_keypress(self, *event):
        ''' Navigate by key '''

        if event[0].keysym == 'r':
            self.player.connect()

        if event[0].keysym in 'jk0G':
            self.navi_focus(*event)
            return

        if event[0].keysym == "a":
            ''' Add current position to marker '''
            index = self.markers.insertMarker(self.player.getPostion())
            if index >= 0:
                self.lb.insert(index, self.markers.allines[index][1])
                self.updateTitle()
            return

        if event[0].keysym == "l":
            ''' Load marker file '''
            fd = LoadFileDialog(self.root)
            path = fd.go()
            if not path:
                return
            self.markers.clear()
            self.lb.delete(0, self.lb.size())
            self.markers.loadMarkers(path)

            index = 0
            for l in self.markers.allines:
                self.lb.insert(index, self.markers.allines[index][1])
                index += 1
            self.saved_path = path
            self.updateTitle()
            return

        if event[0].keysym == "s":
            ''' Save the file '''
            if not self.markers.allines:
                return
            default_path = self.saved_path or ''
            fd = SaveFileDialog(self.root)
            path = fd.go(default=default_path)
            if path:
                self.markers.saveMarkers(path);
                self.saved_path = path
                self.updateTitle()
            return

        if event[0].keysym == "p":
            ''' Toggle Play and Pause '''
            if self.player.getState()[0]:
                self.player.play()
            else:
                self.player.pause()
            return

        if event[0].keysym == "n":
            ''' Hilight the nearest marker '''
            curpos = self.player.getPostion()
            if curpos >= 0:
                index = self.markers.findMarker(curpos)
                if index >= 0:
                    self.sel_item(index)
            return

        cursel = self.get_list_selected()
        if cursel >= 0:
            if event[0].keysym == "equal":
                ''' Inc the tmpos of current marker '''
                def update(index, newtmpos, newtext):
                    """ Change time, change label """
                    ''' by time or index '''
                    tmpos = self.markers.allines[cursel][0] + 500
                    self.markers.deleteMarker(cursel)
                    newindex = self.markers.insertMarker(tmpos)

                    self.lb.delete(cursel, cursel)
                    self.lb.insert(newindex, self.markers.allines[newindex][1])
                    self.sel_item(newindex)

                    pass

                def add(index, tmpos, text):
                    pass

                tmpos = self.markers.allines[cursel][0] + 500
                self.markers.deleteMarker(cursel)
                newindex = self.markers.insertMarker(tmpos)

                self.lb.delete(cursel, cursel)
                self.lb.insert(newindex, self.markers.allines[newindex][1])
                self.sel_item(newindex)
                self.updateTitle()
                return

            if event[0].keysym == "minus":
                ''' Dec the tmpos of current marker '''
                tmpos = self.markers.allines[cursel][0] - 500
                self.markers.deleteMarker(cursel)
                newindex = self.markers.insertMarker(tmpos)

                self.lb.delete(cursel, cursel)
                self.lb.insert(newindex, self.markers.allines[newindex][1])
                self.sel_item(newindex)
                self.updateTitle()
                return

            if event[0].keysym == "d":
                ''' Delete the current '''
                self.markers.deleteMarker(cursel)
                self.lb.delete(cursel, cursel)
                self.sel_item(cursel)
                self.updateTitle()
                return

    def run(self):
        self.root.mainloop()

if __name__ == "__main__":
    tp = TotemPlayer()
    ml = MarkerList()
    tp.connect()
    md = MarkerDialog(tp, ml)
    md.run()

# vim: sw=4 ts=4 sts=4 ai et


class event:
    def __init__(self, event_line=None, leader=None, role=None, recv_node=None, send_node=None, hash_id=None):
        if event_line is not None:
            import re
            self.leader = re.findall(r'leader=\d*', event_line)[0].split('=')[-1]
            self.role = re.findall(r'role=\d*', event_line)[0].split('=')[-1]
            self.recv_node = re.findall(r'recvNode=\d*|destinationNode=\d*', event_line)[0].split('=')[-1]
            self.send_node = re.findall(r'sendNode=\d*|sourceNode=\d*', event_line)[0].split('=')[-1]
            self.hash_id = re.findall(r'hashId=\d*|eventId=\d*', event_line)[0].split('=')[-1]
        else:
            self.leader = leader
            self.role = role
            self.recv_node = recv_node
            self.send_node = send_node
            self.hash_id = hash_id


# Given n, how many structurally unique BST's (binary search trees) that store values 1...n?
#
# For example,
# Given n = 3, there are a total of 5 unique BST's.
#
#    1         3     3      2      1
#     \       /     /      / \      \
#      3     2     1      1   3      2
#     /     /       \                 \
#    2     1         2                 3
#

class Solution(object):
    def numTrees(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n <= 2:
            return n

        d = [0] * (n+1)
        d[0] = 1 # 节点数为0算一种情况, 即null
        for i in range(1, n+1):   # loop N nodes
            for j in range(i):    # Assume in i Nodes, there are j nodes in left tree, so total i - j - root(1) = i - 1 - j
                d[i] += d[j] * d[i-1-j] # Then it would be d[j] * d[i-1-j]
        return d[n]

        # http://chaoren.is-programmer.com/posts/42907.html
        # http://blog.csdn.net/monkeyduck/article/details/38079861 best explain
        class Solution:
            # @return an integer
            def numTrees(self, n):
                if n == 0 or n == 1:
                    return 1
                elif n ==2:
                    return 2
                else:
                    ans = 0
                    for i in range(0,n):
                        ans += self.numTrees(i)*self.numTrees(n-i-1)
                    return ans
        # https://github.com/kamyu104/LeetCode/blob/master/Python/unique-binary-search-trees.py

        # 这里有个解题技巧：一般来说求数量，要首先想到使用动态规划（dp），而如果是像下一题的要求，不只是数量，还要把所有的树都枚举出来，就要使用dfs（深度优先搜索）来遍历决策树了。


import nsml
import logging
import numpy as np

import torch
import torch.nn as nn
import torch.optim as optim

from model import LSTMClassifier
from evaluation import ic_metric

logging.basicConfig(format='%(asctime)s - %(levelname)s - %(name)s -   %(message)s',
                    datefmt='%m/%d/%Y %H:%M:%S',
                    level=logging.INFO)
logger = logging.getLogger(__name__)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

def sort_batch(batch):
    input_ids, input_lengths, labels = batch
    input_lengths, sorted_idx = input_lengths.sort(0, descending=True)
    sorted_idx = sorted_idx.squeeze(1)

    input_ids = input_ids[sorted_idx]
    input_lengths = input_lengths.squeeze(1)
    labels = labels[sorted_idx].squeeze(1)

    return input_ids, input_lengths, labels

class Trainer:
    def __init__(self, config, n_gpu, vocab, train_loader=None, val_loader=None):
        self.config = config
        self.vocab = vocab
        self.n_gpu = n_gpu
        self.train_loader = train_loader
        self.val_loader = val_loader

        # Build model
        vocab_size = self.vocab.vocab_size()

        self.model = LSTMClassifier(self.config, vocab_size, self.config.n_label)
        self.model.to(device)

        if self.n_gpu > 1:
            self.model = nn.DataParallel(self.model)

        # Build optimizer
        self.optimizer = optim.Adam(self.model.parameters(), lr=self.config.lr)

        # Build criterion
        self.criterion = nn.CrossEntropyLoss()

    def train(self):
        best_f1 = 0.0
        best_acc = 0.0
        global_step = 0
        batch_f1 = []
        batch_acc = []
        for epoch in range(self.config.num_epoch):
            batch_loss = []
            for step, batch in enumerate(self.train_loader):
                self.model.train()
                batch = tuple(t.to(device) for t in batch)
                batch = sort_batch(batch)
                input_ids, input_lengths, labels = batch

                outputs = self.model(input_ids, input_lengths)
                loss = self.criterion(outputs['logits'].view(-1, self.config.n_label), labels.view(-1))

                f1, acc = ic_metric(labels.cpu(), outputs['predicted_intents'].cpu())

                if self.n_gpu > 1:
                    loss = loss.mean()

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

                global_step += 1
                batch_loss.append(loss.float().item())
                batch_f1.append(f1)
                batch_acc.append(acc)

                if (global_step == 1) or (global_step % self.config.log_interval == 0):
                    mean_loss = np.mean(batch_loss)
                    mean_f1 = np.mean(batch_f1)
                    mean_acc = np.mean(batch_acc)
                    batch_loss = []
                    nsml.report(summary=True, scope=locals(), epoch=epoch, train_loss=mean_loss, step=global_step)

                if (global_step > 0) and (global_step % self.config.val_interval == 0):
                    val_loss, val_f1, val_acc = self.evaluation()
                    nsml.report(summary=True, scope=locals(), epoch=epoch, val_loss=val_loss,
                                val_f1=val_f1, val_acc=val_acc, step=global_step)

                    if val_f1 > best_f1:
                        best_f1 = val_f1
                        best_acc = val_acc
                        nsml.save(global_step)

    def evaluation(self):
        self.model.eval()
        total_loss = []
        preds = []
        targets = []
        with torch.no_grad():
            for step, batch in enumerate(self.val_loader):
                batch = tuple(t.to(device) for t in batch)
                batch = sort_batch(batch)
                input_ids, input_lengths, labels = batch

                outputs = self.model(input_ids, input_lengths)
                loss = self.criterion(outputs['logits'].view(-1, self.config.n_label), labels.view(-1))

                pred = outputs['predicted_intents'].squeeze(-1).cpu().numpy().tolist()
                target = labels.cpu().numpy().tolist()

                preds.extend(pred)
                targets.extend(target)
                total_loss.append(loss.float().item())

        mean_loss = np.mean(total_loss)
        mean_f1, mean_acc = ic_metric(targets, preds)
        return mean_loss, mean_f1, mean_acc


import dash
import dash_daq
import re
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc

FOOTER_CONTENT = '''
This is still very much a work in progress, and there are probably still some bugs.
I'm [/u/Uily](https://www.reddit.com/user/uily) on Reddit, so please let me know if
you find any. Checkout the code for this project here: https://github.com/akabbeke/WarhammerStatsEngine

For the shots and damage characteristic, you can either use a fixed number or
XdY notation to represent a rolling
X dice with Y sides. You can also add modifiers to the hit and wound rolls that stack
(e.g. re-rolling 1's to hit and -1 to hit).
You can also download an image of the graph by clicking the camera icon
while hovering over the graph.

##### Updates:
* Removed the +/- 2 and 3 modifiers and instead you can now add +/-1 multiple times.
* Added the 'exploding dice' mechanic for hit rolls. You can stack them so for
example two "+1 hit on 6+" will yield +2 hits on a 6+.
* Added mortal wound generation for hit and wound rolls
* Added Haywire

##### Todo:
* Figure out feed-forward abilities like rend
* ???

There are no **ads** funding this, so please don't be a dick. Otherwise,
I hope you find this useful!
'''

class Layout(object):
  def __init__(self, tab_count=0, weapon_count=0):
    self.tab_count = tab_count
    self.weapon_count = weapon_count

  def layout(self):
    return html.Div([
      dcc.Location(id='url'),
      html.Div(id='page_content')
    ])

  def base_layout(self):
    return html.Div(
      [
        self.navbar(),
        dbc.Select(),
        self.base_title(),
        dbc.Row(
          dbc.Col(
            GraphLayout(self.tab_count).layout(),
            className='portlet-container portlet-dropzone',
          ),
          style={'align-items': 'center'},
          className='flex-fill fill d-flex justify-content-start',
        ),
        dbc.Row(
          [
            dbc.Col(
              InputLayout(self.tab_count, self.weapon_count).layout(),
            ),
          ]
        ),
      ],
      className='container-fluid d-flex flex-column',
    )

  def base_title(self):
    content = dbc.InputGroup(
      [
        dbc.InputGroupAddon("Title", addon_type="prepend"),
        dbc.Input(
          type="text",
          id='title',
          value='',
          debounce=True,
          minLength=2,
          persistence=True,
          persistence_type='session',
          maxLength=140,
        ),
      ],
    )
    return dbc.CardBody(dbc.Row([dbc.Col(content)], className="mb-2 ",))

  def static_layout(self):
    return html.Div(
      [
        self.static_navbar(),
        html.Div(id='static_graph_debug', style={'display': 'none'}),
        dcc.RadioItems(
          id='page-2-radios',
          options=[{'label': i, 'value': i} for i in ['Orange', 'Blue', 'Red']],
          value='Orange',
          style={'display': 'none'}
        ),
        dbc.Row(
          dbc.Col(
            GraphLayout(self.tab_count).static_layout(),
            className='portlet-container portlet-dropzone',
          ),
          style={'align-items': 'center'},
          className='flex-fill fill d-flex justify-content-start',
        ),
      ],
      className='container-fluid d-flex flex-column',
    )

  def navbar(self):
    return dbc.NavbarSimple(
      children=[
        dbc.NavItem(
          dbc.NavLink(
            "permalink to this graph",
            id='permalink',
            href="https://github.com/akabbeke/WarhammerStatsEngine",
            external_link=True,
          )
        ),
      ],
      brand="Warhammer-Stats-Engine",
      brand_href="/",
      color="primary",
      dark=True,
    )

  def static_navbar(self):
    return dbc.NavbarSimple(
      children=[
        dbc.NavItem(
          dbc.NavLink(
            "Create your own graph",
            id='permalink',
            href="/"
          )
        ),
      ],
      brand="Warhammer-Stats-Engine",
      brand_href="/",
      color="primary",
      dark=True,
    )

app_color = {"graph_bg": "#082255", "graph_line": "#a3a7b0"}

class GraphLayout(object):
  def __init__(self, tab_count=0):
    self.tab_count = tab_count

  def layout(self):
    content = dcc.Graph(
      id='damage_graph',
      style={'height':'60vh'},
      figure=self.figure_template(),
      config={
        'scrollZoom': False,
        'toImageButtonOptions': {
          'format': 'jpeg',
          'filename': 'warhammer_plot',
          'height': 1080,
          'width': 1920,
          'scale': 1
        },
        # 'displayModeBar': False,
      },

    )
    return content

  def static_layout(self):
    content = dcc.Graph(
      id='static_damage_graph',
      style={'height':'85vh'},
      figure=self.figure_template(),
      config={
        'scrollZoom': False,
        'toImageButtonOptions': {
          'format': 'jpeg',
          'filename': 'warhammer_plot',
          'height': 1080,
          'width': 1920,
          'scale': 1
        },
        # 'displayModeBar': False,
      },

    )
    return content

  def figure_template(self, data=None, max_len=10, title=None, static=False):
    return {
      'data': data or [{}] * self.tab_count,
      'layout': {
        'title': title,
        'showlegend': True,
        'legend': dict(orientation='h',yanchor='top',xanchor='center',y=1, x=0.5),
        # 'template': 'plotly_dark',
        'xaxis': {
            'title': 'Minimum Wounds Dealt to Target',
            'type': 'linear',
            'range': [0, max_len],
            'tickmode': 'linear',
            'tick0': 0,
            'dtick': 1,
            "gridcolor": app_color["graph_line"],
            "color": app_color["graph_line"],
            'fixedrange': True,
        },
        'yaxis': {
            'title': 'Probability of Minimum Wounds Dealt',
            'type': 'linear',
            'range': [0, 100],
            'tickmode': 'linear',
            'tick0': 0,
            'dtick': 10,
            "gridcolor": app_color["graph_line"],
            "color": app_color["graph_line"],
            'fixedrange': True,
        },
        'margin':{
          'l': 70,
          'r': 70,
          'b': 50,
          't': 50,
          'pad': 4,
        },
        'autosize': True,
      },
    }

class InputLayout(object):
  def __init__(self, tab_count=0, weapon_count=0):
    self.tab_count = tab_count
    self.weapon_count = weapon_count

  def layout(self):
    tabs = []
    for i in range(self.tab_count):
      tab = InputTabLayout(i, self.tab_count, self.weapon_count).layout()
      tabs.append(tab)
    tabs.append(
      dbc.Tab(
        dbc.CardBody(dcc.Markdown(FOOTER_CONTENT)),
        label='Info Tab',
        style={'width': '100%'},
      )
    )
    return dbc.Tabs(
      tabs,
      className='nav-justified',
      style={'padding-top': '4px', 'padding-bottom': '0px'},
    )

class InputTabLayout(object):
  def __init__(self, tab_index, tab_count=0, weapon_count=0):
    self.tab_index = tab_index
    self.tab_count = tab_count
    self.weapon_count = weapon_count

  def layout(self):
    return dbc.Tab(
      self.tab_content(),
      id='tab_{}'.format(self.tab_index),
      label='Profile {}'.format(self.tab_index + 1),
      style={'width': '100%'},
    )

  def tab_content(self):
    form_input = [
      self._data_input_row(),
      self._target_input_row(),
      self._weapon_tabs(),
    ]
    return self._wrap_card(form_input)

  def _wrap_card(self, content):
    return dbc.Card(dbc.CardBody(content),className="mb-2 ")

  def _data_input_row(self):
    return dbc.Row(
      [
        dbc.Col(self._tab_enable_inout(), width=2),
        dbc.Col(self._tab_name_input()),
        dbc.Col(html.P("Average", id=f'avgdisplay_{self.tab_index}'), width=2),
        dbc.Col(html.P("σ", id=f'stddisplay_{self.tab_index}'), width=2),
      ],
      className='mb-2',
    )

  def _tab_enable_inout(self):
    content = [
      dbc.Select(
        options=[
          {"label": "Enabled", "value": 'enabled'},
          {"label": "Disabled", "value": 'disabled'}
        ],
        value='enabled' if self.tab_index == 0 else 'disabled',
        disabled=self.tab_index == 0,
        id=f'enabled_{self.tab_index}',
        persistence=True,
        persistence_type='session',
      )
    ]
    return dbc.InputGroup(content, size="sm")

  def _tab_name_input(self):
    content = [
      dbc.InputGroupAddon("Name", addon_type="prepend"),
      dbc.Input(
        type="text",
        id=f'tabname_{self.tab_index}',
        value=f'Profile {self.tab_index}',
        debounce=True,
        minLength=2,
        persistence=True,
        persistence_type='session',
        maxLength=60
      ),
    ]
    return dbc.InputGroup(content, size="sm")

  def _target_input_row(self):
    content = dbc.InputGroup(
      [
        dbc.InputGroupAddon("Target", addon_type="prepend"),
        *self._toughness_input(),
        *self._save_input(),
        *self._invuln_input(),
        *self._fnp_input(),
        *self._wounds_input(),
      ],
      size="sm",
    )
    return dbc.Row([dbc.Col(content)], className="mb-2 ",)

  def _toughness_input(self):
    return [
      dbc.InputGroupAddon('T', id=f'toughness_addon_{self.tab_index}', addon_type='prepend'),
      dbc.Select(
        id=f'toughness_{self.tab_index}',
        options=[{'label': f'{i}', 'value': i} for i in range(1,11)],
        value=4,
        persistence=True,
        persistence_type='session',
      ),
      dbc.Tooltip(
        'Set the toughness of the target',
        target=f'toughness_addon_{self.tab_index}',
      ),
    ]

  def _save_input(self):
    return [
      dbc.InputGroupAddon('SV', id=f'save_addon_{self.tab_index}', addon_type='prepend'),
      dbc.Select(
        id=f'save_{self.tab_index}',
        options=[{'label': f'{i}+', 'value': i} for i in range(2,8)],
        value=3,
        persistence=True,
        persistence_type='session',
      ),
      dbc.Tooltip(
        'Set the save value of the target',
        target=f'save_addon_{self.tab_index}',
      ),
    ]

  def _invuln_input(self):
    return [
      dbc.InputGroupAddon('INV', id=f'invuln_addon_{self.tab_index}', addon_type='prepend'),
      dbc.Select(
        id=f'invuln_{self.tab_index}',
        options=[{'label': f'{i}++', 'value': i} for i in range(2,8)],
        value=7,
        persistence=True,
        persistence_type='session',
      ),
      dbc.Tooltip(
        'Set the invulnerable save value of the target',
        target=f'invuln_addon_{self.tab_index}',
      ),
    ]

  def _fnp_input(self):
    return [
      dbc.InputGroupAddon('FNP', id=f'fnp_addon_{self.tab_index}', addon_type='prepend'),
      dbc.Select(
        id=f'fnp_{self.tab_index}',
        options=[{'label': f'{i}+++', 'value': i} for i in range(2,8)],
        value=7,
        persistence=True,
        persistence_type='session',
      ),
      dbc.Tooltip(
        'Set the feel no pain value of the target',
        target=f'fnp_addon_{self.tab_index}',
      ),
    ]

  def _wounds_input(self):
    return [
      dbc.InputGroupAddon('W', id=f'wounds_addon_{self.tab_index}', addon_type='prepend'),
      dbc.Select(
        id=f'wounds_{self.tab_index}',
        options=[{'label': f'{i}', 'value': i} for i in range(1,25)],
        value=2,
        persistence=True,
        persistence_type='session',
      ),
      dbc.Tooltip(
        'Set the target wounds value',
        target=f'wounds_addon_{self.tab_index}',
      ),
    ]

  def _weapon_tabs(self):
    weapon_tabs = []
    for weapon_index in range(self.weapon_count):
      weapon_tab = WeaponTabLayout(
        self.tab_index,
        weapon_index,
        self.tab_count,
        self.weapon_count
      ).layout()
      weapon_tabs.append(weapon_tab)
    return dbc.Tabs(
      weapon_tabs,
      className='nav-justified',
      style={'padding-top': '0px', 'padding-bottom': '0px'},
    )

class WeaponTabLayout(object):
  def __init__(self, tab_index, weapon_index, tab_count=0, weapon_count=0):
    self.tab_index = tab_index
    self.weapon_index = weapon_index
    self.tab_count = tab_count
    self.weapon_count = weapon_count

  def layout(self):
    return dbc.Tab(
      self._tab_content(),
      id=f'weapontab_{self.tab_index}_{self.weapon_index}',
      label='Weapon {}'.format(self.weapon_index + 1),
      style={'width': '100%'}
    )

  def _tab_content(self):
    form_input = [
      self._weapon_name_row(),
      self._attack_input_row(),
      *self._modifier_rows()
    ]
    return self._wrap_card(form_input)

  def _wrap_card(self, content):
    return dbc.Card(dbc.CardBody(content))

  def _wrap_single_row(self, content):
    return dbc.Row([dbc.Col(content)], className="mb-2 ",)

  def _weapon_name_row(self):
    return dbc.Row(
      [
        dbc.Col(self._weapon_enable_input(), width=2),
        dbc.Col(self._weapon_name_input()),
      ],
      className='mb-2',
    )

  def _weapon_enable_input(self):
    return dbc.InputGroup([
      dbc.Select(
        options=[
          {'label': 'Enabled', 'value': 'enabled'},
          {'label': 'Disabled', 'value': 'disabled'}
        ],
        value='enabled' if self.weapon_index == 0 else 'disabled',
        disabled=self.weapon_index == 0,
        persistence=True,
        persistence_type='session',
        id=f'weaponenabled_{self.tab_index}_{self.weapon_index}',
      ),
    ], size="sm")

  def _weapon_name_input(self):
    return dbc.InputGroup([
      dbc.InputGroupAddon("Name", addon_type="prepend"),
      dbc.Input(
        type="text",
        id=f'weaponname_{self.tab_index}_{self.weapon_index}',
        value=f'Weapon {self.weapon_index+1}',
        debounce=True,
        minLength=2,
        persistence=True,
        persistence_type='session',
        maxLength=60
      ),
    ], size="sm")

  def _attack_input_row(self):
    content = [
      *self._strength_input(),
      *self._ap_input(),
      *self._weapon_skill_input(),
      *self._shots_input(),
      *self._damage_input(),
    ]

    return self._wrap_single_row(dbc.InputGroup(content, size="sm",))

  def _weapon_skill_input(self):
    return [
      dbc.InputGroupAddon(
        'WS',
        id=f'ws_addon_{self.tab_index}_{self.weapon_index}',
        addon_type='prepend'
      ),
      dbc.Select(
        id=f'ws_{self.tab_index}_{self.weapon_index}',
        options=[{'label': f'{i}+', 'value': i} for i in range(1,8)],
        value=4,
        persistence=True,
        persistence_type='session',
      ),
      dbc.Tooltip(
        'Set the weapons skill value',
        target=f'ws_addon_{self.tab_index}_{self.weapon_index}',
      ),
    ]

  def _strength_input(self):
    return [
      dbc.InputGroupAddon(
        'S',
        id=f'strength_addon_{self.tab_index}_{self.weapon_index}',
        addon_type='prepend'
      ),
      dbc.Select(
        id=f'strength_{self.tab_index}_{self.weapon_index}',
        options=[{'label': f'{i}', 'value': i} for i in range(1,21)],
        value=4,
        persistence=True,
        persistence_type='session',
      ),
      dbc.Tooltip(
        'Set the strength value',
        target=f'strength_addon_{self.tab_index}_{self.weapon_index}',
      ),
    ]

  def _ap_input(self):
    return [
      dbc.InputGroupAddon(
        'AP',
        id=f'ap_addon_{self.tab_index}_{self.weapon_index}',
        addon_type="prepend"
      ),
      dbc.Select(
        id=f'ap_{self.tab_index}_{self.weapon_index}',
        options=[{'label': '0' if i==0 else f'-{i}', 'value': i} for i in range(0,7)],
        value=1,
        persistence=True,
        persistence_type='session',
      ),
      dbc.Tooltip(
        'Set the AP value',
        target=f'ap_addon_{self.tab_index}_{self.weapon_index}',
      ),
    ]

  def _shots_input(self):
    return [
      dbc.InputGroupAddon(
        '#',
        id=f'shots_addon_{self.tab_index}_{self.weapon_index}',
        addon_type="prepend"
      ),
      dbc.Input(
        type='text',
        id=f'shots_{self.tab_index}_{self.weapon_index}',
        value='2d6',
        style={'text-align': 'right'},
        persistence=True,
        persistence_type='session',
        debounce=True,
        pattern=r'^(\d+)?[dD]?(\d+)$',
      ),
      dbc.Tooltip(
        'Set the number of shots (1, 2d6, d3, ...)',
        target=f'shots_addon_{self.tab_index}_{self.weapon_index}',
      ),
    ]

  def _damage_input(self):
    return [
      dbc.InputGroupAddon(
        'D',
        id=f'damage_addon_{self.tab_index}_{self.weapon_index}',
        addon_type='prepend'
      ),
      dbc.Input(
        type='text',
        id=f'damage_{self.tab_index}_{self.weapon_index}',
        value='2',
        style={'text-align': 'right'},
        persistence=True,
        persistence_type='session',
        debounce=True,
        pattern=r'^(\d+)?[dD]?(\d+)$',
      ),
      dbc.Tooltip(
        'Set the damage dealt (1, 2d6, d3, ...)',
        target=f'damage_addon_{self.tab_index}_{self.weapon_index}',
      ),
    ]

  def _modifier_rows(self):
    shot_modifier = dcc.Dropdown(
      options=self._shot_modifier_options(),
      multi=True,
      placeholder='Modify shot volume rolls',
      optionHeight=20,
      id=f'shotmods_{self.tab_index}_{self.weapon_index}',
      persistence=True,
      persistence_type='session',
      value=[],
    )
    hit_modifier = dcc.Dropdown(
      options=self._hit_modifier_options(),
      multi=True,
      placeholder='Modify hit rolls',
      optionHeight=20,
      id=f'hitmods_{self.tab_index}_{self.weapon_index}',
      persistence=True,
      persistence_type='session',
      value=[],
    )
    wound_modifier = dcc.Dropdown(
      options=self._wound_modifier_options(),
      multi=True,
      placeholder='Modify wound rolls',
      optionHeight=20,
      id=f'woundmods_{self.tab_index}_{self.weapon_index}',
      persistence=True,
      persistence_type='session',
      value=[],
    )
    save_modifier = dcc.Dropdown(
      options=self._save_modifier_options(),
      multi=True,
      placeholder='Modify save rolls',
      optionHeight=20,
      id=f'savemods_{self.tab_index}_{self.weapon_index}',
      persistence=True,
      persistence_type='session',
      value=[],
    )
    fnp_modifier = dcc.Dropdown(
      options=self._fnp_modifier_options(),
      multi=True,
      placeholder='Modify FNP rolls',
      optionHeight=20,
      id=f'fnpmods_{self.tab_index}_{self.weapon_index}',
      persistence=True,
      persistence_type='session',
      value=[],
    )
    damage_modifier = dcc.Dropdown(
      options=self._damage_modifier_options(),
      multi=True,
      placeholder='Modify damage rolls',
      optionHeight=20,
      id=f'damagemods_{self.tab_index}_{self.weapon_index}',
      persistence=True,
      persistence_type='session',
      value=[],
    )
    return [
      dbc.Row([dbc.Col(shot_modifier), dbc.Col(hit_modifier), dbc.Col(wound_modifier)], className="mb-2 "),
      dbc.Row([dbc.Col(save_modifier), dbc.Col(fnp_modifier), dbc.Col(damage_modifier)]),
    ]

  def _shot_modifier_options(self):
    options = [
      {'label': f'Reroll all dice', 'value': f'reroll_allvol'},
      {'label': f'Reroll one dice', 'value': f'reroll_one_dicevol'},
      {'label': f'Reroll ones', 'value': f'reroll_ones'},
      {'label': f'Roll two dice choose highest', 'value': f'reroll_melta'},
      {'label': f'Add +D6', 'value': f'addvol_d6'},
      {'label': f'Add +D3', 'value': f'addvol_d3'},
    ]
    for i in range(1, 7):
      options.append({'label': f'Add +{i}', 'value': f'addvol_{i}'})
    for i in range(1, 7):
      options.append({'label': f'Sub -{i}', 'value': f'subvol_{i}'})
    return options

  def _hit_modifier_options(self):
    options = [
      {'label': f'Reroll all dice', 'value': f'reroll_all'},
      {'label': f'Reroll failed dice', 'value': f'reroll_failed'},
      {'label': f'Reroll one dice', 'value': f'reroll_one_dice'},
      {'label': f'Reroll ones', 'value': f'reroll_ones'},
    ]
    for i in range(1, 7):
      options.append({'label': f'Add +{i}', 'value': f'add_{i}'})
    for i in range(1, 7):
      options.append({'label': f'Sub -{i}', 'value': f'sub_{i}'})
    for x in ['MW', 'hits', 'shots']:
      for i in range(1, 7):
        for j in range(2, 7):
          options.append({'label': f'+{i} {x} on a {j}+', 'value': f'addon_{i}_{x}_{j}_mod'})
    for x in ['MW', 'hits', 'shots']:
      for i in range(1, 7):
        for j in range(2, 7):
          values = ', '.join([str(x) for x in range(j, 7)])
          options.append({'label': f'+{i} {x} on a {values}', 'value': f'addon_{i}_{x}_{j}'})
    return options

  def _wound_modifier_options(self):
    options = [
      {'label': f'Reroll all dice', 'value': f'reroll_all'},
      {'label': f'Reroll failed dice', 'value': f'reroll_failed'},
      {'label': f'Reroll one dice', 'value': f'reroll_one_dice'},
      {'label': f'Reroll ones', 'value': f'reroll_ones'},
      {'label': f'Haywire', 'value': f'haywire'},
    ]
    for i in range(1, 7):
      options.append({'label': f'Add +{i}', 'value': f'add_{i}'})
    for i in range(1, 7):
      options.append({'label': f'Sub -{i}', 'value': f'sub_{i}'})
    # for i in range(2, 7):
    #   options.append({'label': f'Only wound on {i}+', 'value': f'lower_{i}'})
    for x in ['MW', 'wounds']:
      for i in range(1, 7):
        for j in range(2, 7):
          options.append({'label': f'+{i} {x} on a {j}+', 'value': f'addon_{i}_{x}_{j}_mod'})
    for x in ['MW', 'wounds']:
      for i in range(1, 7):
        for j in range(2, 7):
          values = ', '.join([str(x) for x in range(j, 7)])
          options.append({'label': f'+{i} {x} on a {values}', 'value': f'addon_{i}_{x}_{j}'})
    return options

  def _save_modifier_options(self):
    options = [
      {'label': f'Reroll all dice', 'value': f'reroll_all'},
      {'label': f'Reroll failed dice', 'value': f'reroll_failed'},
      {'label': f'Reroll one dice', 'value': f'reroll_one_dice'},
      {'label': f'Reroll ones', 'value': f'reroll_ones'},
      {'label': f'Ignore invulnerable', 'value': f'ignoreinv'},
    ]
    for i in range(1, 7):
      options.append({'label': f'Add +{i} to save', 'value': f'saveadd_{i}'})
    for i in range(1, 7):
      options.append({'label': f'Sub -{i} to save', 'value': f'savesub_{i}'})
    for i in range(1, 7):
      options.append({'label': f'Add +{i} to invuln', 'value': f'invadd_{i}'})
    for i in range(1, 7):
      options.append({'label': f'Sub -{i} to invuln', 'value': f'invsub_{i}'})
    for i in range(1, 7):
      options.append({'label': f'Ignore AP -{i} and lower', 'value': f'ignoreap_{i}'})
    return options

  def _fnp_modifier_options(self):
    options = [
      {'label': f'Reroll all dice', 'value': f'reroll_all'},
      {'label': f'Reroll failed dice', 'value': f'reroll_failed'},
      {'label': f'Reroll one dice', 'value': f'reroll_one_dice'},
      {'label': f'Reroll ones', 'value': f'reroll_ones'},
    ]
    for i in range(1, 7):
      options.append({'label': f'Add +{i} to FNP', 'value': f'fnpadd_{i}'})
    for i in range(1, 7):
      options.append({'label': f'Sub -{i} to FNP', 'value': f'fnpsub_{i}'})
    return options

  def _damage_modifier_options(self):
    options = [
      {'label': f'Reroll all dice', 'value': f'reroll_allvol'},
      {'label': f'Reroll one dice', 'value': f'reroll_one_dicevol'},
      {'label': f'Reroll ones', 'value': f'reroll_ones'},
      {'label': f'Roll two dice choose highest', 'value': f'reroll_melta'},
      {'label': f'Half damage (rounding up)', 'value': f'halfdam'},
    ]
    for i in range(1, 7):
      options.append({'label': f'Add +{i}', 'value': f'addvol_{i}'})
    for i in range(1, 7):
      options.append({'label': f'Sub -{i}', 'value': f'subvol_{i}'})
    for i in range(2, 7):
      options.append({'label': f'Minimum {i} damage', 'value': f'minval_{i}'})
    return options


import cv2
import tensorflow as tf
import numpy as np
from pathlib import Path
import os

def draw_box(image, box, color, thickness=2):
    """ Draws a box on an image with a given color.
    @param image     : The image to draw on.
    @param box       : A list of 4 elements (x1, y1, x2, y2).
    @param color     : The color of the box.
    @param thickness : The thickness of the lines to draw a box with.
    @return image with drawn box.
    """
    b = np.array(box).astype(int)
    image = image.astype(np.uint8)
    image = cv2.rectangle(image, (b[0], b[1]), (b[2], b[3]), color, thickness, cv2.LINE_AA) # RGB color
    return image

def draw_caption(image, box, caption):
    """ Draws a caption above the box in an image.
    @param image   : The image to draw on.
    @param box     : A list of 4 elements (x1, y1, x2, y2).
    @param caption : String containing the text to draw.
    @return image with drawn caption.
    """
    b = np.array(box).astype(int)
    image = cv2.putText(image, caption, (b[0], b[1] - 10), cv2.FONT_HERSHEY_PLAIN, 0.8, (0, 0, 0), 2)
    image = cv2.putText(image, caption, (b[0], b[1] - 10), cv2.FONT_HERSHEY_PLAIN, 0.8, (255, 255, 255), 1)
    return image

def draw_boxes(image, boxes, color, thickness=2):
    """ Draws boxes on an image with a given color.
    @param image     : The image to draw on.
    @param boxes     : A [N, 4] matrix (x1, y1, x2, y2).
    @param color     : The color of the boxes.
    @param thickness : The thickness of the lines to draw boxes with.
    @return image with drawn boxes
    """
    for b in boxes:
        image = draw_box(image, b, color, thickness=thickness)

    return image

def draw_detections(image, boxes, scores, classes, filename, save_dir, label_to_name, score_threshold=0.20):
    """ Draws detections in an image.
    @param image: The image to draw on. Image size is determined by input size for network.
    @param boxes: A [N, 4] matrix (x1, y1, x2, y2).
    @param scores: A list of N classification scores.
    @param classes: A list of N labels.
    @param filename: filename of the image.
    @param save_dir: directory to save image in.
    @param label_to_name: (optional) Functor for mapping a label to a name.
    @param score_threshold: Threshold used for determining what detections to draw.
    """

    # Remove batch dimension
    image = tf.reshape(image, tf.shape(image)[1:]).numpy() * 255
    boxes = tf.reshape(boxes, tf.shape(boxes)[1:]).numpy()
    classes = tf.reshape(classes, tf.shape(classes)[1:]).numpy()

    if not boxes.shape[0] == 0:
        # if boxes are detected
        save_dir = os.path.join(save_dir, Path(filename.numpy().decode('utf-8')).stem + '_detections.png')
        # Convert to absolute coordinates
        boxes[:, 0] *= image.shape[0]
        boxes[:, 1] *= image.shape[1]
        boxes[:, 2] *= image.shape[0]
        boxes[:, 3] *= image.shape[1]

        selection = np.where(scores > score_threshold)[1]

        scores = tf.reshape(scores, tf.shape(scores)[1:]).numpy()

        for i in selection:
            image = draw_box(image, boxes[i, :], color=(0, 255, 0))

            # draw labels
            caption = (label_to_name[classes[i]] if label_to_name else classes[i]) + ': {0:.2f}'.format(scores[i])
            image = draw_caption(image, boxes[i, :], caption)

        cv2.imwrite(save_dir, image)


from django.conf.urls import include, url
from .apps.backends import urls as omni_backends_urls
from .apps.host_node import urls as omni_host_urls
from djcelery import urls as djcelery_urls
from asset import urls as asset_urls

from . import views as omni_view

urlpatterns = [
    url(r'^$|^index\.html$', omni_view.index),
    url(r'^login\.html$', omni_view.login),
    url(r'^logout\.htm$', omni_view.logout),
]

urlpatterns += [
    url(r'^backends/', include(omni_backends_urls))
]

urlpatterns += [
    url(r'^asset/', include(asset_urls))
]

urlpatterns += [
    url(r'^host/', include(omni_host_urls))
]

urlpatterns += [
    url(r'^celery/', include(djcelery_urls))
]


'''
Created on 2019年4月4日

@author: jinglingzhiyu
'''
'''
Created on 2019年3月7日

@author: jinglingzhiyu
'''
import torch
import os, time
import torch.nn as nn
from torchvision.models import vgg
import functools
import torch.nn.functional as F

class UnetSkipConnectionBlock(nn.Module):
    """Defines the Unet submodule with skip connection.
        X -------------------identity----------------------
        |-- downsampling -- |submodule| -- upsampling --|
    """

    def __init__(self, outer_nc, inner_nc, input_nc=None,
                 submodule=None, outermost=False, innermost=False, norm_layer=nn.BatchNorm2d, use_dropout=False):
        """Construct a Unet submodule with skip connections.

        Parameters:
            outer_nc (int) -- the number of filters in the outer conv layer
            inner_nc (int) -- the number of filters in the inner conv layer
            input_nc (int) -- the number of channels in input images/features
            submodule (UnetSkipConnectionBlock) -- previously defined submodules
            outermost (bool)    -- if this module is the outermost module
            innermost (bool)    -- if this module is the innermost module
            norm_layer          -- normalization layer
            user_dropout (bool) -- if use dropout layers.
        """
        super(UnetSkipConnectionBlock, self).__init__()
        self.outermost = outermost
        if type(norm_layer) == functools.partial:
            use_bias = norm_layer.func == nn.InstanceNorm2d
        else:
            use_bias = norm_layer == nn.InstanceNorm2d
        if input_nc is None:
            input_nc = outer_nc
        downconv = nn.Conv2d(input_nc, inner_nc, kernel_size=4,
                             stride=2, padding=1, bias=use_bias)
        downrelu = nn.LeakyReLU(0.2, True)
        downnorm = norm_layer(inner_nc)
        uprelu = nn.ReLU(True)
        upnorm = norm_layer(outer_nc)

        if outermost:
            upconv = nn.ConvTranspose2d(inner_nc * 2, outer_nc,
                                        kernel_size=4, stride=2,
                                        padding=1)
            down = [downconv]
            up = [uprelu, upconv, nn.Tanh()]
            model = down + [submodule] + up
        elif innermost:
            upconv = nn.ConvTranspose2d(inner_nc, outer_nc,
                                        kernel_size=4, stride=2,
                                        padding=1, bias=use_bias)
            down = [downrelu, downconv]
            up = [uprelu, upconv, upnorm]
            model = down + up
        else:
            upconv = nn.ConvTranspose2d(inner_nc * 2, outer_nc,
                                        kernel_size=4, stride=2,
                                        padding=1, bias=use_bias)
            down = [downrelu, downconv, downnorm]
            up = [uprelu, upconv, upnorm]

            if use_dropout:
                model = down + [submodule] + up + [nn.Dropout(0.5)]
            else:
                model = down + [submodule] + up

        self.model = nn.Sequential(*model)

    def forward(self, x):
        if self.outermost:
            return self.model(x)
        else:   # add skip connections
            return torch.cat([x, self.model(x)], 1)

class UnetGenerator(nn.Module):
    """Create a Unet-based generator"""

    def __init__(self, input_nc, output_nc, num_downs, ngf=64, norm_layer=nn.BatchNorm2d, use_dropout=False):
        """Construct a Unet generator
        Parameters:
            input_nc (int)  -- the number of channels in input images
            output_nc (int) -- the number of channels in output images
            num_downs (int) -- the number of downsamplings in UNet. For example, # if |num_downs| == 7,
                                image of size 128x128 will become of size 1x1 # at the bottleneck
            ngf (int)       -- the number of filters in the last conv layer
            norm_layer      -- normalization layer

        We construct the U-Net from the innermost layer to the outermost layer.
        It is a recursive process.
        """
        super(UnetGenerator, self).__init__()
        # construct unet structure
        unet_block = UnetSkipConnectionBlock(ngf * 8, ngf * 8, input_nc=None, submodule=None, norm_layer=norm_layer, innermost=True)  # add the innermost layer
        for i in range(num_downs - 5):          # add intermediate layers with ngf * 8 filters
            unet_block = UnetSkipConnectionBlock(ngf * 8, ngf * 8, input_nc=None, submodule=unet_block, norm_layer=norm_layer, use_dropout=use_dropout)
        # gradually reduce the number of filters from ngf * 8 to ngf
        unet_block = UnetSkipConnectionBlock(ngf * 4, ngf * 8, input_nc=None, submodule=unet_block, norm_layer=norm_layer)
        unet_block = UnetSkipConnectionBlock(ngf * 2, ngf * 4, input_nc=None, submodule=unet_block, norm_layer=norm_layer)
        unet_block = UnetSkipConnectionBlock(ngf, ngf * 2, input_nc=None, submodule=unet_block, norm_layer=norm_layer)
        self.model = UnetSkipConnectionBlock(output_nc, ngf, input_nc=input_nc, submodule=unet_block, outermost=True, norm_layer=norm_layer)  # add the outermost layer

    def forward(self, input):
        """Standard forward"""
        return self.model(input)

class discriminator(nn.Module):
    def __init__(self):
        super(discriminator, self).__init__()
        self.netD = nn.Sequential(
                                        nn.Conv2d(6, 64, (4,4), stride=(2,2), padding=(1,1)),
                                        nn.LeakyReLU(0.2, inplace=True),
                                        nn.Conv2d(64, 128, (4,4), stride=(2,2), padding=(1,1), bias=False),
                                        nn.BatchNorm2d(128, eps=1e-5, momentum=0.1),
                                        nn.LeakyReLU(0.2, inplace=True),
                                        nn.Conv2d(128, 256, (4,4), stride=(2,2), padding=(1,1), bias=False),
                                        nn.BatchNorm2d(256, eps=1e-5, momentum=0.1),
                                        nn.LeakyReLU(0.2, inplace=True),
                                        nn.Conv2d(256, 512, (4,4), stride=(1,1), padding=(1,1), bias=False),
                                        nn.BatchNorm2d(512, eps=1e-5, momentum=0.1),
                                        nn.LeakyReLU(0.2, inplace=True),
                                        nn.Conv2d(512, 1, (4,4), stride=(1,1), padding=(1,1)))
    def forward(self, data):
        out = self.netD(data)
        return out

class cGAN(nn.Module):
    def GANLoss(self, predict, mode):
        if mode is True:
            target = torch.ones(predict.shape).cuda()
        else:
            target = torch.zeros(predict.shape).cuda()
        return F.binary_cross_entropy_with_logits(predict, target)

    def __init__(self):
        super(cGAN, self).__init__()
        self.generator = UnetGenerator(3,3,8, use_dropout=True)
        self.discriminator = discriminator()
        self.discriminator = torch.nn.DataParallel(self.discriminator).cuda()
        self.generator = torch.nn.DataParallel(self.generator).cuda()
        self.optimizer_G = torch.optim.Adam(self.generator.parameters(), lr=0.0002, betas=(0.5, 0.999))
        self.optimizer_D = torch.optim.Adam(self.discriminator.parameters(), lr=0.0002, betas=(0.5, 0.999))

    def set_requires_grad(self, nets, requires_grad=False):
        """Set requies_grad=Fasle for all the networks to avoid unnecessary computations
        Parameters:
            nets (network list)   -- a list of networks
            requires_grad (bool)  -- whether the networks require gradients or not
        """
        if not isinstance(nets, list):
            nets = [nets]
        for net in nets:
            if net is not None:
                for param in net.parameters():
                    param.requires_grad = requires_grad

    def forward(self, image, label):
        self.image, self.label = image, label
        self.output = self.generator(image)
        return self.output

    def backward_D(self):
        fakedata = torch.cat((self.image, self.output), 1)
        realdata = torch.cat((self.image, self.label), 1)
        pred_fake = self.discriminator(fakedata.detach())
        self.loss_D_fake = self.GANLoss(pred_fake, False)
        pred_real = self.discriminator(realdata)
        self.loss_D_real = self.GANLoss(pred_real, True)
        self.loss_D = (self.loss_D_fake + self.loss_D_real) * 0.5
        self.loss_D.backward()

    def backward_G(self):
        fakedata = torch.cat((self.image, self.output), 1)
        pred_fake= self.discriminator(fakedata)
        self.loss_G_GAN = self.GANLoss(pred_fake, True)
        self.loss_L = F.l1_loss(self.output, self.label) * 100
        self.loss_G = self.loss_G_GAN + self.loss_L
        self.loss_G.backward()

    def optimize(self, image, label):
        #更新D
        image, label = image.cuda(), label.cuda()
        self.forward(image, label)
        self.set_requires_grad(self.discriminator, True)
        self.optimizer_D.zero_grad()
        self.backward_D()
        self.optimizer_D.step()
        #更新G
        self.set_requires_grad(self.discriminator, False)
        self.optimizer_G.zero_grad()
        self.backward_G()
        self.optimizer_G.step()

def temp_test():
    model = cGAN()
    model.discriminator = torch.nn.DataParallel(model.discriminator).cuda()
    model.generator = torch.nn.DataParallel(model.generator).cuda()
    data = torch.ones(4,3,256,256).cuda()
    target = torch.ones(4,3,256,256).cuda()
    model.optimize(data, target)

if __name__ == '__main__':
    temp_test()


#!/usr/bin/env python3
from __future__ import annotations

import sys
from math import isclose, nan
import numpy as np
from pathlib import Path

from matlab_mapping import matlab_mapping

import matlab.engine
from pymap3d.vincenty import vdist

cwd = Path(__file__).parent

eng = matlab.engine.start_matlab("-nojvm")
eng.addpath(eng.genpath(str(cwd)), nargout=0)

has_map = matlab_mapping(eng)

def distance(lat1, lon1, lat2, lon2) -> tuple[float, float]:
    """Using Matlab Engine to do same thing as Pymap3d"""

    if has_map:
        return eng.distance(lat1, lon1, lat2, lon2, eng.wgs84Ellipsoid(), nargout=2)
    else:
        return eng.matmap3d.vdist(lat1, lon1, lat2, lon2, nargout=2)

dlast, alast = nan, nan
lon1, lon2 = 0.0, 1.0
for i in range(20):
    lat1 = lat2 = 10.0 ** (-i)

    dist_m, az_deg = vdist(lat1, lon1, lat2, lon2)

    assert dist_m != dlast
    assert az_deg != alast
    mat_match = True
    dist_matlab, az_matlab = distance(lat1, lon1, lat2, lon2)

    assert np.isreal(dist_m), f"Python vdist distance is not real for input latitude {lat1}"
    assert np.isreal(dist_matlab), f"Matlab distance is not real for input latitude {lat1}"

    if not isclose(dist_matlab, dist_m):
        mat_match = False
        print(
            f"MISMATCH: latitude {lat1} {lat2}: Python: {dist_m}  Matlab: {dist_matlab}",
            file=sys.stderr,
        )
    if not isclose(az_matlab, az_deg):
        mat_match = False
        print(
            f"MISMATCH: latitude {lat1} {lat2}: Python: {az_matlab}  Matlab: {az_deg}",
            file=sys.stderr,
        )
    if mat_match:
        print(f"latitudes {lat1} {lat2}: {dist_m} meters {az_deg} deg azimuth")


def solution(array, commands):
    result = []
    for command in commands:
        i, j, k = command
        result.append(list(sorted(array[i-1:j]))[k-1])

    return result

print(solution([1, 5, 2, 6, 3, 7, 4], [[2,5,3], [4,4,1], [1,7,3]]))

# for 문에서 i, j, k를 한꺼번에 받을 수 있다.

프로그래머스 문제풀이/Level1/K번째 수.py