import ast
import json
import hashlib
from datetime import datetime, timedelta

from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
from django.utils.safestring import mark_safe
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.db.models import Q
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib import messages
from django.http.request import QueryDict
from django.contrib.auth.decorators import login_required, user_passes_test

try:
    from urllib.parse import urlencode
except ImportError:
    from urllib import urlencode

from .forms import CampaignForm, ExperimentForm, DeviceForm, ConfigurationForm, LocationForm, UploadFileForm, DownloadFileForm, OperationForm, NewForm
from .forms import OperationSearchForm, FilterForm, ChangeIpForm

from .tasks import task_start

from apps.rc.forms import RCConfigurationForm, RCLineCode, RCMixConfigurationForm
from apps.dds.forms import DDSConfigurationForm
from apps.jars.forms import JARSConfigurationForm
from apps.cgs.forms import CGSConfigurationForm
from apps.abs.forms import ABSConfigurationForm
from apps.usrp.forms import USRPConfigurationForm
from .utils import Params

from .models import Campaign, Experiment, Device, Configuration, Location, RunningExperiment, DEV_STATES
from apps.cgs.models import CGSConfiguration
from apps.jars.models import JARSConfiguration, EXPERIMENT_TYPE
from apps.usrp.models import USRPConfiguration
from apps.abs.models import ABSConfiguration
from apps.rc.models import RCConfiguration, RCLine, RCLineType
from apps.dds.models import DDSConfiguration

from radarsys.celery import app

CONF_FORMS = {
    'rc': RCConfigurationForm,
    'dds': DDSConfigurationForm,
    'jars': JARSConfigurationForm,
    'cgs': CGSConfigurationForm,
    'abs': ABSConfigurationForm,
    'usrp': USRPConfigurationForm,
}

CONF_MODELS = {
    'rc': RCConfiguration,
    'dds': DDSConfiguration,
    'jars': JARSConfiguration,
    'cgs': CGSConfiguration,
    'abs': ABSConfiguration,
    'usrp': USRPConfiguration,
}

MIX_MODES = {
    '0': 'P',
    '1': 'S',
}

MIX_OPERATIONS = {
    '0': 'OR',
    '1': 'XOR',
    '2': 'AND',
    '3': 'NAND',
}

def is_developer(user):

    groups = [str(g.name) for g in user.groups.all()]
    return 'Developer' in groups or user.is_staff

def is_operator(user):

    groups = [str(g.name) for g in user.groups.all()]
    return 'Operator' in groups or user.is_staff

def has_been_modified(model):

    prev_hash = model.hash
    new_hash = hashlib.sha256(str(model.parms_to_dict)).hexdigest()
    if prev_hash != new_hash:
        model.hash = new_hash
        model.save()
        return True
    return False

def index(request):
    kwargs = {'no_sidebar': True}

    return render(request, 'index.html', kwargs)

def locations(request):

    page = request.GET.get('page')
    order = ('name',)

    kwargs = get_paginator(Location, page, order)

    kwargs['keys'] = ['name', 'description']
    kwargs['title'] = 'Radar System'
    kwargs['suptitle'] = 'List'
    kwargs['no_sidebar'] = True

    return render(request, 'base_list.html', kwargs)

def location(request, id_loc):

    location = get_object_or_404(Location, pk=id_loc)

    kwargs = {}
    kwargs['location'] = location
    kwargs['location_keys'] = ['name', 'description']

    kwargs['title'] = 'Location'
    kwargs['suptitle'] = 'Details'

    return render(request, 'location.html', kwargs)

@login_required
def location_new(request):

    if request.method == 'GET':
        form = LocationForm()

    if request.method == 'POST':
        form = LocationForm(request.POST)

        if form.is_valid():
            form.save()
            return redirect('url_locations')

    kwargs = {}
    kwargs['form'] = form
    kwargs['title'] = 'Radar System'
    kwargs['suptitle'] = 'New'
    kwargs['button'] = 'Create'

    return render(request, 'base_edit.html', kwargs)

@login_required
def location_edit(request, id_loc):

    location = get_object_or_404(Location, pk=id_loc)

    if request.method == 'GET':
        form = LocationForm(instance=location)

    if request.method == 'POST':
        form = LocationForm(request.POST, instance=location)

        if form.is_valid():
            form.save()
            return redirect('url_locations')

    kwargs = {}
    kwargs['form'] = form
    kwargs['title'] = 'Location'
    kwargs['suptitle'] = 'Edit'
    kwargs['button'] = 'Update'

    return render(request, 'base_edit.html', kwargs)

@login_required
def location_delete(request, id_loc):

    location = get_object_or_404(Location, pk=id_loc)

    if request.method == 'POST':

        if request.user.is_staff:
            location.delete()
            return redirect('url_locations')

        messages.error(request, 'Not enough permission to delete this object')
        return redirect(location.get_absolute_url())

    kwargs = {
        'title': 'Delete',
        'suptitle': 'Location',
        'object': location,
        'delete': True
    }

    return render(request, 'confirm.html', kwargs)

def devices(request):

    page = request.GET.get('page')
    order = ('location', 'device_type')

    filters = request.GET.copy()
    kwargs = get_paginator(Device, page, order, filters)
    form = FilterForm(initial=request.GET, extra_fields=['tags'])

    kwargs['keys'] = ['device_type', 'location',
                      'ip_address', 'port_address', 'actions']
    kwargs['title'] = 'Device'
    kwargs['suptitle'] = 'List'
    kwargs['no_sidebar'] = True
    kwargs['form'] = form
    kwargs['add_url'] = reverse('url_add_device')
    filters.pop('page', None)
    kwargs['q'] = urlencode(filters)
    kwargs['menu'] = 'device'

    return render(request, 'base_list.html', kwargs)

def device(request, id_dev):

    device = get_object_or_404(Device, pk=id_dev)

    kwargs = {}
    kwargs['device'] = device
    kwargs['device_keys'] = ['device_type',
                             'ip_address', 'port_address', 'description']

    kwargs['title'] = 'Device'
    kwargs['suptitle'] = 'Details'

    return render(request, 'device.html', kwargs)

@login_required
def device_new(request):

    if request.method == 'GET':
        form = DeviceForm()

    if request.method == 'POST':
        form = DeviceForm(request.POST)

        if form.is_valid():
            form.save()
            return redirect('url_devices')

    kwargs = {}
    kwargs['form'] = form
    kwargs['title'] = 'Device'
    kwargs['suptitle'] = 'New'
    kwargs['button'] = 'Create'

    return render(request, 'base_edit.html', kwargs)

@login_required
def device_edit(request, id_dev):

    device = get_object_or_404(Device, pk=id_dev)

    if request.method == 'GET':
        form = DeviceForm(instance=device)

    if request.method == 'POST':
        form = DeviceForm(request.POST, instance=device)

        if form.is_valid():
            form.save()
            return redirect(device.get_absolute_url())

    kwargs = {}
    kwargs['form'] = form
    kwargs['title'] = 'Device'
    kwargs['suptitle'] = 'Edit'
    kwargs['button'] = 'Update'

    return render(request, 'base_edit.html', kwargs)

@login_required
def device_delete(request, id_dev):

    device = get_object_or_404(Device, pk=id_dev)

    if request.method == 'POST':

        if request.user.is_staff:
            device.delete()
            return redirect('url_devices')

        messages.error(request, 'Not enough permission to delete this object')
        return redirect(device.get_absolute_url())

    kwargs = {
        'title': 'Delete',
        'suptitle': 'Device',
        'object': device,
        'delete': True
    }

    return render(request, 'confirm.html', kwargs)

@login_required
def device_change_ip(request, id_dev):

    device = get_object_or_404(Device, pk=id_dev)

    if request.method == 'POST':

        if request.user.is_staff:
            device.change_ip(**request.POST.dict())
            level, message = device.message.split('|')
            messages.add_message(request, level, message)
        else:
            messages.error(
                request, 'Not enough permission to delete this object')
        return redirect(device.get_absolute_url())

    kwargs = {
        'title': 'Device',
        'suptitle': 'Change IP',
        'object': device,
        'previous': device.get_absolute_url(),
        'form': ChangeIpForm(initial={'ip_address': device.ip_address}),
        'message': ' ',
    }

    return render(request, 'confirm.html', kwargs)

def campaigns(request):

    page = request.GET.get('page')
    order = ('start_date',)
    filters = request.GET.copy()

    kwargs = get_paginator(Campaign, page, order, filters)

    form = FilterForm(initial=request.GET, extra_fields=[
                      'range_date', 'tags', 'template'])
    kwargs['keys'] = ['name', 'start_date', 'end_date', 'actions']
    kwargs['title'] = 'Campaign'
    kwargs['suptitle'] = 'List'
    kwargs['no_sidebar'] = True
    kwargs['form'] = form
    kwargs['add_url'] = reverse('url_add_campaign')
    filters.pop('page', None)
    kwargs['q'] = urlencode(filters)

    return render(request, 'base_list.html', kwargs)

def campaign(request, id_camp):

    campaign = get_object_or_404(Campaign, pk=id_camp)
    experiments = Experiment.objects.filter(campaign=campaign)

    form = CampaignForm(instance=campaign)

    kwargs = {}
    kwargs['campaign'] = campaign
    kwargs['campaign_keys'] = ['template', 'name',
                               'start_date', 'end_date', 'tags', 'description']

    kwargs['experiments'] = experiments
    kwargs['experiment_keys'] = [
        'name', 'radar_system', 'start_time', 'end_time']

    kwargs['title'] = 'Campaign'
    kwargs['suptitle'] = 'Details'

    kwargs['form'] = form
    kwargs['button'] = 'Add Experiment'

    return render(request, 'campaign.html', kwargs)

@login_required
def campaign_new(request):

    kwargs = {}

    if request.method == 'GET':

        if 'template' in request.GET:
            if request.GET['template'] == '0':
                form = NewForm(initial={'create_from': 2},
                               template_choices=Campaign.objects.filter(template=True).values_list('id', 'name'))
            else:
                kwargs['button'] = 'Create'
                kwargs['experiments'] = Configuration.objects.filter(
                    experiment=request.GET['template'])
                kwargs['experiment_keys'] = ['name', 'start_time', 'end_time']
                camp = Campaign.objects.get(pk=request.GET['template'])
                form = CampaignForm(instance=camp,
                                    initial={'name': '{}_{:%Y%m%d}'.format(camp.name, datetime.now()),
                                             'template': False})
        elif 'blank' in request.GET:
            kwargs['button'] = 'Create'
            form = CampaignForm()
        else:
            form = NewForm()

    if request.method == 'POST':
        kwargs['button'] = 'Create'
        post = request.POST.copy()
        experiments = []

        for id_exp in post.getlist('experiments'):
            exp = Experiment.objects.get(pk=id_exp)
            new_exp = exp.clone(template=False)
            experiments.append(new_exp)

        post.setlist('experiments', [])

        form = CampaignForm(post)

        if form.is_valid():
            campaign = form.save(commit=False)
            campaign.author = request.user
            for exp in experiments:
                campaign.experiments.add(exp)
            campaign.save()
            return redirect('url_campaign', id_camp=campaign.id)

    kwargs['form'] = form
    kwargs['title'] = 'Campaign'
    kwargs['suptitle'] = 'New'

    return render(request, 'campaign_edit.html', kwargs)

@login_required
def campaign_edit(request, id_camp):

    campaign = get_object_or_404(Campaign, pk=id_camp)

    if request.method == 'GET':
        form = CampaignForm(instance=campaign)

    if request.method == 'POST':
        exps = campaign.experiments.all().values_list('pk', flat=True)
        post = request.POST.copy()
        new_exps = post.getlist('experiments')
        post.setlist('experiments', [])
        form = CampaignForm(post, instance=campaign)

        if form.is_valid():
            camp = form.save()
            for id_exp in new_exps:
                if int(id_exp) in exps:
                    exps.pop(id_exp)
                else:
                    exp = Experiment.objects.get(pk=id_exp)
                    if exp.template:
                        camp.experiments.add(exp.clone(template=False))
                    else:
                        camp.experiments.add(exp)

            for id_exp in exps:
                camp.experiments.remove(Experiment.objects.get(pk=id_exp))

            return redirect('url_campaign', id_camp=id_camp)

    kwargs = {}
    kwargs['form'] = form
    kwargs['title'] = 'Campaign'
    kwargs['suptitle'] = 'Edit'
    kwargs['button'] = 'Update'

    return render(request, 'campaign_edit.html', kwargs)

@login_required
def campaign_delete(request, id_camp):

    campaign = get_object_or_404(Campaign, pk=id_camp)

    if request.method == 'POST':
        if request.user.is_staff:

            for exp in campaign.experiments.all():
                for conf in Configuration.objects.filter(experiment=exp):
                    conf.delete()
                exp.delete()
            campaign.delete()

            return redirect('url_campaigns')

        messages.error(request, 'Not enough permission to delete this object')
        return redirect(campaign.get_absolute_url())

    kwargs = {
        'title': 'Delete',
        'suptitle': 'Campaign',
        'object': campaign,
        'delete': True
    }

    return render(request, 'confirm.html', kwargs)

@login_required
def campaign_export(request, id_camp):

    campaign = get_object_or_404(Campaign, pk=id_camp)
    content = campaign.parms_to_dict()
    content_type = 'application/json'
    filename = '%s_%s.json' % (campaign.name, campaign.id)

    response = HttpResponse(content_type=content_type)
    response['Content-Disposition'] = 'attachment; filename="%s"' % filename
    response.write(json.dumps(content, indent=2))

    return response

@login_required
def campaign_import(request, id_camp):

    campaign = get_object_or_404(Campaign, pk=id_camp)

    if request.method == 'GET':
        file_form = UploadFileForm()

    if request.method == 'POST':
        file_form = UploadFileForm(request.POST, request.FILES)

        if file_form.is_valid():
            new_camp = campaign.dict_to_parms(
                json.load(request.FILES['file']), CONF_MODELS)
            messages.success(
                request, "Parameters imported from: '%s'." % request.FILES['file'].name)
            return redirect(new_camp.get_absolute_url_edit())

        messages.error(request, "Could not import parameters from file")

    kwargs = {}
    kwargs['title'] = 'Campaign'
    kwargs['form'] = file_form
    kwargs['suptitle'] = 'Importing file'
    kwargs['button'] = 'Import'

    return render(request, 'campaign_import.html', kwargs)

def experiments(request):

    page = request.GET.get('page')
    order = ('location',)
    filters = request.GET.copy()

    if 'my experiments' in filters:
        filters.pop('my experiments', None)
        filters['mine'] = request.user.id

    kwargs = get_paginator(Experiment, page, order, filters)

    fields = ['tags', 'template']
    if request.user.is_authenticated:
        fields.append('my experiments')

    form = FilterForm(initial=request.GET, extra_fields=fields)

    kwargs['keys'] = ['name', 'radar_system',
                      'start_time', 'end_time', 'actions']
    kwargs['title'] = 'Experiment'
    kwargs['suptitle'] = 'List'
    kwargs['no_sidebar'] = True
    kwargs['form'] = form
    kwargs['add_url'] = reverse('url_add_experiment')
    filters = request.GET.copy()
    filters.pop('page', None)
    kwargs['q'] = urlencode(filters)

    return render(request, 'base_list.html', kwargs)

def experiment(request, id_exp):

    experiment = get_object_or_404(Experiment, pk=id_exp)

    configurations = Configuration.objects.filter(
        experiment=experiment, type=0)

    kwargs = {}

    kwargs['experiment_keys'] = ['template', 'radar_system',
                                 'name', 'freq', 'start_time', 'end_time']
    kwargs['experiment'] = experiment

    kwargs['configuration_keys'] = ['name', 'device__ip_address',
                                    'device__port_address', 'device__status']
    kwargs['configurations'] = configurations

    kwargs['title'] = 'Experiment'
    kwargs['suptitle'] = 'Details'

    kwargs['button'] = 'Add Configuration'

    ###### SIDEBAR ######
    kwargs.update(sidebar(experiment=experiment))

    return render(request, 'experiment.html', kwargs)

@login_required
def experiment_new(request, id_camp=None):

    if not is_developer(request.user):
        messages.error(
            request, 'Developer required, to create new Experiments')
        return redirect('index')
    kwargs = {}

    if request.method == 'GET':
        if 'template' in request.GET:
            if request.GET['template'] == '0':
                form = NewForm(initial={'create_from': 2},
                               template_choices=Experiment.objects.filter(template=True).values_list('id', 'name'))
            else:
                kwargs['button'] = 'Create'
                kwargs['configurations'] = Configuration.objects.filter(
                    experiment=request.GET['template'])
                kwargs['configuration_keys'] = ['name', 'device__name',
                                                'device__ip_address', 'device__port_address']
                exp = Experiment.objects.get(pk=request.GET['template'])
                form = ExperimentForm(instance=exp,
                                      initial={'name': '{}_{:%y%m%d}'.format(exp.name, datetime.now()),
                                               'template': False})
        elif 'blank' in request.GET:
            kwargs['button'] = 'Create'
            form = ExperimentForm()
        else:
            form = NewForm()

    if request.method == 'POST':
        form = ExperimentForm(request.POST)
        if form.is_valid():
            experiment = form.save(commit=False)
            experiment.author = request.user
            experiment.save()

            if 'template' in request.GET:
                configurations = Configuration.objects.filter(
                    experiment=request.GET['template'], type=0)
                for conf in configurations:
                    conf.clone(experiment=experiment, template=False)

            return redirect('url_experiment', id_exp=experiment.id)

    kwargs['form'] = form
    kwargs['title'] = 'Experiment'
    kwargs['suptitle'] = 'New'

    return render(request, 'experiment_edit.html', kwargs)

@login_required
def experiment_edit(request, id_exp):

    experiment = get_object_or_404(Experiment, pk=id_exp)

    if request.method == 'GET':
        form = ExperimentForm(instance=experiment)

    if request.method == 'POST':
        form = ExperimentForm(request.POST, instance=experiment)

        if form.is_valid():
            experiment = form.save()
            return redirect('url_experiment', id_exp=experiment.id)

    kwargs = {}
    kwargs['form'] = form
    kwargs['title'] = 'Experiment'
    kwargs['suptitle'] = 'Edit'
    kwargs['button'] = 'Update'

    return render(request, 'experiment_edit.html', kwargs)

@login_required
def experiment_delete(request, id_exp):

    experiment = get_object_or_404(Experiment, pk=id_exp)

    if request.method == 'POST':
        if request.user.is_staff:
            for conf in Configuration.objects.filter(experiment=experiment):
                conf.delete()
            experiment.delete()
            return redirect('url_experiments')

        messages.error(request, 'Not enough permission to delete this object')
        return redirect(experiment.get_absolute_url())

    kwargs = {
        'title': 'Delete',
        'suptitle': 'Experiment',
        'object': experiment,
        'delete': True
    }

    return render(request, 'confirm.html', kwargs)

@login_required
def experiment_export(request, id_exp):

    experiment = get_object_or_404(Experiment, pk=id_exp)
    content = experiment.parms_to_dict()
    content_type = 'application/json'
    filename = '%s_%s.json' % (experiment.name, experiment.id)

    response = HttpResponse(content_type=content_type)
    response['Content-Disposition'] = 'attachment; filename="%s"' % filename
    response.write(json.dumps(content, indent=2))

    return response

@login_required
def experiment_import(request, id_exp):

    experiment = get_object_or_404(Experiment, pk=id_exp)
    configurations = Configuration.objects.filter(experiment=experiment)

    if request.method == 'GET':
        file_form = UploadFileForm()

    if request.method == 'POST':
        file_form = UploadFileForm(request.POST, request.FILES)

        if file_form.is_valid():
            new_exp = experiment.dict_to_parms(
                json.load(request.FILES['file']), CONF_MODELS)
            messages.success(
                request, "Parameters imported from: '%s'." % request.FILES['file'].name)
            return redirect(new_exp.get_absolute_url_edit())

        messages.error(request, "Could not import parameters from file")

    kwargs = {}
    kwargs['title'] = 'Experiment'
    kwargs['form'] = file_form
    kwargs['suptitle'] = 'Importing file'
    kwargs['button'] = 'Import'

    kwargs.update(sidebar(experiment=experiment))

    return render(request, 'experiment_import.html', kwargs)

@login_required
def experiment_start(request, id_exp):

    exp = get_object_or_404(Experiment, pk=id_exp)

    if exp.status == 2:
        messages.warning(request, 'Experiment {} already runnnig'.format(exp))
    else:
        exp.status = exp.start()
        if exp.status == 0:
            messages.error(request, 'Experiment {} not start'.format(exp))
        if exp.status == 2:
            messages.success(request, 'Experiment {} started'.format(exp))

        exp.save()

    return redirect(exp.get_absolute_url())

@login_required
def experiment_stop(request, id_exp):

    exp = get_object_or_404(Experiment, pk=id_exp)

    if exp.status == 2:
        exp.status = exp.stop()
        exp.save()
        messages.success(request, 'Experiment {} stopped'.format(exp))
    else:
        messages.error(request, 'Experiment {} not running'.format(exp))

    return redirect(exp.get_absolute_url())

def experiment_status(request, id_exp):

    exp = get_object_or_404(Experiment, pk=id_exp)

    exp.get_status()

    return redirect(exp.get_absolute_url())

@login_required
def experiment_mix(request, id_exp):

    experiment = get_object_or_404(Experiment, pk=id_exp)
    rc_confs = [conf for conf in RCConfiguration.objects.filter(
        experiment=id_exp,
        type=0,
        mix=False)]

    if len(rc_confs) < 2:
        messages.warning(
            request, 'You need at least two RC Configurations to make a mix')
        return redirect(experiment.get_absolute_url())

    mix_confs = RCConfiguration.objects.filter(experiment=id_exp, mix=True)

    if mix_confs:
        mix = mix_confs[0]
    else:
        mix = RCConfiguration(experiment=experiment,
                              device=rc_confs[0].device,
                              ipp=rc_confs[0].ipp,
                              clock_in=rc_confs[0].clock_in,
                              clock_divider=rc_confs[0].clock_divider,
                              mix=True,
                              parameters='')
        mix.save()

        line_type = RCLineType.objects.get(name='mix')
        for i in range(len(rc_confs[0].get_lines())):
            line = RCLine(rc_configuration=mix, line_type=line_type, channel=i)
            line.save()

    initial = {'name': mix.name,
               'result': parse_mix_result(mix.parameters),
               'delay': 0,
               'mask': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
               }

    if request.method == 'GET':
        form = RCMixConfigurationForm(confs=rc_confs, initial=initial)

    if request.method == 'POST':
        result = mix.parameters

        if '{}|'.format(request.POST['experiment']) in result:
            messages.error(request, 'Configuration already added')
        else:
            if 'operation' in request.POST:
                operation = MIX_OPERATIONS[request.POST['operation']]
            else:
                operation = '   '

            mode = MIX_MODES[request.POST['mode']]

            if result:
                result = '{}-{}|{}|{}|{}|{}'.format(mix.parameters,
                                                    request.POST['experiment'],
                                                    mode,
                                                    operation,
                                                    float(
                                                        request.POST['delay']),
                                                    parse_mask(
                                                        request.POST.getlist('mask'))
                                                    )
            else:
                result = '{}|{}|{}|{}|{}'.format(request.POST['experiment'],
                                                 mode,
                                                 operation,
                                                 float(request.POST['delay']),
                                                 parse_mask(
                                                     request.POST.getlist('mask'))
                                                 )

            mix.parameters = result
            mix.save()
            mix.update_pulses()

        initial['result'] = parse_mix_result(result)
        initial['name'] = mix.name

        form = RCMixConfigurationForm(initial=initial, confs=rc_confs)

    kwargs = {
        'title': 'Experiment',
        'suptitle': 'Mix Configurations',
        'form': form,
        'extra_button': 'Delete',
        'button': 'Add',
        'cancel': 'Back',
        'previous': experiment.get_absolute_url(),
        'id_exp': id_exp,

    }

    return render(request, 'experiment_mix.html', kwargs)

@login_required
def experiment_mix_delete(request, id_exp):

    conf = RCConfiguration.objects.get(experiment=id_exp, mix=True, type=0)
    values = conf.parameters.split('-')
    conf.parameters = '-'.join(values[:-1])
    conf.save()

    return redirect('url_mix_experiment', id_exp=id_exp)

def experiment_summary(request, id_exp):

    experiment = get_object_or_404(Experiment, pk=id_exp)
    configurations = Configuration.objects.filter(
        experiment=experiment, type=0)

    kwargs = {}
    kwargs['experiment_keys'] = ['radar_system',
                                 'name', 'freq', 'start_time', 'end_time']
    kwargs['experiment'] = experiment
    kwargs['configurations'] = []
    kwargs['title'] = 'Experiment Summary'
    kwargs['suptitle'] = 'Details'
    kwargs['button'] = 'Verify Parameters'

    c_vel = 3.0*(10**8)  # m/s
    ope_freq = experiment.freq*(10**6)  # 1/s
    radar_lambda = c_vel/ope_freq  # m
    kwargs['radar_lambda'] = radar_lambda

    ipp = None
    nsa = 1
    code_id = 0
    tx_line = {}

    for configuration in configurations.filter(device__device_type__name = 'rc'):

        if configuration.mix:
            continue
        conf = {'conf': configuration}
        conf['keys'] = []
        conf['NTxs'] = configuration.ntx
        conf['keys'].append('NTxs')
        ipp = configuration.ipp
        conf['IPP'] = ipp
        conf['keys'].append('IPP')
        lines = configuration.get_lines(line_type__name='tx')

        for tx_line in lines:
            tx_params = json.loads(tx_line.params)
            conf[tx_line.get_name()] = '{} Km'.format(tx_params['pulse_width'])
            conf['keys'].append(tx_line.get_name())
            delays = tx_params['delays']
            if delays not in ('', '0'):
                n = len(delays.split(','))
                taus = '{} Taus: {}'.format(n, delays)
            else:
                taus = '-'
            conf['Taus ({})'.format(tx_line.get_name())] = taus
            conf['keys'].append('Taus ({})'.format(tx_line.get_name()))
            for code_line in configuration.get_lines(line_type__name='codes'):
                code_params = json.loads(code_line.params)
                code_id = code_params['code']
                if tx_line.pk == int(code_params['TX_ref']):
                    conf['Code ({})'.format(tx_line.get_name())] = '{}:{}'.format(RCLineCode.objects.get(pk=code_params['code']),
                                                    '-'.join(code_params['codes']))
                    conf['keys'].append('Code ({})'.format(tx_line.get_name()))

            for windows_line in configuration.get_lines(line_type__name='windows'):
                win_params = json.loads(windows_line.params)
                if tx_line.pk == int(win_params['TX_ref']):
                    windows = ''
                    nsa = win_params['params'][0]['number_of_samples']
                    for i, params in enumerate(win_params['params']):
                        windows += 'W{}: Ho={first_height} km DH={resolution} km NSA={number_of_samples}<br>'.format(
                            i, **params)
                    conf['Window'] = mark_safe(windows)
                    conf['keys'].append('Window')

        kwargs['configurations'].append(conf)

    for configuration in configurations.filter(device__device_type__name = 'jars'):

        conf = {'conf': configuration}
        conf['keys'] = []
        conf['Type of Data'] = EXPERIMENT_TYPE[configuration.exp_type][1]
        conf['keys'].append('Type of Data')
        channels_number = configuration.channels_number
        exp_type = configuration.exp_type
        fftpoints = configuration.fftpoints
        filter_parms = json.loads(configuration.filter_parms)
        spectral_number = configuration.spectral_number
        acq_profiles = configuration.acq_profiles
        cohe_integr = configuration.cohe_integr
        profiles_block = configuration.profiles_block

        conf['Num of Profiles'] = acq_profiles
        conf['keys'].append('Num of Profiles')

        conf['Prof per Block'] = profiles_block
        conf['keys'].append('Prof per Block')

        conf['Blocks per File'] = configuration.raw_data_blocks
        conf['keys'].append('Blocks per File')

        if exp_type == 0:  # Short
            bytes_ = 2
            b = nsa*2*bytes_*channels_number
        else:  # Float
            bytes_ = 4
            channels = channels_number + spectral_number
            b = nsa*2*bytes_*fftpoints*channels

        codes_num = 7
        if code_id == 2:
            codes_num = 7
        elif code_id == 12:
            codes_num = 15

        #Jars filter values:

        clock = float(filter_parms['clock'])
        filter_2 = int(filter_parms['cic_2'])
        filter_5 = int(filter_parms['cic_5'])
        filter_fir = int(filter_parms['fir'])
        Fs_MHz = clock/(filter_2*filter_5*filter_fir)

        #Jars values:
        if ipp is not None:
            IPP_units = ipp/0.15*Fs_MHz
            IPP_us = IPP_units / Fs_MHz
            IPP_s = IPP_units / (Fs_MHz * (10**6))
            Ts = 1/(Fs_MHz*(10**6))

            Va = radar_lambda/(4*Ts*cohe_integr)
            rate_bh = ((nsa-codes_num)*channels_number*2 *
                        bytes_/IPP_us)*(36*(10**8)/cohe_integr)
            rate_gh = rate_bh/(1024*1024*1024)

            conf['Time per Block'] = IPP_s * profiles_block * cohe_integr
            conf['keys'].append('Time per Block')
            conf['Acq time'] = IPP_s * acq_profiles
            conf['keys'].append('Acq time')
            conf['Data rate'] = str(rate_gh)+" (GB/h)"
            conf['keys'].append('Data rate')
            conf['Va (m/s)'] = Va
            conf['keys'].append('Va (m/s)')
            conf['Vrange (m/s)'] = 3/(2*IPP_s*cohe_integr)
            conf['keys'].append('Vrange (m/s)')

        kwargs['configurations'].append(conf)

    ###### SIDEBAR ######
    kwargs.update(sidebar(experiment=experiment))

    return render(request, 'experiment_summary.html', kwargs)

@login_required
def experiment_verify(request, id_exp):

    experiment = get_object_or_404(Experiment, pk=id_exp)
    experiment_data = experiment.parms_to_dict()
    configurations = Configuration.objects.filter(
        experiment=experiment, type=0)

    kwargs = {}

    kwargs['experiment_keys'] = ['template',
                                 'radar_system', 'name', 'start_time', 'end_time']
    kwargs['experiment'] = experiment

    kwargs['configuration_keys'] = ['name', 'device__ip_address',
                                    'device__port_address', 'device__status']
    kwargs['configurations'] = configurations
    kwargs['experiment_data'] = experiment_data

    kwargs['title'] = 'Verify Experiment'
    kwargs['suptitle'] = 'Parameters'

    kwargs['button'] = 'Update'

    jars_conf = False
    rc_conf = False
    dds_conf = False

    for configuration in configurations:
        #-------------------- JARS -----------------------:
        if configuration.device.device_type.name == 'jars':
            jars_conf = True
            jars = configuration
            kwargs['jars_conf'] = jars_conf
            filter_parms = json.loads(jars.filter_parms)
            kwargs['filter_parms'] = filter_parms
            #--Sampling Frequency
            clock = filter_parms['clock']
            filter_2 = filter_parms['cic_2']
            filter_5 = filter_parms['cic_5']
            filter_fir = filter_parms['fir']
            samp_freq_jars = clock/filter_2/filter_5/filter_fir

            kwargs['samp_freq_jars'] = samp_freq_jars
            kwargs['jars'] = configuration

        #--------------------- RC ----------------------:
        if configuration.device.device_type.name == 'rc' and not configuration.mix:
            rc_conf = True
            rc = configuration

            rc_parms = configuration.parms_to_dict()

            win_lines = rc.get_lines(line_type__name='windows')
            if win_lines:
                dh = json.loads(win_lines[0].params)['params'][0]['resolution']
                #--Sampling Frequency
                samp_freq_rc = 0.15/dh
                kwargs['samp_freq_rc'] = samp_freq_rc

                kwargs['rc_conf'] = rc_conf
                kwargs['rc'] = configuration

        #-------------------- DDS ----------------------:
        if configuration.device.device_type.name == 'dds':
            dds_conf = True
            dds = configuration
            dds_parms = configuration.parms_to_dict()

            kwargs['dds_conf'] = dds_conf
            kwargs['dds'] = configuration

    #------------Validation------------:
    #Clock
    if dds_conf and rc_conf and jars_conf:
        if float(filter_parms['clock']) != float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) and float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) != float(dds_parms['configurations']['byId'][str(dds.pk)]['clock']):
            messages.warning(request, "Devices don't have the same clock.")
    elif rc_conf and jars_conf:
        if float(filter_parms['clock']) != float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']):
            messages.warning(request, "Devices don't have the same clock.")
    elif rc_conf and dds_conf:
        if float(rc_parms['configurations']['byId'][str(rc.pk)]['clock_in']) != float(dds_parms['configurations']['byId'][str(dds.pk)]['clock']):
            messages.warning(request, "Devices don't have the same clock.")
        if float(samp_freq_rc) != float(dds_parms['configurations']['byId'][str(dds.pk)]['frequencyA']):
            messages.warning(
                request, "Devices don't have the same Frequency A.")

    #------------POST METHOD------------:
    if request.method == 'POST':
        if request.POST['suggest_clock']:
            try:
                suggest_clock = float(request.POST['suggest_clock'])
            except:
                messages.warning(request, "Invalid value in CLOCK IN.")
                return redirect('url_verify_experiment', id_exp=experiment.id)
        else:
            suggest_clock = ""
        if suggest_clock:
            if rc_conf:
                rc.clock_in = suggest_clock
                rc.save()
            if jars_conf:
                filter_parms = jars.filter_parms
                filter_parms = ast.literal_eval(filter_parms)
                filter_parms['clock'] = suggest_clock
                jars.filter_parms = json.dumps(filter_parms)
                jars.save()
                kwargs['filter_parms'] = filter_parms
            if dds_conf:
                dds.clock = suggest_clock
                dds.save()

        if request.POST['suggest_frequencyA']:
            try:
                suggest_frequencyA = float(request.POST['suggest_frequencyA'])
            except:
                messages.warning(request, "Invalid value in FREQUENCY A.")
                return redirect('url_verify_experiment', id_exp=experiment.id)
        else:
            suggest_frequencyA = ""
        if suggest_frequencyA:
            if jars_conf:
                filter_parms = jars.filter_parms
                filter_parms = ast.literal_eval(filter_parms)
                filter_parms['fch'] = suggest_frequencyA
                jars.filter_parms = json.dumps(filter_parms)
                jars.save()
                kwargs['filter_parms'] = filter_parms
            if dds_conf:
                dds.frequencyA_Mhz = request.POST['suggest_frequencyA']
                dds.save()

    kwargs.update(sidebar(experiment=experiment))
    return render(request, 'experiment_verify.html', kwargs)

def parse_mix_result(s):

    values = s.split('-')
    html = 'EXP                MOD OPE DELAY         MASK\r\n'

    if not values or values[0] in ('', ' '):
        return mark_safe(html)

    for i, value in enumerate(values):
        if not value:
            continue
        pk, mode, operation, delay, mask = value.split('|')
        conf = RCConfiguration.objects.get(pk=pk)
        if i == 0:
            html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
                conf.name,
                mode,
                '   ',
                delay,
                mask)
        else:
            html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
                conf.name,
                mode,
                operation,
                delay,
                mask)

    return mark_safe(html)

def parse_mask(l):

    values = []

    for x in range(16):
        if '{}'.format(x) in l:
            values.append(1)
        else:
            values.append(0)

    values.reverse()

    return int(''.join([str(x) for x in values]), 2)

def dev_confs(request):

    page = request.GET.get('page')
    order = ('programmed_date', )
    filters = request.GET.copy()
    if 'my configurations' in filters:
        filters.pop('my configurations', None)
        filters['mine'] = request.user.id
    kwargs = get_paginator(Configuration, page, order, filters)
    fields = ['tags', 'template', 'historical']
    if request.user.is_authenticated:
        fields.append('my configurations')
    form = FilterForm(initial=request.GET, extra_fields=fields)
    kwargs['keys'] = ['name', 'experiment',
                      'type', 'programmed_date', 'actions']
    kwargs['title'] = 'Configuration'
    kwargs['suptitle'] = 'List'
    kwargs['no_sidebar'] = True
    kwargs['form'] = form
    kwargs['add_url'] = reverse('url_add_dev_conf', args=[0])
    filters = request.GET.copy()
    filters.pop('page', None)
    kwargs['q'] = urlencode(filters)

    return render(request, 'base_list.html', kwargs)

def dev_conf(request, id_conf):

    conf = get_object_or_404(Configuration, pk=id_conf)

    return redirect(conf.get_absolute_url())

@login_required
def dev_conf_new(request, id_exp=0, id_dev=0):

    if not is_developer(request.user):
        messages.error(
            request, 'Developer required, to create new configurations')
        return redirect('index')

    initial = {}
    kwargs = {}

    if id_exp != 0:
        initial['experiment'] = id_exp

    if id_dev != 0:
        initial['device'] = id_dev

    if request.method == 'GET':

        if id_dev:
            kwargs['button'] = 'Create'
            device = Device.objects.get(pk=id_dev)
            DevConfForm = CONF_FORMS[device.device_type.name]
            initial['name'] = request.GET['name']
            form = DevConfForm(initial=initial)
        else:
            if 'template' in request.GET:
                if request.GET['template'] == '0':
                    choices = [(conf.pk, '{}'.format(conf))
                               for conf in Configuration.objects.filter(template=True)]
                    form = NewForm(initial={'create_from': 2},
                                   template_choices=choices)
                else:
                    kwargs['button'] = 'Create'
                    conf = Configuration.objects.get(
                        pk=request.GET['template'])
                    id_dev = conf.device.pk
                    DevConfForm = CONF_FORMS[conf.device.device_type.name]
                    form = DevConfForm(instance=conf,
                                       initial={'name': '{}_{:%y%m%d}'.format(conf.name, datetime.now()),
                                                'template': False,
                                                'experiment': id_exp})
            elif 'blank' in request.GET:
                kwargs['button'] = 'Create'
                form = ConfigurationForm(initial=initial)
            else:
                form = NewForm()

    if request.method == 'POST':

        device = Device.objects.get(pk=request.POST['device'])
        DevConfForm = CONF_FORMS[device.device_type.name]

        form = DevConfForm(request.POST)
        kwargs['button'] = 'Create'
        if form.is_valid():
            conf = form.save(commit=False)
            conf.author = request.user
            conf.save()

            if 'template' in request.GET and conf.device.device_type.name == 'rc':
                lines = RCLine.objects.filter(
                    rc_configuration=request.GET['template'])
                for line in lines:
                    line.clone(rc_configuration=conf)

                new_lines = conf.get_lines()
                for line in new_lines:
                    line_params = json.loads(line.params)
                    if 'TX_ref' in line_params:
                        ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
                        line_params['TX_ref'] = ['{}'.format(
                            l.pk) for l in new_lines if l.get_name() == ref_line.get_name()][0]
                        line.params = json.dumps(line_params)
                        line.save()

            return redirect('url_dev_conf', id_conf=conf.pk)

    kwargs['id_exp'] = id_exp
    kwargs['form'] = form
    kwargs['title'] = 'Configuration'
    kwargs['suptitle'] = 'New'

    if id_dev != 0:
        device = Device.objects.get(pk=id_dev)
        kwargs['device'] = device.device_type.name

    return render(request, 'dev_conf_edit.html', kwargs)

@login_required
def dev_conf_edit(request, id_conf):

    conf = get_object_or_404(Configuration, pk=id_conf)

    DevConfForm = CONF_FORMS[conf.device.device_type.name]

    if request.method == 'GET':
        form = DevConfForm(instance=conf)

    if request.method == 'POST':
        form = DevConfForm(request.POST, instance=conf)

        if form.is_valid():
            form.save()
            return redirect('url_dev_conf', id_conf=id_conf)

    kwargs = {}
    kwargs['form'] = form
    kwargs['title'] = 'Device Configuration'
    kwargs['suptitle'] = 'Edit'
    kwargs['button'] = 'Update'

    ###### SIDEBAR ######
    kwargs.update(sidebar(conf=conf))

    return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)

@login_required
def dev_conf_start(request, id_conf):

    conf = get_object_or_404(Configuration, pk=id_conf)

    if conf.start_device():
        messages.success(request, conf.message)
    else:
        messages.error(request, conf.message)

    #conf.status_device()

    return redirect(conf.get_absolute_url())

@login_required
def dev_conf_stop(request, id_conf):

    conf = get_object_or_404(Configuration, pk=id_conf)

    if conf.stop_device():
        messages.success(request, conf.message)
    else:
        messages.error(request, conf.message)

    #conf.status_device()

    return redirect(conf.get_absolute_url())

def dev_conf_status(request, id_conf):

    conf = get_object_or_404(Configuration, pk=id_conf)

    respuesta_status_device = conf.status_device() #Agregado

    if respuesta_status_device in (True, 1):         #cambiado original conf.status_device()
        messages.success(request, conf.message)
    elif respuesta_status_device==2:
        messages.warning(request, conf.message)
    elif respuesta_status_device in (False, 0):
        messages.error(request, conf.message)

    return redirect(conf.get_absolute_url())

@login_required
def dev_conf_reset(request, id_conf):

    conf = get_object_or_404(Configuration, pk=id_conf)

    if conf.reset_device():
        messages.success(request, conf.message)
    else:
        messages.error(request, conf.message)

    return redirect(conf.get_absolute_url())

@login_required
def dev_conf_write(request, id_conf):

    conf = get_object_or_404(Configuration, pk=id_conf)

    if conf.write_device():
        messages.success(request, conf.message)
        if has_been_modified(conf):
            conf.clone(type=1, template=False)
    else:
        messages.error(request, conf.message)

    return redirect(get_object_or_404(Configuration, pk=id_conf).get_absolute_url())

@login_required
def dev_conf_read(request, id_conf):

    conf = get_object_or_404(Configuration, pk=id_conf)

    DevConfForm = CONF_FORMS[conf.device.device_type.name]

    if request.method == 'GET':

        parms = conf.read_device()
        #conf.status_device()

        if not parms:
            messages.error(request, conf.message)
            return redirect(conf.get_absolute_url())

        form = DevConfForm(initial=parms, instance=conf)

    if request.method == 'POST':
        form = DevConfForm(request.POST, instance=conf)

        if form.is_valid():
            form.save()
            return redirect(conf.get_absolute_url())

        messages.error(request, "Parameters could not be saved")

    kwargs = {}
    kwargs['id_dev'] = conf.id
    kwargs['form'] = form
    kwargs['title'] = 'Device Configuration'
    kwargs['suptitle'] = 'Parameters read from device'
    kwargs['button'] = 'Save'

    ###### SIDEBAR ######
    kwargs.update(sidebar(conf=conf))

    return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)

@login_required
def dev_conf_import(request, id_conf):

    conf = get_object_or_404(Configuration, pk=id_conf)
    DevConfForm = CONF_FORMS[conf.device.device_type.name]

    if request.method == 'GET':
        file_form = UploadFileForm()

    if request.method == 'POST':
        file_form = UploadFileForm(request.POST, request.FILES)

        if file_form.is_valid():

            data = conf.import_from_file(request.FILES['file'])
            parms = Params(data=data).get_conf(
                dtype=conf.device.device_type.name)

            if parms:

                form = DevConfForm(initial=parms, instance=conf)

                kwargs = {}
                kwargs['id_dev'] = conf.id
                kwargs['form'] = form
                kwargs['title'] = 'Device Configuration'
                kwargs['suptitle'] = 'Parameters imported'
                kwargs['button'] = 'Save'
                kwargs['action'] = conf.get_absolute_url_edit()
                kwargs['previous'] = conf.get_absolute_url()

                ###### SIDEBAR ######
                kwargs.update(sidebar(conf=conf))

                messages.success(
                    request, "Parameters imported from: '%s'." % request.FILES['file'].name)

                return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)

        messages.error(request, "Could not import parameters from file")

    kwargs = {}
    kwargs['id_dev'] = conf.id
    kwargs['title'] = 'Device Configuration'
    kwargs['form'] = file_form
    kwargs['suptitle'] = 'Importing file'
    kwargs['button'] = 'Import'

    kwargs.update(sidebar(conf=conf))

    return render(request, 'dev_conf_import.html', kwargs)

@login_required
def dev_conf_export(request, id_conf):

    conf = get_object_or_404(Configuration, pk=id_conf)

    if request.method == 'GET':
        file_form = DownloadFileForm(conf.device.device_type.name)

    if request.method == 'POST':
        file_form = DownloadFileForm(
            conf.device.device_type.name, request.POST)

        if file_form.is_valid():
            fields = conf.export_to_file(
                format=file_form.cleaned_data['format'])
            if not fields['content']:
                messages.error(request, conf.message)
                return redirect(conf.get_absolute_url_export())
            response = HttpResponse(content_type=fields['content_type'])
            response['Content-Disposition'] = 'attachment; filename="%s"' % fields['filename']
            response.write(fields['content'])

            return response

        messages.error(request, "Could not export parameters")

    kwargs = {}
    kwargs['id_dev'] = conf.id
    kwargs['title'] = 'Device Configuration'
    kwargs['form'] = file_form
    kwargs['suptitle'] = 'Exporting file'
    kwargs['button'] = 'Export'

    return render(request, 'dev_conf_export.html', kwargs)

@login_required
def dev_conf_delete(request, id_conf):

    conf = get_object_or_404(Configuration, pk=id_conf)

    if request.method == 'POST':
        if request.user.is_staff:
            conf.delete()
            return redirect('url_dev_confs')

        messages.error(request, 'Not enough permission to delete this object')
        return redirect(conf.get_absolute_url())

    kwargs = {
        'title': 'Delete',
        'suptitle': 'Configuration',
        'object': conf,
        'delete': True
    }

    return render(request, 'confirm.html', kwargs)

def sidebar(**kwargs):

    side_data = {}

    conf = kwargs.get('conf', None)
    experiment = kwargs.get('experiment', None)

    if not experiment:
        experiment = conf.experiment

    if experiment:
        side_data['experiment'] = experiment
        campaign = experiment.campaign_set.all()
        if campaign:
            side_data['campaign'] = campaign[0]
            experiments = campaign[0].experiments.all().order_by('name')
        else:
            experiments = [experiment]
        configurations = experiment.configuration_set.filter(type=0)
        side_data['side_experiments'] = experiments
        side_data['side_configurations'] = configurations.order_by(
            'device__device_type__name')

    return side_data

def get_paginator(model, page, order, filters={}, n=8):

    kwargs = {}
    query = Q()
    if isinstance(filters, QueryDict):
        filters = filters.dict()
    [filters.pop(key) for key in filters.keys() if filters[key] in ('', ' ')]
    filters.pop('page', None)

    fields = [f.name for f in model._meta.get_fields()]

    if 'template' in filters:
        filters['template'] = True
    if 'historical' in filters:
        filters.pop('historical')
        filters['type'] = 1
    elif 'type' in fields:
        filters['type'] = 0
    if 'start_date' in filters:
        filters['start_date__gte'] = filters.pop('start_date')
    if 'end_date' in filters:
        filters['start_date__lte'] = filters.pop('end_date')
    if 'tags' in filters:
        tags = filters.pop('tags')
        if 'tags' in fields:
            query = query | Q(tags__icontains=tags)
        if 'label' in fields:
            query = query | Q(label__icontains=tags)
        if 'location' in fields:
            query = query | Q(location__name__icontains=tags)
        if 'device' in fields:
            query = query | Q(device__device_type__name__icontains=tags)
            query = query | Q(device__location__name__icontains=tags)
        if 'device_type' in fields:
            query = query | Q(device_type__name__icontains=tags)

    if 'mine' in filters:
        filters['author_id'] = filters['mine']
        filters.pop('mine')
    object_list = model.objects.filter(query, **filters).order_by(*order)
    paginator = Paginator(object_list, n)

    try:
        objects = paginator.page(page)
    except PageNotAnInteger:
        objects = paginator.page(1)
    except EmptyPage:
        objects = paginator.page(paginator.num_pages)

    kwargs['objects'] = objects
    kwargs['offset'] = (int(page)-1)*n if page else 0

    return kwargs

def operation(request, id_camp=None):

    kwargs = {}
    kwargs['title'] = 'Radars Operation'
    kwargs['no_sidebar'] = True
    campaigns = Campaign.objects.filter(start_date__lte=datetime.now(),
                                        end_date__gte=datetime.now()).order_by('-start_date')

    if id_camp:
        campaign = get_object_or_404(Campaign, pk=id_camp)
        form = OperationForm(
            initial={'campaign': campaign.id}, campaigns=campaigns)
        kwargs['campaign'] = campaign
    else:
        # form = OperationForm(campaigns=campaigns)
        kwargs['campaigns'] = campaigns
        return render(request, 'operation.html', kwargs)

    #---Experiment
    keys = ['id', 'name', 'start_time', 'end_time', 'status']
    kwargs['experiment_keys'] = keys[1:]
    kwargs['experiments'] = experiments
    #---Radar
    kwargs['locations'] = campaign.get_experiments_by_radar()
    kwargs['form'] = form

    return render(request, 'operation.html', kwargs)

@login_required
def radar_start(request, id_camp, id_radar):

    campaign = get_object_or_404(Campaign, pk=id_camp)
    experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']
    now = datetime.now()
    for exp in experiments:
        start = datetime.combine(datetime.now().date(), exp.start_time)
        end = datetime.combine(datetime.now().date(), exp.end_time)
        if end < start:
            end += timedelta(1)

        if exp.status == 2:
            messages.warning(
                request, 'Experiment {} already running'.format(exp))
            continue

        if exp.status == 3:
            messages.warning(
                request, 'Experiment {} already programmed'.format(exp))
            continue

        if start > campaign.end_date or start < campaign.start_date:
            messages.warning(request, 'Experiment {} out of date'.format(exp))
            continue

        if now > start and now <= end:
            exp.status = 3
            exp.save()
            task = task_start.delay(exp.id)
            exp.status = task.wait()
            if exp.status == 0:
                messages.error(request, 'Experiment {} not start'.format(exp))
            if exp.status == 2:
                messages.success(request, 'Experiment {} started'.format(exp))
        else:
            task = task_start.apply_async(
                (exp.pk, ), eta=start+timedelta(hours=5))
            exp.task = task.id
            exp.status = 3
            messages.success(
                request, 'Experiment {} programmed to start at {}'.format(exp, start))

        exp.save()

    return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))

@login_required
def radar_stop(request, id_camp, id_radar):

    campaign = get_object_or_404(Campaign, pk=id_camp)
    experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']

    for exp in experiments:

        if exp.task:
            app.control.revoke(exp.task)
        if exp.status == 2:
            exp.stop()
            messages.warning(request, 'Experiment {} stopped'.format(exp))
        exp.status = 1
        exp.save()

    return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))

@login_required
def radar_refresh(request, id_camp, id_radar):

    campaign = get_object_or_404(Campaign, pk=id_camp)
    experiments = campaign.get_experiments_by_radar(id_radar)[0]['experiments']

    for exp in experiments:
        exp.get_status()

    return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))

def real_time(request):

    graphic_path = "/home/fiorella/Pictures/catwbeanie.jpg"

    kwargs = {}
    kwargs['title'] = 'CLAIRE'
    kwargs['suptitle'] = 'Real Time'
    kwargs['no_sidebar'] = True
    kwargs['graphic_path'] = graphic_path
    kwargs['graphic1_path'] = 'http://www.bluemaize.net/im/girls-accessories/shark-beanie-11.jpg'

    return render(request, 'real_time.html', kwargs)


query = "{query}"
import time
import oss2
import json

from AppKit import NSPasteboard, NSPasteboardTypePNG, NSPasteboardTypeTIFF

access_key_id = '<yourAccessKeyId>'
access_key_secret = '<yourAccessKeySecret>'
bucket_name = '<yourBucketName>'

def get_paste_img_file():
    """
    将剪切板数据保存到本地文件并返回文件路径
    """
    pb = NSPasteboard.generalPasteboard()  # 获取当前系统剪切板数据
    data_type = pb.types()  # 获取剪切c板数据的格式类型

    # 根据剪切板数据类型进行处理
    if NSPasteboardTypePNG in data_type:          # PNG处理
        data = pb.dataForType_(NSPasteboardTypePNG)
        filename = '%s.png' % int(time.time())
        filepath = '/tmp/%s' % filename            # 保存文件的路径
        ret = data.writeToFile_atomically_(filepath, False)    # 将剪切板数据保存为文件
        if ret:   # 判断文件写入是否成功
            return filepath
    elif NSPasteboardTypeTIFF in data_type:         #TIFF处理： 一般剪切板里都是这种
        # tiff
        data = pb.dataForType_(NSPasteboardTypeTIFF)
        filename = 'HELLO_TIFF.tiff'
        filepath = '/tmp/%s' % filename
        ret = data.writeToFile_atomically_(filepath, False)
        if ret:
            return filepath

def upload_file():

    auth = oss2.Auth(access_key_id, access_key_secret)
    # Endpoint以杭州为例，其它Region请按实际情况填写。
    bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', bucket_name)
    file_name = get_paste_img_file()
    key_name = file_name[file_name.rfind('/'):]
    date = time.strftime("%Y-%m-%d", time.localtime())
    key = date + key_name
    result = bucket.put_object_from_file(key, file_name)
    url = result.resp.response.url
    data = {
        'items' : [
            {'title' : 'url', 'arg': url,  "icon":
                {
                    'type': 'png',
                    'path': 'icon.png'
                }
             },
            {'title': 'md', 'arg': '![](%s)' % url, 'icon':
                {
                    'type': 'png',
                    'path': 'icon.png'
                }
             }
        ]
    }
    url_result = json.dumps(data)
    print(url_result)

if __name__ == '__main__':
    upload_file()


from textblob import TextBlob
import re
import json
import numpy
from nltk.corpus import stopwords
import string

# will be removed from tweets
punctuation = list(string.punctuation)
stoplist =  punctuation + ['rt', 'via']

def clean_tweet(line):
        '''
        Utility function to clean tweet text by removing links, special characters.
        '''
        line = removeLink(line)
        line = line.lower()

        for word in stoplist:
            line = line.replace(word,'') #needed for textblob

        return line

def get_tweet_sentiment(tweet):
    '''
    Utility function to classify sentiment of passed tweet
    using textblob's sentiment method
    '''
    # create TextBlob object of passed tweet text
    analysis = TextBlob(tweet)

    # set sentiment
    if analysis.sentiment.polarity > 0:
        return 'positive'
    elif analysis.sentiment.polarity == 0:
        return 'neutral'
    else:
        return 'negative'

def removeLink(line):

    pattern = 'https'
    line = line.split(' ')
    tmp = []

    for elm in line:
        if not pattern in elm:
            tmp.append(elm)

    line = ''
    for l in tmp:
        line += l+' '

    if pattern in line:
        removeLink(line)
    else:
        return line

def find_between( s, first, last ):
    try:
        start = s.index( first ) + len( first )
        end = s.index( last, start )
        return s[start:end]
    except ValueError:
        return ""

fil = open('log', 'r') # read raw tweet data from log
outfil = open('tweetdata','w') # dump clean data to tweetdata for analysis
outfil.write('date~,~tweet~,~sentiment\n')
for line in fil.readlines():

    # skip if line is empty
    if line == '' or line == ' ':
        continue

    line = line.replace(r'\r','\n')

    # try to load data as a dict
    try:
        line = json.loads(line)
    except:
        continue

    # keep timestamp
    time = line['created_at']

    # get clean tweet
    text = clean_tweet(line['text'])

    if text == '' or text == ' ':
        continue

    #if (not 'pandora' in line )or (not 'Pandora' in line):
    #    continue

    sentiment = get_tweet_sentiment(text)

    # write to file
    outfil.write("{}~,~{}~,~{}\n".format(time, text, sentiment))

outfil.close()
fil.close()


# Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
#
#     For example, given array S = {-1 2 1 -4}, and target = 1.
#
#     The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

class Solution(object):
    def threeSumClosest(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        nums.sort()
        min_sums = 2147483648
        max_sums = -2147483647
        n = len(nums)
        for i in range(0, n - 2):
            if i and nums[i] == nums[i - 1]:
                continue
            left = i + 1
            right = n - 1
            while left < right:
                tmp = nums[i] + nums[left] + nums[right]
                if tmp == target:
                    return target
                elif tmp < target:
                    max_sums = max(max_sums, tmp)
                    left += 1
                else:
                    min_sums = min(min_sums, tmp)
                    right -= 1
        if abs(target - min_sums) > abs(target - max_sums):
            return max_sums
        else:
            return min_sums


def getTuples(s):
    tuples, s, i = [], s[1:len(s)-1], 0
    while i < len(s):
        if s[i] == '{':
            tp, i, j = [], i+1, i+1
            while (1):
                if s[i] == ',' or s[i] == '}':
                    tp.append(int(s[j:i]))
                    if s[i] == '}':
                        break
                    j = i+1
                i += 1
            tuples.append(tp)
        i += 1
    return tuples

def solution(s):
    answer = []
    tuples = sorted(getTuples(s), key=lambda x: len(x))
    for tp in tuples:
        for i in range(len(tp)):
            if not tp[i] in answer:
                answer.append(tp[i])
    return answer


maxStepDistance = 10
chanceToChangeUsage = 10 # this is a percent(0-100)

maxStepsPerHill = 10000

buyT = [0, 0, 0, 0, 0, 0, 0, 0]
sellT = [0, 0, 0, 0, 0, 0, 0, 0]
buyU = [0, 0, 0, 0, 0, 0, 0, 0]
sellU = [0, 0, 0, 0, 0, 0, 0, 0]

class parameterSet:

    buyT = [0, 0, 0, 0, 0, 0, 0, 0]
    buyU = [0, 0, 0, 0, 0, 0, 0, 0]
    sellT = [0, 0, 0, 0, 0, 0, 0, 0]
    sellU = [0, 0, 0, 0, 0, 0, 0, 0]
    minValues = [0, 0, 0, 0, 0, 0, 0, 0]
    maxValues = [0, 0, 0, 0, 0, 0, 0, 0]

    def __init__(self, bT, bU, sT, sU,minV,maxV):
        self.buyT = bT
        self.buyU = bU
        self.sellT = sT
        self.sellU = sU
        self.minValues = minV
        self.maxValues = maxV

    def getBuyT(self):
        return self.buyT

    def getBuyU(self):
        return self.buyU

    def getSellT(self):
        return self.sellT

    def getSellU(self):
        return self.sellU

    def mutate(self, stepdistance, chancetochangeusage):
        import random
        for i in range(0, 8):
            buyTDir = random.randint(0, 1)
            sellTDir = random.randint(0, 1)
            chgBuyURoll = random.randint(0, 100)
            chgSellURoll = random.randint(0, 100)

            if (buyTDir == 1):
                self.buyT[i] += random.randint(0, stepdistance)
            elif (buyTDir == 0):
                self.buyT[i] -= random.randint(0, stepdistance)
            if (sellTDir == 1):
                self.sellT[i] += random.randint(0, stepdistance)
            elif (sellTDir == 0):
                self.sellT[i] -= random.randint(0, stepdistance)

            if(self.buyT[i] >= self.maxValues[i]):
                self.buyT[i]=self.maxValues[i]-1
            if (self.sellT[i] >= self.maxValues[i]):
                self.sellT[i] = self.maxValues[i] - 1

            if (self.buyT[i] <= self.minValues[i]):
                self.buyT[i] = self.minValues[i] + 1
            if (self.sellT[i] <= self.minValues[i]):
                self.sellT[i] = self.minValues[i] + 1

            if (chgBuyURoll <= chancetochangeusage):
                self.buyU[i] = random.randint(0, 2)
            if (chgSellURoll <= chancetochangeusage):
                self.sellU[i] = random.randint(0, 2)

    def getBalance(self,file,startingBalance,feeBuy,feeSell):
        import backtest
        return backtest.testStrategy(file, False, False, feeBuy, feeSell, startingBalance, self.buyT, self.buyU, self.sellT, self.sellU)

def climbRandomHill(self,minValues,maxValues):

    #print("Generating random hills")
    file = "marketdata/"+self.builder.get_object("dropdownData").get()
    #print("File: ",file)

    try:
        startingBalance = float(self.builder.get_object("txtBalance").get())
        feeBuy = float(self.builder.get_object("txtSetBuyFee").get())
        feeSell = float(self.builder.get_object("txtSetSellFee").get())
        if(startingBalance < 0):
            startingBalance = 1000
            self.builder.get_object("txtBalance").delete(0, 1000)
            self.builder.get_object("txtBalance").insert(0, "1000")
            #print("starting balance cant be negative")
        if (feeBuy < 0):
            self.builder.get_object("txtSetBuyFee").delete(0, 1000)
            self.builder.get_object("txtSetBuyFee").insert(0, ".30")
            feeBuy = .3
            #print("FEE CANNOT BE A NEGATIVE VALUE")
        if (feeSell < 0):
            self.builder.get_object("txtSetSellFee").insert(0, ".30")
            self.builder.get_object("txtSetSellFee").insert(0, ".30")
            feeSell = .3
            #print("FEE CANNOT BE A NEGATIVE VALUE")
    except:
        feeBuy = .3
        feeSell = .3
        startingBalance = 1000
        # print("invalid value entered for balance, buy fee, and/or sell fee")
        self.builder.get_object("txtBalance").delete(0, 1000)
        self.builder.get_object("txtSetBuyFee").delete(0, 1000)
        self.builder.get_object("txtSetSellFee").delete(0, 1000)
        self.builder.get_object("txtBalance").insert(0, "1000")
        self.builder.get_object("txtSetBuyFee").insert(0, ".30")
        self.builder.get_object("txtSetSellFee").insert(0, ".30")

    newBalance = 1000
    import random
    #create a random strategy that makes a profit
    timeoutCounter = 0
    while (newBalance <= startingBalance):

        dataset = self.builder.get_object("dropdownData").get()
        buyT = [0, 0, 0, 0, 0, 0, 0, 0]
        sellT = [0, 0, 0, 0, 0, 0, 0, 0]
        buyU = [0, 0, 0, 0, 0, 0, 0, 0]
        sellU = [0, 0, 0, 0, 0, 0, 0, 0]
        for i in range(0, len(minValues)):
            buyT[i] = random.randint(minValues[i], maxValues[i])
            buyU[i] = random.randint(0, 2)
            sellT[i] = random.randint(minValues[i], maxValues[i])
            sellU[i] = random.randint(0, 2)
        # print(dataset)
        # print(buyT)
        # print(buyU)
        # print(sellT)
        # print(sellU)

        # process necessary data complete
        timeoutCounter+=1
        if(timeoutCounter>20):
            break

        import backtest
        newBalance = backtest.testStrategy(file,False,False,feeBuy,feeSell,startingBalance,buyT,buyU,sellT,sellU)[0]
        #print("in hill climber, new balance: ",str(newBalance))

    # print("starting with random strategy that made: ",newBalance)
    # print("Iniitial Strategy Paremeters: ")
    # print(buyT)
    # print(buyU)
    # print(sellT)
    # print(sellU)

    #print("Ascending hill.. (this could take a bit)")

    p_init = parameterSet(buyT, buyU, sellT, sellU,minValues,maxValues)
    p_optimal = p_init
    currentHigh = p_optimal.getBalance(file,startingBalance,feeBuy,feeSell)[0]
    stepsSinceNewOptimal = 0

    for j in range(0, maxStepsPerHill):

        tbt = list(map(int, p_optimal.getBuyT()))
        tbu = list(map(int, p_optimal.getBuyU()))
        tst = list(map(int, p_optimal.getSellT()))
        tsu = list(map(int, p_optimal.getSellU()))
        p_temp = parameterSet(tbt, tbu, tst, tsu,minValues,maxValues)
        p_temp.mutate(maxStepDistance, chanceToChangeUsage)

        temp_bal = p_temp.getBalance(file,startingBalance,feeBuy,feeSell)[0]

        if (temp_bal > currentHigh):
            # print("--- *** OPTIMAL PARAMS FOUND *** ---")
            p_optimal = parameterSet(p_temp.getBuyT(), p_temp.getBuyU(), p_temp.getSellT(), p_temp.getSellU(),minValues,maxValues)
            currentHigh = temp_bal
            # print("new currentHigh: ",currentHigh)
            stepsSinceNewOptimal = 0

            #print("new local profit high: $", round(currentHigh, 2))
        else:
            stepsSinceNewOptimal += 1

        #if(stepsSinceNewOptimal % 5 == 0):
           #print("number of steps since last optimal: ",stepsSinceNewOptimal)
        if (stepsSinceNewOptimal >= 50):

            #print("assuming local maxima found")
            break

    # report
    #print("=========================")
    #print("Current Hill Best Strategy:")
    #print("With final balance of: ", p_optimal.getBalance(file,startingBalance,feeBuy,feeSell)[0])
    #print("# trades = ",p_optimal.getBalance(file,startingBalance,feeBuy,feeSell)[1])

    #print("=========================")

    buyT = p_optimal.getBuyT()
    sellT = p_optimal.getSellT()
    buyU = p_optimal.getBuyU()
    sellU = p_optimal.getSellU()

    return [buyT,buyU,sellT,sellU,currentHigh]


import os
import shutil
import requests
from bs4 import BeautifulSoup
from datetime import datetime
from tqdm import tqdm
import pandas as pd
import time

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import certifi

import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def crawl():
    ret = dict()
    ret['ERR'] = None
    d = datetime.now()
    ret['time'] = d
    ret['Day'] = d.strftime('%A')
    ret['Hour'] = d.strftime('%H:%M')
    ret['Price'] = None

    try:
        url = r'https://fastlane.co.il/'
        page = requests.get(url, verify=False)
        soup = BeautifulSoup(page.content, 'html.parser')

        mydivs = soup.find_all("span", {"class": "price"})
        if len(mydivs) == 1:
            c_div = mydivs[0]
            price = float(c_div.text)
            ret['Price'] = price
        else:
            raise Exception("mydivs is invalid")
    except Exception as e:
        ret['ERR'] = e
        return ret
    return ret

def clear_folder(path, clear_if_exist=True):
    if os.path.exists(path) and clear_if_exist:
        all_items_to_remove = [os.path.join(path, f) for f in os.listdir(path)]
        for item_to_remove in all_items_to_remove:
            if os.path.exists(item_to_remove) and not os.path.isdir(item_to_remove):
                os.remove(item_to_remove)
            else:
                shutil.rmtree(item_to_remove)

    if not os.path.exists(path):
        os.makedirs(path, mode=0o777)
    time.sleep(0.1)

if __name__ == '__main__':
    datapath = os.path.dirname(__file__)
    save_path = os.path.join(datapath, 'prices.csv')
    info_path = os.path.join(datapath, 'info')

    section_crawl = True
    if section_crawl:
        sample_rate = 30  # Every 30 seconds
        sample_days = 28
        save_rate = 180  # Every 60 seconds

        hits = int((sample_days * 24 * 60 * 60) / float(sample_rate))

        cols = ['time', 'Day', 'Hour', 'Price', 'ERR']
        df = pd.DataFrame(columns=cols)
        curr_idx = 0
        if os.path.exists(save_path):
            df = pd.read_csv(save_path, index_col=0)
            curr_idx = df.index[-1] + 1

        time_start_time = datetime.now()
        for i in range(hits):
            q = crawl()
            df.loc[curr_idx] = q
            curr_idx += 1

            msg = ''
            msg += f'[{i + 1} / {hits}][{100 * (i + 1) / hits:>.2f}%]\t'
            dtime = q['time']
            formatted = dtime.strftime("%d-%b-%Y %H:%M:%S")
            msg += formatted + '\t'
            msg += f"Price: {q['Price']}\t"
            print(msg, flush=True)

            time_passed = (datetime.now() - time_start_time).total_seconds()
            if time_passed > save_rate:
                time_start_time = datetime.now()
                df.to_csv(save_path)
                print(f'File saved. Path: {save_path}\tItems: {df.shape[0]}', flush=True)

            time.sleep(sample_rate)

    section_process = True
    if section_process:
        clear_folder(info_path)
        hours = [6, 12]

        df = pd.read_csv(save_path)
        df['Date'] = pd.to_datetime(df['time']).dt.date
        datacols = list()
        sumdf = None
        for c_date in df['Date'].unique():
            ddf = df[df['Date'].eq(c_date)]
            ddf = ddf[ddf['ERR'].isna()]
            if len(ddf['Price'].unique()) <= 1:
                continue
            else:
                print(f"For date [{c_date}], {len(ddf['Price'].unique())} prices found.")
            ddf['time'] = pd.to_datetime(ddf['time'])
            sig = ddf.iloc[0]['time'].strftime('%b-%d-%Y-%A')
            hr = ddf['Hour'].str.split(':', expand=True).astype(int)
            ddf = ddf[(hr[0] >= hours[0]) & (hr[0] <= hours[1])]

            xdf = ddf.groupby('Hour')['Price'].mean()
            if sumdf is None:
                sumdf = pd.DataFrame(index=xdf.index.values, columns=['time', sig], dtype='object')
                sumdf['time'] = xdf.index
                sumdf[sig] = xdf.values
            else:
                idx_missing_in_sumdf = [t for t in xdf.index.to_list() if t not in sumdf.index.to_list()]
                idx_missing_in_xdf = [t for t in sumdf.index.to_list() if t not in xdf.index.to_list()]
                common = [t for t in sumdf.index.to_list() if t in xdf.index.to_list()]

                sumdf.loc[common, sig] = xdf.loc[common]
                for tidx in idx_missing_in_sumdf:
                    sumdf.loc[tidx, sig] = xdf.loc[tidx]

            csv_path = os.path.join(info_path, f'{sig}.csv')
            datacols += [sig]
            ddf.to_csv(csv_path)
            print(f"Export: {csv_path}", flush=True)

        csv_path = os.path.join(info_path, f'summary.csv')
        sumdf.to_csv(csv_path)

        section_aggregate = True
        if section_aggregate:
            smooth = sumdf[datacols].rolling(3).mean().ffill().bfill()
            smoothavg = smooth.mean(axis=1)
            csv_path = os.path.join(info_path, f'averaged.csv')
            img_path = os.path.join(info_path, f'averaged.png')
            smoothavg.to_csv(csv_path, header='Price')

            plt.plot(smoothavg)
            plt.savefig(img_path)
            plt.close('all')

        print(f"Summary: {csv_path}")


import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'

import torch
from dataset import HorseZebraDataset
from utils import save_checkpoint, load_checkpoint
from torch.utils.data import DataLoader
import torch.nn as nn
import torch.optim as optim
import config
from tqdm import tqdm
from torchvision.utils import save_image
from discriminator_model import Discriminator
from generator_model import Generator

def main():
    disc_H = Discriminator(in_channels=3).to(config.DEVICE)
    disc_Z = Discriminator(in_channels=3).to(config.DEVICE)
    gen_Z = Generator(img_channels=3, num_residuals=9).to(config.DEVICE)
    gen_H = Generator(img_channels=3, num_residuals=9).to(config.DEVICE)
    opt_disc = optim.Adam(
        list(disc_H.parameters()) + list(disc_Z.parameters()),
        lr=config.LEARNING_RATE,
        betas=(0.5, 0.999),
    )
    opt_gen = optim.Adam(
        list(gen_Z.parameters()) + list(gen_H.parameters()),
        lr=config.LEARNING_RATE,
        betas=(0.5, 0.999),
    )

    if config.LOAD_MODEL:
        load_checkpoint(
            config.CHECKPOINT_GEN_H, gen_H, opt_gen, config.LEARNING_RATE,
        )
        load_checkpoint(
            config.CHECKPOINT_GEN_Z, gen_Z, opt_gen, config.LEARNING_RATE,
        )
        load_checkpoint(
            config.CHECKPOINT_CRITIC_H, disc_H, opt_disc, config.LEARNING_RATE,
        )
        load_checkpoint(
            config.CHECKPOINT_CRITIC_Z, disc_Z, opt_disc, config.LEARNING_RATE,
        )

    dataset = HorseZebraDataset(
        config.TRAIN_DIR+"/horses", config.TRAIN_DIR+"/zebras", config.transforms
    )
    loader = DataLoader(
        dataset,
        batch_size=config.BATCH_SIZE,
        shuffle=True,
        num_workers=config.NUM_WORKERS,
        pin_memory=True
    )

    loop = tqdm(loader, leave=True)

    for idx, (zebra, horse) in enumerate(loop):
        zebra = zebra.to(config.DEVICE)
        horse = horse.to(config.DEVICE)

        #Train Discriminator H and Z
        with torch.cuda.amp.autocast():
            fake_horse = gen_H(zebra)
            fake_zebra = gen_Z(horse)

        save_image(fake_horse * 0.5 + 0.5, f"saved_images/horse_{idx}.png")
        save_image(fake_zebra * 0.5 + 0.5, f"saved_images/zebra_{idx}.png")

if __name__ == "__main__":
    main()


import socket
import threading
import time

host=socket.gethostbyname(socket.gethostname())
port=4444
print(host)

client=socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)
client.connect((host,port))

def receive():
        data=client.recv(1024).decode()
        print("[Message intercepted]"+data)
        print('-->')
        receive()

def sent():
        message=input('-->')
        client.send(message.encode('utf-8'))
        sent()

t_receive=threading.Thread(target=receive)

if __name__=="__main__":
        t_receive.start()
        sent()

        client.close()


import numpy as np
import sys
sys.path.append("../")

import tensorflow as tf
from tensorflow.python.platform import flags

from utils.utils_tf import *
from tutorial_models import dnn

FLAGS = flags.FLAGS

# data_set_list = ['adult', 'compas', 'german']
# data_shape_list = [(None, 18), (None, 10), (None, 11)]
# data_path_list = ['../data/npy_data_from_aif360/adult-aif360preproc/',
#                   '../data/npy_data_from_aif360/compas-aif360preproc/',
#                   '../data/npy_data_from_aif360/german-aif360preproc/']
# data_set_list = ['bank']
# data_shape_list = [(None, 28)]
# data_path_list = ['../data/npy_data_from_aif360/bank-aif360preproc/']
data_set_list = ['default']
data_shape_list = [(None, 26)]
data_path_list = ['../data/npy_data_from_aif360/default-aif360preproc/']
def training(dataset, model_path, nb_epochs, batch_size,learning_rate,
             dataset_path='../data/npy_data_from_aif360/adult-aif360preproc/',
             input_shape=(None, 18),
             nb_classes=2
             ):
    # prepare the data and model
    X = np.load(dataset_path + "features-train.npy")
    Y = np.load(dataset_path + "2d-labels-train.npy")
    input_shape = input_shape
    nb_classes = nb_classes

    tf.set_random_seed(1234)
    config = tf.ConfigProto()
    config.gpu_options.allow_growth = True
    sess = tf.Session(config=config)
    # config = tf.ConfigProto()
    # config.gpu_options.per_process_gpu_memory_fraction = 0.8
    # sess = tf.Session(config=config)
    x = tf.placeholder(tf.float32, shape=input_shape)
    y = tf.placeholder(tf.float32, shape=(None, nb_classes))
    model = dnn(input_shape, nb_classes)
    preds = model(x)

    # training parameters
    train_params = {
        'nb_epochs': nb_epochs,
        'batch_size': batch_size,
        'learning_rate': learning_rate,
        'train_dir': model_path + dataset + "/",
        'filename': 'test.model'
    }

    # training procedure
    sess.run(tf.global_variables_initializer())
    rng = np.random.RandomState([2019, 7, 15])
    model_train(sess, x, y, preds, X, Y, args=train_params,
                rng=rng, save=True)

    # evaluate the accuracy of trained model
    eval_params = {'batch_size': 128}
    accuracy = model_eval(sess, x, y, preds, X, Y, args=eval_params)
    print('Test accuracy on legitimate test examples: {0}'.format(accuracy))
    sess.close()

def main(argv=None):

    for i in range(len(data_set_list)):
        # if 'session' in locals() and sess is not None:
        #     sess.close()

        training(dataset = data_set_list[i],
                model_path = FLAGS.model_path,
                nb_epochs=FLAGS.nb_epochs,
                batch_size=FLAGS.batch_size,
                learning_rate=FLAGS.learning_rate,
                dataset_path= data_path_list[i],
                input_shape= data_shape_list[i]
                 )
    print('bank\'s original models trained with dataset bank marketing from aif360 done.')

if __name__ == '__main__':
    # flags.DEFINE_string("dataset", "adult", "the name of dataset")
    flags.DEFINE_string("model_path", "../model_from_aif360data/", "the name of path for saving model")
    flags.DEFINE_integer('nb_epochs', 1000, 'Number of epochs to train model')
    flags.DEFINE_integer('batch_size', 128, 'Size of training batches')
    flags.DEFINE_float('learning_rate', 0.01, 'Learning rate for training')

    tf.app.run()


import socket
import sys

IP = socket.gethostbyname(socket.gethostname())
PORT = 12345
ADDR = (IP, PORT)
FORMAT= "utf-8"

print("[Starting] server is starting")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(ADDR)
s.listen(5)
print("[Listening] server is listening")

while True:
    clientsocket, address = s.accept()
    print("Connection established with {}".format(address))

    file = open("Downloads/download.jpeg",'wb')
    msg = clientsocket.recv(1024)

    while msg:
        file.write(msg)
        msg = clientsocket.recv(1024)

    arr = list(msg)
    arr = list(map(int, arr))
    arr.reverse()
    ansParity = []

    r = 0
    while((len(arr) + 1) > pow(2,r)):
        r = r+1

    for j in range(1, r+1):
        sum = 0
        for i in range(1, len(arr)+1):
            x = format(i, "b")
            if(j <= len(x) and x[0-j] == '1'):
                sum += arr[i-1]

        if(sum%2 == 0): ansParity.append(0)                #EVEN PARITY USED
        else: ansParity.append(1)

    ansParity.reverse()
    print(ansParity)
    tempString = ''.join(str(x) for x in ansParity)
    num = len(tempString)

    if(num == 0):
        print("NO ERROR IN CHECKSUM")
        print("File received successfully")
        clientsocket.send(bytes("NO ERROR", FORMAT))
    else:
        print("ERROR at INDEX => " + str(num))
        clientsocket.send(bytes("ERROR at INDEX => " + str(num), FORMAT))
    file.close()
    clientsocket.close()
    #print(f"[Disconnected] {addr} disconnected")


import gymnasium

from ..envs.base import BaseOfflineEnv
from ..utils.maze_utils import set_map_cell
from ..samplers.maze_sampler import MazeSampler

class PointMaze(BaseOfflineEnv):
    def __init__(self, data_path, horizon, maze_map, start, goal,
                 sample_args,
                 debug=False, render=False):
        '''
        data_path: path to dataset
        maze_map: list(list), basic map of the game, only specifies 0, 1. R and G are specified by start and goal.
        start, array (2,), int, the start point of the game we want to learn
        goal, array (2,), int, the goal point of the game we want to learn
        horizon: horizon of every trajectory
        n_trajs: number of trajectories for dataset
        sample_starts: list, list of starts for sampling
        sample_goals: list, list of goals for sampling
        '''

        self.MAZE_MAP = maze_map
        target_map = set_map_cell(self.MAZE_MAP, goal, 'g')
        target_map = set_map_cell(target_map, start, 'r')

        render_mode = "human" if render else None
        env_cls = lambda : gymnasium.make('PointMaze_UMazeDense-v3',
                                    maze_map = target_map,
                                    continuing_task = False,
                                    max_episode_steps=self.horizon,
                                    render_mode=render_mode)

        sampler = MazeSampler(horizon=horizon,
                              maze_map=self.MAZE_MAP,
                              target_start=start,
                              target_goal=goal,
                              debug=debug,
                              render=render)

        super().__init__(data_path, env_cls, horizon,
                         sampler = sampler, sample_args=sample_args)


import sys,os
import shutil
from sensor.exception import SensorException
from sensor.logger import logging
from sensor.entity.artifact_entity import ModelTrainerArtifact,ModelEvaluationArtifact,ModelPusherArtifact
from sensor.entity.config_entity import ModelTrainerConfig,ModelEvaluationConfig,ModelPusherConfig
from sensor.ml.metric.classification_metric import get_classfication_score
from sensor.ml.model.estimator import SensorModel,ModelResolver
from sensor.utils.main_utils import save_object,load_object,write_yaml_file

class ModelPusher:
    def __init__(self,model_evaluation_artifact:ModelEvaluationArtifact,
                 model_pusher_config:ModelPusherConfig):
        """
        : param model_Evaluation_artifact  : Output reference of data Transformation artifact stage
        : param model_pusher_config       : configuration for model pusher
        """
        try:
            self.model_evaluation_artifact = model_evaluation_artifact
            self.model_pusher_config       = model_pusher_config
        except Exception as e:
            raise SensorException(e,sys)

    def initiate_model_pusher(self) -> ModelPusherArtifact:
        try:
            logging.info("Inside Model Pusher initiate")
            trained_model_path = self.model_evaluation_artifact.trained_model_path
            logging.info(f"trained_model_path : {trained_model_path}")

            # creating model pusher dir to save the model
            model_file_path = self.model_pusher_config.model_file_path
            logging.info(f"model_file_path : {model_file_path}")

            os.makedirs(os.path.dirname(model_file_path),exist_ok=True)
            shutil.copy(src= trained_model_path,dst=model_file_path)

            # copy the model in saved model directory
            saved_model_file_path = self.model_pusher_config.saved_model_path
            os.makedirs(os.path.dirname(saved_model_file_path),exist_ok=True)
            shutil.copy(src= trained_model_path,dst=saved_model_file_path)

            #prepare the artifact
            model_pusher_artifact= ModelPusherArtifact( saved_model_path=saved_model_file_path,model_file_path=model_file_path   )
            logging.info(f"Model Pusher artifact {model_pusher_artifact}")
            return model_pusher_artifact

        except Exception as e:
            raise SensorException(e,sys)


import gym
from gym import spaces
import math
import numpy as np

TIME_STEP = 1. / 50.

class BaseWorldObject(object):
    def __init__(self, x=0., y=0., vx=0., vy=0., a=1.):
        self.updateXY(x, y)
        self.updateV(vx, vy)
        self.updateTargetV(vx, vy)
        self.a = a

    def updateXY(self, x, y):
        self.x = x
        self.y = y

    def updateV(self, vx, vy):
        self.vx = vx
        self.vy = vy

    def updateTargetV(self, tvx, tvy):
        self.tvx = tvx
        self.tvy = tvy

def calc_shift(v0, target_v, a_abs):
    is_always_accelerating_during_timestep = True
    is_a_positive = target_v > v0

    a = a_abs if is_a_positive else -a_abs

    v1 = v0 + TIME_STEP * a

    if (is_a_positive and target_v < v1) or (not is_a_positive and target_v > v1):
        v1 = target_v
        is_always_accelerating_during_timestep = False

    delta = (v1 * v1 - v0 * v0) / (2 * a)

    if not is_always_accelerating_during_timestep:
        delta += (TIME_STEP - (v1 - v0) / a) * v1

    return (delta, v1)

class BaseWorld(object):
    def __init__(self):
        self.objects = []
        self.time = 0.

    def add_object(self, obj: BaseWorldObject):
        self.objects.append(obj)

    def step(self):
        self.time += TIME_STEP
        for obj in self.objects:
            if obj.a < 0.01:
                obj.updateXY(obj.x + obj.vx * TIME_STEP,
                             obj.y + obj.vy * TIME_STEP)
                continue

            if abs(obj.vx - obj.tvx) < 0.001:
                vx1 = obj.tvx
                delta_x = vx1 * TIME_STEP
            else:
                delta_x, vx1 = calc_shift(obj.vx, obj.tvx, obj.a)

            if abs(obj.vy - obj.tvy) < 0.001:
                vy1 = obj.tvy
                delta_y = vy1 * TIME_STEP
            else:
                delta_y, vy1 = calc_shift(obj.vy, obj.tvy, obj.a)

            obj.updateXY(obj.x + delta_x, obj.y + delta_y)
            obj.updateV(vx1, vy1)

class CFWorldEnv(gym.Env):
    '''
    二维伪连续世界
    '''
    metadata = {
        'render.modes': ['human', 'rgb_array'],
        'video.frames_per_second': 50
    }

    def __init__(self):
        world = self.world = BaseWorld()
        uav = self.uav = BaseWorldObject(
            x=0.0,
            y=0.0,
            vx=0.0,
            vy=0.0,
            a=6.0
        )
        source = self.source = BaseWorldObject(
            x=16.0,
            y=16.0,
            vx=0.0,
            vy=0.0,
            a=0.0
        )
        world.add_object(uav)
        world.add_object(source)

        # specify (target v_x, target v_y) of UAV
        self.action_space = spaces.Box(
            low=-50.0,
            high=50.0,
            shape=(2,)
        )
        self.observation_space = spaces.Box(
            low=0.0,
            high=100.0,
            shape=(1,)
        )

    def reset(self):
        self.uav.updateXY(0, 0)
        self.uav.updateV(0, 0)
        self.uav.updateTargetV(0, 0)
        self.source.updateXY(16.0, 16.0)
        self.source.updateV(0, 0)
        return [math.sqrt(16 * 16 * 2)]

    # As TIME_STEP = `0.02s` and DISTANCE_BUFFER_MAXLEN = `4`,
    # the real distance doesn't takes effect on the observed
    # distance until `80ms` later.
    distance_buffer = []
    DISTANCE_BUFFER_MAXLEN = 4

    def step(self, action):
        assert self.action_space.contains(
            action), "%r (%s) invalid" % (action, type(action))

        self.uav.updateTargetV(action[0], action[1])
        self.world.step()

        distance = (self.source.x - self.uav.x) ** 2 + \
            (self.source.y - self.uav.y) ** 2
        distance = math.sqrt(distance)

        if len(self.distance_buffer) == self.DISTANCE_BUFFER_MAXLEN:
            self.distance_buffer.pop()

        self.distance_buffer.insert(0, distance)

        for i in range(1, len(self.distance_buffer)):
            distance += self.distance_buffer[i]

        distance /= len(self.distance_buffer)

        info = {
            'time': self.world.time,
            'uav': self.uav,
            'source': self.source,
        }

        return [distance], 1.0, (distance < 1.0), info

    viewer = None

    def render(self, mode='human'):
        screen_width = 600
        screen_height = 600

        def cord_world_to_screen(x: float, y: float):
            return x * 25 + 100, y * 25 + 100

        if self.viewer is None:
            from gym.envs.classic_control import rendering

            self.viewer = rendering.Viewer(screen_width, screen_height)

            # TODO: 绘图

        return None

        # TODO: 绘图

        return self.viewer.render(return_rgb_array=mode == 'rgb_array')

    def close(self):
        if self.viewer:
            self.viewer.close()
            self.viewer = None


# MotorDataReader
# handles parsing .eng files and extracting data from them
# also handles calculating the thrust and weight of the motor at any time using interpolation
# somewhat accurate, the details of how http://www.thrustcurve.org calculates this information is not given
# TODO implement polynomial fitting curve to increase accuracy

class MotorDataReader:
    # constructor
    def __init__(self,file):
        self.file = file
        self.parseFile()
        self.computeStatistics()

    # calculate the trust and weight of the motor at any given time
    def getThrustWeight(self,time):
        #compute the thrust and weight of the motor at a given time
        if(time > self.burnTime):
            #after burn...
            return [0, self.motorDryWeight]
        elif(time < 0):
            #hmmmmmmmmmmmmmm
            return [0,self.motorTotalWeight]
        else:
            # estimate the thrust using linear interpolation, estimate the weight by the proportion of total impulse left in the system
            # for thrust, find which points are in the middle
            counter = 1
            found = False
            thrust = 0
            impulse = 0
            # loop until a greater time stamp is found
            while(found == False):
                if(self.thrustData[counter][0] >= time):
                    # found the upper bound, do an interpolation,
                    thrust = self.thrustData[counter-1][1] + (self.thrustData[counter][1] - self.thrustData[counter-1][1])/(self.thrustData[counter][0] - self.thrustData[counter - 1][0]) * (time - self.thrustData[counter][0])
                    # do an impulse midpoint approximation
                    impulse += (thrust + self.thrustData[counter-1][1])/2 * (time - self.thrustData[counter][0])
                    found = True
                else:
                    # do a midpoint impulse approximation
                    midThrust = (self.thrustData[counter][1] + self.thrustData[counter-1][1])/2
                    impulse += midThrust*(self.thrustData[counter][0] - self.thrustData[counter-1][0])
                counter += 1
            # calculate the motor weight by the proportion of impulse to totalImpulse
            weight = self.motorDryWeight + self.motorPropWeight*(1-impulse/self.totalImpulse)
            return [thrust,weight]

    # calculate some needed statistics including average thrust, total impulse, and burn duration
    def computeStatistics(self):
        #compute some data for ease of access, including: average thrust, total impulse
        #average thrust and total impulse use midpoint reimann sum
        self.totalImpulse = 0
        for i in range(1,len(self.thrustData)):
            #calculate the midpoint
            midThrust = (self.thrustData[i][1] + self.thrustData[i-1][1])/2
            self.totalImpulse += midThrust*(self.thrustData[i][0] - self.thrustData[i-1][0])
        self.averageThrust = self.totalImpulse/ (self.thrustData[-1][0])
        self.burnTime = self.thrustData[-1][0] # not exactly the best way of doing this (motors sometimes trail off)

    def parseFile(self):
        data = open(self.file, 'r')
        self.thrustData = []
        for i,line in enumerate(data):
            # the first line should be a comment on the motor
            if i == 0:
                # parse out the name of the motor, go until a character other than ';' or ' ' is found
                counter = 0
                found = False
                while(found == False and counter < len(line)):
                    if(line[counter] != ';' and line[counter] != ' '):
                        self.motorName = line[counter:].rstrip()
                        found = True
                    else:
                        counter += 1
            elif i == 1:
                # should be a set of data points for the motor.
                info = line.split()
                self.motorDesignation = info[0]
                self.motorDiam = float(info[1])
                self.motorLength = float(info[2])
                # idk what the 4th info block is...
                self.motorPropWeight = float(info[4])
                self.motorTotalWeight = float(info[5])
                self.motorDryWeight = self.motorTotalWeight - self.motorPropWeight
                self.motorManufacturer = info[6]
            # print(str((i+1)) + ": " + line,'')
            else:
                # this is actual burn data
                # separated into seconds thrust(N)
                burnData = line.split()
                #print(burnData)
                #print(burnData[0])

                # store in [s,t] pairs
                self.thrustData.append([float(burnData[0]), float(burnData[1])])

if __name__ == "__main__":
    # load up a sample data file
    data = MotorDataReader("./Cesaroni_J760.eng")
    # print out some data from it
    print(data.totalImpulse)
    print(data.averageThrust)
    print(data.getThrustWeight(0.1))


class Solution:
    def minimumSum(self, num: int) -> int:
        sumArr = []
        m = 0
        while num > 0:
            sumArr.append(num%10)
            num = num//10
            # m+=1
        print(sumArr)
        sumArr.sort()
        print(sumArr)
        num1 = sumArr[0]*10 + sumArr[3]
        num2 =sumArr[1]*10 + sumArr[2]
        return num1+num2


from VOC_loader import VOCSeg
from concurrent.futures import ThreadPoolExecutor
import os

if __name__ == "__main__":

    for phase in ['train', 'val']:
        print('processing {} data'.format(phase))
        target_folder = VOCSeg.create_target_folder('VOC/')

        def _preprocess_target(target_img_path):
            VOCSeg.preprocess_targets(target_folder, target_img_path)

        target_list_path = 'VOC/VOCdevkit/VOC2012/ImageSets/Segmentation/' + phase + '.txt'
        mask_dir = 'VOC/VOCdevkit/VOC2012/SegmentationClass/'
        with open(target_list_path, "r") as f:
            target_list = [mask_dir + x.strip() + '.png' for x in f.readlines()]

        with ThreadPoolExecutor(max_workers=4) as executor:
            executor.map(_preprocess_target, target_list)