from __future__ import absolute_import
from __future__ import division

import contextlib
import logging

import six

from vdsm.common.time import monotonic_time
from vdsm.utils import convertToStr

from vdsm.virt.utils import isVdsmImage

_log = logging.getLogger('virt.vmstats')

def produce(vm, first_sample, last_sample, interval):
    """
    Translates vm samples into stats.
    """

    stats = {}

    cpu(stats, first_sample, last_sample, interval)
    networks(vm, stats, first_sample, last_sample, interval)
    disks(vm, stats, first_sample, last_sample, interval)
    balloon(vm, stats, last_sample)
    cpu_count(stats, last_sample)
    tune_io(vm, stats)
    memory(stats, first_sample, last_sample, interval)

    return stats

def translate(vm_stats):
    stats = {}

    for var in vm_stats:
        if var == "ioTune":
            value = vm_stats[var]
            if value:
                # Convert ioTune numbers to strings to avoid xml-rpc issue
                # with numbers bigger than int32_t
                for ioTune in value:
                    ioTune["ioTune"] = dict(
                        (k, convertToStr(v)) for k, v
                        in six.iteritems(ioTune["ioTune"]))
                stats[var] = vm_stats[var]
        elif type(vm_stats[var]) is not dict:
            stats[var] = convertToStr(vm_stats[var])
        elif var in ('disks', 'network', 'balloonInfo', 'memoryStats'):
            value = vm_stats[var]
            if value:
                stats[var] = value

    return stats

def tune_io(vm, stats):
    """
    Collect the current ioTune settings for all disks VDSM knows about.

    This assumes VDSM always has the correct info and nobody else is
    touching the device without telling VDSM about it.

    TODO: We might want to move to XML parsing (first update) and events
    once libvirt supports them:
    https://bugzilla.redhat.com/show_bug.cgi?id=1114492
    """
    io_tune_info = []

    for disk in vm.getDiskDevices():
        iotune = disk.iotune
        if iotune:
            io_tune_info.append({
                "name": disk.name,
                "path": disk.path,
                "ioTune": iotune
            })

    stats['ioTune'] = io_tune_info

def cpu(stats, first_sample, last_sample, interval):
    """
    Add cpu statistics to the `stats' dict:
    - cpuUser
    - cpuSys
    - cpuTime
    - cpuActual
    Expect two samplings `first_sample' and `last_sample'
    which must be data in the format of the libvirt bulk stats.
    `interval' is the time between the two samplings, in seconds.
    Fill `stats' as much as possible, bailing out at first error.
    Return None on error,  if any needed data is missing or wrong.
    Return the `stats' dictionary on success.
    """
    stats['cpuUser'] = 0.0
    stats['cpuSys'] = 0.0
    stats['cpuUsage'] = 0.0
    stats['cpuActual'] = False

    if first_sample is None or last_sample is None:
        return None
    if interval <= 0:
        _log.warning(
            'invalid interval %i when computing CPU stats',
            interval)
        return None

    keys = ('cpu.system', 'cpu.user')
    samples = (last_sample, first_sample)

    if all(k in s for k in keys for s in samples):
        # TODO: cpuUsage should have the same type as cpuUser and cpuSys.
        # we may block the str() when xmlrpc is deserted.
        stats['cpuUsage'] = str(last_sample['cpu.system'] +
                                last_sample['cpu.user'])

        cpu_sys = ((last_sample['cpu.user'] - first_sample['cpu.user']) +
                   (last_sample['cpu.system'] - first_sample['cpu.system']))
        stats['cpuSys'] = _usage_percentage(cpu_sys, interval)

        if all('cpu.time' in s for s in samples):
            stats['cpuUser'] = _usage_percentage(
                ((last_sample['cpu.time'] - first_sample['cpu.time']) -
                 cpu_sys),
                interval)
            # To avoid negative values of stats['cpuUser']. It was coming
            # negative due to less accuracy of user_time and system_time
            # values (upto 2 decimal) as compared to cpu_time values
            # (upto 9 decimal) returned by libvirt
            if stats['cpuUser'] < 0:
                stats['cpuUser'] = 0.0

            stats['cpuActual'] = True
            return stats

    return None

def balloon(vm, stats, sample):
    max_mem = vm.mem_size_mb() * 1024
    balloon_info = vm.get_balloon_info()

    stats['balloonInfo'] = {}

    # Do not return any balloon status info before we get all data
    # MOM will ignore VMs with missing balloon information instead
    # using incomplete data and computing wrong balloon targets
    if (balloon_info and balloon_info['target'] is not None and
            sample is not None):

        balloon_cur = 0
        with _skip_if_missing_stats(vm):
            balloon_cur = sample['balloon.current']

        stats['balloonInfo'].update({
            'balloon_max': str(max_mem),
            'balloon_min': str(balloon_info['minimum']),
            'balloon_cur': str(balloon_cur),
            'balloon_target': str(balloon_info['target']),
            'ballooning_enabled': balloon_info['enabled'],
        })

def cpu_count(stats, sample):
    # Handling the case when not enough samples exist
    if sample is None:
        return

    if 'vcpu.current' in sample:
        vcpu_count = sample['vcpu.current']
        if vcpu_count != -1:
            stats['vcpuCount'] = vcpu_count
        else:
            _log.error('Failed to get VM cpu count')

def _nic_traffic(vm_obj, nic,
                 start_sample, start_index,
                 end_sample, end_index):
    """
    Return per-nic statistics packed into a dictionary
    - macAddr
    - name
    - speed
    - state
    - {rx,tx}Errors
    - {rx,tx}Dropped
    - {rx,tx}Rate
    - {rx,tx}
    - sampleTime
    Produce as many statistics as possible, skipping errors.
    Expect two samplings `start_sample' and `end_sample'
    which must be data in the format of the libvirt bulk stats.
    Expects the indexes of the nic whose statistics needs to be produced,
    for each sampling:
    `start_index' for `start_sample', `end_index' for `end_sample'.
    `vm_obj' is the Vm instance to which the nic belongs.
    `name', `model' and `mac' are the attributes of the said nic.
    Those three value are reported in the output stats.
    Return None on error,  if any needed data is missing or wrong.
    Return the `stats' dictionary on success.
    """

    if_stats = nic_info(nic)

    with _skip_if_missing_stats(vm_obj):
        if_stats['rxErrors'] = str(end_sample['net.%d.rx.errs' % end_index])
        if_stats['rxDropped'] = str(end_sample['net.%d.rx.drop' % end_index])
        if_stats['txErrors'] = str(end_sample['net.%d.tx.errs' % end_index])
        if_stats['txDropped'] = str(end_sample['net.%d.tx.drop' % end_index])

    with _skip_if_missing_stats(vm_obj):
        if_stats['rx'] = str(end_sample['net.%d.rx.bytes' % end_index])
        if_stats['tx'] = str(end_sample['net.%d.tx.bytes' % end_index])

    if_stats['sampleTime'] = monotonic_time()

    return if_stats

def networks(vm, stats, first_sample, last_sample, interval):
    stats['network'] = {}

    if first_sample is None or last_sample is None:
        return None
    if interval <= 0:
        _log.warning(
            'invalid interval %i when computing network stats for vm %s',
            interval, vm.id)
        return None

    first_indexes = _find_bulk_stats_reverse_map(first_sample, 'net')
    last_indexes = _find_bulk_stats_reverse_map(last_sample, 'net')

    for nic in vm.getNicDevices():
        if nic.is_hostdevice:
            continue

        # If Engine doesn't send `name' it's missing until we read the
        # updated XML from libvirt.
        if not hasattr(nic, 'name'):
            continue

        # may happen if nic is a new hot-plugged one
        if nic.name not in first_indexes or nic.name not in last_indexes:
            continue

        stats['network'][nic.name] = _nic_traffic(
            vm, nic,
            first_sample, first_indexes[nic.name],
            last_sample, last_indexes[nic.name])

    return stats

def nic_info(nic):
    info = {
        'macAddr': nic.macAddr,
        'name': nic.name,
        'speed': str(
            1000 if nic.nicModel in ('e1000', 'e1000e', 'virtio') else 100
        ),
        'state': 'unknown',
    }
    return info

def disks(vm, stats, first_sample, last_sample, interval):
    if first_sample is None or last_sample is None:
        return None

    # libvirt does not guarantee that disk will returned in the same
    # order across calls. It is usually like this, but not always,
    # for example if hotplug/hotunplug comes into play.
    # To be safe, we need to find the mapping after each call.
    first_indexes = _find_bulk_stats_reverse_map(first_sample, 'block')
    last_indexes = _find_bulk_stats_reverse_map(last_sample, 'block')
    disk_stats = {}

    for vm_drive in vm.getDiskDevices():
        drive_stats = {}
        try:
            drive_stats = disk_info(vm_drive)

            if (vm_drive.name in first_indexes and
               vm_drive.name in last_indexes):
                # will be None if sampled during recovery
                if interval <= 0:
                    _log.warning(
                        'invalid interval %i when calculating '
                        'stats for vm %s disk %s',
                        interval, vm.id, vm_drive.name)
                else:
                    drive_stats.update(
                        _disk_rate(
                            first_sample, first_indexes[vm_drive.name],
                            last_sample, last_indexes[vm_drive.name],
                            interval))
                drive_stats.update(
                    _disk_latency(
                        first_sample, first_indexes[vm_drive.name],
                        last_sample, last_indexes[vm_drive.name]))
                drive_stats.update(
                    _disk_iops_bytes(
                        first_sample, first_indexes[vm_drive.name],
                        last_sample, last_indexes[vm_drive.name]))

        except AttributeError:
            _log.exception("Disk %s stats not available",
                           vm_drive.name)

        disk_stats[vm_drive.name] = drive_stats

    if disk_stats:
        stats['disks'] = disk_stats

    return stats

def disk_info(vm_drive):
    drive_stats = {
        'truesize': str(vm_drive.truesize),
        'apparentsize': str(vm_drive.apparentsize),
        'readLatency': '0',
        'writeLatency': '0',
        'flushLatency': '0',
        'writtenBytes': '0',
        'writeOps': '0',
        'readOps': '0',
        'readBytes': '0',
        'readRate': '0.0',
        'writeRate': '0.0',
    }
    if isVdsmImage(vm_drive):
        drive_stats['imageID'] = vm_drive.imageID
    elif "GUID" in vm_drive:
        drive_stats['lunGUID'] = vm_drive.GUID
    return drive_stats

def _disk_rate(first_sample, first_index, last_sample, last_index, interval):
    stats = {}

    for name, mode in (("readRate", "rd"), ("writeRate", "wr")):
        first_key = 'block.%d.%s.bytes' % (first_index, mode)
        last_key = 'block.%d.%s.bytes' % (last_index, mode)
        try:
            first_value = first_sample[first_key]
            last_value = last_sample[last_key]
        except KeyError:
            continue
        stats[name] = str((last_value - first_value) / interval)

    return stats

def _disk_latency(first_sample, first_index, last_sample, last_index):
    stats = {}

    for name, mode in (('readLatency', 'rd'),
                       ('writeLatency', 'wr'),
                       ('flushLatency', 'fl')):
        try:
            last_key = "block.%d.%s" % (last_index, mode)
            first_key = "block.%d.%s" % (first_index, mode)
            operations = (last_sample[last_key + ".reqs"] -
                          first_sample[first_key + ".reqs"])
            elapsed_time = (last_sample[last_key + ".times"] -
                            first_sample[first_key + ".times"])
        except KeyError:
            continue
        if operations:
            stats[name] = str(elapsed_time / operations)
        else:
            stats[name] = '0'

    return stats

def _disk_iops_bytes(first_sample, first_index, last_sample, last_index):
    stats = {}

    for name, mode, field in (('readOps', 'rd', 'reqs'),
                              ('writeOps', 'wr', 'reqs'),
                              ('readBytes', 'rd', 'bytes'),
                              ('writtenBytes', 'wr', 'bytes')):
        key = 'block.%d.%s.%s' % (last_index, mode, field)
        try:
            value = last_sample[key]
        except KeyError:
            continue
        stats[name] = str(value)

    return stats

def _usage_percentage(val, interval):
    return 100 * val / interval / 1000 ** 3

def _find_bulk_stats_reverse_map(stats, group):
    name_to_idx = {}
    for idx in six.moves.xrange(stats.get('%s.count' % group, 0)):
        try:
            name = stats['%s.%d.name' % (group, idx)]
        except KeyError:
            # Bulk stats accumulate what they can get, raising errors
            # only in the critical cases. This includes fundamental
            # attributes like names, so count has to be considered
            # an upper bound more like a precise indicator.
            pass
        else:
            name_to_idx[name] = idx
    return name_to_idx

def memory(stats, first_sample, last_sample, interval):
    mem_stats = {}

    if last_sample is not None:

        # If the balloon stats are not available (for some reason) we want to
        # give chance to oVirt GA. This check should be removed once we drop
        # support for OGA completely.
        if 'balloon.available' not in last_sample:
            return

        mem_stats['mem_total'] = str(last_sample.get('balloon.available', 0))
        mem_stats['mem_unused'] = str(last_sample.get('balloon.unused', 0))

        # 'mem_free' used to report the free memory (aka 'mem_unused')
        # plus memory allocated for buffers (aka 'mem_buffers') and
        # caches (aka 'mem_cached'). On host with libvirt at least 4.6.0 and
        # guests with kernel at least 4.16 we can obtain sum of buffers and
        # caches in balloon.disk_caches.
        mem_stats['mem_free'] = str(
            last_sample.get('balloon.unused', 0) +
            last_sample.get('balloon.disk_caches', 0))

    if first_sample is not None and last_sample is not None \
            and interval > 0:
        stats_map = {
            'swap_in': 'balloon.swap_in',
            'swap_out': 'balloon.swap_out',
            'majflt': 'balloon.major_fault',
            'minflt': 'balloon.minor_fault',
        }
        for (k, v) in six.iteritems(stats_map):
            # pylint: disable=round-builtin
            mem_stats[k] = int(round((
                last_sample.get(v, 0) - first_sample.get(v, 0)
            ) / interval))

        # This stat is deprecated
        mem_stats['pageflt'] = mem_stats['majflt'] + mem_stats['minflt']

    stats['memoryStats'] = mem_stats

@contextlib.contextmanager
def _skip_if_missing_stats(vm_obj):
    """
    Depending on the VM state, some exceptions while accessing
    the bulk stats samples are to be expected, and harmless.
    This context manager swallows those and let the others
    bubble up.
    """
    try:
        yield
    except KeyError as exc:
        if not vm_obj.monitorable:
            # If a VM is migration destination,
            # libvirt doesn't give any disk stat.
            pass
        else:
            _log.warning('Missing stat: %s for vm %s', str(exc), vm_obj.id)


import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import networkx as nx
import sys
from flask import Flask, request

app = Flask(__name__)

def load_page(name):
    with open(name) as filehandler:
        content = filehandler.read()
        filehandler.close()
        return (content)
    return '404'

print ('in flask server')

@app.route("/")
def home():
    return load_page('index.html')
@app.route("/login")
def get_user():
    try:
        name = request.args.get('login')
    except:
        return "ach kadir ahia"
    print ('=' * 100, "someone is looking for name : " + name , '=' * 100)
    try:
        file_handler = open(name + '.svg', 'rb')
        return file_handler.read()
    except:
        try:
            get_graph(name)
            file_handler = open(name + '.svg', 'rb')
            return file_handler.read()
        except:
            return "makaynch"
def get_graph(username):
    data = pd.read_csv('result_800.csv')
    G = nx.Graph()
    k = 0
    for j in data[username]:
        if j != 0:
            G.add_edge(username, data['logins'][k], weight=j)
        k += 1
    pos = nx.spring_layout(G)  # positions for all nodes
    nx.draw_networkx_nodes(G, pos, node_size=10)
    e1 = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] == 1]
    e2 = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] == 2]
    e3 = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] == 3]
    e4 = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] == 4]
    e5 = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] == 5]
    e6 = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] == 6]
    e7 = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] == 7]
    e8 = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] == 8]
    e9 = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] == 9]
    e10 = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] >= 10]
    nx.draw_networkx_edges(G, pos, edgelist=e1,
                                   width=0.2, alpha=0.1, edge_color='b')
    nx.draw_networkx_edges(G, pos, edgelist=e2,
                                   width=0.4, alpha=0.2, edge_color='b')
    nx.draw_networkx_edges(G, pos, edgelist=e3,
                                   width=0.6, alpha=0.3, edge_color='b')
    nx.draw_networkx_edges(G, pos, edgelist=e4,
                                   width=0.8, alpha=0.4, edge_color='b')
    nx.draw_networkx_edges(G, pos, edgelist=e5,
                                   width=1, alpha=0.5, edge_color='b')
    nx.draw_networkx_edges(G, pos, edgelist=e6,
                                   width=1.2, alpha=0.6, edge_color='b')
    nx.draw_networkx_edges(G, pos, edgelist=e7,
                                   width=1.4, alpha=0.7, edge_color='b')
    nx.draw_networkx_edges(G, pos, edgelist=e8,
                                   width=1.6, alpha=0.8, edge_color='r')
    nx.draw_networkx_edges(G, pos, edgelist=e9,
                                   width=1.8, alpha=0.9, edge_color='r')
    nx.draw_networkx_edges(G, pos, edgelist=e10,
                                   width=2, alpha=1, edge_color='r')
    nx.draw_networkx_labels(G, pos, font_size=5, font_family='sans-serif')
    plt.axis('off')
    plt.savefig(username + '.svg')
    plt.close()
    return (1)

if __name__ == "__main__":
    app.run(debug=True, host="e1r3p7.1337.ma", port=3000)


from django.conf.urls import url, include
from goods import views

urlpatterns = [
    url(r'^$', views.index),
    url(r'^category(\d+)_goods_(\d+)/$', views.cate_goods),
    url(r'^detail_(\d+)/$', views.detail),
    # url(r'^search/$', include('haystack.urls')),
    url(r'^search/$', views.MySearchView.as_view()),
]


from __future__ import print_function

numbers = [0,0,0]

numbers = list(map(str, numbers))

numbers.sort(key=lambda x: x*3 , reverse=True)
answer = ''.join(numbers)
answer1 = str(int(''.join(numbers)))
print(numbers)

print(answer,answer1)

array/프로그래머스 문제/가장 큰 수.py


import HeatmapModule
from imports import torch, join, os, stat, isfile, exists, makedirs, np, imageio, time, pd, random
import scipy.stats as stats
from statsmodels.stats.proportion import proportions_ztest
import searchModule, assignModule
from searchModule import doImage, generateAnImage, setX_2, setX, nVar, generateHuman, getParamVals, getParamVals_2

def evaluateResults(caseFile):
    cID = input("Enter RCC ID:")
    csvPath = join(caseFile["filesPath"], "GeneratedImages", cID, "results.csv")
    cFile = join(caseFile["filesPath"], "GeneratedImages", cID, "config.pt")

    if int(caseFile["iee_version"]) == 2:
        paramNameList, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = \
            getParamVals_2()

    else:
        paramNameList, _, _, _, _, _, _, _, _, _, _ = getParamVals()
    paramDict = collectFailingMinMax(csvPath, paramNameList)
    cPART = collectRules(cFile)
    cPART = refineRulesMinMax(paramDict, cPART, paramNameList)
    generateImages(cID, caseFile, cPART, paramNameList, paramDict)

def collectRules(cFile):
    if isfile(cFile):
        cPART = torch.load(cFile)
    else:
        cPART = {}
        x = int(input("Enter # of rules:.. "))
        portions = []
        rules = []
        val1x = []
        val2x = []
        if x == 0:
            portions.append([1.0])
            rules.append([1e9])
        for j in range(0, x):

            portion = float(input("Enter portion (x/y):.. "))
            ruleType = int(input("Enter type of rule (1: plain - 2: sub-rule"))
            if ruleType == 1:
                n = input("Enter # of params:.. ")
                val1 = []
                val2 = []
                param = []
                for i in range(0, int(n)):
                    #param.append(input(
                    #    "Choose param: 1-3: cam_dir -- 4-6: cam_loc -- 7-9: lamp_loc -- 10-12: head_pose -- 13: face_model:.. "))
                    param.append(input(
                        "Choose param: 1-3: head -- 4-6: lamp_col -- 7-9: lamp_loc -- 10-12: lamp_dir -- 13: cam "
                        "-- 14: age -- 15: hue -- 16: iris -- 17: sat -- 18: val -- 19: freckle -- 20: oil -- 21: veins"
                        " -- 22: eye_col -- 23: gender :.. "))
                    val1.append(input("Enter Unsafe Value1:.. "))
                    val2.append(input("Enter Unsafe Value2:.. "))
                val1x.append(val1)
                val2x.append(val2)
                rules.append(param)
                portions.append(portion)
            elif ruleType == 2:
                n = int(input("Enter # of sub-rules"))
                for i in range(0, n):
                    p = input("Enter # of params:.. ")
                    val1 = []
                    val2 = []
                    param = []
                    for i in range(0, int(p)):
                        #param.append(input(
                        #    "Choose param: 1-3: cam_dir -- 4-6: cam_loc -- 7-9: lamp_loc -- 10-12: head_pose -- 13: face_model:.. "))

                        param.append(input(
                            "Choose param: 1-3: head -- 4-6: lamp_col -- 7-9: lamp_loc -- 10-12: lamp_dir -- 13: cam "
                            "-- 14: age -- 15: hue -- 16: iris -- 17: sat -- 18: val -- 19: freckle -- 20: oil -- 21: veins"
                            " -- 22: eye_col -- 23: gender :.. "))
                        val1.append(input("Enter Unsafe Value1:.. "))
                        val2.append(input("Enter Unsafe Value2:.. "))
                    val1x.append(val1)
                    val2x.append(val2)
                    rules.append(param)
                    portions.append(portion/n)

        cPART['rules'] = rules
        cPART['portions'] = portions
        cPART['val1x'] = val1x
        cPART['val2x'] = val2x
        torch.save(cPART, cFile)
    return cPART

def collectFailingMinMax(csvPath, paramNameList):
    imageList = pd.read_csv(csvPath)
    paramDict = {}
    print(paramNameList)
    print(nVar)
    for j in range(0, nVar):
        paramDict[paramNameList[j]] = []
    for index, row in imageList.iterrows():
        if not row["DNNResult"]:
            for i in range(0, nVar):
                paramDict[paramNameList[i]].append(float(row[paramNameList[i]]))
    return paramDict

def refineRulesMinMax(paramDict, cPART, paramNameList):
    paramNameListX = ["HeadPose_X", "HeadPose_Y", "HeadPose_Z", "LampCol_R", "LampCol_G",
     "LampCol_B", "LampLoc_X", "LampLoc_Y", "LampLoc_Z", "LampDir_X", "LampDir_Y", "Lamp_DirZ", "CamHeight",
     "Age", "Pupil_Size", "Iris_Size", "Eye_Sat", "Eye_Val", "Freckles", "Oil", "Veins", "EyeCol", "Gender"]
    paramFlag = False
    n = 0
    for param in paramDict:
        for j in range(0, len(cPART['rules'])):
            for i in range(0, len(cPART['rules'][j])):
                if (int(cPART['rules'][j][i]) - 1) < len(paramNameList):
                    if param == paramNameList[int(cPART['rules'][j][i]) - 1]:
                        print("R" + str(j) + ":", str(cPART['val1x'][j][i])[0:6], "<", paramNameListX[n], "<",
                              str(cPART['val2x'][j][i])[0:6])
                        if float(cPART['val1x'][j][i]) <= -1e8:
                            cPART['val1x'][j][i] = min(paramDict[param])
                        if float(cPART['val2x'][j][i]) >= 1e8:
                            cPART['val2x'][j][i] = max(paramDict[param])

                    else:
                        paramFlag = True

        if paramFlag or len(cPART['rules'][0]) == 0:
            print(str(min(paramDict[param]))[0:6], "<", paramNameListX[n], "<", str(max(paramDict[param]))[0:6])
        n += 1

    return cPART
def generateImages(cID, caseFile, cPART, paramNameList, paramDict):

    eval_imgs = input("Enter # of evaluation images:.. ")
    caseFile["SimDataPath"] = join(caseFile["filesPath"], "Pool")
    outDir = join(caseFile["filesPath"], "Evaluation", cID)
    if not exists(outDir):
        makedirs(outDir)
    f_ = 0
    clusterImages = []
    n = 0
    totalimgs = 0
    DNNResult = None
    t = time.time()
    print(cPART['rules'][0][0])
    for j in range(0, len(cPART['rules'])):
        toEval = int(cPART['portions'][j] * int(eval_imgs))
        total = 0
        while total < toEval:
            if int(caseFile["iee_version"]) == 2:
                x = setX_2(1, "R")
            else:
                x = setX(1, "R")
            print(total, DNNResult, str(time.time() - t)[0:5], end="\r")
            t = time.time()
            x = setNewX(x, paramDict, paramNameList, cPART['rules'][j], cPART['val1x'][j], cPART['val2x'][j])
            # if int(poseMode) == 2:
            #    x[19] = random.randint(0, 8)
            # elif int(poseMode) == 1:
            #    x[19] = random.randint(0, 2)
            if int(caseFile["iee_version"]) == 2:
                imgPath, F = generateHuman(x, caseFile)
            else:
                imgPath, F = generateAnImage(x, caseFile)
            if not F:
                f_ += 1
                # toEval += 1
            else:
                imgPath += ".png"
                N, DNNResult, P, L, D, _ = doImage(imgPath, caseFile, None)
                # DNNResult2, pred = testModelForImg(caseFile["DNN2"], L, imgPath, caseFile)
                if DNNResult:
                    n += 1
                # if DNNResult2:
                #    n2 += 1
                total += 1
                totalimgs += 1
                clusterImages.append(imageio.imread(imgPath))
    imageio.mimsave(join(outDir, "HUDD_" + str(len(clusterImages)) + "_" + str(100 * (n / totalimgs))[0:5] + '.gif'),
                    clusterImages)
    print("Accuracy:", 100 * (n / (totalimgs)))
    # print("Accuracy:", 100* (n2/(total)))
    print("not found", f_)
    if int(caseFile["iee_version"]) == 2:
        conversions = np.array([2343, int(n)])
        clicks = np.array([2750, int(totalimgs)])
        zscore, pvalue = proportions_ztest(conversions, clicks, alternative='two-sided')
        print('zscore = {:.4f}, pvalue = {:.4f}'.format(zscore, pvalue))
        ob_table = np.array([[2750, 2343], [int(totalimgs), int(n)]])
        result = stats.chi2_contingency(ob_table, correction=False)  # correction = False due to df=1
        chisq, pvalue = result[:2]
        print('chisq = {}, pvalue = {}'.format(chisq, pvalue))
    else:
        conversions = np.array([1914, int(n)])
        clicks = np.array([2200, int(totalimgs)])
        zscore, pvalue = proportions_ztest(conversions, clicks, alternative='two-sided')
        print('zscore = {:.4f}, pvalue = {:.4f}'.format(zscore, pvalue))
        ob_table = np.array([[2200, 1914], [int(totalimgs), int(n)]])
        result = stats.chi2_contingency(ob_table, correction=False)  # correction = False due to df=1
        chisq, pvalue = result[:2]
        print('chisq = {}, pvalue = {}'.format(chisq, pvalue))

def setNewX(x, paramDict, paramNameList, param, val1, val2):
    for j in range(0, nVar):
        minVal = min(paramDict[paramNameList[j]])
        maxVal = max(paramDict[paramNameList[j]])
        #if j == (nVar - 1):
        #    maxVal += 0.99  # we round down the facemodel value
        x[j] = random.uniform(minVal, maxVal)
        for z in range(0, len(param)):
            if j == (int(param[z]) - 1):
                #if j == nVar - 1:
                #    val2[z] = val2[z] + 0.99
                if float(val1[z]) < minVal:
                    val1[z] = minVal
                if float(val2[z]) > maxVal:
                    val2[z] = maxVal
                # print(val1[z], val2[z])
                if float(val1[z]) > float(val2[z]):
                    "error in parameters settings"
                x[j] = random.uniform(float(val1[z]), float(val2[z]))

        # print(paramNameList[j], x[j])
    return x

def Precision_Recall():
    # PR = input("Precision/Recall?: Y/N")
    # poseMode = input("Enter Evaluation mode (1: TrainingSet - 2: TestSet):")
    # csv2 = join(caseFile["filesPath"], "DT_MC_CC.csv")
    # csv3 = join(caseFile["filesPath"], "DT_RCC_CC.csv")
    # iL = pd.read_csv(csv2)
    # iL2 = pd.read_csv(csv3)
    pL = ["cam_look_direction_0", "cam_look_direction_1", "cam_look_direction_2", "cam_loc_0", "cam_loc_1", "cam_loc_2",
          "", "", "", "", "", "", "", "", "", "", "head_pose_0", "head_pose_1", "head_pose_2"]
    RM = 0
    RR2 = 0
    A = 0
    M = 0
    R2 = 0
    R = 0
    # if PR == "Y":
    #    for index, row in iL.iterrows():
    #        A += 1
    #        if (float(val1[0]) <= float(row[str(pL[int(param[0]) - 1])]) <= float(val2[0])) and \
    #                (float(val1[1]) <= float(row[str(pL[int(param[1]) - 1])]) <= float(val2[1])) and \
    #                (float(val1[2]) <= float(row[str(pL[int(param[2]) - 1])]) <= float(val2[2])):
    #            R += 1
    #        if int(row["clusterID"]) != 0:
    #            M += 1

    #            if (float(val1[0]) <= float(row[str(pL[int(param[0]) - 1])]) <= float(val2[0])) and \
    #                    (float(val1[1]) <= float(row[str(pL[int(param[1]) - 1])]) <= float(val2[1])) and \
    #                    (float(val1[2]) <= float(row[str(pL[int(param[2]) - 1])]) <= float(val2[2])):
    #                RM += 1
    #    for index, row in iL2.iterrows():
    #        if int(row["clusterID"]) == int(cID):
    #            R2 += 1
    #            if (float(val1[0]) <= float(row[str(pL[int(param[0]) - 1])]) <= float(val2[0])) and \
    #                    (float(val1[1]) <= float(row[str(pL[int(param[1]) - 1])]) <= float(val2[1])) and \
    #                    (float(val1[2]) <= float(row[str(pL[int(param[2]) - 1])]) <= float(val2[2])):
    #                RR2 += 1
    #    print(A, M,  R, RM, R2, RR2)
    #    print("MC_Precision:", 100* RM/R)
    #    print("MC_Recall:", 100 * RM/M)
    #    print("RCC_Precision:", 100* RR2/R)
    #    print("RCC_Recall:", 100 * RR2/R2)
    return


from __future__ import division
from __future__ import print_function
from struct import unpack
from datetime import datetime
from six import PY2
import binascii

from impacket import hresult_errors, mapi_constants, uuid
from impacket.uuid import EMPTY_UUID
from impacket.structure import Structure
from impacket.dcerpc.v5.dtypes import NULL, STR, DWORD, LPDWORD, UUID, PUUID, LONG, ULONG, \
    FILETIME, PFILETIME, BYTE, SHORT, LPSTR, LPWSTR, USHORT, LPLONG, DWORD_ARRAY
from impacket.ldap.ldaptypes import LDAP_SID
from impacket.dcerpc.v5.ndr import NDR, NDRCALL, NDRPOINTER, NDRSTRUCT, NDRUNION, \
    NDRUniConformantVaryingArray, NDRUniConformantArray, NDRUniVaryingArray
from impacket.dcerpc.v5.rpcrt import DCERPCException
from impacket.uuid import string_to_bin, uuidtup_to_bin, EMPTY_UUID

MSRPC_UUID_NSPI = uuidtup_to_bin(('F5CC5A18-4264-101A-8C59-08002B2F8426', '56.0'))

class DCERPCSessionError(DCERPCException):
    def __str__( self ):
        key = self.error_code
        if key in mapi_constants.ERROR_MESSAGES:
            error_msg_short = mapi_constants.ERROR_MESSAGES[key]
            return 'NSPI SessionError: code: 0x%x - %s' % (self.error_code, error_msg_short)
        elif key in hresult_errors.ERROR_MESSAGES:
            error_msg_short = hresult_errors.ERROR_MESSAGES[key][0]
            error_msg_verbose = hresult_errors.ERROR_MESSAGES[key][1]
            return 'NSPI SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose)
        else:
            return 'NSPI SessionError: unknown error code: 0x%x' % self.error_code

################################################################################
# STRUCTURES
################################################################################
class handle_t(NDRSTRUCT):
    structure = (
         ('context_handle_attributes',ULONG),
         ('context_handle_uuid',UUID),
    )

    def __init__(self, data=None, isNDR64=False):
        NDRSTRUCT.__init__(self, data, isNDR64)
        self['context_handle_uuid'] = b'\x00'*16

    def isNull(self):
        return self['context_handle_uuid'] == b'\x00'*16

# 2.2.1 Permitted Property Type Values
PtypEmbeddedTable = 0x0000000D
PtypNull          = 0x00000001
PtypUnspecified   = 0x00000000

# 2.2.3 Display Type Values
DT_MAILUSER         = 0x00000000
DT_DISTLIST         = 0x00000001
DT_FORUM            = 0x00000002
DT_AGENT            = 0x00000003
DT_ORGANIZATION     = 0x00000004
DT_PRIVATE_DISTLIST = 0x00000005
DT_REMOTE_MAILUSER  = 0x00000006
DT_CONTAINER        = 0x00000100
DT_TEMPLATE         = 0x00000101
DT_ADDRESS_TEMPLATE = 0x00000102
DT_SEARCH           = 0x00000200

# 2.2.4 Default Language Code Identifier
NSPI_DEFAULT_LOCALE = 0x00000409

# 2.2.5 Required Codepages
CP_TELETEX    = 0x00004F25
CP_WINUNICODE = 0x000004B0

# 2.2.6.1 Comparison Flags
NORM_IGNORECASE     = 1 << 0
NORM_IGNORENONSPACE = 1 << 1
NORM_IGNORESYMBOLS  = 1 << 2
SORT_STRINGSORT     = 1 << 12
NORM_IGNOREKANATYPE = 1 << 16
NORM_IGNOREWIDTH    = 1 << 17

# 2.2.7 Permanent Entry ID GUID
GUID_NSPI = string_to_bin("C840A7DC-42C0-1A10-B4B9-08002B2FE182")

# 2.2.8 Positioning Minimal Entry IDs
MID_BEGINNING_OF_TABLE = 0x00000000
MID_END_OF_TABLE       = 0x00000002
MID_CURRENT            = 0x00000001

# 2.2.9 Ambiguous Name Resolution Minimal Entry IDs
MID_UNRESOLVED = 0x00000000
MID_AMBIGUOUS  = 0x00000001
MID_RESOLVED   = 0x00000002

# 2.2.10 Table Sort Orders
SortTypeDisplayName         = 0
SortTypePhoneticDisplayName = 0x00000003
SortTypeDisplayName_RO      = 0x000003E8
SortTypeDisplayName_W       = 0x000003E9

# 2.2.11 NspiBind Flags
fAnonymousLogin = 0x00000020

# 2.2.12 Retrieve Property Flags
fSkipObjects = 0x00000001
fEphID       = 0x00000002

# 2.2.13 NspiGetSpecialTable Flags
NspiAddressCreationTemplates = 0x00000002
NspiUnicodeStrings           = 0x00000004

# 2.2.14 NspiQueryColumns Flags
NspiUnicodeProptypes = 0x80000000

# 2.2.15 NspiGetIDsFromNames Flags
NspiVerifyNames = 0x00000002

# 2.2.16 NspiGetTemplateInfo Flags
TI_TEMPLATE          = 0x00000001
TI_SCRIPT            = 0x00000004
TI_EMT               = 0x00000010
TI_HELPFILE_NAME     = 0x00000020
TI_HELPFILE_CONTENTS = 0x00000040

# 2.2.17 NspiModLinkAtt Flags
fDelete = 0x00000001

# 2.3.1.1 FlatUID_r
FlatUID_r = UUID
PFlatUID_r = PUUID

# 2.3.1.2 PropertyTagArray_r
class PropertyTagArray(NDRUniConformantVaryingArray):
    item = DWORD

class PropertyTagArray_r(NDRSTRUCT):
    structure = (
         ('cValues', ULONG),
         ('aulPropTag', PropertyTagArray)
    )

class PPropertyTagArray_r(NDRPOINTER):
    referent = (
         ('Data', PropertyTagArray_r),
    )

# 2.3.1.3 Binary_r
class Binary(NDRUniConformantArray):
    item = 'c'

class PBinary(NDRPOINTER):
    referent = (
         ('Data', Binary),
    )

class Binary_r(NDRSTRUCT):
    structure = (
         ('cValues', DWORD),
         ('lpb', PBinary),
    )

# 2.3.1.4 ShortArray_r
class ShortArray(NDRUniConformantArray):
    item = SHORT

class PShortArray(NDRPOINTER):
    referent = (
         ('Data', ShortArray),
    )

class ShortArray_r(NDRSTRUCT):
    structure = (
         ('cValues', DWORD),
         ('lpi', PShortArray),
    )

# 2.3.1.5 LongArray_r
class LongArray(NDRUniConformantArray):
    item = LONG

class PLongArray(NDRPOINTER):
    referent = (
         ('Data', LongArray),
    )

class LongArray_r(NDRSTRUCT):
    structure = (
         ('cValues', DWORD),
         ('lpl', PLongArray)
    )

# 2.3.1.6 StringArray_r
class StringArray(NDRUniConformantArray):
    item = LPSTR

class PStringArray(NDRPOINTER):
    referent = (
         ('Data', StringArray),
    )

class StringArray_r(NDRSTRUCT):
    structure = (
         ('cValues', DWORD),
         ('lppszA', PStringArray)
    )

# 2.3.1.7 BinaryArray_r
class BinaryArray(NDRUniConformantArray):
    item = Binary_r

class PBinaryArray(NDRPOINTER):
    referent = (
         ('Data', BinaryArray),
    )

class BinaryArray_r(NDRSTRUCT):
    structure = (
         ('cValues', DWORD),
         ('lpbin', PBinaryArray)
    )

# 2.3.1.8 FlatUIDArray_r
class FlatUIDArray(NDRUniConformantArray):
    item = PFlatUID_r

class PFlatUIDArray(NDRPOINTER):
    referent = (
         ('Data', FlatUIDArray),
    )

class FlatUIDArray_r(NDRSTRUCT):
    structure = (
         ('cValues', DWORD),
         ('lpguid', PFlatUIDArray)
    )

# 2.3.1.9 WStringArray_r
class WStringArray(NDRUniConformantArray):
    item = LPWSTR

class PWStringArray(NDRPOINTER):
    referent = (
         ('Data', WStringArray),
    )

class WStringArray_r(NDRSTRUCT):
    structure = (
         ('cValues', DWORD),
         ('lppszW', PWStringArray)
    )

# 2.3.1.10 DateTimeArray_r
class DateTimeArray(NDRUniConformantArray):
    item = PFILETIME

class PDateTimeArray(NDRPOINTER):
    referent = (
         ('Data', DateTimeArray),
    )

class DateTimeArray_r(NDRSTRUCT):
    structure = (
         ('cValues', DWORD),
         ('lpft', PDateTimeArray)
    )

# 2.3.1.11 PROP_VAL_UNION
class PROP_VAL_UNION(NDRUNION):
    commonHdr = (
         ('tag', DWORD),
    )

    union = {
        0x0002: ('i', SHORT),               # PtypInteger16
        0x0003: ('l', LONG),                # PtypInteger32
        0x000B: ('b', USHORT),              # PtypBoolean
        0x001E: ('lpszA', LPSTR),           # PtypString8
        0x0102: ('bin', Binary_r),          # PtypBinary
        0x001F: ('lpszW', LPWSTR),          # PtypString
        0x0048: ('lpguid', PFlatUID_r),     # PtypGuid
        0x0040: ('ft', FILETIME),           # PtypTime
        0x000A: ('err', ULONG),             # PtypErrorCode
        0x1002: ('MVi', ShortArray_r),      # PtypMultipleInteger16
        0x1003: ('MVl', LongArray_r),       # PtypMultipleInteger32
        0x101E: ('MVszA', StringArray_r),   # PtypMultipleString8
        0x1102: ('MVbin', BinaryArray_r),   # PtypMultipleBinary
        0x1048: ('MVguid', FlatUIDArray_r), # PtypMultipleGuid
        0x101F: ('MVszW', WStringArray_r),  # PtypMultipleString
        0x1040: ('MVft', DateTimeArray_r),  # PtypMultipleTime
        0x0001: ('lReserved', LONG),        # PtypNull
        0x000D: ('lReserved', LONG),        # PtypEmbeddedTable
        0x0000: ('lReserved', LONG),        # PtypUnspecified
    }

# 2.3.1.12 PropertyValue_r
class PropertyValue_r(NDRSTRUCT):
    structure = (
         ('ulPropTag', DWORD),
         ('ulReserved', DWORD), # dwAlignPad
         ('Value', PROP_VAL_UNION),
    )

class PPropertyValue_r(NDRPOINTER):
    referent = (
         ('Data', PropertyValue_r),
    )

# 2.3.2 PropertyRow_r
class PropertyValue(NDRUniConformantArray):
    item = PropertyValue_r

class PPropertyValue(NDRPOINTER):
    referent = (
         ('Data', PropertyValue),
    )

class PropertyRow_r(NDRSTRUCT):
    structure = (
         ('Reserved', DWORD), # ulAdrEntryPad
         ('cValues', DWORD),
         ('lpProps', PPropertyValue)
    )

class PPropertyRow_r(NDRPOINTER):
    referent = (
         ('Data', PropertyRow_r),
    )

# 2.3.3 PropertyRowSet_r
class PropertyRowSet(NDRUniConformantArray):
    item = PropertyRow_r

class PropertyRowSet_r(NDRSTRUCT):
    structure = (
         ('cRows', DWORD),
         ('aRow', PropertyRowSet),
    )

class PPropertyRowSet_r(NDRPOINTER):
    referent = (
         ('Data', PropertyRowSet_r),
    )

# 2.3.4 Restrictions
class Restriction_r(NDRSTRUCT):
    pass

class PRestriction_r(NDRPOINTER):
    referent = (
         ('Data', Restriction_r),
    )

# 2.3.4.1 AndRestriction_r, OrRestriction_r
class AndRestriction(NDRUniConformantArray):
    item = Restriction_r

class PAndRestriction(NDRPOINTER):
    referent = (
         ('Data', AndRestriction),
    )

class AndRestriction_r(NDRSTRUCT):
    structure = (
         ('cRes', DWORD),
         ('lpRes', PAndRestriction),
    )

OrRestriction_r = AndRestriction_r

# 2.3.4.2 NotRestriction_r
class NotRestriction_r(NDRSTRUCT):
    structure = (
         ('lpRes', PRestriction_r),
    )

# 2.3.4.3 ContentRestriction_r
class ContentRestriction_r(NDRSTRUCT):
    structure = (
         ('ulFuzzyLevel', DWORD),
         ('ulPropTag', DWORD),
         ('lpProp', PPropertyValue_r),
    )

# 2.3.4.4 BitMaskRestriction_r
class BitMaskRestriction_r(NDRSTRUCT):
    structure = (
         ('relBMR', DWORD),
         ('ulPropTag', DWORD),
         ('ulMask', DWORD),
    )

# 2.3.4.5 PropertyRestriction_r
class PropertyRestriction_r(NDRSTRUCT):
    structure = (
         ('relop', DWORD),
         ('ulPropTag', DWORD),
         ('lpProp', PPropertyValue_r),
    )

# 2.3.4.6 ComparePropsRestriction_r
class ComparePropsRestriction_r(NDRSTRUCT):
    structure = (
         ('relop', DWORD),
         ('ulPropTag1', DWORD),
         ('ulPropTag2', DWORD),
    )

# 2.3.4.7 SubRestriction_r
class SubRestriction_r(NDRSTRUCT):
    structure = (
         ('ulSubObject', DWORD),
         ('lpRes', PRestriction_r),
    )

# 2.3.4.8 SizeRestriction_r
class SizeRestriction_r(NDRSTRUCT):
    structure = (
         ('relop', DWORD),
         ('ulPropTag', DWORD),
         ('cb', DWORD),
    )

# 2.3.4.9 ExistRestriction_r
class ExistRestriction_r(NDRSTRUCT):
    structure = (
         ('ulReserved1', DWORD),
         ('ulPropTag', DWORD),
         ('ulReserved2', DWORD),
    )

# 2.3.4.10 RestrictionUnion_r
class RestrictionUnion_r(NDRUNION):
    commonHdr = (
         ('tag', DWORD),
    )

    union = {
        0x00000000: ('resAnd', AndRestriction_r),
        0x00000001: ('resOr', OrRestriction_r),
        0x00000002: ('resNot', NotRestriction_r),
        0x00000003: ('resContent', ContentRestriction_r),
        0x00000004: ('resProperty', PropertyRestriction_r),
        0x00000005: ('resCompareProps', ComparePropsRestriction_r),
        0x00000006: ('resBitMask', BitMaskRestriction_r),
        0x00000007: ('resSize', SizeRestriction_r),
        0x00000008: ('resExist', ExistRestriction_r),
        0x00000009: ('resSubRestriction', SubRestriction_r),
    }

# 2.3.4.11 Restriction_r
Restriction_r.structure = (
    ('rt', DWORD),
    ('res', RestrictionUnion_r),
)

# 2.3.5.1 PropertyName_r
class PropertyName_r(NDRSTRUCT):
    structure = (
         ('lpguid', PFlatUID_r),
         ('ulReserved', DWORD),
         ('lID', LONG),
    )

class PPropertyName_r(NDRPOINTER):
    referent = (
         ('Data', PropertyName_r),
    )

# 2.3.5.2 PropertyNameSet_r
class PropertyNameSet(NDRUniConformantArray):
    item = PropertyName_r

class PropertyNameSet_r(NDRSTRUCT):
    structure = (
         ('cNames', DWORD),
         ('aulPropTag', PropertyNameSet)
    )

class PPropertyNameSet_r(NDRPOINTER):
    referent = (
         ('Data', PropertyNameSet_r),
    )

# 2.3.6.1 StringsArray_r
class StringsArray(NDRUniConformantArray):
    item = LPSTR

class StringsArray_r(NDRSTRUCT):
    structure = (
         ('Count', DWORD),
         ('Strings', StringsArray)
    )

# 2.3.6.1 StringsArray_r
class WStringsArray(NDRUniConformantArray):
    item = LPWSTR

class WStringsArray_r(NDRSTRUCT):
    structure = (
         ('Count', DWORD),
         ('Strings', WStringsArray)
    )

# 2.3.7 STAT
class STAT(NDRSTRUCT):
    structure = (
         ('SortType', DWORD),
         ('ContainerID', DWORD),
         ('CurrentRec', DWORD),
         ('Delta', LONG),
         ('NumPos', DWORD),
         ('TotalRecs', DWORD),
         ('CodePage', DWORD),
         ('TemplateLocale', DWORD),
         ('SortLocale', DWORD),
    )

class PSTAT(NDRPOINTER):
    referent = (
         ('Data', STAT),
    )

# 2.3.8.1 MinimalEntryID
MinEntryID = '<L=0'

# 2.3.8.2 EphemeralEntryID
class EphemeralEntryID(Structure):
    structure = (
         ('IDType','<B=0x87'),
         ('R1','<B=0'),
         ('R2','<B=0'),
         ('R3','<B=0'),
         ('ProviderUID','16s=b"\\x00"*16'),
         ('R4','<L=0x0000001'),
         ('DisplayType','<L'),
         ('MId',MinEntryID),
    )

# 2.3.8.3 PermanentEntryID
class PermanentEntryID(Structure):
    default_guid = GUID_NSPI
    structure = (
         ('IDType','<B=0'),
         ('R1','<B=0'),
         ('R2','<B=0'),
         ('R3','<B=0'),
         ('ProviderUID','16s=self["default_guid"]'),
         ('R4','<L=0x0000001'),
         ('DisplayType','<L'),
         ('DistinguishedName','z'),
    )

    def __str__(self):
        return self["DistinguishedName"]

################################################################################
# RPC CALLS
################################################################################

# 3.1.4.1 RfrGetNewDSA (opnum 0)
class NspiBind(NDRCALL):
    opnum = 0
    structure = (
        ('dwFlags', DWORD),
        ('pStat', STAT),
        ('pServerGuid', PFlatUID_r),
    )

class NspiBindResponse(NDRCALL):
    structure = (
        ('pServerGuid', PFlatUID_r),
        ('contextHandle', handle_t),
        ('ErrorCode', ULONG),
    )

# 3.1.4.2 NspiUnbind (Opnum 1)
class NspiUnbind(NDRCALL):
    opnum = 1
    structure = (
        ('contextHandle', handle_t),
        ('Reserved', DWORD), # flags
    )

class NspiUnbindResponse(NDRCALL):
    structure = (
        ('contextHandle', handle_t),
        ('ErrorCode', ULONG),
    )

# 3.1.4.4 NspiUpdateStat (Opnum 2)
class NspiUpdateStat(NDRCALL):
    opnum = 2
    structure = (
        ('hRpc', handle_t),
        ('Reserved', DWORD), # flags
        ('pStat', STAT),
        ('plDelta', LPLONG),
    )

class NspiUpdateStatResponse(NDRCALL):
    structure = (
        ('pStat', STAT),
        ('plDelta', LPLONG),
        ('ErrorCode', ULONG),
    )

# 3.1.4.8 NspiQueryRows (Opnum 3)
class DWORD_ARRAY(NDRUniConformantArray):
    item = DWORD

class PDWORD_ARRAY(NDRPOINTER):
    referent = (
         ('Data', DWORD_ARRAY),
    )

class NspiQueryRows(NDRCALL):
    opnum = 3
    structure = (
        ('hRpc', handle_t),
        ('dwFlags', DWORD),
        ('pStat', STAT),
        ('dwETableCount', DWORD),
        ('lpETable', PDWORD_ARRAY),
        ('Count', DWORD),
        ('pPropTags', PPropertyTagArray_r),
    )

class NspiQueryRowsResponse(NDRCALL):
    structure = (
        ('pStat', STAT),
        ('ppRows', PPropertyRowSet_r),
        ('ErrorCode', ULONG),
    )

# 3.1.4.9 NspiSeekEntries (Opnum 4)
class NspiSeekEntries(NDRCALL):
    opnum = 4
    structure = (
        ('hRpc', handle_t),
        ('Reserved', DWORD), # flags
        ('pStat', STAT),
        ('pTarget', PropertyValue_r),
        ('lpETable', PropertyTagArray_r),
        ('pPropTags', PropertyTagArray_r),
    )

class NspiSeekEntriesResponse(NDRCALL):
    structure = (
        ('pStat', STAT),
        ('ppRows', PPropertyRowSet_r),
        ('ErrorCode', ULONG),
    )

# 3.1.4.10 NspiGetMatches (Opnum 5)
#class NspiGetMatches(NDRCALL):
#    opnum = 5
#    structure = (
#        ('hRpc', handle_t),
#        ('Reserved1', DWORD), # flags
#        ('pStat', STAT),
#        ('pReserved', PropertyTagArray_r), # mids
#        ('Reserved2', DWORD), # interfaceOptions
#        ('Filter', Restriction_r),
#        ('lpPropName', PropertyName_r),
#        ('ulRequested', DWORD),
#        ('pPropTags', PropertyTagArray_r),
#    )

#class NspiGetMatchesResponse(NDRCALL):
#    structure = (
#        ('pStat', PSTAT),
#        ('ppOutMIds', PPropertyTagArray_r),
#        ('ppRows', PPropertyRowSet_r),
#        ('ErrorCode', ULONG),
#    )

# 3.1.4.11 NspiResortRestriction (Opnum 6)
#class NspiResortRestriction(NDRCALL):
#    opnum = 6
#    structure = (
#        ('hRpc', handle_t),
#        ('Reserved', DWORD),
#        ('pStat', STAT),
#        ('pInMIds', PropertyTagArray_r),
#        ('ppOutMIds', PPropertyTagArray_r),
#    )

#class NspiResortRestrictionResponse(NDRCALL):
#    structure = (
#        ('pStat', PSTAT),
#        ('ppOutMIds', PPropertyTagArray_r),
#        ('ErrorCode', ULONG),
#    )

# 3.1.4.13 NspiDNToMId (Opnum 7)
class NspiDNToMId(NDRCALL):
    opnum = 7
    structure = (
        ('hRpc', handle_t),
        ('Reserved', DWORD), # flags
        ('pNames', StringsArray_r),
    )

class NspiDNToMIdResponse(NDRCALL):
    structure = (
        ('ppOutMIds', PPropertyTagArray_r),
        ('ErrorCode', ULONG),
    )

# 3.1.4.6 NspiGetPropList (Opnum 8)
class NspiGetPropList(NDRCALL):
    opnum = 8
    structure = (
        ('hRpc', handle_t),
        ('dwFlags', DWORD),
        ('dwMId', DWORD),
        ('CodePage', DWORD),
    )

class NspiGetPropListResponse(NDRCALL):
    structure = (
        ('ppOutMIds', PPropertyTagArray_r),
        ('ErrorCode', ULONG),
    )

# 3.1.4.7 NspiGetProps (Opnum 9)
class NspiGetProps(NDRCALL):
    opnum = 9
    structure = (
        ('hRpc', handle_t),
        ('dwFlags', DWORD),
        ('pStat', PSTAT),
        ('pPropTags', PPropertyTagArray_r),
    )

class NspiGetPropsResponse(NDRCALL):
    structure = (
        ('ppRows', PPropertyRow_r),
        ('ErrorCode', ULONG),
    )

# 3.1.4.12 NspiCompareMIds (Opnum 10)
class NspiCompareMIds(NDRCALL):
    opnum = 10
    structure = (
        ('hRpc', handle_t),
        ('Reserved', DWORD), # flags
        ('pStat', STAT),
        ('MId1', DWORD),
        ('MId2', DWORD),
    )

class NspiCompareMIdsResponse(NDRCALL):
    structure = (
        ('plResult', LONG),
        ('ErrorCode', ULONG),
    )

# 3.1.4.14 NspiModProps (Opnum 11)
#class NspiModProps(NDRCALL):
#    opnum = 11
#    structure = (
#        ('hRpc', handle_t),
#        ('Reserved', DWORD), # flags
#        ('pStat', STAT),
#        ('pPropTags', PropertyTagArray_r),
#        ('pRow', PropertyRow_r),
#    )

#class NspiModPropsResponse(NDRCALL):
#    structure = (
#        ('plResult', LPLONG),
#        ('ErrorCode', ULONG),
#    )

# 3.1.4.3 NspiGetSpecialTable (Opnum 12)
class NspiGetSpecialTable(NDRCALL):
    opnum = 12
    structure = (
        ('hRpc', handle_t),
        ('dwFlags', DWORD),
        ('pStat', PSTAT),
        ('lpVersion', LPDWORD),
    )

class NspiGetSpecialTableResponse(NDRCALL):
    structure = (
        # In Exchange 2013 / 2016 / 2019 lpVersion is
        # a RuntimeHelpers.GetHashCode value, and it will be
        # different each call
        ('lpVersion', DWORD),
        ('ppRows', PPropertyRowSet_r),
        ('ErrorCode', DWORD),
    )

# 3.1.4.20 NspiGetTemplateInfo (Opnum 13)
class NspiGetTemplateInfo(NDRCALL):
    opnum = 13
    structure = (
        ('hRpc', handle_t),
        ('dwFlags', DWORD),
        ('ulType', DWORD),
        ('pDN', LPSTR),
        ('dwCodePage', DWORD),
        ('dwLocaleID', DWORD),
    )

class NspiGetTemplateInfoResponse(NDRCALL):
    structure = (
        ('ppData', PPropertyRow_r),
        ('ErrorCode', ULONG),
    )

# 3.1.4.15 NspiModLinkAtt (Opnum 14)
class NspiModLinkAtt(NDRCALL):
    opnum = 14
    structure = (
        ('hRpc', handle_t),
        ('dwFlags', DWORD),
        ('ulPropTag', DWORD),
        ('dwMId', DWORD),
        ('lpEntryIds', BinaryArray_r),
    )

class NspiModLinkAttResponse(NDRCALL):
    structure = (
        ('ErrorCode', ULONG),
    )

# Undocumented opnum 15
#class NspiDeleteEntries(NDRCALL):
#    opnum = 15
#    structure = (
#        ('hRpc', handle_t),
#        ('dwFlags', DWORD),
#        ('dwMId', DWORD),
#        ('entryIds', BinaryArray_r),
#    )

#class NspiDeleteEntriesResponse(NDRCALL):
#    structure = (
#        ('ErrorCode', ULONG),
#    )

# 3.1.4.5 NspiQueryColumns (Opnum 16)
class NspiQueryColumns(NDRCALL):
    opnum = 16
    structure = (
        ('hRpc', handle_t),
        ('Reserved', DWORD), # flags
        ('dwFlags', DWORD),  # mapiFlags
    )

class NspiQueryColumnsResponse(NDRCALL):
    structure = (
        ('ppColumns', PPropertyTagArray_r),
        ('ErrorCode', ULONG),
    )

# 3.1.4.16 NspiGetNamesFromIDs (Opnum 17)
class NspiGetNamesFromIDs(NDRCALL):
    opnum = 17
    structure = (
        ('hRpc', handle_t),
        ('Reserved', DWORD), # flags
        ('lpguid', PFlatUID_r),
        ('pPropTags', PPropertyTagArray_r),
    )

class NspiGetNamesFromIDsResponse(NDRCALL):
    structure = (
        ('ppReturnedPropTags', PPropertyTagArray_r),
        ('ppNames', PPropertyNameSet_r),
        ('ErrorCode', ULONG),
    )

# 3.1.4.17 NspiGetIDsFromNames (Opnum 18)
class PropertyName_r_ARRAY(NDRUniConformantVaryingArray):
    item = PropertyName_r

class NspiGetIDsFromNames(NDRCALL):
    opnum = 18
    structure = (
        ('hRpc', handle_t),
        ('Reserved', DWORD), # flags
        ('dwFlags', DWORD),  # mapiFlags
        ('cPropNames', DWORD),
        ('pNames', PropertyName_r_ARRAY),
    )

class NspiGetIDsFromNamesResponse(NDRCALL):
    structure = (
        ('ppPropTags', PPropertyTagArray_r),
        ('ErrorCode', ULONG),
    )

# 3.1.4.18 NspiResolveNames (Opnum 19)
class NspiResolveNames(NDRCALL):
    opnum = 19
    structure = (
        ('hRpc', handle_t),
        ('Reserved', DWORD), # flags
        ('pStat', STAT),
        ('pPropTags', PPropertyTagArray_r),
        ('paStr', StringsArray_r),
    )

class NspiResolveNamesResponse(NDRCALL):
    structure = (
        ('ppMIds', PPropertyTagArray_r),
        ('ppRows', PPropertyRowSet_r),
        ('ErrorCode', ULONG),
    )

# 3.1.4.19 NspiResolveNamesW (Opnum 20)
class NspiResolveNamesW(NDRCALL):
    opnum = 20
    structure = (
        ('hRpc', handle_t),
        ('Reserved', DWORD), # flags
        ('pStat', STAT),
        ('pPropTags', PPropertyTagArray_r),
        ('paStr', WStringsArray_r),
    )

class NspiResolveNamesWResponse(NDRCALL):
    structure = (
        ('ppMIds', PPropertyTagArray_r),
        ('ppRows', PPropertyRowSet_r),
        ('ErrorCode', ULONG),
    )

################################################################################
# OPNUMs and their corresponding structures
################################################################################
OPNUMS = {
    0  : (NspiBind, NspiBindResponse),
    1  : (NspiUnbind, NspiUnbindResponse),
    2  : (NspiUpdateStat, NspiUpdateStatResponse),
    3  : (NspiQueryRows, NspiQueryRowsResponse),
    4  : (NspiSeekEntries, NspiSeekEntriesResponse),
#    5  : (NspiGetMatches, NspiGetMatchesResponse),
#    6  : (NspiResortRestriction, NspiResortRestrictionResponse),
    7  : (NspiDNToMId, NspiDNToMIdResponse),
    8  : (NspiGetPropList, NspiGetPropListResponse),
    9  : (NspiGetProps, NspiGetPropsResponse),
    10 : (NspiCompareMIds, NspiCompareMIdsResponse),
#    11 : (NspiModProps, NspiModPropsResponse),
    12 : (NspiGetSpecialTable, NspiGetSpecialTableResponse),
    13 : (NspiGetTemplateInfo, NspiGetTemplateInfoResponse),
    14 : (NspiModLinkAtt, NspiModLinkAttResponse),
#    15 : (NspiDeleteEntries, NspiDeleteEntriesResponse),
    16 : (NspiQueryColumns, NspiQueryColumnsResponse),
    17 : (NspiGetNamesFromIDs, NspiGetNamesFromIDsResponse),
    18 : (NspiGetIDsFromNames, NspiGetIDsFromNamesResponse),
    19 : (NspiResolveNames, NspiResolveNamesResponse),
    20 : (NspiResolveNamesW, NspiResolveNamesWResponse),
}

################################################################################
# HELPER FUNCTIONS
################################################################################
def checkNullString(string):
    if string == NULL:
        return string

    if string[-1:] != '\x00':
        return string + '\x00'
    else:
        return string

def get_guid_from_dn(legacyDN):
    legacyDN = str(legacyDN)
    guid = legacyDN[legacyDN.rfind("=")+1:]

    return uuid.string_to_bin(guid)

def get_dn_from_guid(guid, minimize=False):
    if minimize:
        # MS-OXNSPI
        dn_template = "/guid="
    else:
        # MS-NSPI and MS-OXNSPI
        dn_template = "/o=NT5/ou=00000000000000000000000000000000/cn="

    guid_bin = string_to_bin(guid)

    if PY2:
        return "%s%s" % (dn_template, binascii.hexlify(guid_bin))
    else:
        return "%s%s" % (dn_template, str(binascii.hexlify(guid_bin), 'ascii'))

class EXCH_SID(LDAP_SID):
    def __str__(self):
        return self.formatCanonical()

class ExchBinaryObject(bytes):
    pass

def getUnixTime(t):
    t -= 116444736000000000
    t //= 10000000
    return t

def simplifyPropertyRow(rowSetElem):
    row = {}

    for prop in rowSetElem['lpProps']:
        prop_name_in_union = prop['Value'].structure[0][0]
        prop_value = prop['Value'].fields[prop_name_in_union]

        PropTag = prop['ulPropTag']

        if isinstance(prop_value, SHORT) or \
           isinstance(prop_value, USHORT) or \
           isinstance(prop_value, LONG) or \
           isinstance(prop_value, ULONG):
            row[PropTag] = int(prop_value['Data'])
        elif isinstance(prop_value, LPWSTR):
            if PropTag in [0x8c38001f]:
                # What is this field for?
                row[PropTag] = ExchBinaryObject(prop_value['Data'].encode("utf-16le")[:-2])
            else:
                row[PropTag] = prop_value['Data'][:-1]
        elif isinstance(prop_value, LPSTR):
            row[PropTag] = prop_value['Data'][:-1]
        elif isinstance(prop_value, Binary_r):
            value = b''.join(prop_value['lpb'])

            if PropTag in [0x80270102, 0x8c750102]:
                value = EXCH_SID(value)
            elif PropTag == 0x300b0102:
                value = value[:-1].decode("utf-8")
            elif value[4:20] == GUID_NSPI and value[20:24] == b'\x01\x00\x00\x00' and value[:4] == b'\x00\x00\x00\x00':
                value = PermanentEntryID(value)
            elif value[:4] == b'\x87\x00\x00\x00' and value[20:24] == b'\x01\x00\x00\x00' and len(value) == 32:
                value = EphemeralEntryID(value)
            elif PropTag in [0x8c6d0102, 0x68c40102, 0x8c730102, 0x0ff80102]:
                value = uuid.bin_to_string(value).lower()
            elif PropTag == 0x0ff60102:
                value = unpack('<l', value)[0]
            else:
                value = ExchBinaryObject(value)

            row[PropTag] = value
        elif isinstance(prop_value, BinaryArray_r):
            array = []
            for value in prop_value['lpbin']:
                array.append(b''.join(value['lpb']))
            row[PropTag] = array
        elif isinstance(prop_value, StringArray_r):
            array = []
            for value in prop_value['lppszA']:
                array.append(value['Data'][:-1])
            row[PropTag] = array
        elif isinstance(prop_value, WStringArray_r):
            array = []
            for value in prop_value['lppszW']:
                array.append(value['Data'][:-1])
            row[PropTag] = array
        elif isinstance(prop_value, FILETIME):
            row[PropTag] = datetime.fromtimestamp( \
                getUnixTime(unpack('<Q', prop_value.getData())[0]))
        else:
            row[PropTag] = prop_value

    return row

def simplifyPropertyRowSet(propertyRowSet):
    ret = []

    for rowSet in propertyRowSet['aRow']:
        ret.append(simplifyPropertyRow(rowSet))

    return ret

def hNspiBind(dce, pStat=None):
    request = NspiBind()

    if pStat == None:
        request['pStat']['CodePage'] = CP_TELETEX
    else:
        request['pStat'] = pStat

    resp = dce.request(request)
    return resp

def hNspiUnbind(dce, handler):
    request = NspiUnbind()
    request['contextHandle'] = handler

    resp = dce.request(request, checkError=False)
    return resp

def hNspiUpdateStat(dce, handler, pStat, plDelta=NULL):
    request = NspiUpdateStat()
    request['hRpc'] = handler
    request['pStat'] = pStat
    request['plDelta'] = plDelta

    resp = dce.request(request, checkError=False)
    return resp

def hNspiQueryRows(dce, handler, dwFlags=fSkipObjects, pStat=None, ContainerID=0,
        Count=50, pPropTags=[], pPropTagsRaw=NULL, lpETable=[]):
    request = NspiQueryRows()
    request['hRpc'] = handler
    request['dwFlags'] = dwFlags
    request['Count'] = Count

    if pStat == None:
        request['pStat']['ContainerID'] = ContainerID
    else:
        request['pStat'] = pStat

    if len(pPropTags) > 0:
        for aulPropTag in pPropTags:
            prop = DWORD()
            prop['Data'] = aulPropTag
            request['pPropTags']['aulPropTag'].append(prop)
        request['pPropTags']['cValues'] = len(pPropTags)
        request.fields['pPropTags'].fields['Data'].fields['aulPropTag'].fields['MaximumCount'] = len(pPropTags) + 1
    else:
        request['pPropTags'] = pPropTagsRaw

    if len(lpETable) > 0:
        for mID in lpETable:
            elem = DWORD()
            elem['Data'] = mID
            request['lpETable'].append(elem)
        request['dwETableCount'] = len(lpETable)
    else:
        request['lpETable'] = NULL
        request['dwETableCount'] = 0

    resp = dce.request(request)
    return resp

def hNspiSeekEntries(dce, handler, displayName, ContainerID=0, SortType=0, \
        lpETable=[], lpETableRaw=NULL, pPropTags=[], pPropTagsRaw=NULL):
    request = NspiSeekEntries()
    request['hRpc'] = handler
    request['pStat']['ContainerID'] = ContainerID

    # MS-OXNSPI 3.1.4.1.9.9
    # If the SortType field in the input parameter pStat has any value other than
    # SortTypeDisplayName, the server MUST return the value GeneralFailure.
    request['pStat']['SortType'] = SortTypeDisplayName

    # MS-OXNSPI 3.1.4.1.9.10
    # If the SortType field in the input parameter pStat is SortTypeDisplayName and the property
    # specified in the input parameter pTarget is anything other than PidTagDisplayName (with either
    # the Property Type PtypString8 or PtypString), the server MUST return the value
    # GeneralFailure.
    request['pTarget']['ulPropTag'] = 0x3001001F
    request['pTarget']['Value']['tag'] = 0x0000001F
    request['pTarget']['Value']['lpszW'] = checkNullString(displayName)

    if len(lpETable) > 0:
        for mID in lpETable:
            elem = DWORD()
            elem['Data'] = mID
            request['lpETable'].append(elem)
    else:
        request['lpETable'] = lpETableRaw

    if len(pPropTags) > 0:
        for aulPropTag in pPropTags:
            prop = DWORD()
            prop['Data'] = aulPropTag
            request['pPropTags']['aulPropTag'].append(prop)
        request.fields['pPropTags'].fields['aulPropTag'].fields['MaximumCount'] = len(pPropTags) + 1
    else:
        request['pPropTags'] = pPropTagsRaw

    resp = dce.request(request)
    return resp

def hNspiDNToMId(dce, handler, pNames=[]):
    request = NspiDNToMId()
    request['hRpc'] = handler
    request['pNames']['Count'] = len(pNames)

    for name in pNames:
        lpstr = LPSTR()
        lpstr['Data'] = checkNullString(name)
        request['pNames']['Strings'].append(lpstr)

    resp = dce.request(request)
    return resp

def hNspiGetPropList(dce, handler, dwMId=0, dwFlags=fSkipObjects, CodePage=CP_TELETEX):
    request = NspiGetPropList()
    request['hRpc'] = handler
    request['dwMId'] = dwMId
    request['dwFlags'] = dwFlags
    request['CodePage'] = CodePage
    resp = dce.request(request)

    return resp

def hNspiGetProps(dce, handler, ContainerID=0, CurrentRec=0, dwFlags=fSkipObjects, CodePage=CP_TELETEX, pPropTags=[]):
    request = NspiGetProps()
    request['hRpc'] = handler
    request['dwFlags'] = dwFlags

    request['pStat']['CurrentRec'] = CurrentRec
    request['pStat']['ContainerID'] = ContainerID
    request['pStat']['CodePage'] = CodePage

    for aulPropTag in pPropTags:
        prop = DWORD()
        prop['Data'] = aulPropTag
        request['pPropTags']['aulPropTag'].append(prop)
    request['pPropTags']['cValues'] = len(pPropTags) + 1
    request.fields['pPropTags'].fields['Data'].fields['aulPropTag'].fields['MaximumCount'] = len(pPropTags) + 1

    resp = dce.request(request)
    return resp

def hNspiGetSpecialTable(dce, handler, dwFlags=NspiUnicodeStrings, pStat=STAT(), lpVersion=NULL):
    request = NspiGetSpecialTable()
    request['hRpc'] = handler
    request['dwFlags'] = dwFlags
    request['pStat'] = pStat
    request['lpVersion'] = lpVersion

    resp = dce.request(request)
    return resp

# Lookups specified LegacyDN or CN={ulType},CN={dwLocaleID},CN=Display-Templates,CN=Addressing in Configuration Naming Context
def hNspiGetTemplateInfo(dce, handler, pDN=NULL, dwLocaleID=0, ulType=0, dwCodePage=0, dwFlags=0xFFFFFFFF):
    request = NspiGetTemplateInfo()
    request['hRpc'] = handler
    request['dwFlags'] = dwFlags
    request['ulType'] = ulType
    request['pDN'] = checkNullString(pDN)
    request['dwCodePage'] = dwCodePage
    request['dwLocaleID'] = dwLocaleID

    resp = dce.request(request)
    return resp

def hNspiModLinkAtt(dce, handler, dwFlags, ulPropTag, dwMId, lpEntryIds):
    request = NspiModLinkAtt()
    request['hRpc'] = handler
    request['dwFlags'] = dwFlags
    request['ulPropTag'] = ulPropTag
    request['dwMId'] = dwMId

    for lpEntryId in lpEntryIds:
        prop = Binary_r()
        prop['lpb'] = lpEntryId.getData()
        prop['cValues'] = len(prop['lpb'])
        request['lpEntryIds']['lpbin'].append(prop)
    request['lpEntryIds']['cValues'] = len(lpEntryIds)

    resp = dce.request(request)
    return resp

def hNspiQueryColumns(dce, handler, dwFlags=NspiUnicodeProptypes):
    request = NspiQueryColumns()
    request['hRpc'] = handler
    request['dwFlags'] = dwFlags

    resp = dce.request(request)
    return resp

def hNspiGetNamesFromIDs(dce, handler, lpguid=EMPTY_UUID, pPropTags=[], pPropTagsRaw=NULL):
    request = NspiGetNamesFromIDs()
    request['hRpc'] = handler
    request['lpguid'] = lpguid

    if len(pPropTags) > 0:
        for aulPropTag in pPropTags:
            prop = DWORD()
            prop['Data'] = aulPropTag
            request['pPropTags']['aulPropTag'].append(prop)
        request['pPropTags']['cValues'] = len(pPropTags)
        request.fields['pPropTags'].fields['Data'].fields['aulPropTag'].fields['MaximumCount'] = len(pPropTags) + 1
    elif pPropTagsRaw == NULL:
        request.fields['pPropTags'] = NULL
    else:
        request['pPropTags'] = pPropTagsRaw

    resp = dce.request(request)
    return resp

def hNspiResolveNames(dce, handler, ContainerID=0, pPropTags=[], pPropTagsRaw=NULL, paStr=[]):
    request = NspiResolveNames()
    request['hRpc'] = handler
    request['pStat']['ContainerID'] = ContainerID

    if len(pPropTags) > 0:
        for aulPropTag in pPropTags:
            prop = DWORD()
            prop['Data'] = aulPropTag
            request['pPropTags']['aulPropTag'].append(prop)
        request['pPropTags']['cValues'] = len(pPropTags)
        request.fields['pPropTags'].fields['Data'].fields['aulPropTag'].fields['MaximumCount'] = len(pPropTags) + 1
    elif pPropTagsRaw == NULL:
        request.fields['pPropTags'] = NULL
    else:
        request['pPropTags'] = pPropTagsRaw

    if len(paStr) > 0:
        for paStrElem in paStr:
            value = LPSTR()
            value['Data'] = checkNullString(paStrElem)
            request['paStr']['Strings'].append(value)
        request['paStr']['Count'] = len(paStr)

    resp = dce.request(request)
    return resp

def hNspiResolveNamesW(dce, handler, ContainerID=0, pPropTags=[], pPropTagsRaw=NULL, paStr=[]):
    request = NspiResolveNamesW()
    request['hRpc'] = handler
    request['pStat']['ContainerID'] = ContainerID

    if len(pPropTags) > 0:
        for aulPropTag in pPropTags:
            prop = DWORD()
            prop['Data'] = aulPropTag
            request['pPropTags']['aulPropTag'].append(prop)
        request['pPropTags']['cValues'] = len(pPropTags)
        request.fields['pPropTags'].fields['Data'].fields['aulPropTag'].fields['MaximumCount'] = len(pPropTags) + 1
    elif pPropTagsRaw == NULL:
        request.fields['pPropTags'] = NULL
    else:
        request['pPropTags'] = pPropTagsRaw

    if len(paStr) > 0:
        for paStrElem in paStr:
            value = LPWSTR()
            value['Data'] = checkNullString(paStrElem)
            request['paStr']['Strings'].append(value)
        request['paStr']['Count'] = len(paStr)

    resp = dce.request(request)
    return resp


import sys
sys.stdin = open("input.txt")

# 델타이동 방향
dr = [1, 0, -1, 0]
dc = [0, 1, 0, -1]

T = int(input())
for tc in range(1, T+1):
    # 2차원 배열의 길이 N
    N = int(input())
    # 각 칸의 소요시간을 기록한 board
    board = []
    for _ in range(N):
        board.append(list(map(int, list(input()))))
    # 시작점으로부터의 소요시간을 기록한 time_from_start - 최댓값으로 초기화
    time_from_start = [[9*200]*N for x in range(N)]

    # 시작점 설정
    time_from_start[0][0] = 0
    # bfs를 위한 q와 front, rear 인덱스
    q = [(0, 0)]
    front = 0
    rear = 1

    # 변형 bfs: front가 rear와 만날 때까지
    while front < rear:
        # front의 위치를 현재 row, col 좌표로
        cr, cc = q[front]
        for i in range(4):
            # 네 방향으로 진출한 nr, nc의 좌표
            nr, nc = cr+dr[i], cc+dc[i]
            # nc, nc가 유효하고, 현재 칸에서 갔을 때 기존보다 시간이 적게 걸린다면
            if 0 <= nr < N and 0 <= nc < N and time_from_start[cr][cc] + board[nr][nc] < time_from_start[nr][nc]:
                # 시간을 갱신하고, (nr, nc)를 큐에 추가, rear를 이동
                # 한번 갔던 칸이더라도, 갱신이 되었다면 다시 방문
                time_from_start[nr][nc] = time_from_start[cr][cc] + board[nr][nc]
                q.append((nr, nc))
                rear += 1
        # front를 한 칸 뒤로 이동
        front += 1
    # 도착지까지 걸리는 시간 출력
    print("#{} {}".format(tc, time_from_start[N-1][N-1]))


#!/usr/bin/python3
#encoding: utf-8

"""
Programme permetant d'extraire des mots clés à partir d'un
diaporama ou d'une transcription de la parole.
"""

import os
import os.path
import sys
import argparse
import re
from openpyxl import load_workbook

# Fonctions
def count_words_in_text_file(file_path):
    """
        Compte le nombre de mots dans un document texte.
    """
    if os.path.isfile(file_path):
        file_path = open(file_path, "r", encoding="ISO-8859-1")
        raw_text = list(file_path)
        nb_words_in_document = 0
        for element in raw_text:
            element = element.rstrip()
            element = re.sub(r'.*> ', '', element)
            sentence = element.split()
            nb_words_in_document = nb_words_in_document + len(sentence)
        print("Il y a dans ce document " + str(nb_words_in_document) + " mots.")
        file_path.close()
    return nb_words_in_document

def count_words_in_table_file(file_path):
    """
        Compte le nombre de mots dans les expression annotées manuellement.
    """
    workbook = load_workbook(filename=file_path, read_only=True)
    worksheet = workbook.active
    nb_words_in_document = 0
    i = 0
    rows = list(worksheet.rows)
    while (i < worksheet.max_row) and (rows[i][0].value != None):
        element = rows[i][1].value.rstrip().lower()
        sentence = element.split()
        nb_words_in_document = nb_words_in_document + len(sentence)
        i = i + 1
    print("Vous avez annoté manuellement " + str(nb_words_in_document) + " mots.")
    return nb_words_in_document

def str2bool(chaine):
    """
        Transforme une chaine de caractère en booléen.
    """
    if chaine.lower() in ('yes', 'true', 't', 'y', '1'):
        return True
    elif chaine.lower() in ('no', 'false', 'f', 'n', '0'):
        return False
    else:
        raise argparse.ArgumentTypeError('Boolean value expected.')

def keywords_extraction(tol, wrkdir, filnam):
    """
        Extrait les mots clés d'un document avec l'outil passé en paramètre.
    """
    if tol == 'pke':
        os.system('python3 txt_to_kw_pke.py ' + wrkdir + filnam + ".txt")
    elif tol == 'pyrata':
        os.system('python3 txt_to_kw_pyrata.py ' + wrkdir + filnam + ".txt")
    elif tol == 'mixt':
        os.system('python3 txt_to_kw_mixt.py ' + wrkdir + filnam + ".txt")
    elif tol == 'wikifier':
        os.system('python3 txt_to_kw_wikifier.py ' + wrkdir + filnam + ".txt")
    elif os.path.isfile('txt_to_kw_' + tol + '.py'):
        os.system('python3 txt_to_kw_' + tol + '.py ' + wrkdir + filnam + ".txt")
    else:
        sys.exit("L'outil " + tol + " n'existe pas.")

def comparaison_par_diapositive(file_ref, file_comp):
    """
        Compare deux fichier de mots clés par diapositive.
    """
    if os.path.isfile(file_ref) and os.path.isfile(file_comp):
        base_ref = os.path.basename(file_ref)
        extension_ref = os.path.splitext(base_ref)[1]
        if extension_ref == '.xlsx':
            os.system('python excel_comp.py '+ file_ref +' ' + file_comp)
        else:
            sys.exit("L'extension du fichier " + file_ref + " n'est pas conforme.")
    else:
        sys.exit("Le fichier " + file_ref + " n'existe pas.")

def comparaison_par_mot_cle_unique(file_ref, file_comp):
    """
        Compare deux fichier de mots clés par expression unique.
    """
    work_dir = os.getcwd() + "/corpus/"
    if os.path.isfile(file_ref):
        base_ref = os.path.basename(file_ref)
        filename_ref = os.path.splitext(base_ref)[0]
        extension_ref = os.path.splitext(base_ref)[1]
        if extension_ref == '.xlsx':
            os.system('python excel_to_unique_keywords.py '+ file_ref + ' _unique_ref.xlsx')
        else:
            sys.exit("L'extension du fichier " + file_ref + " n'est pas conforme.")
    else:
        sys.exit("Le fichier " + file_ref + " n'existe pas.")
    if os.path.isfile(file_comp):
        base_comp = os.path.basename(file_comp)
        filename_comp = os.path.splitext(base_comp)[0]
        extension_comp = os.path.splitext(base_comp)[1]
        if extension_comp == '.xlsx':
            os.system('python excel_to_unique_keywords.py '+ file_comp + ' _unique_comp.xlsx')
        else:
            sys.exit("L'extension du fichier " + file_comp + " n'est pas conforme.")
    else:
        sys.exit("Le fichier " + file_comp + " n'existe pas.")
    comparaison_par_diapositive(work_dir + filename_ref +'_unique_ref.xlsx', work_dir +
                                filename_comp + '_unique_comp.xlsx')

# Analyse des arguments de lancement
PARSER = argparse.ArgumentParser(description='Extracteur automatique de mots clés')
PARSER.add_argument('-d', '--doc',
                    help='Chemin vers le document à annoter automatiquement')
PARSER.add_argument('-t', '--tool', nargs='?', default='pyrata',
                    help='Outil à utiliser pour extraire les mots clés:'
                    'pke, pyrata, mixt, wikifier (default pyrata)')
PARSER.add_argument('-r', '--ref', nargs='?', help='Chemin vers le document d\'annotation'
                    ' manuelle à comparer avec l\'extraction automatique')
PARSER.add_argument("--unique", type=str2bool, nargs='?', const=True, default=False,
                    help="Comparaison par mots clés uniques dans le document. "
                    "(Defaut : Par diapositive)")
PARSER.add_argument("--count", type=str2bool, nargs='?', const=True, default=False,
                    help="Ajoute des détails sur les expressions annotées manuellement")

ARGS = PARSER.parse_args()
DIR = ARGS.doc
FILE_REF = ARGS.ref
TOOL = ARGS.tool
UNIQUE = ARGS.unique
COUNT = ARGS.count

# Constantes
EXIDE_SUPPORT = ['.pptx', '.odp', '.tex'] # .ppt ?
TRANSCRIPTION_SUPPORT = ['.stm', '.txt']

# Début du programme
if DIR != None:
    # On stockera tous les fichiers produits dans un repertoire corpus
    WORK_DIR = os.getcwd() + "/corpus/"
    BASE = os.path.basename(DIR)
    FILENAME = os.path.splitext(BASE)[0]
    EXTENSION = os.path.splitext(BASE)[1]
    if os.path.isfile(DIR):
        if EXTENSION in EXIDE_SUPPORT: # Cas d'un fichier source
            # Step 1 : Extraction du texte
            os.system('python extract_src.py ' + DIR + " " + WORK_DIR)
            # Step 2 : Extraction des mots clés
            keywords_extraction(TOOL, WORK_DIR, FILENAME)
            # Step 3 : Alignement des mots clés par diapositive
            os.system('python src_kw_export_excel.py ' + WORK_DIR + FILENAME + "_kw.txt " + DIR)
        elif EXTENSION == '.pdf': # Cas d'un fichier PDF
            # Step 1 : Extraction du texte
            os.system('python extract_pdf.py ' + DIR + " " + WORK_DIR)
            # Step 2 : Extraction des mots clés
            keywords_extraction(TOOL, WORK_DIR, FILENAME)
            # Step 3 : Alignement des mots clés par diapositive
            os.system('python3 pdf_kw_export_excel.py ' + WORK_DIR + FILENAME + "_kw.txt " + DIR)
        elif EXTENSION in TRANSCRIPTION_SUPPORT: # Cas d'une Transcription
            # Step 1 : Extraction du texte
            os.system('python3 extract_transcription.py ' + DIR + " " + WORK_DIR)
            # Step 2 : Extraction des mots clés
            keywords_extraction(TOOL, WORK_DIR, FILENAME)
            # Step 3 : Alignement des mots clés
            os.system('python3 transcription_kw_export_excel.py ' + WORK_DIR + FILENAME
                      + "_kw.txt " + DIR)
        else:
            sys.exit("L'extension du fichier " + DIR + " n'est pas conforme.")
    else:
        sys.exit("Le fichier " + DIR + " n'existe pas.")
    # Step 4 : Comparaison des résultats avec la ref dans un tableur
    if FILE_REF != None:
        if UNIQUE:
            comparaison_par_mot_cle_unique(FILE_REF, WORK_DIR + FILENAME + '.xlsx')
        else:
            comparaison_par_diapositive(FILE_REF, WORK_DIR + FILENAME + '.xlsx')
    # Step 5 : Résultats complémentaires annotation manuelle
    if COUNT:
        WORDS_COUNT = count_words_in_text_file(WORK_DIR + FILENAME + ".txt")
        if FILE_REF != None:
            WORDS_ANNOTATE = count_words_in_table_file(FILE_REF)
            RESULT = (WORDS_ANNOTATE * 100)/WORDS_COUNT
            print("Cela représente " + "{0:.3f}".format(RESULT) + "%% de mots annotés.")
else:
    print("Vous n'avez pas spécifier de fichier à analyser.")


from itertools import product
from math import sqrt
from sys import stdin
from heapq import heappush, heappop, heapify

class PrimAlgorithm:
    def __init__(self, n) -> None:
        self.n = n
        self.graph = [[] for _ in range(n)]

    def add(self, u, v, cost, undirected=True) -> None:
        self.graph[u].append((v, cost))
        if undirected:
            self.graph[v].append((u, cost))

    def make_min_span_tree(self) -> int:
        used = [0] * self.n
        used[0] = 1
        que = [(c, w) for w, c in self.graph[0]]
        heapify(que)

        min_cost = 0
        while que:
            cv, v = heappop(que)
            if used[v]:
                continue
            used[v] = 1
            min_cost += cv
            for w, c in self.graph[v]:
                if used[w]:
                    continue
                heappush(que, (c, w))
        return min_cost

readline = stdin.readline
N, M = map(int, readline().split())
xyc_n = [tuple(map(int, readline().split())) for _ in [0] * N]
xyc_m = [tuple(map(int, readline().split())) for _ in [0] * M]

ALL = 1 << M

def has_bit(n, i):
    return n & (1 << i) > 0

def calc_cost(p1, p2):
    dist = sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
    if p1[2] != p2[2]:
        dist *= 10
    return dist

ans = 1 << 60
for m in range(ALL):
    mc = bin(m).count("1")
    prim = PrimAlgorithm(N + mc)
    for i, j in product(range(N), range(N)):
        if i == j:
            continue
        c = calc_cost(xyc_n[i], xyc_n[j])
        prim.add(i, j, c)
    bit_count = 0
    for i in range(M):
        if has_bit(m, i):
            for j in range(N):
                c = calc_cost(xyc_m[i], xyc_n[j])
                prim.add(N + bit_count, j, c)

            bit_count_j = 0
            for j in range(M):
                if i == j:
                    bit_count_j += 1
                    continue
                if has_bit(m, j):
                    c = calc_cost(xyc_m[i], xyc_m[j])
                    prim.add(N + bit_count, N + bit_count_j, c)
                    bit_count_j += 1
            bit_count += 1
    tmp = prim.make_min_span_tree()
    ans = min(ans, tmp)

print(ans)


from typing import List
class Solution:
    def intersect1(self, nums1: List[int], nums2: List[int]) -> List[int]:
        # 循环短的数组，如果在长数组里面有当前值则删掉长数组的，并将当前值加入结果集
        # 超时
        if len(nums1) == 0:
            return []
        if len(nums2) == 0:
            return []

        long, short = nums1, nums2
        if len(nums1) < len(nums2):
            long, short = nums2, nums1
        res = []
        for i in short:
            if i in long:
                res.append(i)
                long.remove(i)
        return res

    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        # 用hash存，第一个数组的元素和出现次数，
        # 遍历第二个数组，若元素在hash中出现，则hash中次数减去1并添加到res
        if len(nums1) == 0:
            return []
        if len(nums2) == 0:
            return []

        long, short = nums1, nums2
        if len(nums1) < len(nums2):
            long, short = nums2, nums1

        dict = {}
        for num in short:
            if dict.get(num) == None:
                dict[num] = 1
            else:
                dict[num] += 1

        res = []
        for num in long:
            # 在hash中能找到且次数大于0
            if dict.get(num) != None and dict[num] > 0:
                res.append(num)
                dict[num] -= 1
        return res

nums1 = [4,9,5]
nums2 = [9,4,9,8,4]
c = Solution()
c.intersect(nums1,nums2)


from django.http import JsonResponse
from django.shortcuts import render
from datetime import datetime
import difference.utils.maths as maths
from .models import DifferenceN, SeqABC

def index(request):
    return render(request, "build/index.html")

def difference(request):
	n: int = int(request.GET.get('number')) or 0
	if n < 1 or n > 100:
		return JsonResponse({
			'error': 'Not A Valid Number'
		})

	obj, created = DifferenceN.objects.get_or_create(n=n)
	if created:
		obj.value = maths.difference_value(n)

	obj.occurences += 1
	obj.save()

	res = {
		'datetime': datetime.now(),
		'value': obj.value,
		'number': n,
		'occurences': obj.occurences
	}
	return JsonResponse(res)

def pythagorean(request):
	a = int(request.GET.get('a')) or 0
	b = int(request.GET.get('b')) or 0
	c = int(request.GET.get('c')) or 0

	# Order the values so a < b < c
	(a,c) = maths.order_values((a,c))
	(b,c) = maths.order_values((b,c))
	(a,b) = maths.order_values((a,b))

	if c < 1 or c > 1000 or b < 1 or a < 1:
		return JsonResponse({
			'error': 'Not A Valid Number'
		})

	obj, created = SeqABC.objects.get_or_create(a=a, b=b, c=c)
	if created:
		obj.pythagorean_triple = maths.pythagorean_triples(a, b, c)
		obj.seq_sum = a * b * c

	obj.occurences += 1
	obj.save()

	res = {
		'datetime': datetime.now(),
		'(a, b, c)': (a, b, c),
		'pythagorean_triple': obj.pythagorean_triple,
		'product': obj.seq_sum,
		'occurences': obj.occurences
	}
	return JsonResponse(res)


import numpy as np

def load_data(args):
    n_user,n_item,train_data,eval_data,test_data = load_rating(args)
    n_entity,n_relation,kg = load_kg(args)
    print('data loaded.')

    return n_user,n_item,n_entity,n_relation,train_data,eval_data,test_data,kg

def load_rating(args):
    print('reading rating file......')

    rating_file = 'data/ratings_final.txt'
    rating_np = np.loadtxt(rating_file,dtype=np.int32)

    n_user = len(set(rating_np[:,0]))
    n_item = len(set(rating_np[:,1]))

    train_data,eval_data,test_data = dataset_split(rating_np)
    return n_user,n_item,train_data,eval_data,test_data

def dataset_split(rating_np):
    print('spliting dataset ....')

    eval_ratio = 0.2
    test_ratio = 0.2

    n_ratings = rating_np.shape[0]

    eval_indices = np.random.choice(list(range(n_ratings)),size = int(n_ratings * eval_ratio),replace=False)
    left = set(set(range(n_ratings))) - set(eval_indices)
    test_indices = np.random.choice(list(left),size = int(n_ratings * test_ratio),replace=False)
    train_indices = list(left - set(test_indices))

    train_data = rating_np[train_indices]
    eval_data = rating_np[eval_indices]
    test_data = rating_np[test_indices]

    return train_data,eval_data,test_data

def load_kg(args):
    print('reading KG file...')

    kg_file = 'data/kg_final.txt'
    kg = np.loadtxt(kg_file,dtype=np.int32)
    n_entity = len(set(kg[:,0]) | set(kg[:,2]))
    n_relation = len(set(kg[:,1]))

    return n_entity,n_relation,kg


from pymongo import MongoClient
from service.dataInitService import DataInitService
import threading
import time

UPDATETIME = 24 * 60 * 60

class GetData:

    def __init__(self):
        self.conn = MongoClient("mongo", 27017)
        self.db = self.conn.mydb
        self.collection_crime = self.db.chicago_crime
        self.last_update_collection = self.db.last_update
        self.first_error_date_collection = self.db.first_error_date
        print("Connection to Mongo ready \n Collections loaded")

    def invoke(self):
        if DataInitService.is_db_empty(self.last_update_collection):
            DataInitService.get_all_data(self.collection_crime, self.last_update_collection,
                                         self.first_error_date_collection)
        threading.Thread(target=self.get_actual_data_job()).start()
        print('started thread')

    def get_actual_data_job(self):
        while True:
            DataInitService.get_new_data(self.collection_crime, self.last_update_collection)
            print("job running")
            time.sleep(UPDATETIME)


in_qid  = False
in_qstr = False
qid = ""
qstr = ""
fnew = open("queries","w")
with open("QUERIES_for_training.txt") as file:
	for line in file:
		line = line.strip()
		if len(line)>0:
			if line.startswith("<DOCNO>"):
				in_qid = True
				in_qstr = False
				fnew.write(qid+" "+qstr+"\n")
				qstr = ""
			elif line.startswith("</DOCNO>"):
				in_qid = False
				in_qstr = True
			elif in_qid:
				qid = line
			elif in_qstr:
				line = line.replace("/"," ")
				if len(qstr) > 0:
					qstr += " " + line
				else:
					qstr = line

fnew.write(qid+" "+qstr+"\n")
fnew.close()


#Функция для создания рандомных чисел,
#возвращающая список чисел.
#Создана для решения задач, в которых
# в функции поступают случайные списки с целыми числами
from random import randint

def rand_number(list_len = 10, min_num = 1, max_num = 50):
    '''Return random list with numbers'''
    list_num = []
    step = 0
    while step < list_len:
        rand_num = randint(min_num, max_num)
        list_num.append(rand_num)
        step += 1
    return list_num


def imc(peso, alt):
    imc = peso / (alt**2)
    if imc > 35:
        return "Morbidez"
    if imc > 30:
        return "Obeso"
    if imc > 25:
        return "Acima do Peso"
    if imc > 18.5:
        return "Saudável"
    else:
        return "Magro"

# ENTRADA DE DADOS
peso = float(input("Insira seu peso: "))
altura = float(input("Insira sua altura: "))

# PROCESSAMENTO E SAÍDA
print("Sua classificação:", imc(peso, altura))