from __future__ import print_function
import os
import argparse
import torch
import json
import csv
import shutil
import torch.backends.cudnn as cudnn
import numpy as np
from data import cfg_mnet, cfg_re50, cfg_mnet_highway
from layers.functions.prior_box import PriorBox
from utils.nms.py_cpu_nms import py_cpu_nms
import cv2
# from models.retinaface_highway import RetinaFace
from utils.box_utils import decode, decode_landm
from utils.timer import Timer
from utils.model_parse import  mask_decorater
from utils.filter_pruner import filter_pruner
from utils.graph_from_trace import VisualGraph

parser = argparse.ArgumentParser(description='Retinaface')
parser.add_argument('-m', '--trained_model', default='./weights/mobilenet0.25_Final.pth')
parser.add_argument('--network', default='mobile0.25', help='Backbone network mobile0.25, resnet50, or mobile0.25_highway')
parser.add_argument('--cpu', action="store_true", default=False, help='Use cpu inference')
# parser.add_argument('--sparsity_file', required=True, help='config file for the pruner')
args = parser.parse_args()

if args.network == 'mobile0.25_highway':
    args.trained_model = './weights/scratch_epoch_250.pth.tar'

cfg = None
if args.network == "mobile0.25":
    cfg = cfg_mnet
elif args.network == "resnet50":
    cfg = cfg_re50
elif args.network == "mobile0.25_highway":
        cfg = cfg_mnet_highway

def check_keys(model, pretrained_state_dict):
    ckpt_keys = set(pretrained_state_dict.keys())
    model_keys = set(model.state_dict().keys())
    used_pretrained_keys = model_keys & ckpt_keys
    unused_pretrained_keys = ckpt_keys - model_keys
    missing_keys = model_keys - ckpt_keys
    print('Missing keys:{}'.format(len(missing_keys)))
    print('Unused checkpoint keys:{}'.format(len(unused_pretrained_keys)))
    print('Used keys:{}'.format(len(used_pretrained_keys)))
    assert len(used_pretrained_keys) > 0, 'load NONE from pretrained checkpoint'
    return True

def remove_prefix(state_dict, prefix):
    ''' Old style model is stored with all names of parameters sharing common prefix 'module.' '''
    print('remove prefix \'{}\''.format(prefix))
    f = lambda x: x.split(prefix, 1)[-1] if x.startswith(prefix) else x
    return {f(key): value for key, value in state_dict.items()}

def load_model(model, pretrained_path, load_to_cpu):
    print('Loading pretrained model from {}'.format(pretrained_path))
    if load_to_cpu:
        pretrained_dict = torch.load(pretrained_path, map_location=lambda storage, loc: storage)
    else:
        device = torch.cuda.current_device()
        pretrained_dict = torch.load(pretrained_path, map_location=lambda storage, loc: storage.cuda(device))
    if "state_dict" in pretrained_dict.keys():
        pretrained_dict = remove_prefix(pretrained_dict['state_dict'], 'module.')
    else:
        pretrained_dict = remove_prefix(pretrained_dict, 'module.')
    check_keys(model, pretrained_dict)
    model.load_state_dict(pretrained_dict, strict=False)
    return model

def forward_hook(module, inputs, output):
    if hasattr(module, 'flops'):
        return
    input=inputs[0]
    g = module.groups
    n, c, _, _ = input.size()
    _, _, h,w= output.size()
    k1, k2 = module.kernel_size
    flops = (1*c*k1*k2 ) * h * w * module.out_channels / g
    module.flops = flops

def get_flops(net, data):
    Flops = {}
    total_flops = 0
    for name, layer in net.named_modules():
        if isinstance(layer, torch.nn.Conv2d):
            layer.register_forward_hook(forward_hook)
    net(data)
    for name, layer in net.named_modules():
        if isinstance(layer, torch.nn.Conv2d):
            total_flops += layer.flops
            Flops[name] = layer.flops
    print('TOTAL FLOPS', total_flops)
    return Flops

def load_sparsity(filepath):
    jf = open(filepath, 'r')
    tmp_cfg = json.load(jf)
    jf.close()
    for c in json.loads(tmp_cfg["config_list"]):
        print(c['op_names'][0])
        print(c['sparsity'])
        prune_cfg[c['op_names'][0]] = 1.0 - c['sparsity']

def flops_traverse(node, ratio):
    #print(node)
    if node in gf.c2py and gf.c2py[node].isOp and node.kind()=='aten::_convolution':
        # print(node)
        name = gf.c2py[node].name
        if name not in in_prune_ratio:
            in_prune_ratio[name] = ratio
        else:
            in_prune_ratio[name] = max(ratio, in_prune_ratio[name])
        ratio = 1.0
        if name in prune_cfg:
            ratio = prune_cfg[name]
    if node in gf.forward_edge:
        for _next in gf.forward_edge[node]:
            flops_traverse(_next, ratio)

if __name__ == '__main__':
    performances = {}
    flops = {}

    sparsities = [0.1, 0.3, 0.5, 0.7, 0.9]
    pruners = ['NetAdaptPruner005', 'SimulatedAnnealingPruner']
    for pruner in pruners:
        performances[pruner] = []
        flops[pruner] = []
        for sparsity in sparsities:
            with open(os.path.join('experiment_data/archive640/', pruner, str(sparsity).replace('.', ''), 'performance.json'), 'r') as jsonfile:
                performance = json.load(jsonfile)
                performances[pruner].append(performance['finetuned'])

            sparsity_file = os.path.join('experiment_data/archive640/', pruner, str(sparsity).replace('.', ''), 'search_result.json')

            # FLOPS calc
            # load pre-trained model
            if args.network == "mobile0.25":
                from models.retinaface import RetinaFace
            elif args.network == "mobile0.25_highway":
                from models.retinaface_highway import RetinaFace
            net = RetinaFace(cfg=cfg)
            net = load_model(net, args.trained_model, args.cpu)

            print('Finished loading model!')
            #print(net)
            cudnn.benchmark = False
            device = torch.device("cpu" if args.cpu else "cuda")
            net = net.to(device)
            # data = torch.rand(1, 3, 560, 1024)
            data = torch.rand(1,3, 640, 480)
            data = data.to(device)
            gf = VisualGraph(net,data)
            FLOPS = get_flops(net, data)
            pruned_flops = 0.0
            visited = set()
            in_prune_ratio = {}
            prune_cfg = {}

            load_sparsity(sparsity_file)
            for input in gf.graph.inputs():
                if input.type().kind() == 'ClassType':
                    continue
                flops_traverse(input, 1.0)
            for name in FLOPS:
                #print(prune_cfg[name])
                #print(in_prune_ratio.keys())
                remained = 1.0
                if name in prune_cfg:
                    remained = prune_cfg[name]
                # print(name)
                if name not in in_prune_ratio:
                    in_prune_ratio[name] = 1
                pruned_flops += FLOPS[name] * remained * in_prune_ratio[name]

            flops[pruner].append(int(pruned_flops))

    for pruner in pruners:
        with open(os.path.join('experiment_data/flops_{}.csv'.format(pruner)), 'w+') as csvfile:
            writer = csv.writer(csvfile)
            writer.writerow(['accuracy', 'flops', 'sparsity'])
            for idx, performance in enumerate(performances[pruner]):
                writer.writerow([performance, flops[pruner][idx], sparsities[idx]])


from flask import Flask, request

app = Flask(__name__)
app.config['DEBUG'] = True

form="""
<!doctype html>

        <form action = "/hello" method="post">
            First Name:
            <input id="first-name" type="text" name="first_name" />
            <input type ="submit" />

        </form>

"""

@app.route("/")
def index():
    return form

@app.route("/hello", methods=["POST"])
def hello():
    first_name = request.form['first_name']
    return '
Hello, ' + first_name + '
'

app.run()


# 모든 도로의 거리가 1이므로 BFS 접근
from collections import deque
N, M, K, X= map(int, input().split())
graph=[[0]*(N+1) for _ in range(N+1)]
for i in range(M):
    A, B = map(int, input().split())
    graph[A][B]=graph[B][A]=1

def bfs(start, min, count):
    visited=[start]
    queue=deque([start])

    while queue:
        n=queue.popleft()
        count+=1
        for c in range(len(graph[start])):
            if graph[n][c]==1 and (c not in visited):
                visited.append(c)
                queue.append(c)
                if min[c]<count:
                    min[c]=count
    return min
result=bfs(X, [0]*(N+1), 0)
for i in range(1, N+1):
    if result[i]==K:
        print(i)
if K not in result:
    print("-1")
# print(result)

특정거리의도시찾기.py


from openpyxl import load_workbook
from .classes import *
from datetime import datetime

def read_workbook(wb):
    sheet = wb.active
    data = sheet.iter_rows()
    return data

def insert_data(rows):
    data = []

    for row in rows:
        data.append(Record(row[0].value, row[1].value, row[3].value))

    return [x for x in data if x.date is not None]

def calculate_date(data, given_date):
    index, current = get_current(data)
    date_pairs = []

    for record in data[index:]:
        # only consider the case in Canada
        if record.location != "Canada":
            continue

        # handle new in and out cycle
        if record.type == "In":
            current = record
            continue

        # handle current cycle
        if (current is not None) and (record.type == "Out"):
            date_pairs.append({"In": current.date, "Out": record.date})
            current = None

    date_pairs.append({"In": current.date, "Out": given_date})

    return get_result(date_pairs)

def get_result(data):
    result = 0
    last_out = None
    for item in data:
        placeholder = 1
        if item["In"] == last_out:
            placeholder = 0

        duration = (item["Out"] - item["In"]).days + placeholder
        result += duration
        last_out = item["Out"]

    return result

def get_current(data):
    for index, record in enumerate(data):
        if (record.type == "In") and (record.location == "Canada"):
            return index, record

    return -1, None

def get_given_date():
    while True:
        input_date = input("Please enter given date in format 'mm/dd/yyyy':  ")
        if validate_date(input_date):
            return datetime.strptime(input_date, '%m/%d/%Y')

def validate_date(d):
    try:
        if len(d) == 10:
            datetime.strptime(d, '%m/%d/%Y')
            return True
        else:
            print("Input is Invalid, please input again")
            return False

    except ValueError:
        print("Input is Invliad, please input again")
        return False

def get_file():
    while True:
        try:
            filename = input("Please enter the .xlsx data file")
            # return load_workbook("test.xlsx")
            return load_workbook(filename)

        except FileNotFoundError:
            print("File is not found, please check your file path and enter again")


from django.test import TestCase
from django.core.exceptions import ValidationError
from django.db import transaction, IntegrityError
from myhpom.models import State, StateRequirementLink

class StateRequirementLinkTestCase(TestCase):
    """
    * cannot create without required fields: requirement, text, href (all non-blank)
    """

    def test__valid_create(self):
        req = State.objects.get(name='NC').staterequirement_set.first()
        valid_data = {'requirement': req, 'text': 'Why?', 'href': 'http://example.com/because'}
        StateRequirementLink.objects.create(**valid_data)

    def test__invalid_create(self):
        req = State.objects.get(name='NC').staterequirement_set.first()
        valid_data = {'requirement': req, 'text': 'Why?', 'href': 'http://example.com/because'}

        for key in ['text', 'href']:
            data = {k: v for k, v in valid_data.items() if k != key}  # missing each key
            with transaction.atomic():
                with self.assertRaises(ValidationError):
                    StateRequirementLink.objects.create(**data)

        data = {k: v for k, v in valid_data.items() if k != 'requirement'}
        with transaction.atomic():
            with self.assertRaises(IntegrityError):
                StateRequirementLink.objects.create(**data)


from django.utils import timezone
from .models import Post, SiteSettings
from django.shortcuts import render, get_object_or_404, redirect
from .forms import SiteSettingsForm, UploadHeaderImageForm
from django.contrib.auth.decorators import login_required
from django.urls import reverse
from django.http import HttpResponseForbidden, HttpResponseNotFound, Http404, HttpResponse, JsonResponse
from tagging.models import Tag, TaggedItem
from django.conf import settings
from django.core.files.storage import FileSystemStorage
from django.core.paginator import Paginator, EmptyPage
from django.core.files import File
from django.db.models import Q
from django.utils.html import escape
import urllib
import os
import operator
import time
from functools import reduce
from django.utils.translation import ugettext_lazy as _

def post_list(request, page=1, query=False, type=False, tag=False):
    site = SiteSettings.get_solo()
    posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('-published_date')
    page_title = site.title
    paged_url = 'posts_list_paged'
    tag_name = ''

    if query:
        page_title = _('Searching %s') % '«'+escape(query)+'»'
        query_list = query.split()
        posts = posts.filter(
            reduce(operator.and_,
                    (Q(title__contains=q) for q in query_list)) |
            reduce(operator.and_,
                   (Q(html__contains=q) for q in query_list))
        )

    if(type == 'featured'):
        posts = posts.filter(is_starred=True)
        page_title = _('Featured posts')
        paged_url = 'posts_list_featured_paged'

    if (type == 'drafts'):
        posts = Post.objects.filter(published_date=None).order_by('-created_date')
        page_title = _('Drafts')
        paged_url = 'posts_list_drafts_paged'

    if(tag):
        rq_tag = Tag.objects.get(name=tag)
        posts = TaggedItem.objects.get_by_model(Post, rq_tag).filter(published_date__lte=timezone.now()).order_by('-published_date')
        page_title = _('Tagged %s') % '«'+rq_tag.name+'»'
        paged_url = 'tagged_posts_paged'
        tag_name = rq_tag.name

    paginator = Paginator(posts, settings.POSTS_PER_PAGE)
    try:
        current_page = paginator.page(page)
    except EmptyPage:
        raise Http404
    return render(request, 'blog/post_list.html', {'title': page_title, 'page': current_page, 'url_paged': paged_url, 'tag': tag_name})

def post_detail(request, postURL):
    post = get_object_or_404(Post, url=postURL)
    if post.published_date == None and not request.user.is_authenticated:
        raise Http404
    return render(request, 'blog/show_post.html', {'post': post})

def tags_list(request):
    return render(request, 'blog/tags.html')

@login_required(login_url='/admin/')
def post_editor(request, postURL=None):
    if(postURL):
        post = get_object_or_404(Post, url=postURL)
        return render(request, 'blog/editor.html', {'post': post, 'tags': post.getTags(True), 'title': post.title})
    else:
        return render(request, 'blog/editor.html', {'title': 'New post'})

@login_required(login_url='/admin/')
def post_manage(request):
    if request.method == "POST":

        if request.POST.get('id', False): # Post exists, edit it!
            post = get_object_or_404(Post, pk=request.POST.get('id'))
            post.content = request.POST.get('content', '')
            post.title = request.POST.get('title', _('No title'))
            post.modified_date = timezone.now()
            post.process().tag(request.POST.get('tags')).save();
            return JsonResponse({'url': reverse('post_detail', args=[post.url])})

        else:  # Create a new post
            newPost = Post.objects.create(author=request.user, title=request.POST.get('title', _('No title')), content=request.POST.get('content', ''))
            newPost.modified_date = timezone.now()
            newPost.process().tag(request.POST.get('tags')).save()
            return JsonResponse({'url': reverse('post_detail', args=[newPost.url])})

@login_required(login_url='/admin/')
def post_publish(request):
    if request.method == "POST":
        post = get_object_or_404(Post, pk=request.POST.get('id'))
        if post.author != request.user:
            return HttpResponseForbidden()
        post.publish();
        return redirect('post_detail', postURL=post.url)

@login_required(login_url='/admin/')
def post_remove(request, postID):
    if request.method == "GET":
        post = get_object_or_404(Post, pk=postID)
        if post.author != request.user:
            return HttpResponseForbidden()
        post.delete();
        return redirect('post_list')

@login_required(login_url='/admin/')
def post_star(request, postID):
    if request.method == "GET":
        post = get_object_or_404(Post, pk=postID)
        if post.author != request.user:
            return HttpResponseForbidden()
        post.toggleStar();
        return redirect('post_detail', postURL=post.url)

@login_required(login_url='/admin/')
def upload_image_file(request):
    uploaded_file = request.FILES['image']
    fs = FileSystemStorage()
    name = fs.save(uploaded_file.name, uploaded_file)
    return JsonResponse({
        'success': 1,
        'file': {
            'url': fs.url(name)
        }})

@login_required(login_url='/admin/')
def upload_image_link(request):
    image = urllib.request.urlretrieve(request.POST.get('url'))
    fs = FileSystemStorage()
    image_file = File(open(image[0], 'rb'))
    name = fs.save(str(int(time.time()))+'.jpg', image_file)
    return JsonResponse({
        'success': 1,
        'file': {
            'url': fs.url(name)
        }})

@login_required(login_url='/admin/')
def upload_header_image(request):
    if request.method == 'POST':
        form = UploadHeaderImageForm(request.POST, request.FILES)
        if form.is_valid():
            site = SiteSettings.get_solo()
            if request.POST.get('image_type') == 'cover':
                # handle cover
                site.cover = request.FILES['image']
                site.save()
            elif request.POST.get('image_type') == 'avatar':
                # handle avatar
                site.avatar = request.FILES['image']
                site.save()
                site.crop_avatar()
            else:
                return HttpResponseForbidden('method not allowed')
            return JsonResponse({'success': 1})
        else:
            return HttpResponseForbidden('this file type is not allowed')
    return HttpResponseForbidden('allowed only via POST')

@login_required(login_url='/admin/')
def blog_settings(request):
    site = SiteSettings.get_solo()
    if request.method == "POST":
        form = SiteSettingsForm(request.POST, instance=site)
        if form.is_valid():
            form.save()
            return render(request, 'blog/site_settings.html', {'form': form, 'is_saved': True})
    else:
        form = SiteSettingsForm(instance=site)
        return render(request, 'blog/site_settings.html', {'form': form})

def handler404(request, exception):
    context = RequestContext(request)
    response = render(request, "blog/errors/404.html", context=context)
    response.status_code = 404
    return response


import numpy as np
import cv2
import os

def downSample(img):
    result = cv2.resize(img, None, fx=0.25, fy=0.25, interpolation=cv2.INTER_CUBIC)
    height, weight = result.shape[:2]
    result = result[height // 2 - 135: height // 2 + 135, weight // 2 - 135:weight // 2 + 135, :]
    return result

def bigEnough(img):
    height, weight = img.shape[:2]
    if height >= 1080 and  weight >= 1080:
        return True
    return False

def isHighFrequency(img):
    sobelx = cv2.Sobel(img, ddepth=cv2.CV_64F, dx=1, dy=0)
    sobelx = cv2.convertScaleAbs(sobelx)
    # print(np.mean(sobelx))
    sobely = cv2.Sobel(img, ddepth=cv2.CV_64F, dx=0, dy=1)
    sobely = cv2.convertScaleAbs(sobely)
    # print(np.mean(sobely))
    sobel = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
    ave = np.mean(sobel)
    print("Sobel is {}".format(ave))
    if ave >= 13:
        return True
    return False

def sufficentMotion(flow):
    distance = np.sqrt(flow[:,:,0] ** 2 + flow[:,:,1] ** 2)
    # tempx = np.abs(flow[:,:,0])
    # tempx = np.array(tempx >= 8,dtype='bool')
    # tempy = np.abs(flow[:,:,1])
    # tempy = np.array(tempy >= 8,dtype='bool')
    # temp = np.logical_and(tempx,tempy)
    sum = np.sum(distance >= 8)
    shape = flow[:,:,0].size
    prop = sum /shape
    print("prop is {}".format(prop))
    if prop < 0.1:
        return False
    return True

def limitedMotion(flow):
    temp = np.abs(flow)
    mean = np.mean(temp)
    print("mean is {}".format(mean))
    if mean > 16:
        return False
    return True

def noAbruptChanges(img1,img2,flow):
    weight = int(img1.shape[1])
    height = int(img2.shape[0])
    y_coords, x_coords = np.mgrid[0:height, 0:weight]
    coords = np.float32(np.dstack([x_coords, y_coords]))
    pixel_map = coords + flow
    new_frame = cv2.remap(img1, pixel_map, None, cv2.INTER_LINEAR)
    # cv2.imshow('image', new_frame)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()
    l1_distance = np.linalg.norm(new_frame-img2,ord=1)
    print("l1 is {}".format(l1_distance))
    if l1_distance > 13:
        return False
    return True
def isLinearMotion(flow1,flow2):
    diff = flow1 - flow2
    absDiff = np.abs(diff)
    meanDiff = np.mean(absDiff)
    print("mean diff is {}".format(meanDiff))
    if meanDiff > 0.8:
        return False
    return True

def goodTriplet(img1,img2,img3):
    if not bigEnough(img1) or not bigEnough(img2) or not bigEnough(img3):
        print("not big enough")
        return False
    img1 = downSample(img1)
    img2 = downSample(img2)
    img3 = downSample(img3)
    if not isHighFrequency(img1) or not isHighFrequency(img2) or not isHighFrequency(img3):
        print("not high frequency")
        return False
    img1_gray = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
    img2_gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
    img3_gray = cv2.cvtColor(img3,cv2.COLOR_BGR2GRAY)
    flow1 = cv2.calcOpticalFlowFarneback(img1_gray,img2_gray,None,pyr_scale=0.5,levels=3,winsize=7,iterations=3,poly_n=5,poly_sigma=1.2,flags=cv2.OPTFLOW_FARNEBACK_GAUSSIAN)
    flow2 = cv2.calcOpticalFlowFarneback(img2_gray,img3_gray,None,pyr_scale=0.5,levels=3,winsize=7,iterations=3,poly_n=5,poly_sigma=1.2,flags=cv2.OPTFLOW_FARNEBACK_GAUSSIAN)
    if not sufficentMotion(flow1) or not sufficentMotion(flow2):
        print("not sufficent motion")
        return False
    if not limitedMotion(flow1) or not limitedMotion(flow2):
        print("not limited motion")
        return False
    if not isLinearMotion(flow1,flow2):
        print("not linear motion")
        return False
    if not noAbruptChanges(img1,img2,flow1) or not noAbruptChanges(img2,img3,flow2):
        print("not no abrupt changes")
        return False
    return True

if __name__ == '__main__':
    datafolderpath = "C://data//deeplearning//test1"
    resultpath = "c://data//deeplearning//result"
    # img1path = os.path.join(datafolderpath, "368.png")
    # img2path = os.path.join(datafolderpath, "369.png")
    # img3path = os.path.join(datafolderpath, "370.png")
    # img1 = cv2.imread(img1path)
    # img2 = cv2.imread(img2path)
    # img3 = cv2.imread(img3path)
    imglist = []
    filelist = os.listdir(datafolderpath)
    for file in filelist:
        print(file)
        imgPath = os.path.join(datafolderpath,file)
        img = cv2.imread(imgPath)
        imglist.append(img)
    length = imglist.__len__()
    for i in range(0,length-2):
        img1 = imglist[i]
        img2 = imglist[i+1]
        img3 = imglist[i+2]
        good = goodTriplet(img1,img2,img3)
        print("Triplet {0} is {1}".format(i,good))


from flask import Flask, request
import json
import requests

app = Flask(__name__)

@app.route("/", methods=['POST'])
def hello():
    data = request.data
    dataDict = json.loads(data)
    x = int(dataDict['key']) * int(dataDict['key'])
    r = requests.get("https://fantasy.premierleague.com/drf/elements/")
    r = r.json()
    #return str(x)
    return str(r)


"""
MIT License

Copyright (c) 2020 NaveenKumar

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
from utils.display import print_message, Colors

def attribute_check(tree, element):
    """
    Performs additional attribute checks on IfController or LoopController
    @param tree: The parsed JMX
    @param element: The element to check
    """
    root = tree.getroot()
    # Set flag = 1 for issue found
    flag = 0
    for node in root.iter(element):
        #
        for child in node.getchildren():
            for i, j in child.attrib.items():
                # print(i, j)
                if str(j) == 'IfController.useExpression':
                    # Set flag = 0 for no issues
                    flag = 0
                elif str(j) == 'LoopController.loops':
                    loop_count = child.text
                    if int(loop_count) == -1:
                        flag = 0
                else:
                    flag = 1
    if flag == 1:
        if element == 'IfController':
            print_message(message_color=Colors.white, message="For performance, check \"Interpret Condition as Variable"
                                                              " Expression\" in If Controller.")
        elif element == 'LoopController':
            print_message(message_color=Colors.white, message="Loop Count is set to infinity. Double check "
                                                              "the count before you start the test.")


import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from uncertainties import ufloat
from uncertainties import unumpy
from scipy import stats
from uncertainties.unumpy import (nominal_values as noms,
                                  std_devs as stds)
from linregress import linregress

#bestätigung von Abbildungsgesetz und Linsengleichung

def Linsengl(b,g):
    return 1/(1/b+1/g)

def Abbildges(B,G):
    return B/G

g1data=64
b1data,l1data=np.genfromtxt('Messpaare1.txt',unpack=True)

b1=l1data-b1data
g1=g1data-l1data

f1=Linsengl(b1,g1)
print(b1,'b1')
print(g1,'g1')
print(f1,'f1')
f1mittel=ufloat(np.mean(f1),np.std(f1))
print(f1mittel*10,'f1mittel in mm')

a = np.zeros(shape=(len(b1),1))

plt.plot(a,b1, 'kx', label='Messpaare')
plt.plot(g1,a, 'kx')
i=0
while i<len(b1):
    plt.plot([g1[i],a[i]],[a[i],b1[i]],'k-')
    i+=1

Ax=(b1[len(b1)-1]-b1[0])/(-b1[0]/g1[0]+b1[len(b1)-1]/g1[len(g1)-1])
A=-b1[0]/g1[0]*Ax+b1[0]
# print(Ax,A,'Ax,A')
plt.plot(Ax,A,'kx',label='A Schnittpunkt bei [4.38,4.61]')
plt.text(Ax+.1, A+.1, r'A')
plt.xlabel(r'$ g\ / \ 10e-2 \,\mathrm{m}$')
plt.ylabel(r'$ b\ / \ 10e-2 \,\mathrm{m}$')
plt.legend(loc='best')
plt.tight_layout()
plt.savefig('plot1.pdf')
plt.close()

f1A=4.495
print(f1A*10,'f1A in mm')

#unbekannte Linse
print('-----------------------------------unbekannte Linse----------------------------------')
g2data=95
b2data,l2data=np.genfromtxt('Messpaare2.txt',unpack=True)

b2=(l2data-b2data)
g2=(g2data-l2data)

f2=Linsengl(b2,g2)

print(b2,'b2')
print(g2,'g2')
print(f2,'f2')
f2mittel=ufloat(np.mean(f2),np.std(f2))
print(f2mittel*10,'f2mittel in mm')

a = np.zeros(shape=(len(b2),1))

plt.plot(a,b2, 'kx', label='Messpaare')
plt.plot(g2,a, 'kx')
i=0
while i<len(b2):
    plt.plot([g2[i],a[i]],[a[i],b2[i]],'k-')
    i+=1

Ax=(max(b2)-min(b2))/(-min(b2)/max(g2)+max(b2)/min(g2))
A=-max(b2)/min(g2)*Ax+max(b2)
# print(Ax,A,'Ax,A')
plt.plot(Ax,A,'kx',label='A Schnittpunkt bei [18.9,20.6]')
plt.text(Ax+.2, A+.2, r'A')
# plt.xlim(15,25)
# plt.ylim(10,30)
plt.xlabel(r'$ g\ / \ 10e-1 \,\mathrm{m}$')
plt.ylabel(r'$ b\ / \ 10e-1 \,\mathrm{m}$')
plt.legend(loc='best')
plt.tight_layout()
plt.savefig('plot2.pdf')
plt.close()

f2A=19.7
print(f2A*10,'f2A in mm')

#Bessel
print('-----------------------------bessel------------------------------------')
#weiß
def Besselbrennweite(e,d):
    return (e**2-d**2)/(4*e)

bbesseldata=10
lbesseldata1,lbesseldata2,gbesseldata=np.genfromtxt('Messpaarebessel.txt',unpack=True)

bbessel1=lbesseldata1-bbesseldata
bbessel2=lbesseldata2-bbesseldata

gbessel1=gbesseldata-lbesseldata1
gbessel2=gbesseldata-lbesseldata2

e=gbessel1+bbessel1
d=bbessel1-gbessel1

fbessel=Besselbrennweite(e,d)

print(gbessel1,'gbessel1')
print(bbessel1,'bbessel1')
print(e,'e')
print(d,'d')
print(fbessel,'fbessel')

fbesselmittel=ufloat(np.mean(fbessel),np.std(fbessel))
print(fbesselmittel*10,'fbesselmittel in mm')

#blau#rot
bchrom=10
lblau,lrot,gchromdata=np.genfromtxt('chromaAbberation.txt',unpack=True)
#blau
bchromblau=lblau-bchrom
gchromblau=gchromdata-lblau

eblau=bchromblau+gchromblau
dblau=gchromblau-bchromblau

fblau=Besselbrennweite(eblau,dblau)

np.savetxt('e.txt', np.column_stack([eblau]), header='e in cm')
np.savetxt('bblau.txt', np.column_stack([bchromblau]), header='bblau in cm')
np.savetxt('gblau.txt', np.column_stack([gchromblau]), header='gblau in cm')
np.savetxt('fblau.txt', np.column_stack([fblau]), header='fblau in mm')

print(bchromblau,gchromblau,eblau,dblau,'bchromblau,gchromblau,eblau,dblau')
print(fblau,'fblau')
fblaumittel=ufloat(np.mean(fblau),np.std(fblau))
print(fblaumittel*10,'fblaumittel in mm')

#rot
bchromrot=lrot-bchrom
gchromrot=gchromdata-lrot

erot=bchromrot+gchromrot
drot=gchromrot-bchromrot

frot=Besselbrennweite(eblau,drot)
np.savetxt('brot.txt', np.column_stack([bchromrot]), header='brot in cm')
np.savetxt('grot.txt', np.column_stack([gchromrot]), header='grot in cm')
np.savetxt('frot.txt', np.column_stack([frot*10]), header='frot in mm')

print(bchromrot,gchromrot,erot,drot,'bchromrot,gchromrot,erot,drot')
print(frot,'frot')
frotmittel=ufloat(np.mean(frot),np.std(frot))
print(frotmittel*10,'frotmittel in mm')

#Abbe
print('-----------------------------------Abbe---------------------------------------')
babbedata=10
posA,Bild,gabbedata=np.genfromtxt('Messpaareabbe.txt',unpack=True)
# L=np.ones(shape=(len(Bild),1))
L=1.65

gstrich=gabbedata-posA
bstrich=posA-babbedata
np.savetxt('gstrich.txt', np.column_stack([gstrich]), header='gstrich in cm')
np.savetxt('bstrich.txt', np.column_stack([bstrich]), header='bstrich in cm')

V=Abbildges(Bild,L)
# print(V,'V')
np.savetxt('V.txt', np.column_stack([V]), header='V ')

a,aerr,b,berr=linregress(1+1/V,gstrich)
a1,aerr1,b1,berr1=linregress(1+V,bstrich)
# print(a,aerr,b,berr,'a,aerr,b,berr')
# print(a1,aerr1,b1,berr1,'a1,aerr1,b1,berr1')

x = np.linspace(1,1.6, 100)
plt.plot(x,a*x+b, 'k-', label='Lineare Regression')
plt.plot(1+1/V,gstrich, 'kx', label='Messwerte g\'')
plt.xlabel(r'$ 1+\frac{1}{V} $')
plt.ylabel(r'$ g\'  / \ 10e-2 \, \mathrm{m}$')
plt.xlim(1+1/V[0],1+1/V[len(V)-1])
plt.legend(loc='best')
plt.tight_layout()
plt.savefig('plotabb1.pdf')
plt.close()

x = np.linspace(0,8, 100)
plt.plot(x,a1*x+b1,'k-',label='Lineare Regression')
plt.plot(1+V,bstrich,'kx',label='Messwerte b\'')
plt.xlabel(r'$ 1+V$')
plt.ylabel(r'$ b\' / \ 10e-2 \, \mathrm{m}$')
plt.xlim(1+V[len(V)-1],1+V[0])
plt.legend(loc='best')
plt.tight_layout()
plt.savefig('plotabb2.pdf')
plt.close()

h=ufloat(b,berr)
hstrich=ufloat(b1,berr1)
print(h,hstrich,'h,hstrich in cm')
fabbeg=ufloat(a,aerr)
fabbeb=ufloat(a1,aerr1)
print(fabbeg,fabbeb,'fabbeg,fabbeb')
fabbemittel=np.mean([fabbeg,fabbeb])
print(fabbemittel*10,'fabbemittel in mm')

print(' ------------------------------------------------prozente---------------------------------------')

def pro(b,c):
    x=c*100/b
    return 100-x

prof1=pro(50,f1mittel*10)
print(prof1,'prof1')

prof1A=pro(50,f1A*10)
print(prof1A,'prof1A')

prof2=pro(f2A,f2mittel)
print(prof2,'prof2 zu abgelesenem Wert')

profbessel=pro(50,fbesselmittel*10)
print(profbessel,'profbessel')

profblau=pro(50,fblaumittel*10)
print(profblau,'profblau')

profrot=pro(50,frotmittel*10)
print(profrot,'profrot')

proabbe=pro(41.67,fabbemittel*10)
print(proabbe,'proabbe')


from django import forms
from django.utils.safestring import mark_safe
from django.template.loader import render_to_string
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from parsley.decorators import parsleyfy
from django.forms import ModelForm

from wastelinqbroker.globals import *
from wastelinqbroker import settings
from facility.models import *
from generator._models.Profiles import *
from tools._models.MasterContacts import *
from lookup.models import (DisposalMethod, )
from processcode.models import *

class CustomerProfileForm(ModelForm):
    Active_DF_CHOICES_RADIO = (
        ("PrimaryDF","Active"),
        ("SecondaryDF","Active"),
    )
    """  DateExpires1 = forms.DateField(input_formats=(settings.DATE_INPUT_FORMATS, ),required=False, widget=forms.DateInput(format=settings.DATE_INPUT_FORMATS,attrs={'class': 'w1 inputcalendar','required':'false'}))
    DisposalFacility1 = forms.ModelChoiceField(queryset=DisposalFacility.objects.all().order_by('Name'))
    HandlingCode1 = forms.ChoiceField(choices=HandlingCode_CHOICES, widget=forms.Select(attrs={'class': 'w4'}))

    DateExpires2 = forms.DateField(input_formats=(settings.DATE_INPUT_FORMATS, ),required=False, widget=forms.DateInput(format=settings.DATE_INPUT_FORMATS,attrs={'class': 'w1 inputcalendar','required':'false'}))
    DisposalFacility2 = forms.ModelChoiceField(queryset=DisposalFacility.objects.all().order_by('Name'))
    HandlingCode2 = forms.ChoiceField(choices=HandlingCode_CHOICES, widget=forms.Select(attrs={'class': 'w4'})) """

    #Active_DF = forms.ChoiceField( widget=forms.RadioSelect())
    Status= forms.ChoiceField(choices=CUSTOMER_PROFILE_STATUS_CHOICES, widget=forms.Select(attrs={'class': 'w4'}))

    class Meta:
        model = CustomerProfile
        fields = '__all__'
        exclude = ('Customer','Active_DF')
        widgets ={
            'Name': forms.TextInput(),
            #'DisposalFacility' : forms.ForeignKey(DisposalFacility, on_delete=forms.SET_NULL) ,
            #CostCenter :  forms.ForeignKey(CostCenters, on_delete=forms.PROTECT)
            'Status': forms.TextInput() ,
            'DateExpires' : forms.DateInput(format=settings.DATE_INPUT_FORMATS,attrs={'class': 'w1 inputcalendar'}),
            'ApprovalNumber' : forms.TextInput(),
            'HandlingCode' : forms.TextInput(),#forms.ForeignKey(HandlingCodes, on_delete=forms.PROTECT)
        }

class CustProfileDisposalFacilityForm(ModelForm):
    HandlingCode_CHOICES = (
        ("N/A","N/A"),
        ("H010- METALS RECOVERY","H010- METALS RECOVERY"),
        ("H020- SOLVENTS RECOVERY","H020- SOLVENTS RECOVERY"),
        ("H039- OTHER RECOVERY OR RECLAMATION FOR REUSE","H039- OTHER RECOVERY OR RECLAMATION FOR REUSE"),
        ("H050- ENERGY RECOVERY","H050- ENERGY RECOVERY"),
        ("H061- FUEL BLENDING","H061- FUEL BLENDING"),
        ("H040- INCINERATION","H040- INCINERATION"),
        ("H070- CHEMICAL TREATMENT","H070- CHEMICAL TREATMENT"),
        ("H081- BIOLOGICAL TREATMENT","H081- BIOLOGICAL TREATMENT"),
        ("H100- PHYSICAL TREATMENT ONLY","H100- PHYSICAL TREATMENT ONLY"),
        ("H110- STABILIZATION","H110- STABILIZATION"),
        ("H120- COMB. OF CHEMICAL","H120- COMB. OF CHEMICAL"),
        ("H121- NEUTRALIZATION ONLY","H121- NEUTRALIZATION ONLY"),
        ("H122- EVAPORATION","H122- EVAPORATION"),
        ("H129- OTHER TREATMENT","H129- OTHER TREATMENT"),
        ("H131- LAND TREATMENT OR APPLICATION","H131- LAND TREATMENT OR APPLICATION"),
        ("H132- LANDFILL OR SURFACE IMPOUNDMENT","H132- LANDFILL OR SURFACE IMPOUNDMENT"),
        ("H134- DEEPWELL OR UNDERGROUND INJECTION","H134- DEEPWELL OR UNDERGROUND INJECTION"),
        ("H135- DISCHARGE TO SEWER","H135- DISCHARGE TO SEWER"),
        ("H141- STORAGE","H141- STORAGE"),
    )
    DateExpires = forms.DateField(input_formats=(settings.DATE_INPUT_FORMATS, ),required=False, widget=forms.DateInput(format=settings.DATE_INPUT_FORMATS,attrs={'class': 'w1 inputcalendar','required':'false'}))
    #DisposalFacility = forms.ModelChoiceField(queryset=DisposalFacility.objects.all().order_by('Name'))
    HandlingCode = forms.ChoiceField(choices=HandlingCode_CHOICES, widget=forms.Select(attrs={'class': 'w4'}))
    class Meta:
        model = CustProfileDisposalFacility
        fields = '__all__'
class GeneratorAndCustomerInformationForm(ModelForm):

    EmergencyNumber = forms.CharField(max_length=255)

    FacilityState = forms.ChoiceField(choices=STATE_CHOICES, widget=forms.Select(attrs={'class': 'w33','placeholder':'State'}))

    SiteMailingState = forms.ChoiceField(choices=STATE_CHOICES, widget=forms.Select(attrs={'class': 'w33','placeholder':'State'}))

    BillingState = forms.ChoiceField(choices=STATE_CHOICES, widget=forms.Select(attrs={'class': 'w33','placeholder':'State'}))

    class Meta:
        model=GeneratorAndCustomerInformation
        fields = '__all__'
        exclude = ('EPAId', 'StateId', 'NAISC', )
        widgets = {
            'FacilityAddress1': forms.TextInput(),
            'FacilityAddress2': forms.TextInput(),
            'FacilityCity': forms.TextInput(),
            'FacilityState': forms.Select(),
            'FacilityZip': forms.TextInput(),
            'FacilityPhone': forms.TextInput(),

            'SiteMailingAddress1': forms.TextInput(),
            'SiteMailingAddress2': forms.TextInput(),
            'SiteMailingCity': forms.TextInput(),
            'SiteMailingState': forms.Select(),
            'SiteMailingZip': forms.TextInput(),
            'SiteMailingPhone': forms.TextInput(),

            'BillingAddress1': forms.TextInput(),
            'BillingAddress2': forms.TextInput(),
            'BillingCity': forms.TextInput(),
            'BillingState': forms.Select(),
            'BillingZip': forms.TextInput(),
            'BillingPhone': forms.TextInput(),
        }

class GeneratingProcessAndMaterialCompositionForm(ModelForm):
    class Meta:
        model = GeneratingProcessAndMaterialComposition
        fields = '__all__'
        widgets = {
            'WasteStreamDescription': forms.Textarea(attrs={'class': 'txtarea ',"rows":"3"}),
            'ProcessGeneratingTheWaste': forms.Textarea(attrs={'class': 'txtarea ',"rows":"3"}),
        }

class PhysicalAndChemicalPropertiesForm(ModelForm):
    CHEMICAL_PHYSICALSTATE_CHOICES = (
        ("Solid","Solid"),
        ("Dust/Powder","Dust/Powder"),
        ("Debris","Debris"),
        ("Sludge","Sludge"),
        ("Liquid","Liquid"),
        ("Gas/Aerosol","Gas/Aerosol"),
        ("Varies","Varies"),
    )
    pH_RADIO_CHOICES = (
        ("≤ 2","≤ 2"),
        ("> 2 to ≤ 5","> 2 to ≤ 5"),
        ("> 5 to ≤ 10","> 5 to ≤ 10"),
        ("> 10 to ≤ 12.5","> 10 to ≤ 12.5"),
        (">12.5",">12.5"),
        ("N/A","N/A"),
    )
    FLASH_POINT_RADIO_CHOICES = (
        ("< 90°F","< 90°F"),
        ("≥ 90°F to < 140°F","≥ 90°F to < 140°F"),
        ("≥ 140°F to < 150°F","≥ 140°F to < 150°F"),
        ("≥ 150°F to < 199°F","≥ 150°F to < 199°F"),
        ("≥ 200°F","≥ 200°F"),
    )
    YESNO_CHOICES_RADIO = (
        ("Yes","Yes"),
        ("No","No"),
    )
    PCPColor= forms.CharField(max_length=255)
    PCPOdor= forms.CharField(max_length=255)
    PCPBTUValue= forms.CharField(max_length=255)
    PCPViscosity= forms.CharField(max_length=255)
    PCPDensity= forms.CharField(max_length=255)
    PCPhysicalStateSolidLiquidSemiSolid = forms.ChoiceField(choices=CHEMICAL_PHYSICALSTATE_CHOICES, widget=forms.RadioSelect())
    PCpH = forms.ChoiceField(choices=pH_RADIO_CHOICES, widget=forms.RadioSelect())
    PCFlashPoint = forms.ChoiceField(choices=FLASH_POINT_RADIO_CHOICES, widget=forms.RadioSelect())
    #RegulatoryDOTHazardousMaterial= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    RegulatoryRestrictedUnderLDR= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    RegulatoryLDRSubcaterogyWastewater= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    RegulatoryUHCs= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    Regulatory500PPMVOC= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    RegulatoryLDRSubcaterogyNonWastewater= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    RegulatoryAlternativeStandardsofSoil= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    #Facility = forms.ForeignKey(Facility, on_delete=forms.PROTECT)
    #CopyNumber = forms.IntegerField()
    #CustomerProfile = forms.ForeignKey(CustomerProfile, on_delete=forms.CASCADE)

    class Meta:
        model =   PhysicalAndChemicalProperties
        fields = '__all__'
        widgets ={
            'PCPhysicalStateSolid2' : forms.CheckboxInput(),
            'PCPPhysicalStateLiquid2': forms.CheckboxInput(),
            'PCPPhysicalStateSludge2': forms.CheckboxInput(),
            'PCPPhysicalStateGas2': forms.CheckboxInput(),
            'PCPPhysicalStateSolidPercent': forms.TextInput(),
            'PCPPhysicalStateLiquidPercent':  forms.TextInput(),
            'PCPPhysicalStateSludgePercent':  forms.TextInput(),
            'PCPPhysicalStateGasPercent':  forms.TextInput(),
            'PCPOtherPropertiesExplosive': forms.CheckboxInput(),
            'PCPOtherPropertiesRadioactive': forms.CheckboxInput(),
            'PCPOtherPropertiesThermallyUnstable': forms.CheckboxInput(),
            'PCPOtherPropertiesShockSensitive': forms.CheckboxInput(),
            'PCPOtherPropertiesPyrophoric': forms.CheckboxInput(),
            'PCPOtherPropertiesOxidizer': forms.CheckboxInput(),
            'PCPOtherPropertiesWaterReactive': forms.CheckboxInput(),
            'PCPOtherPropertiesAirReactive': forms.CheckboxInput(),
            'PCPOtherPropertiesReactiveCyanides': forms.CheckboxInput(),
            'PCPOtherPropertiesReactiveSulfides': forms.CheckboxInput(),
            'PCPOtherPropertiesPolymerizable': forms.CheckboxInput(),
            'PCPOtherPropertiesPolymerizableInhibited': forms.CheckboxInput(),
            'PCPOtherPropertiesAbestosFriable': forms.CheckboxInput(),
            'PCPOtherPropertiesAbestosNonFriable': forms.CheckboxInput(),
            'PCPOtherPropertiesMetalFines': forms.CheckboxInput(),
            'PCPOtherPropertiesOrganaicPeroxides': forms.CheckboxInput(),
            'PCPOtherPropertiesDioxins': forms.CheckboxInput(),
            'PCPOtherPropertiesFurans': forms.CheckboxInput(),
            'PCPOtherPropertiesNORM': forms.CheckboxInput(),
            'PCPOtherPropertiesBiohazard': forms.CheckboxInput(),
            'PCPOtherPropertiesNONE': forms.CheckboxInput(),
        }

class ShippingAndPackagingInformationForm(ModelForm):
    VOLUMETYPE_CHOICES_RADIO = (
        ("Tons","Tons"),
        ("Lbs","Lbs"),
        ("Yds","Yds"),
        ("Gals","Gals"),
        ("Kgs","Kgs"),
    )
    FREQUENCY_CHOICES_RADIO = (
        ("One Time","One Time"),
        ("Monthly","Monthly"),
        ("Annually","Annually"),
    )
    YESNO_CHOICES_RADIO = (
        ("Yes","Yes"),
        ("No","No"),
    )
    ShippingAndPackagingVolume= forms.CharField(max_length=255, widget=forms.TextInput(attrs={"style":"float:left;margin-left:15px;"}))
    ShippingAndPackagingVolumeType= forms.ChoiceField(choices=VOLUMETYPE_CHOICES_RADIO, widget=forms.Select(attrs={"style":"width:auto;float:left;margin-left:5px;padding: 0.25rem 0;"}))
    #ShippingAndPackagingVolume= forms.CharField(max_length=255, widget=forms.TextInput(attrs={"class":"left"}))
    #ShippingAndPackagingVolumeType= forms.ChoiceField(choices=VOLUMETYPE_CHOICES_RADIO, widget=forms.Select(attrs={"class":"width-auto left"}))
    ShippingAndPackagingFrequency= forms.ChoiceField(choices=FREQUENCY_CHOICES_RADIO, widget=forms.RadioSelect())
    ShippingAndPackagingUSDOT= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    #WasteManagementUnits = forms.CharField(max_length=255)
    #ShippingAndPackagingUSDOTComment= forms.CharField(max_length=255)
    #CustomerProfile = forms.ForeignKey(CustomerProfile, on_delete=forms.CASCADE)

    class Meta:
        model = ShippingAndPackagingInformation
        fields = '__all__'
        widgets = {
            'ShippingAndPackagingUSDOTComment': forms.Textarea(attrs={'class': 'w1',"rows":"5"}),
        }

class ProcessingDetailContentForm(ModelForm):
    UNITS_CHOICES= (
        ("G","G"),
    )
    Final_TSDF = forms.ModelChoiceField(queryset=DisposalFacility.objects, empty_label='N/A', widget=forms.Select(attrs={'disabled':'disabled'}))
    Container_Type = forms.ModelChoiceField(queryset=ContainerType.objects, empty_label='N/A', widget=forms.Select(attrs={'onchange':'changeContainerType();'}))
    Container_Size = forms.ModelChoiceField(queryset=ContainerSize.objects, empty_label='N/A', widget=forms.Select(attrs={'disabled':'disabled'}))
    ProcessCode = forms.ModelChoiceField(queryset=ProcessCode.objects, empty_label='N/A', widget=forms.Select(attrs={'disabled':'disabled'}))
    Cost_Basis = forms.ModelChoiceField(queryset=CostBasis.objects, empty_label='N/A', widget=forms.Select())
    Dollar_Lk = forms.ChoiceField(choices=YESNO_CHOICES, widget=forms.Select())
    Active = forms.ChoiceField(choices=YESNO_CHOICES, widget=forms.Select())
    Shipping_Units = forms.ChoiceField(choices=UNITS_CHOICES, widget=forms.Select())
    Billing_Units = forms.ChoiceField(choices=UNITS_CHOICES, widget=forms.Select())
    class Meta:
        model = ProcessingDetail_Content
        fields = '__all__'
        """ widgets = {
            'Final_TSDF': forms.Select(attrs={'class': 'w1'}),
            'Vendor_Process_Code': forms.TextInput(attrs={'class': 'w1'}),
            'Container_Type': forms.Select(attrs={'class': 'w1'}),
            'Container_Size': forms.Select(attrs={'class': 'w1'}),
            'Cost_Basis': forms.Select(attrs={'class': 'w1'}),
            'Cost': forms.TextInput(attrs={'class': 'w1'}),
            'Min_Cost': forms.TextInput(attrs={'class': 'w1'}),
        } """

class RegulatoryInformationForm(ModelForm):
    YESNO_CHOICES_RADIO = (
        ("Yes","Yes"),
        ("No","No"),
    )
    WasteDetermination_CHOICES_RADIO = (
        ("Generator Knowledge","Generator Knowledge"),
        ("Waste Analysis","Waste Analysis"),
        ("SDS","SDS"),
    )

    Exemption_CHOICES_RADIO = (
        ("§261.4(a)(1) - Domestic Sewage and Mixtures of Domestic Sewage","§261.4(a)(1) - Domestic Sewage and Mixtures of Domestic Sewage"),
        ("§261.4(a)(2) - Point Source Discharge","§261.4(a)(2) - Point Source Discharge"),
        ("§261.4(a)(3) - Irrigation Return Flow","§261.4(a)(3) - Irrigation Return Flow"),
        ("§261.4(a)(4) - Radioactive Waste","§261.4(a)(4) - Radioactive Waste"),
        ("§261.4(a)(5) - In-Situ Mining","§261.4(a)(5) - In-Situ Mining"),
        ("§261.4(a)(6) - Pulping Liquors","§261.4(a)(6) - Pulping Liquors"),
        ("§261.4(a)(7) - Spent Sulfuric Acid","§261.4(a)(7) - Spent Sulfuric Acid"),
        ("§261.4(a)(8) - Reclamation in Enclosed Tanks","§261.4(a)(8) - Reclamation in Enclosed Tanks"),
        ("§261.4(a)(9) - Spent Wood Preservatives","§261.4(a)(9) - Spent Wood Preservatives"),
        ("§261.4(a)(10) - Coke By-Product Wastes","§261.4(a)(10) - Coke By-Product Wastes"),
        ("§261.4(a)(11) - Splash Condenser Dross Residue","§261.4(a)(11) - Splash Condenser Dross Residue"),
        ("§261.4(a)(12) - Hazardous Secondary Materials From the Petroleum Refining Industry","§261.4(a)(12) - Hazardous Secondary Materials From the Petroleum Refining Industry"),
        ("§261.4(a)(13) - Excluded Scrap Metal","§261.4(a)(13) - Excluded Scrap Metal"),
        ("§261.4(a)(14) - Shredded Circuit Boards","§261.4(a)(14) - Shredded Circuit Boards"),
        ("§261.4(a)(15) - Pulping Condensates Derived from Kraft Mill Steam Strippers","§261.4(a)(15) - Pulping Condensates Derived from Kraft Mill Steam Strippers"),
        ("§261.4(a)(17) - Spent materials generated within the primary mineral processing industry from which minerals, acids, cyanide, water, or other values are recovered by mineral processing or by beneficiation","§261.4(a)(17) - Spent materials generated within the primary mineral processing industry from which minerals, acids, cyanide, water, or other values are recovered by mineral processing or by beneficiation"),
        ("§261.4(a)(18) - Petrochemical recovered oil from an associated organic chemical manufacturing facility","§261.4(a)(18) - Petrochemical recovered oil from an associated organic chemical manufacturing facility"),
        ("§261.4(a)(19) - Spent caustic solutions from petroleum refining liquid treating processes used as a feedstock to produce cresylic or naphthenic acid","§261.4(a)(19) - Spent caustic solutions from petroleum refining liquid treating processes used as a feedstock to produce cresylic or naphthenic acid"),
        ("§261.4(a)(20) - Hazardous secondary materials used to make zinc fertilizers","§261.4(a)(20) - Hazardous secondary materials used to make zinc fertilizers"),
        ("§261.4(a)(21) - Zinc fertilizers made from hazardous wastes, or excluded hazardous secondary materials","§261.4(a)(21) - Zinc fertilizers made from hazardous wastes, or excluded hazardous secondary materials"),
        ("§261.4(a)(22) - Used cathode ray tubes (CRTs)","§261.4(a)(22) - Used cathode ray tubes (CRTs)"),
        ("§261.4(a)(23) - Hazardous secondary material generated and legitimately reclaimed within the United States or its territories and under the control of the generator","§261.4(a)(23) - Hazardous secondary material generated and legitimately reclaimed within the United States or its territories and under the control of the generator"),
        ("§261.4(a)(24) - Hazardous secondary material that is generated and then transferred to a verified reclamation facility for the purpose of reclamation is not a solid waste","§261.4(a)(24) - Hazardous secondary material that is generated and then transferred to a verified reclamation facility for the purpose of reclamation is not a solid waste"),
        ("§261.4(a)(26) - Solvent-contaminated wipes that are sent for cleaning and reuse are not solid wastes from the point of generation","§261.4(a)(26) - Solvent-contaminated wipes that are sent for cleaning and reuse are not solid wastes from the point of generation"),
        ("§261.4(a)(27) - Hazardous secondary material that is generated and then transferred to another person for the purpose of remanufacturing is not a solid waste","§261.4(a)(27) - Hazardous secondary material that is generated and then transferred to another person for the purpose of remanufacturing is not a solid waste"),
    )
    ORIGIN_CHOICES = (
        ('1 - Was generated on-site from a product or service activity.', '1 - Was generated on-site from a product or service activity.'),
        ('2 - Resulted from a spill clean-up, equipment decommissioning, or emergency removal.', '2 - Resulted from a spill clean-up, equipment decommissioning, or emergency removal.'),
        ('3 - Derived from the on-site management of a non-hazardous waste.', '3 - Derived from the on-site management of a non-hazardous waste.'),
        ('4 - Was received from off-site and was not recycled or treated on-site.', '4 - Was received from off-site and was not recycled or treated on-site.'),
        ('5 - Was residual from the on-site treatment, disposal, or recycling of preciously existing hazardous waste.', '5 - Was residual from the on-site treatment, disposal, or recycling of preciously existing hazardous waste.'),
        ('6 - Was from a state, federal, or locally funded cleanup.', '6 - Was from a state, federal, or locally funded cleanup.'),
        ('7 - Was from a corrective action or closure.', '7 - Was from a corrective action or closure.'),
    )

    EPAForm_CHOICES = (
        ("0","N/A"),
        ("Mixed Media/Debris/Devices",(
                                    ("W001 - LAB PACKS FROM ANY SOURCE NOT CONTAINING ACUTE HAZARDOUS WASTE","W001 - LAB PACKS FROM ANY SOURCE NOT CONTAINING ACUTE HAZARDOUS WASTE"),
                                    ("W002 - CONTAMINATED DEBRIS: PAPER, CLOTHING, RAGS, WOOD, EMPTY FIBER OR PLASTIC CONTAINERS, GLASS, PIPING, OTHER SOLIDS","W002 - CONTAMINATED DEBRIS: PAPER, CLOTHING, RAGS, WOOD, EMPTY FIBER OR PLASTIC CONTAINERS, GLASS, PIPING, OTHER SOLIDS"),
                                    ("W004 - LAB PACKS FROM ANY SOURCE CONTAINING ACUTE HAZARDOUS WASTE","W004 - LAB PACKS FROM ANY SOURCE CONTAINING ACUTE HAZARDOUS WASTE"),
                                    ("W005 - WASTE PHARMACEUTICALS MANAGED AS HAZARDOUS WASTE","W005 - WASTE PHARMACEUTICALS MANAGED AS HAZARDOUS WASTE"),
                                    ("W301 - CONTAMINATED SOIL","W301 - CONTAMINATED SOIL"),
                                    ("W309 - BATTERIES, BATTERY PARTS, CORES, CASINGS","W309 - BATTERIES, BATTERY PARTS, CORES, CASINGS"),
                                    ("W310 - FILTERS, SOLID ADSORBENTS, ION EXCHANGE RESINS AND SPENT CARBON","W310 - FILTERS, SOLID ADSORBENTS, ION EXCHANGE RESINS AND SPENT CARBON"),
                                    ("W320 - ELECTRICAL DEVICES (LAMPS, THERMOSTATS, CRTS, ETC.)","W320 - ELECTRICAL DEVICES (LAMPS, THERMOSTATS, CRTS, ETC.)"),
                                    ("W512 - SEDIMENT OR LAGOON DRAGOUT, DRILLING OR OTHER MUDS","W512 - SEDIMENT OR LAGOON DRAGOUT, DRILLING OR OTHER MUDS"),
                                    ("W801 - COMPRESSED GAS","W801 - COMPRESSED GAS"),
                                )
        ),
        ("Inorganic Liquids",(
                            ("W101 - VERY DILUTE AQUEOUS WASTE CONTAINING MORE THAN 99% WATER","W101 - VERY DILUTE AQUEOUS WASTE CONTAINING MORE THAN 99% WATER"),
                            ("W103 - SPENT CONCENTRATED ACID","W103 - SPENT CONCENTRATED ACID"),
                            ("W105 - ACIDIC AQUEOUS WASTES LESS THAN 5% ACID","W105 - ACIDIC AQUEOUS WASTES LESS THAN 5% ACID"),
                            ("W107 - AQUEOUS WASTE CONTAINING CYANIDES","W107 - AQUEOUS WASTE CONTAINING CYANIDES"),
                            ("W110 - CAUSTIC AQUEOUS WASTE WITHOUT CYANIDES","W110 - CAUSTIC AQUEOUS WASTE WITHOUT CYANIDES"),
                            ("W113 - OTHER AQUEOUS WASTE OR WASTEWATERS","W113 - OTHER AQUEOUS WASTE OR WASTEWATERS"),
                            ("W117 - WASTE LIQUID MERCURY","W117 - WASTE LIQUID MERCURY"),
                            ("W119 - OTHER INORGANIC LIQUID","W119 - OTHER INORGANIC LIQUID"),
                        )
        ),
        ("Organic Liquids",(
                            ("W200 - STILL BOTTOMS IN LIQUID FORM","W200 - STILL BOTTOMS IN LIQUID FORM"),
                            ("W202 - CONCENTRATED HALOGENATED (E.G. CHLORINATED) SOLVENT","W202 - CONCENTRATED HALOGENATED (E.G. CHLORINATED) SOLVENT"),
                            ("W203 - CONCENTRATED NON-HALOGENATED (E.G. NON-CHLORINATED) SOLVENT","W203 - CONCENTRATED NON-HALOGENATED (E.G. NON-CHLORINATED) SOLVENT"),
                            ("W204 - CONCENTRATED HALOGENATED / NON-HALOGENATED SOLVENT MIXTURE","W204 - CONCENTRATED HALOGENATED / NON-HALOGENATED SOLVENT MIXTURE"),
                            ("W205 - OIL-WATER EMULSION OR MIXTURE","W205 - OIL-WATER EMULSION OR MIXTURE"),
                            ("W206 - WASTE OIL MANAGED AS HAZARDOUS WASTE","W206 - WASTE OIL MANAGED AS HAZARDOUS WASTE"),
                            ("W209 - PAINT, INK, LACQUER, OR VARNISH","W209 - PAINT, INK, LACQUER, OR VARNISH"),
                            ("W210 - REACTIVE OR POLYMERIZABLE ORGANIC LIQUIDS AND ADHESIVES","W210 - REACTIVE OR POLYMERIZABLE ORGANIC LIQUIDS AND ADHESIVES"),
                            ("W211 - PAINT THINNER OR PETROLEUM DISTILLATES","W211 - PAINT THINNER OR PETROLEUM DISTILLATES"),
                            ("W219 - OTHER ORGANIC LIQUID","W219 - OTHER ORGANIC LIQUID"),
                        )
        ),
        ("Inorganic Solids",(
                            ("W303 - ASH","W303 - ASH"),
                            ("W304 - SLAGS, DROSSES, AND OTHER SOLID THERMAL RESIDUES","W304 - SLAGS, DROSSES, AND OTHER SOLID THERMAL RESIDUES"),
                            ("W307 - METAL SCALE, FILINGS AND SCRAP (INCLUDING METAL DRUMS)","W307 - METAL SCALE, FILINGS AND SCRAP (INCLUDING METAL DRUMS)"),
                            ("W312 - CYANIDE OR METAL CYANIDE BEARING SOLIDS, SALTS OR CHEMICALS","W312 - CYANIDE OR METAL CYANIDE BEARING SOLIDS, SALTS OR CHEMICALS"),
                            ("W316 - METAL SALTS OR CHEMICALS NOT CONTAINING CYANIDES","W316 - METAL SALTS OR CHEMICALS NOT CONTAINING CYANIDES"),
                            ("W319 - OTHER INORGANIC SOLIDS","W319 - OTHER INORGANIC SOLIDS"),
                        )
        ),
        ("Organic Solids",(
                            ("W401 - PESTICIDE SOLIDS","W401 - PESTICIDE SOLIDS"),
                            ("W403 - SOLID RESINS, PLASTICS OR POLYMERIZED ORGANICS","W403 - SOLID RESINS, PLASTICS OR POLYMERIZED ORGANICS"),
                            ("W405 - EXPLOSIVES OR REACTIVE ORGANIC SOLIDS","W405 - EXPLOSIVES OR REACTIVE ORGANIC SOLIDS"),
                            ("W406 - DRIED PAINT (PAINT CHIPS, FILTERS, AIR FILTERS, OTHER)","W406 - DRIED PAINT (PAINT CHIPS, FILTERS, AIR FILTERS, OTHER)"),
                            ("W409 - OTHER ORGANIC SOLIDS","W409 - OTHER ORGANIC SOLIDS"),
                        )
        ),
        ("Inorganic Sludges",(
                            ("W501 - LIME AND/OR METAL HYDROXIDE SLUDGES AND SOLIDS WITH NO CYANIDES","W501 - LIME AND/OR METAL HYDROXIDE SLUDGES AND SOLIDS WITH NO CYANIDES"),
                            ("W503 - GYPSUM SLUDGES FROM WASTEWATER TREATMENT OR AIR POLLUTION CONTROL","W503 - GYPSUM SLUDGES FROM WASTEWATER TREATMENT OR AIR POLLUTION CONTROL"),
                            ("W504 - OTHER SLUDGES FROM WASTEWATER TREATMENT OR AIR POLLUTION CONTROL","W504 - OTHER SLUDGES FROM WASTEWATER TREATMENT OR AIR POLLUTION CONTROL"),
                            ("W505 - METAL BEARING SLUDGES (INCLUDING PLATING SLUDGE) NOT CONTAINING CYANIDES","W505 - METAL BEARING SLUDGES (INCLUDING PLATING SLUDGE) NOT CONTAINING CYANIDES"),
                            ("W506 - CYANIDE-BEARING SLUDGES","W506 - CYANIDE-BEARING SLUDGES"),
                            ("W519 - OTHER INORGANIC SLUDGES","W519 - OTHER INORGANIC SLUDGES"),
                            ("W603 - OILY SLUDGE","W603 - OILY SLUDGE"),
                            ("W604 - PAINT OR INK SLUDGES, STILL BOTTOMS IN SLUDGE FORM","W604 - PAINT OR INK SLUDGES, STILL BOTTOMS IN SLUDGE FORM"),
                            ("W606 - RESINS, TARS, POLYMER OR TARRY SLUDGE","W606 - RESINS, TARS, POLYMER OR TARRY SLUDGE"),
                            ("W609 - OTHER ORGANIC SLUDGE","W609 - OTHER ORGANIC SLUDGE"),
            )
        ),
    )

    WCHazardous= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    WCHazardousComment= forms.ChoiceField(choices=Exemption_CHOICES_RADIO, widget=forms.Select())
    WCHazardousF= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    #WCHazardousFYes= forms.ManyToManyField(EPA_FK, related_name='WasteStream_WasteClassHazardousF')
    WCHazardousK= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    #WCHazardousKYes= forms.ManyToManyField(EPA_FK, related_name='WasteStream_WasteClassHazardousK')
    WCHazardousP= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    #WCHazardousPYes= forms.ManyToManyField(EPA_PU, related_name='WasteStream_WasteClassHazardousP')
    WCHazardousU= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    #WCHazardousUYes= forms.ManyToManyField(EPA_PU, related_name='WasteStream_WasteClassHazardousU')
    WCHazardousIgnitable= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    WCHazardousCorrosive = forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    WCHazardousReactive= forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    WCHazardousToxic = forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())

    StateWasteCode = forms.CharField(max_length=255)
    UniversalWaste = forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    UsedOil = forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    TSCARegulatedPCBWaste = forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    NonHazardousWaste = forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    HazardousWaste = forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    RCRAExempt = forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    CERCLARegulatedWaste = forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    BenzeneNESHAPWaste  = forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())
    HalogenatedOrganicCompound = forms.ChoiceField(choices=YESNO_CHOICES_RADIO, widget=forms.RadioSelect())

    OriginCode = forms.ChoiceField(choices=ORIGIN_CHOICES, widget=forms.Select())
    EPAFormCode = forms.ChoiceField(choices=EPAForm_CHOICES, widget=forms.Select())
    WasteDeterminationBasedOn = forms.ChoiceField(choices=WasteDetermination_CHOICES_RADIO, widget=forms.RadioSelect())
    #WCHazardousToxicYes= forms.ManyToManyField(EPA_D, related_name='WasteStream_WasteClassHazardousD')
    #CustomerProfile = forms.ForeignKey(CustomerProfile, on_delete=forms.CASCADE)

    class Meta:
        model = RegulatoryInformation
        fields = '__all__'
        exclude = ('WCHazardousFYes','WCHazardousKYes','WCHazardousPYes','WCHazardousUYes','WCHazardousToxicYes','WCSolidWaste','WCSolidWasteComment',)

class CertificationForm(ModelForm):
    #CertificationGeneratorRepresentativeName= forms.ModelChoiceField(queryset=Personnel.objects.filter(AcctMgr=True).order_by('Name'))
    #CertificationGeneratorTitle= forms.CharField(max_length=4000)
    CertificationGeneratorSignature= forms.CharField(max_length=4000)
    CertificationDate= forms.DateField(input_formats=(settings.DATE_INPUT_FORMATS, ), widget=forms.DateInput(format=settings.DATE_INPUT_FORMATS,attrs={'class': 'inputcalendar2'}))
    #UserId = forms.ForeignKey(User, on_delete=forms.PROTECT)
    #CustomerProfile = forms.ForeignKey(CustomerProfile, on_delete=forms.CASCADE)

    class Meta:
        model = Certification
        fields = '__all__'

        widgets = {
            'CertificationGeneratorRepresentativeName': forms.Select(attrs={'onchange': 'changecontact(this.value)'}),
        }
    def __init__(self, *args, **kwargs):
        Customer_id = kwargs.pop('Customer_id', None)
        super(CertificationForm, self).__init__(*args, **kwargs)
        if Customer_id:
            self.fields['CertificationGeneratorRepresentativeName'].queryset = MasterContact.objects.filter(gen_mastercontact__Customer_id=Customer_id)

class WasteProfileChemicalForm(ModelForm):
    CHEMICAL_UNITTYPE_CHOICES = (
        ("","-----"),
        ("Vol %","Vol %"),
        ("Wt %","Wt %"),
        ("PPM","PPM"),
    )
    ChemicalPhysicalComposion = forms.CharField(max_length=255)
    CAS= forms.CharField(max_length=255)
    Typical= forms.CharField(max_length=255)
    Range= forms.CharField(max_length=255)
    UnitType = forms.ChoiceField(choices=CHEMICAL_UNITTYPE_CHOICES, widget=forms.Select())
    #GeneratingProcessAndMaterialComposition = forms.ForeignKey(GeneratingProcessAndMaterialComposition, on_delete=forms.CASCADE)
    class Meta:
        model = WasteProfileChemical
        fields = '__all__'

""" class WasteProfileShippingPackagingForm(ModelForm):
    ContainerType_CHOICES = (
        ("BA","BA - Burlap, cloth, paper or plastic bags"),
        ("CF","CF - Fiber or plastic boxes, cartons, cases"),
        ("CM","CM - Metal boxes, barrel, kegs, cartons, cases (including roll offs)"),
        ("CW","CW - Wooden boxes, carton, cases"),
        ("CY","CY - Cylinder"),
        ("DF","DF - Fiberboard or plastic drums"),
        ("DM","DM - Metal Drums, barrels, kegs"),
        ("DT","DT - Dump Truck"),
        ("DW","DW - Wooden drums, barrels, keg"),
        ("TP","TP - Tanks portable"),
        ("TT","TT - Tank Truck"),
    )
    ContainerType = forms.CharField(max_length=255)
    ContainerSize= forms.CharField(max_length=255)
    VolumeType = forms.CharField(max_length=255)
    CostBasis= forms.CharField(max_length=255)
    Cost= forms.CharField(max_length=255)
    MinCost=forms.CharField(max_length=255)
    MinCostUnit=forms.CharField(max_length=255)
    #ShippingAndPackagingInformation = forms.ForeignKey(ShippingAndPackagingInformation, on_delete=forms.CASCADE)
    class Meta:
        model = WasteProfileShippingPackaging
        fields = '__all__' """


#!/usr/bin/env python
import importlib
import os
import sys

import click
import pytest

from app import app

@click.command()
@click.argument('command')
@click.option(
    '--config',
    default=None,
    help='default: configs, 所有的 config 都在 configs 目录下,'
    ' example: configs.local_settings')
def manage(command, config):
    """
    python manage.py [command]
    command: [runserver|sync_db|test]
    """
    # 加载配置模块
    if config is None:
        config = 'configs'
    click.echo('\nUsing config: %s\n' % config)
    config_object = importlib.import_module(config)
    app.config.from_object(config_object)

    # 查找本模块中的函数并执行
    all_params = globals()
    if command not in all_params:
        raise SystemExit('Wrong command')

    command_func = all_params[command]
    command_func()

def test():
    """
    执行 pytest 测试
    测试时, 允许 cqlengine 修改数据表结构
    """
    os.environ['CQLENG_ALLOW_SCHEMA_MANAGEMENT'] = 'true'

    base_dir = os.path.dirname(os.path.abspath(__file__))
    # 添加 -x option, 遇到 error 和 failed 直接退出
    sys.exit(
        pytest.main([
            '--cov=views', '--cov-report=term-missing',
            '--cov-report=annotate', '-x', '-v', '-s', base_dir
        ]))

def runserver():
    """
    运行服务器
    """
    from app.server import run_server

    run_server()

def sync_db():
    """
    同步数据库
    """
    from models.management import DatabaseManagement

    os.environ['CQLENG_ALLOW_SCHEMA_MANAGEMENT'] = 'true'
    DatabaseManagement().sync_db()

def shell():
    """
    进入 IPython 交互
    """
    from models.management import DatabaseManagement
    from IPython import embed

    data_management = DatabaseManagement()
    data_management.connect()
    embed()

if __name__ == '__main__':
    manage()


from setuptools import find_packages
from setuptools import setup

#####
# We need to install some additional packages in order to compile
# OpenAI Gym on CMLE.
# Reference:
# https://github.com/apache/beam/blob/master/sdks/python/apache_beam/examples/complete/juliaset/setup.py
import subprocess
from distutils.command.build import build as _build

import setuptools

class build(_build):
    """A build command class that will be invoked during package install.
    The package built using the current setup.py will be staged and later
    installed in the worker using `pip install package'. This class will be
    instantiated during install for this specific scenario and will trigger
    running the custom commands specified.
    """
    sub_commands = _build.sub_commands + [('CustomCommands', None)]

# The list of required libraries is taken from:
# https://github.com/openai/gym#installing-everything
_LIBS = 'python-numpy python-dev cmake zlib1g-dev libjpeg-dev xvfb libav-tools xorg-dev python-opengl libboost-all-dev libsdl2-dev swig'.split()

CUSTOM_COMMANDS = [
    ['apt-get', 'update'],
    ['apt-get', 'install', '-y'] + _LIBS,
]

class CustomCommands(setuptools.Command):
    """A setuptools Command class able to run arbitrary commands."""
    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def RunCustomCommand(self, command_list):
        print('Running command: %s' % command_list)
        p = subprocess.Popen(
            command_list,
            stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        # Can use communicate(input='y\n'.encode()) if the command run requires
        # some confirmation.
        stdout_data, _ = p.communicate()
        print('Command output: %s' % stdout_data)
        if p.returncode != 0:
            raise RuntimeError('Command %s failed: exit code: %s' % (command_list, p.returncode))

    def run(self):
        for command in CUSTOM_COMMANDS:
            self.RunCustomCommand(command)

#####

REQUIRED_PACKAGES = [
    'pip>=19.1',
    'absl-py==0.2.2',
    'anago==1.0.8',
    'aniso8601==1.2.0',
    'asn1crypto==0.24.0',
    'astor==0.6.2',
    'beautifulsoup4==4.6.0',
    'bleach==1.5.0',
    'boto==2.48.0',
    'boto3==1.7.24',
    'botocore==1.10.24',
    'bz2file==0.98',
    'certifi==2018.4.16',
    'cffi==1.11.5',
    'chardet==3.0.4',
    'click==6.7',
    'cryptography==2.2.2',
    'docutils==0.14',
    'Flask==1.0.2',
    'Flask-RESTful==0.3.6',
    'gast==0.2.0',
    'gensim==3.4.0',
    'grpcio==1.12.1',
    'h5py==2.9.0',
    'html5lib==0.9999999',
    'idna==2.6',
    'itsdangerous==0.24',
    'Jinja2==2.10',
    'jmespath==0.9.3',
    'Keras==2.2.4',
    'Keras-Applications==1.0.7',
    'Keras-Preprocessing==1.0.9',
    'lxml==4.2.1',
    'Markdown==2.6.11',
    'MarkupSafe==1.0',
    'nltk==3.3',
    'numpy==1.14.3',
    'pandas==0.23.0',
    'protobuf>=3.6.0',
    'pycparser==2.18',
    'pycrypto==2.6.1',
    'pymongo==3.4.0',
    'pyOpenSSL==18.0.0',
    'PySocks==1.6.8',
    'python-dateutil==2.7.3',
    'pytz==2018.4',
    'PyYAML==5.1',
    'requests==2.18.4',
    's3transfer==0.1.13',
    'scikit-learn==0.19.1',
    'scipy==1.1.0',
    'seqeval==0.0.9',
    'six==1.11.0',
    'smart-open==1.5.7',
    'SQLAlchemy==1.2.8',
    'tensorboard==1.8.0',
    'tensorflow==1.8.0',
    'termcolor==1.1.0',
    'urllib3==1.22',
    'uWSGI==2.0.17',
    'Werkzeug==0.14.1'
]

setup(
    name='aloner',
    version='0.1',
    install_requires=REQUIRED_PACKAGES,
    packages=find_packages(),
    include_package_data=True,
    package_data={'trainer': ['data/*.txt','models/*.txt']},
    description='Alodokter NER using Anago',
    cmdclass={
        # Command class instantiated and run during pip install scenarios.
        'build': build,
        'CustomCommands': CustomCommands,
    }
)


#!/usr/bin/env python

import asyncio
from decimal import Decimal
from datetime import datetime

import aiohttp
import logging
# import pandas as pd
# import math

import requests
import cachetools.func

from typing import AsyncIterable, Dict, List, Optional, Any

import time
import ujson
import websockets
from websockets.exceptions import ConnectionClosed

from hummingbot.connector.exchange.dydx.dydx_order_book import DydxOrderBook
from hummingbot.connector.exchange.dydx.dydx_active_order_tracker import DydxActiveOrderTracker
from hummingbot.connector.exchange.dydx.dydx_api_token_configuration_data_source import DydxAPITokenConfigurationDataSource
from hummingbot.connector.exchange.dydx.dydx_utils import convert_from_exchange_trading_pair, convert_to_exchange_trading_pair, convert_v2_pair_to_v1
from hummingbot.core.data_type.order_book_tracker_data_source import OrderBookTrackerDataSource
from hummingbot.logger import HummingbotLogger
from hummingbot.core.data_type.order_book import OrderBook
from hummingbot.core.data_type.order_book_message import OrderBookMessage

MARKETS_URL = "/markets"
TICKER_URL = "/stats/markets"
SNAPSHOT_URL = "/orderbook"

WS_URL = "wss://api.dydx.exchange/v1/ws"
DYDX_V1_API_URL = "https://api.dydx.exchange/v1"
DYDX_V2_API_URL = "https://api.dydx.exchange/v2"
DYDX_ORDERBOOK_URL = "https://api.dydx.exchange/v1/orderbook/{}"
DYDX_MARKET_INFO_URL = "https://api.dydx.exchange/v2/markets/{}"

class DydxAPIOrderBookDataSource(OrderBookTrackerDataSource):

    MESSAGE_TIMEOUT = 30.0
    PING_TIMEOUT = 10.0

    __daobds__logger: Optional[HummingbotLogger] = None

    @classmethod
    def logger(cls) -> HummingbotLogger:
        if cls.__daobds__logger is None:
            cls.__daobds__logger = logging.getLogger(__name__)
        return cls.__daobds__logger

    def __init__(self, trading_pairs: List[str] = None, rest_api_url="", websocket_url="", token_configuration=None):
        super().__init__(trading_pairs)
        self.REST_URL = rest_api_url
        self.WS_URL = websocket_url
        self._get_tracking_pair_done_event: asyncio.Event = asyncio.Event()
        self.order_book_create_function = lambda: OrderBook()
        self._token_configuration: DydxAPITokenConfigurationDataSource = token_configuration
        self.token_configuration
        self._active_order_tracker: DydxActiveOrderTracker = DydxActiveOrderTracker(self.token_configuration)

    @property
    def token_configuration(self) -> DydxAPITokenConfigurationDataSource:
        if not self._token_configuration:
            self._token_configuration = DydxAPITokenConfigurationDataSource.create()
        return self._token_configuration

    @property
    def active_order_tracker(self) -> DydxActiveOrderTracker:
        if not self._active_order_tracker:
            self._active_order_tracker = DydxActiveOrderTracker(self.token_configuration)
        return self._active_order_tracker

    @classmethod
    async def get_last_traded_prices(cls, trading_pairs: List[str]) -> Dict[str, float]:
        async with aiohttp.ClientSession() as client:
            resp = await client.get(f"{DYDX_V1_API_URL}{TICKER_URL}")
            resp_json = await resp.json()
            retval = {}
            for pair in trading_pairs:
                retval[pair] = float(resp_json["markets"][convert_v2_pair_to_v1(pair)]["last"])
            return retval

    @property
    def order_book_class(self) -> DydxOrderBook:
        return DydxOrderBook

    @property
    def trading_pairs(self) -> List[str]:
        return self._trading_pairs

    async def get_snapshot(self, client: aiohttp.ClientSession, trading_pair: str, level: int = 0) -> Dict[str, any]:
        async with client.get(f"{DYDX_V1_API_URL}{SNAPSHOT_URL}/{trading_pair}") as response:
            response: aiohttp.ClientResponse = response
            if response.status != 200:
                raise IOError(
                    f"Error fetching dydx market snapshot for {trading_pair}. " f"HTTP status is {response.status}."
                )
            data: Dict[str, Any] = await response.json()
            data["market"] = trading_pair
            return data

    async def get_new_order_book(self, trading_pair: str) -> OrderBook:
        async with aiohttp.ClientSession() as client:
            snapshot: Dict[str, Any] = await self.get_snapshot(client, trading_pair, 1000)
            snapshot_timestamp: float = time.time()
            snapshot_msg: OrderBookMessage = DydxOrderBook.snapshot_message_from_exchange(
                snapshot,
                snapshot_timestamp,
                metadata={"id": trading_pair}
            )
            order_book: OrderBook = self.order_book_create_function()
            bids, asks = self.active_order_tracker.convert_snapshot_message_to_order_book_row(snapshot_msg)
            order_book.apply_snapshot(bids, asks, snapshot_msg.update_id)
            return order_book

    async def _inner_messages(self, ws: websockets.WebSocketClientProtocol) -> AsyncIterable[str]:
        # Terminate the recv() loop as soon as the next message timed out, so the outer loop can reconnect.
        try:
            while True:
                try:
                    msg: str = await asyncio.wait_for(ws.recv(), timeout=self.MESSAGE_TIMEOUT)
                    yield msg
                except asyncio.TimeoutError:
                    try:
                        pong_waiter = await ws.ping()
                        await asyncio.wait_for(pong_waiter, timeout=self.PING_TIMEOUT)
                    except asyncio.TimeoutError:
                        raise
        except asyncio.TimeoutError:
            self.logger().warning("WebSocket ping timed out. Going to reconnect...")
            return
        except ConnectionClosed:
            return
        finally:
            await ws.close()

    @staticmethod
    @cachetools.func.ttl_cache(ttl=10)
    def get_mid_price(trading_pair: str) -> Optional[Decimal]:
        exchange_pair: str = convert_to_exchange_trading_pair(trading_pair)
        market_info_response = requests.get(url=DYDX_MARKET_INFO_URL.format(exchange_pair))
        market_info = market_info_response.json()
        base_decimals = market_info['market']['baseCurrency']['decimals']
        quote_decimals = market_info['market']['quoteCurrency']['decimals']

        resp = requests.get(url=DYDX_ORDERBOOK_URL.format(exchange_pair))
        record = resp.json()
        conversion_factor = Decimal(f"1e{base_decimals - quote_decimals}")
        best_bid = Decimal(record["bids"][0]["price"]) * conversion_factor
        best_ask = Decimal(record["asks"][0]["price"]) * conversion_factor
        return (best_bid + best_ask) / 2

    @staticmethod
    async def fetch_trading_pairs() -> List[str]:
        try:
            async with aiohttp.ClientSession() as client:
                async with client.get(DYDX_MARKET_INFO_URL.format(""), timeout=5) as response:
                    if response.status == 200:
                        all_trading_pairs: Dict[str, Any] = await response.json()
                        valid_trading_pairs: list = []
                        for item in all_trading_pairs["markets"].keys():
                            if "baseCurrency" in all_trading_pairs["markets"][item]:
                                valid_trading_pairs.append(item)
                        trading_pair_list: List[str] = []
                        for raw_trading_pair in valid_trading_pairs:
                            converted_trading_pair: Optional[str] = convert_from_exchange_trading_pair(raw_trading_pair)
                            if converted_trading_pair is not None:
                                trading_pair_list.append(converted_trading_pair)
                        return trading_pair_list
        except Exception:
            # Do nothing if the request fails -- there will be no autocomplete for dydx trading pairs
            pass

        return []

    async def listen_for_trades(self, ev_loop: asyncio.BaseEventLoop, output: asyncio.Queue):
        while True:
            try:
                async with websockets.connect(f"{WS_URL}") as ws:
                    ws: websockets.WebSocketClientProtocol = ws
                    for pair in self._trading_pairs:
                        subscribe_request: Dict[str, Any] = {
                            "type": "subscribe",
                            "channel": "trades",
                            "id": pair
                        }
                        await ws.send(ujson.dumps(subscribe_request))
                    async for raw_msg in self._inner_messages(ws):
                        msg = ujson.loads(raw_msg)
                        if "contents" in msg:
                            if "trades" in msg["contents"]:
                                for datum in msg["contents"]["trades"]:
                                    trade_msg: OrderBookMessage = DydxOrderBook.trade_message_from_exchange(datum, msg)
                                    output.put_nowait(trade_msg)
            except asyncio.CancelledError:
                raise
            except Exception:
                self.logger().error("Unexpected error with WebSocket connection. Retrying after 30 seconds...",
                                    exc_info=True)
                await asyncio.sleep(30.0)

    async def listen_for_order_book_diffs(self, ev_loop: asyncio.BaseEventLoop, output: asyncio.Queue):
        while True:
            try:
                async with websockets.connect(f"{WS_URL}") as ws:
                    ws: websockets.WebSocketClientProtocol = ws
                    for pair in self._trading_pairs:
                        subscribe_request: Dict[str, Any] = {
                            "type": "subscribe",
                            "channel": "orderbook",
                            "id": pair
                        }
                        await ws.send(ujson.dumps(subscribe_request))
                    async for raw_msg in self._inner_messages(ws):
                        msg = ujson.loads(raw_msg)
                        if "contents" in msg:
                            if "updates" in msg["contents"]:
                                ts = datetime.timestamp(datetime.now())
                                for item in msg["contents"]["updates"]:
                                    order_msg: OrderBookMessage = DydxOrderBook.diff_message_from_exchange(item, ts, msg)
                                    output.put_nowait(order_msg)
                            elif "bids" in msg["contents"]:
                                ts = datetime.timestamp(datetime.now())
                                order_msg: OrderBookMessage = DydxOrderBook.snapshot_message_from_exchange(msg["contents"], ts, msg)
                                output.put_nowait(order_msg)
            except asyncio.CancelledError:
                raise
            except Exception:
                self.logger().error("Unexpected error with WebSocket connection. Retrying after 30 seconds...",
                                    exc_info=True)
                await asyncio.sleep(30.0)

    async def listen_for_order_book_snapshots(self, ev_loop: asyncio.BaseEventLoop, output: asyncio.Queue):
        pass


# the point of this is to find the best orientation of the xarm in terms of
# the workspace volume
import pybullet as pb
import numpy as np
import time
from scipy.spatial.transform import Rotation as R

from nuro_arm.robot.robot_arm import RobotArm

N_GRIPPER_THETAS = 5
gripper_thetas = np.linspace(-np.pi/2, np.pi/2, num=N_GRIPPER_THETAS)

XY_SPACING = 0.01
WIDTH = 0.08
HEIGHT = 0.08
X_CENTER = 0.16
Y_CENTER = 0.0
x_points = np.arange(X_CENTER-HEIGHT, X_CENTER+HEIGHT+XY_SPACING, XY_SPACING)
y_points = np.arange(Y_CENTER-WIDTH, Y_CENTER+WIDTH+XY_SPACING, XY_SPACING)
N_BASE_HEIGHTS = 5
BASE_HEIGHT_SPACING = 0.02
base_heights = BASE_HEIGHT_SPACING*(np.arange(N_BASE_HEIGHTS)-N_BASE_HEIGHTS//2)
xyz_points = np.stack(np.meshgrid(x_points, y_points, base_heights)).T.reshape(-1,3)
print(xyz_points.shape)

feasiblility = np.zeros(xyz_points.shape[:-1], dtype=int)
print(feasiblility.shape)

robot = RobotArm('sim', headless=False, realtime=False)
robot.close_gripper()
pb.removeBody(robot._sim.plane_id)

id_ = pb.createVisualShape(pb.GEOM_BOX,
                           halfExtents=[0.005, 0.005, 0.01],
                           rgbaColor=[0.1,0.8,0.2,0.5])
pos_body = [0, 0, 0]
body = pb.createMultiBody(1, -1, id_, pos_body)

for pos in xyz_points:
    pb.resetBasePositionAndOrientation(body, pos, (0,0,0,1))
    for roll in gripper_thetas:
        yaw = np.arctan2(pos[1], pos[0])
        rot = R.from_euler('z', yaw) * R.from_euler('YZ', (np.pi, roll+np.pi))
        rot = rot.as_quat()

        jpos, info = robot.mp.calculate_ik(pos, rot)
        collisions = robot.mp.find_collisions(jpos, ignore_gripper=1)
        if len(collisions) > 0:
            break

        achieved_pos, achieved_rot = robot._sim.get_hand_pose()
        time.sleep(0.01)

# while 1:
    # pass


from collections import deque
import numpy as np
import random

class Memory():
	def __init__(self, max_size):
		self.mem = deque([], max_size)

	def add(self, memory):
		self.mem.append(memory)

	def sample(self, num):
		if num > len(self.mem):
			batch = list(self.mem)
		else:
			batch = random.sample(self.mem, num)
		observations = np.asarray([b[0] for b in batch]).reshape(-1,2,64,64)
		actions = np.asarray([b[1] for b in batch])
		rewards = np.asarray([b[2] for b in batch])
		new_observations = [b[3] for b in batch]
		return observations, actions, rewards, new_observations


#   home/models.py
#   Copyright (C) 2012 David Yamnitsky
#
#   Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
#   files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
#   modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
#   Software is furnished to do so, subject to the following conditions:
#
#   The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
#   WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
#   OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
#   OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

from django.db import models
from django.db.models import Q
from django.core.files.storage import FileSystemStorage
import operator

class BlogPostManager(models.Manager):
    def search(self, search_terms):
        terms = [term.strip() for term in search_terms.split()]
        q_objects = []

        for term in terms:
            q_objects.append(Q(title__icontains=term))
            q_objects.append(Q(content__icontains=term))

        qs = self.get_query_set()

        return qs.filter(reduce(operator.or_, q_objects))

class BlogPost(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=100)
    live = models.BooleanField()
    date = models.DateField()
    teaser = models.TextField()
    content = models.TextField()
    objects = BlogPostManager()

    def __unicode__(self):
        return self.title

class BlogPostFile(models.Model):
    post = models.ForeignKey(BlogPost)
    file = models.FileField(upload_to='%Y/%m/%d')

    def delete(self, *args, **kwargs):
        self.file.delete(save=True)
        super(BlogPostFile, self).delete(*args, **kwargs)


from wsgiref.util import FileWrapper

from django.contrib import messages
from django.http import HttpResponseNotFound, StreamingHttpResponse, HttpResponseRedirect
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _

from corehq.apps.data_interfaces.dispatcher import require_can_edit_data
from corehq.apps.export.forms import (
    IncrementalExportForm,
    UpdateIncrementalExportForm,
)
from corehq.apps.export.models.incremental import (
    IncrementalExport,
    IncrementalExportCheckpoint,
    generate_and_send_incremental_export,
)
from corehq.apps.reports.datatables import DataTablesColumn, DataTablesHeader
from corehq.apps.reports.dispatcher import DomainReportDispatcher
from corehq.apps.reports.generic import GenericTabularReport
from corehq.apps.reports.standard import DatespanMixin
from corehq.apps.settings.views import BaseProjectDataView
from corehq.apps.hqwebapp.views import CRUDPaginatedViewMixin
from corehq.motech.views import MotechLogDetailView
from corehq.toggles import INCREMENTAL_EXPORTS

@method_decorator(INCREMENTAL_EXPORTS.required_decorator(), name="dispatch")
class IncrementalExportView(BaseProjectDataView, CRUDPaginatedViewMixin):
    page_title = _("Incremental Export")
    urlname = "incremental_export_view"

    template_name = "export/incremental_export.html"

    @property
    def total(self):
        # How many documents are you paginating through?
        return self.base_query.count()

    @property
    def base_query(self):
        return IncrementalExport.objects.filter(domain=self.domain)

    @property
    def column_names(self):
        return [
            _("Active"),
            _("Name"),
            _("Case Data Export"),
            _("Connection Settings"),
            _("Edit"),
            _("Delete"),
            _("Resend all cases")
        ]

    @property
    def page_context(self):
        context = self.pagination_context
        return context

    @property
    def paginated_list(self):
        for incremental_export in self.base_query.all():
            yield {
                "itemData": self._item_data(incremental_export),
                "template": "base-incremental-export-template",
            }

    def _item_data(self, incremental_export):
        return {
            "id": incremental_export.id,
            "active": incremental_export.active,
            "name": incremental_export.name,
            "export_instance": incremental_export.export_instance.name,
            "connection_settings": incremental_export.connection_settings.name,
            "updateForm": self.get_update_form_response(
                self.get_update_form(instance=incremental_export)
            ),
        }

    def post(self, *args, **kwargs):
        return self.paginate_crud_response

    def get_deleted_item_data(self, item_id):
        deleted_export = IncrementalExport.objects.get(id=item_id, domain=self.domain)
        deleted_export.delete()
        return {
            "itemData": self._item_data(deleted_export),
            "template": "deleted-incremental-export-template",
        }

    def get_create_form(self, is_blank=False):
        if self.request.method == "POST" and not is_blank:
            return IncrementalExportForm(self.request, self.request.POST)
        return IncrementalExportForm(self.request)

    create_item_form_class = "form form-horizontal"

    def get_create_item_data(self, create_form):
        new_item = create_form.save()
        return {
            "itemData": self._item_data(new_item),
            "template": "base-incremental-export-template",
        }

    def get_update_form(self, instance=None):
        if instance is None:
            instance = IncrementalExport.objects.get(
                id=self.request.POST.get("id"), domain=self.domain
            )
        if self.request.method == "POST" and self.action == "update":
            return UpdateIncrementalExportForm(self.request, self.request.POST, instance=instance)
        return UpdateIncrementalExportForm(self.request, instance=instance)

    def get_updated_item_data(self, update_form):
        item = update_form.save()
        return {
            "itemData": self._item_data(item),
            "template": "base-incremental-export-template",
        }

class IncrementalExportLogView(GenericTabularReport, DatespanMixin):
    name = "Incremental Export Logs"
    base_template = "reports/base_template.html"
    section_name = "Project Settings"
    slug = "incremental_export_logs"

    dispatcher = DomainReportDispatcher
    ajax_pagination = True
    asynchronous = False
    sortable = False

    fields = [
        "corehq.apps.reports.filters.dates.DatespanFilter",
        "corehq.apps.reports.filters.select.IncrementalExportFilter",
    ]

    default_datespan_end_date_to_today = True

    @property
    def total_records(self):
        return self._get_checkpoints().count()

    def _get_checkpoints(self):
        checkpoints = IncrementalExportCheckpoint.objects.filter(
            incremental_export__domain=self.domain,
            date_created__range=(self.datespan.startdate_param_utc, self.datespan.enddate_param_utc),
        ).order_by("-date_created")

        if self.incremental_export_id:
            checkpoints = checkpoints.filter(incremental_export__id=self.incremental_export_id,)
        return checkpoints

    @property
    def headers(self):
        columns = [
            DataTablesColumn(_("Status")),
            DataTablesColumn(_("Incremenal Export Name")),
            DataTablesColumn(_("Date")),
            DataTablesColumn(_("Cases in export")),
            DataTablesColumn(_("Download File")),
            DataTablesColumn(_("Request Details")),
            DataTablesColumn(_("Resend all cases")),
        ]
        return DataTablesHeader(*columns)

    @property
    def incremental_export_id(self):
        return self.request.GET.get("incremental_export_id")

    @property
    def rows(self):
        rows = []

        for checkpoint in self._get_paged_checkpoints():
            if checkpoint.status == 1:
                status = f'{_("Success")}'
            else:
                status = f'{_("Failure")}'

            log_url = reverse(MotechLogDetailView.urlname, args=[self.domain, checkpoint.request_log_id])
            file_url = reverse("incremental_export_checkpoint_file", args=[self.domain, checkpoint.id])
            reset_url = reverse("incremental_export_reset_checkpoint", args=[self.domain, checkpoint.id])
            if checkpoint.blob_exists():
                download = f''
            else:
                download = _("File Expired")
            rows.append(
                [
                    mark_safe(status),
                    checkpoint.incremental_export.name,
                    checkpoint.date_created.strftime("%Y-%m-%d %H:%M:%S"),
                    checkpoint.doc_count,
                    mark_safe(download),
                    mark_safe(f'{_("Request Details")}'),
                    mark_safe(
                        f'{_("Resend all cases after this checkpoint")}'
                    ),
                ]
            )

        return rows

    def _get_paged_checkpoints(self):
        return self._get_checkpoints()[
            self.pagination.start: (self.pagination.start + self.pagination.count)
        ]

    @property
    def shared_pagination_GET_params(self):
        params = super(IncrementalExportLogView, self).shared_pagination_GET_params
        params.extend(
            [
                {"name": "startdate", "value": self.datespan.startdate.strftime("%Y-%m-%d")},
                {"name": "enddate", "value": self.datespan.enddate.strftime("%Y-%m-%d")},
                {
                    "name": "incremental_export_id",
                    "value": self.request.GET.get("incremental_export_id"),
                },
            ]
        )
        return params

@require_can_edit_data
def incremental_export_checkpoint_file(request, domain, checkpoint_id):
    try:
        checkpoint = IncrementalExportCheckpoint.objects.get(
            id=checkpoint_id,
            incremental_export__domain=domain
        )
    except IncrementalExportCheckpoint.DoesNotExist:
        return HttpResponseNotFound()

    if not checkpoint.blob_exists():
        return HttpResponseNotFound()
    response = StreamingHttpResponse(FileWrapper(checkpoint.get_blob()), content_type='text/csv')
    response['Content-Disposition'] = f'attachment; filename="{checkpoint.filename}"'
    return response

@require_can_edit_data
def incremental_export_reset_checkpoint(request, domain, checkpoint_id):
    """Resend all cases after a particular checkpoint
    """
    try:
        checkpoint = IncrementalExportCheckpoint.objects.get(
            id=checkpoint_id,
            incremental_export__domain=domain
        )
    except IncrementalExportCheckpoint.DoesNotExist:
        return HttpResponseNotFound()

    incremental_export = checkpoint.incremental_export
    date = checkpoint.last_doc_date

    new_checkpoint = generate_and_send_incremental_export(incremental_export, date)
    doc_count = new_checkpoint.doc_count if new_checkpoint else 0
    messages.success(
        request, _(
            f"{doc_count} cases modified after {date.strftime('%Y-%m-%d %H:%M:%S')} have been resent"
        )
    )

    return HttpResponseRedirect(
        reverse('domain_report_dispatcher', args=[domain, IncrementalExportLogView.slug])
    )

@require_can_edit_data
def incremental_export_resend_all(request, domain, incremental_export_id):
    try:
        incremental_export = IncrementalExport.objects.get(id=incremental_export_id, domain=domain)
    except IncrementalExport.DoesNotExist:
        return HttpResponseNotFound()

    new_checkpoint = generate_and_send_incremental_export(incremental_export, from_date=None)
    doc_count = new_checkpoint.doc_count if new_checkpoint else 0
    messages.success(
        request, _(
            f"{doc_count} cases have been resent for export '{incremental_export.name}'"
        )
    )
    url = "{}?{}".format(
        reverse('domain_report_dispatcher', args=[domain, IncrementalExportLogView.slug]),
        "incremental_export_id={}".format(incremental_export_id)
    )
    return HttpResponseRedirect(url)