import sys, os, six

from unittest import TestCase, main
from icu import *

class TestCollator(TestCase):

    def filePath(self, name):

        module = sys.modules[TestCollator.__module__].__file__
        return os.path.join(os.path.dirname(module), name)

    def assertIsInstance(self, obj, cls):
        if hasattr(TestCase, 'assertIsInstance'):
            TestCase.assertIsInstance(self, obj, cls)
        else:
            self.assertTrue(isinstance(obj, cls),
                            u'%s is not an instance of %s' % (obj, cls))

    def testSort(self):

        collator = Collator.createInstance(Locale.getFrance())
        input = open(self.filePath('noms.txt'), 'rb')
        names = [six.text_type(n.strip(), 'utf-8') for n in input.readlines()]
        input.close()
        ecole = names[0]

        names.sort()
        self.assertTrue(names[-1] is ecole)

        if (sys.version_info >= (3,)):
            names.sort(key=collator.getSortKey)
        else:
            names.sort(collator.compare)
        self.assertTrue(names[2] is ecole)

    def testCreateInstancePolymorph(self):

        collator = Collator.createInstance(Locale("epo")) # Esperanto
        self.assertIsInstance(collator, RuleBasedCollator)
        rules = collator.getRules()

    def testGetSortKey(self):

        # Do not test sort key byte sequences directly:
        # They are unstable, that is, likely to change
        # with every UCA/CLDR/ICU release.
        # Instead, test that compare() is consistent with
        # comparing the equivalent sort keys.
        collator = Collator.createInstance(Locale.getJapanese())
        collator.setAttribute(UCollAttribute.NORMALIZATION_MODE,
                              UCollAttributeValue.ON)
        collator.setAttribute(UCollAttribute.ALTERNATE_HANDLING,
                              UCollAttributeValue.SHIFTED)
        collator.setAttribute(UCollAttribute.STRENGTH,
                              UCollAttributeValue.TERTIARY)

        # In Japanese, the following characters should be different
        # only on quaternary level.
        hira_ge = u'\u3052'  # Hiragana letter Ge
        kana_ge = u'\u30B2'  # Katakana letter Ge
        self.assertEqual(0, collator.compare(hira_ge, kana_ge))
        hira_ge_key = collator.getSortKey(hira_ge)
        kana_ge_key = collator.getSortKey(kana_ge)
        self.assertEqual(hira_ge_key, kana_ge_key)

        collator.setAttribute(UCollAttribute.STRENGTH,
                              UCollAttributeValue.QUATERNARY)
        self.assertEqual(-1, collator.compare(hira_ge, kana_ge))
        hira_ge_key = collator.getSortKey(hira_ge)
        kana_ge_key = collator.getSortKey(kana_ge)
        self.assertTrue(hira_ge_key < kana_ge_key)

    def setupCollator(self, collator):

        collator.setAttribute(UCollAttribute.NORMALIZATION_MODE,
                              UCollAttributeValue.ON)
        collator.setAttribute(UCollAttribute.CASE_FIRST,
                              UCollAttributeValue.UPPER_FIRST)
        collator.setAttribute(UCollAttribute.ALTERNATE_HANDLING,
                              UCollAttributeValue.SHIFTED)
        collator.setAttribute(UCollAttribute.STRENGTH,
                              UCollAttributeValue.QUATERNARY)
        collator.setAttribute(UCollAttribute.HIRAGANA_QUATERNARY_MODE,
                              UCollAttributeValue.ON)

    def LoadCollatorFromRules(self):

        rules = u"&z<\u00e6 &h<ch"
        collator = RuleBasedCollator(rules)
        self.setupCollator(collator)

        return collator

    def LoadCollatorFromBinaryBuffer(self, bin):

        root = Collator.createInstance(Locale.getRoot())
        collator = RuleBasedCollator(bin, root)
        self.setupCollator(collator)

        return collator

    def testCollatorLoading(self):

        if ICU_VERSION >= '4.6':
            collator = self.LoadCollatorFromRules()
            s = u'hchz\u00e6'

            key0 = collator.getSortKey(s)
            bin = collator.cloneBinary()

            collator = self.LoadCollatorFromBinaryBuffer(bin)
            key1 = collator.getSortKey(s)

            self.assertTrue(key0 == key1)

    def testAlphabeticIndex(self):

        if ICU_VERSION >= '4.8':
            index = AlphabeticIndex(Locale.getItaly())

            index.addRecord("foo", "bar")
            index.addRecord("topo", "lino")

            def allData(index):
                for ((label, type)) in index:
                    while index.nextRecord():
                        yield (label, type, index.recordData)

            self.assertTrue(list(allData(index)) == [
                ('F', 0, 'bar'), ('T', 0, 'lino')])

            if ICU_VERSION >= '51.0':
                self.assertTrue(len(index.buildImmutableIndex()) == 28)

if __name__ == "__main__":
    main()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Aug 30 18:21:24 2022

@author: juanjo
"""

""" Vamos a usar el transfer learning para el modelo con velocidades, va a consistir en
coger el modelo de ANN para predecir la serie temporal con m = 1000, y vamos a añadirle una
o dos capas más y entrenarlas con fine-tunning, a ver que tal """

import pandas as pd
import numpy as np
import seaborn as sns
import tensorflow.keras as keras
import scipy.integrate as integrate
import tensorflow.keras.optimizers

from Functions import separar_set
from Pendulum import derivs
from tensorflow.keras.layers import Dense, Dropout, Activation
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras.optimizers import Adam
from scipy.stats import reciprocal
from sklearn.model_selection import RandomizedSearchCV

""" Antes de nada, tenemos que generar el dataset, resolviendo m veces el sistema
de ecuaciones diferenciales """
m = 1
t_stop = 50000 # how many seconds to simulate
dt = 0.02 # El salto temporal
t = np.arange(0, t_stop, dt)

""" Sacamos el dataset """
i = 0
xTrain, yTrain, xTest, yTest = np.empty((0, 4)), np.empty((0, 4)), np.empty((0, 4)), np.empty((0, 4))
while(i<=m):

    # Generamos las condiciones inciales
    th1_train = 180.0*np.random.rand()
    w1_train = 180.0*np.random.rand()
    th2_train = 180.0*np.random.rand()
    w2_train = 180.0*np.random.rand()

    # initial state
    state = np.radians([th1_train, w1_train, th2_train, w2_train])

    # integrate your ODE using scipy.integrate.
    y = integrate.odeint(derivs, state, t)

    datos = pd.DataFrame({'x1(Ang1)': y[:, 0], 'x2(Vel1)': y[:, 1], 'x3(Ang2)': y[:, 2], 'x4(Vel2)': y[:, 3]})
    #datos = datos.drop(['x2(Vel1)', 'x4(Vel2)'], axis = 1)
    r = 0.8
    n = len(y)
    xTrain_ind, xTest_ind, yTrain_ind, yTest_ind = separar_set(datos.values[0:n-1], datos.values[1:n], n, r)

    xTrain = np.concatenate((xTrain, xTrain_ind), axis = 0)
    xTest = np.concatenate((xTest, xTest_ind), axis = 0)
    yTrain = np.concatenate((yTrain, yTrain_ind), axis = 0)
    yTest = np.concatenate((yTest, yTest_ind), axis = 0)
    i += 1

""" Ahora, procedemos a la transferencia del aprendizaje """

# Pasamos las capas del modelo 3 al 4 y añadimos al 4 las capas que queriamos
model3 = keras.models.load_model("modelo_definitivo5.h5")
model4 = keras.models.Sequential(model3.layers[:-1])
model4.add(keras.layers.Dense(500, activation = "selu", kernel_initializer = "lecun_normal")) # Añadimos una capa oculta más
#model4.add(keras.layers.BatchNormalization())
model4.add(Dense(500, activation = "selu", kernel_initializer = "lecun_normal"))
#model4.add(keras.layers.BatchNormalization()) # y le añadimos un batch normalization
model4.add(keras.layers.Dense(4)) # Capa de output

learning_rate = 0.001391702 # Es la tasa de aprendizaje más óptima que tenía el modelo 3
optimizer = keras.optimizers.SGD(learning_rate)

# Clonamos el modelo 3 para evitar que modifiquen dicho modelo
model3_clone = keras.models.clone_model(model3)
model3_clone.set_weights(model3.get_weights())

# Congelamos las capas heredadas del modelo 3
for layer in model4.layers[:-2]: # Le etoy diciendo que vaya desde la primera capa hasta dos capas antes del final
    layer.trainable = False

# Compilamos el modelo
model4.compile(loss = "mse", optimizer = optimizer, metrics = ["accuracy"])

# Entrenamos el modelo unas pocas epocas para que se acerquen un poco los pesos
history = model4.fit(xTrain, yTrain, epochs = 2, validation_data = (xTest, yTest))

# Descongelamos las capas para poder entrenarlas un poco ahora
for layer in model4.layers[:-2]:
    layer.trainable = True

# Volvemos a compilar el modelo ahora que las capas son entrenables, y los ajustamos esta vez de verdad
model4.compile(loss = "mse", optimizer = optimizer, metrics = ["accuracy"])
history = model4.fit(xTrain, yTrain, epochs = 5, validation_data = (xTest, yTest))
model4.evaluate(xTest, yTest)

""" Ahora, guardamos el modelo """
model4.save("modelo_definitivo6.h5")


import socket

host, port =('',5566)

socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((host, port))

print("Le serveur est démarré...")

while True:
    socket.listen(5)
    conn, address = socket.accept()
    print("Un client vient de se connecter..")

    data = conn.recv(1024)
    data = data.decode("utf-8")
    print(data)

conn.close()
socket.close()


from setuptools import setup, find_packages

__author__ = 'Haoyan Huo'
__maintainer__ = 'Haoyan Huo'
__email__ = 'haoyan.huo@lbl.gov'

if __name__ == '__main__':
    setup(
        name='s4',
        author='Haoyan Huo',
        author_email='hhaoyann@gmail.com',
        url='https://github.com/CederGroupHub/s4',
        description='Synthesis Science mining from Solid-state Synthesis dataset',
        classifiers=[
            'Programming Language :: Python :: 3.6',
            'Programming Language :: Python :: 3 :: Only',
            'Development Status :: 1 - Planning',
            'Intended Audience :: Science/Research',
            'License :: OSI Approved :: MIT License',
            'Operating System :: OS Independent',
            'Topic :: Scientific/Engineering :: Information Analysis',
            'Topic :: Scientific/Engineering :: Physics',
            'Topic :: Scientific/Engineering :: Chemistry',
            'Topic :: Software Development :: Libraries :: Python Modules'
        ],
        python_requires=">=3.6",
        license='MIT',
        include_package_data=True,
        version='0.1.0',
        packages=find_packages(),
        install_requires=open('requirements.txt').readlines()
    )


from django.conf.urls import url
from travel import views as travelviews

urlpatterns = [
    url(r'^$', travelviews.index, name='homepage'),
    url(r'^personal/$', travelviews.personal, name='personal'),
    url(r'^cities/$', travelviews.cities, name='cities'),
    url(r'^attractions/$', travelviews.attractions, name='attractions'),
    url(r'^attraction_info/$', travelviews.attraction_info, name='attraction_info'),
    url(r'^create_route/$', travelviews.create_route, name='create_route'),
]


import pandas as pd
company = pd.read_csv('/home/pallabeedey/Downloads/company-data.csv')
company1=company.rename(columns={'Co_Code':'comp_code','Year End':'date','Co_Name':'comp_name','Sector':'sector','Industry':'industry','Stock Exchange':'stock_code','Equity Paid Up':'equity_paid_up','Net Sales':'net_sales','Debt-Equity Ratio[Latest]':'debt_equity_ratio[Latest]'})
col4=company1['industry'].unique()
l2=len(col4)
s2=[]
for i in range(0,l2):
    s2.append(str('I')+str(i))
c=pd.DataFrame({'industry_code':s2,'industry_name':col4})
c.to_csv("ind2.csv")


import math
import geneticAlgorithm
import readFile
import afunction

def bin_search(a, b, d):
    print("bin: <", a, ", ", b, ">")
    point = math.floor((a + b) / 2)
    if a == b or a == b - 1:
        if max_area_for(a, d) >= 90:
            return a
        else:
            return b

    result = max_area_for(point, d)

    if result >= 0.9:
        return bin_search(a, point, d)

    elif result < 0.9:
        return bin_search(point, b, d)

def max_area_for(number, d):
    return geneticAlgorithm.main_gen(50, 150, d, number)

def min_value(d):
    max_area_per_sensor = 0
    for i in range(d + 1):
        max_area_per_sensor += 2 * i + 1
    table = readFile.getArray()
    n = len(table[0])
    m = len(table)
    area = 0.9 * m * n
    return math.floor(area / max_area_per_sensor)

def max_value():
    table = readFile.getArray()
    return afunction.seen_counter_for_0(table)


# -*- coding: utf-8 -*-
"""
This program implements improved Euler's (Heun's) Method for solving an ODE.
This is a predictor-corrector method.
User input:
    x0 = initial x value
    y0 = initial y value
    h = step size
    N = number of iterations
"""

import numpy as np
import matplotlib.pyplot as plt

def yeimp(x):           #Exact solution to ODE
    return np.exp(x) - x - 1.0

def feimp(x,y):         #This is the formula for y' from ODE
    return y + x

def eulerimp(x0,y0,h,N):  #Improved Euler Method (Heun's Method)
    xn = np.zeros(N+1)          #Initialize x nodes
    yn = np.zeros(N+1)          #Initalize Improved Euler yn values
    xn[0] = x0
    yn[0] = y0
    for k in range(1,N+1):
        xn[k] = xn[k-1] + h             #Generate x nodes
        k1 = h*feimp(xn[k-1],yn[k-1])       #Predictor component
        k2 = h*feimp(xn[k],yn[k-1]+k1)      #Corrector component
        yn[k] = yn[k-1] + 0.5*(k1+k2)   #Generate Improved Euler yn values

    print('Improved Euler Solution=', yn)

    #Next, we sample y on n=100 x values and plot f & y
    n = 100
    xvalues = np.zeros(n+1)    #Initialize x vector to be zeros
    yvalues = np.zeros(n+1)    #Initialize y vector to be zeros

    step = (xn[N]-x0)/n   #Use this step to get xinterval = [x0,xn(N)].
    for k in range(0,n+1):
        xvalues[k] = x0 + k*step      #Generate vector of x values
        yvalues[k] = yeimp(xvalues[k])    #Generate vector of y(x) values

    plt.plot(xvalues,yvalues,'b',xn,yn,'o--k')
    plt.xlabel('x')
    plt.legend(('Exact','Improved Euler'),loc = 0)
    plt.show()

Math & Computer Science/MATH 366 (Methods of Applied Mathematics 2)/MATH 366 Class Activity/MATH 366 Euler Improved Method.py


import csv
import json
import logging
import os
from io import BytesIO
from zipfile import ZipFile
from django.contrib import messages
from django.http import HttpResponse
from django.conf import settings
from django.shortcuts import redirect
from django.shortcuts import render
from django.views.generic import TemplateView

from ag_data.models import AGMeasurement, AGEvent, AGVenue, AGSensor, AGActiveEvent
from mercury.forms import EventForm, VenueForm
from mercury.grafanaAPI.grafana_api import Grafana
from mercury.models import GFConfig
from ..event_check import require_event_code, require_event_code_function

log = logging.getLogger(__name__)
log.setLevel(logging.ERROR)

GITHUB_DOCS_ROOT = settings.GITHUB_DOCS_ROOT
CONFIGURE_EVENTS_HELP_DOC = "configure_events.md"

@require_event_code_function
def update_venue(request, venue_uuid=None):
    venue_to_update = AGVenue.objects.get(uuid=venue_uuid)
    if venue_to_update:
        venue_to_update.name = request.POST.get("name")
        venue_to_update.description = request.POST.get("description")
        venue_to_update.latitude = request.POST.get("latitude")
        venue_to_update.longitude = request.POST.get("longitude")
        venue_to_update.save()

    return redirect("/events")

@require_event_code_function
def update_event(request, event_uuid=None):
    event_to_update = AGEvent.objects.get(uuid=event_uuid)
    if event_to_update:
        new_name = request.POST.get("name")
        new_venue_id = request.POST.get("venue_uuid")
        new_venue_object = AGVenue.objects.get(uuid=new_venue_id)
        new_description = request.POST.get("description")

        # if the name was changed, update all Grafana dashboards with new name
        if new_name != event_to_update.name:
            gfconfigs = GFConfig.objects.all()

            for gfconfig in gfconfigs:

                # Grafana instance using current GFConfig
                grafana = Grafana(gfconfig)

                try:
                    dashboard = grafana.update_dashboard_title(
                        event_to_update, new_name
                    )
                    if dashboard:
                        messages.success(
                            request,
                            f"{gfconfig.gf_name}: Grafana " f"dashboard title updated",
                        )
                except ValueError as error:
                    messages.error(
                        request,
                        f"{gfconfig.gf_name}: Grafana dashboard "
                        f"title not updated: {error} ",
                    )

        # update the AGEvent object
        event_to_update.name = new_name
        event_to_update.venue_uuid = new_venue_object
        event_to_update.description = new_description
        event_to_update.save()

        messages.success(request, "Event updated successfully")

    return redirect("/events")

@require_event_code_function
def delete_event(request, event_uuid=None):
    event_to_delete = AGEvent.objects.get(uuid=event_uuid)

    # delete any dashboards that exist for this event
    gfconfigs = GFConfig.objects.all()

    # Add panel to each grafana instance
    for gfconfig in gfconfigs:

        # Grafana instance using current GFConfig
        grafana = Grafana(gfconfig)

        deleted = grafana.delete_dashboard_by_name(event_to_delete.name)

        if not deleted:
            messages.error(
                request,
                f"Failed to delete Event dashboard from Grafana instance: "
                f"{gfconfig.gf_host}",
            )

    event_to_delete.delete()
    return redirect("/events")

@require_event_code_function
def export_all_event(request, sensor_id=None):
    if request.path.__contains__("json"):
        events = AGEvent.objects.all().order_by("uuid")
        filenames = []
        for event in events:
            if sensor_id is None:
                measurement_data = AGMeasurement.objects.filter(event_uuid=event.uuid)
            else:
                measurement_data = AGMeasurement.objects.filter(
                    event_uuid=event.uuid, sensor_id=sensor_id
                )
            venue = AGVenue.objects.get(uuid=event.venue_uuid.uuid)
            temp = create_event_json(event, venue, measurement_data)
            json_object = json.dumps(temp)
            filename = event.name.replace(" ", "").lower()
            filenames.append(filename + ".json")
            with open(filename + ".json", "w") as outfile:
                outfile.write(json_object)
        byte_data = BytesIO()
        try:
            event_zip = ZipFile(byte_data, "w")
            for fn in filenames:
                event_zip.write(fn)
        finally:
            event_zip.close()

        response = HttpResponse(byte_data.getvalue(), content_type="application/zip")
        response["Content-Disposition"] = "attachment; filename=events.zip"
        return response
    else:
        response = HttpResponse(content_type="text/csv")
        response["Content-Disposition"] = "attachment; filename=all_events.csv"
        events = AGEvent.objects.all().order_by("uuid")
        writer = csv.writer(response)
        writer.writerow(
            [
                "S.No",
                "Event Name",
                "Event Date",
                "Event Description",
                "Venue Name",
                "Sensor Name",
                "Sensor Data TimeStamp",
                "Sensor Value",
            ]
        )
        for event in events:
            if sensor_id is None:
                measurement_data = AGMeasurement.objects.filter(event_uuid=event.uuid)
            else:
                measurement_data = AGMeasurement.objects.filter(
                    event_uuid=event.uuid, sensor_id=sensor_id
                )
            if len(measurement_data) == 0:
                measurement_data = []
            venue = AGVenue.objects.get(uuid=event.venue_uuid.uuid)
            response = create_event_csv(
                writer, response, event, venue, measurement_data
            )
        return response

def create_event_csv(writer, response, event_object, venue_object, measurements_object):
    i = 0
    if len(measurements_object) > 0:
        sensor = AGSensor.objects.get(uuid=measurements_object[0].sensor_id.uuid)
        for measurement in measurements_object:
            i += 1
            if sensor.uuid != measurement.sensor_id:
                sensor = AGSensor.objects.get(uuid=measurement.sensor_id.uuid)
            writer.writerow(
                [
                    str(i),
                    event_object.name,
                    event_object.date,
                    event_object.description,
                    venue_object.name,
                    sensor.name,
                    measurement.timestamp,
                    measurement.value,
                ]
            )
    else:
        i += 1
        writer.writerow(
            [
                str(i),
                event_object.name,
                event_object.date,
                event_object.description,
                venue_object.name,
                "no data for event",
                "no data for event",
                "no data for event",
            ]
        )

    return response

def create_event_json(event_object, venue_object, measurements_object):
    event_info = {
        "name": event_object.name,
        "event date": str(event_object.date),
        "event description": event_object.description,
    }
    if venue_object:
        event_info["venue name"] = venue_object.name
        event_info["venue description"] = venue_object.description

    measurement_info = []
    if len(measurements_object) > 0:
        sensor = AGSensor.objects.get(uuid=measurements_object[0].sensor_id.uuid)
        for measurement in measurements_object:
            if sensor.uuid != measurement.sensor_id:
                sensor = AGSensor.objects.get(uuid=measurement.sensor_id.uuid)
            temp = {
                "sensor name": sensor.name,
                "timestamp": str(measurement.timestamp),
                "values": measurement.value,
            }
            measurement_info.append(temp)

    data = {"event_info": event_info, "measurement_info": measurement_info}

    return data

@require_event_code_function
def activate_event(request, event_uuid=None):
    event_to_activate = AGEvent.objects.get(uuid=event_uuid)
    if event_to_activate is not None:
        AGActiveEvent.objects.all().delete()
        active_event = AGActiveEvent(agevent=event_to_activate)
        active_event.save()
    return redirect("/events")

@require_event_code_function
def deactivate_event(request, event_uuid=None):
    event_to_deactivate = AGEvent.objects.get(uuid=event_uuid)
    if event_to_deactivate is not None:
        AGActiveEvent.objects.all().delete()
    return redirect("/events")

@require_event_code_function
def export_event(request, event_uuid=None, file_format="CSV"):
    event_to_export = AGEvent.objects.get(uuid=event_uuid)
    if event_to_export:
        filename = event_to_export.name.replace(" ", "").lower()
        measurement_data = AGMeasurement.objects.filter(event_uuid=event_uuid)
        if len(measurement_data) == 0:
            measurement_data = []

        venue = AGVenue.objects.get(uuid=event_to_export.venue_uuid.uuid)
        if request.path.__contains__("json"):
            data = create_event_json(event_to_export, venue, measurement_data)
            event_info = {
                "name": event_to_export.name,
                "event date": str(event_to_export.date),
                "event description": event_to_export.description,
            }
            if venue:
                event_info["venue name"] = venue.name
                event_info["venue description"] = venue.description

            measurement_info = []
            if measurement_data:
                sensor = AGSensor.objects.get(uuid=measurement_data[0].sensor_id.uuid)
                for measurement in measurement_data:
                    if sensor.uuid != measurement.sensor_id:
                        sensor = AGSensor.objects.get(uuid=measurement.sensor_id.uuid)
                    temp = {
                        "sensor name": sensor.name,
                        "timestamp": str(measurement.timestamp),
                        "reading": measurement.value,
                    }
                    measurement_info.append(temp)

            data = {"event_info": event_info, "measurement_info": measurement_info}

            response = HttpResponse(str(data), content_type="application/json")
            response["Content-Disposition"] = (
                'attachment; filename="' + filename + '".json'
            )
            return response
        else:
            response = HttpResponse(content_type="text/csv")
            response["Content-Disposition"] = (
                'attachment; filename="' + filename + '".csv'
            )
            writer = csv.writer(response)
            writer.writerow(
                [
                    "S.No",
                    "Event Name",
                    "Event Date",
                    "Event Description",
                    "Venue Name",
                    "Sensor Name",
                    "Sensor Data TimeStamp",
                    "Sensor Value",
                ]
            )
            response = create_event_csv(
                writer, response, event_to_export, venue, measurement_data
            )
            return response
    else:
        return redirect("/events")

class CreateEventsView(TemplateView):
    """This is the view for creating a new event."""

    template_name = "events.html"

    @require_event_code
    def get(self, request, *args, **kwargs):
        events = AGEvent.objects.all().order_by("uuid")
        venues = AGVenue.objects.all().order_by("uuid")
        event_form = EventForm()
        venue_form = VenueForm()
        active_event_object = AGActiveEvent.objects.all()
        active_event = None
        if len(active_event_object) > 0:
            active_event = active_event_object[0].agevent

        configure_events_github_url = os.path.join(
            GITHUB_DOCS_ROOT, CONFIGURE_EVENTS_HELP_DOC
        )

        context = {
            "event_form": event_form,
            "venue_form": venue_form,
            "events": events,
            "venues": venues,
            "active_event": active_event,
            "configure_events_github_url": configure_events_github_url,
        }
        return render(request, self.template_name, context)

    @require_event_code
    def post(self, request, *args, **kwargs):
        if "submit-venue" in request.POST:
            post_venue_name = request.POST.get("name")
            post_venue_description = request.POST.get("description")
            post_venue_longitude = request.POST.get("longitude")
            post_venue_latitude = request.POST.get("latitude")
            venue_data = AGVenue(
                name=post_venue_name,
                description=post_venue_description,
                longitude=post_venue_longitude,
                latitude=post_venue_latitude,
            )
            venue_data.save()
        if "submit-event" in request.POST:
            post_event_name = request.POST.get("name")
            post_event_location_id = request.POST.get("venue_uuid")
            venue_object = AGVenue.objects.get(uuid=post_event_location_id)
            post_event_date = request.POST.get("date")
            post_event_description = request.POST.get("description")
            event_data = AGEvent(
                name=post_event_name,
                venue_uuid=venue_object,
                date=post_event_date,
                description=post_event_description,
            )

            event_data.save()

            gfconfig = GFConfig.objects.filter(gf_current=True)

            # only create an event dashboard if a current gfconfig exists
            if gfconfig.count() > 0:
                dashboard = None
                # create a dashboard with the same name as the event
                config = gfconfig[0]
                try:
                    grafana = Grafana(config)
                    dashboard = grafana.create_dashboard(post_event_name)
                except ValueError as error:
                    # pass any failure message from the API to the UI
                    messages.error(
                        request,
                        f"Grafana dashboard for this event was not "
                        f"created: {error}",
                    )

                # if a dashboard was created successfully, add panels to it
                if dashboard:
                    # create a panel for each sensor
                    sensors = AGSensor.objects.all()
                    for sensor in sensors:
                        try:
                            grafana.add_panel(sensor, event_data)
                        except ValueError as error:
                            # pass any error messages from the API to the UI
                            messages.error(request, error)

        events = AGEvent.objects.all().order_by("uuid")
        venues = AGVenue.objects.all().order_by("uuid")
        event_form = EventForm()
        venue_form = VenueForm()

        configure_events_github_url = os.path.join(
            GITHUB_DOCS_ROOT, CONFIGURE_EVENTS_HELP_DOC
        )

        context = {
            "event_form": event_form,
            "venue_form": venue_form,
            "events": events,
            "venues": venues,
            "configure_events_github_url": configure_events_github_url,
        }
        return render(request, self.template_name, context)


""" All forms related to coupons. """
from time import strptime
import logging

from django import forms
from django.conf import settings
from django.contrib.localflavor.us.forms import USStateField
from django.forms.util import ErrorDict, ErrorList
from django.template.defaultfilters import date as date_filter
from django.utils.translation import ugettext_lazy as _

from advertiser.models import Business
from category.models import Category
from common.custom_cleaning import trim_fields_in_form
from common.form_widgets import (CheckboxSelectMultiple, RadioSelect,
    CheckboxInput, USStateSelect)
from coupon.config import IS_REDEEMED_BY_SMS_CHOICES
from coupon.models import DefaultRestrictions
from coupon.service.coupons_service import ALL_COUPONS, SORT_COUPONS
from coupon.service.restrictions_service import COUPON_RESTRICTIONS
from coupon.tasks import record_action_multiple_coupons
from market.service import get_current_site

from haystack.forms import SearchForm
from haystack.query import SearchQuerySet

LOG = logging.getLogger('ten.%s' % __name__)
LOG.setLevel(logging.ERROR)

class RestrictionsForm(forms.Form):
    """ The Default Restrictions and Custom Restrictions Form. """
    default_restrictions = forms.ModelMultipleChoiceField(
        widget=CheckboxSelectMultiple,
        queryset=DefaultRestrictions.objects.all().order_by('sort_order'),
        required=False)
    custom_restrictions = forms.CharField(widget=forms.Textarea(attrs={
        'onkeypress' : "return enforceMaxLength(this,1500,event);",
        'onblur' : "return enforceMaxLength(this,1500,event);"
        }), required=False)
    is_redeemed_by_sms = forms.ChoiceField(
        widget=RadioSelect,
        choices=IS_REDEEMED_BY_SMS_CHOICES,
        initial="1")

    def clean(self):
        """ Clean RestrictionsForm fields. """
        self.cleaned_data = trim_fields_in_form(self)
        return self.cleaned_data

    def clean_default_restrictions(self):
        index = 0
        for x in self.cleaned_data['default_restrictions']:
            self.cleaned_data['default_restrictions'][index].restriction = \
                    unicode(x.restriction.strip())
            index += 1
        return self.cleaned_data['default_restrictions']

    def clean_custom_restrictions(self):
        self.cleaned_data['custom_restrictions'] = \
            self.cleaned_data.get(
                'custom_restrictions', None).strip()[:1500]
        return self.cleaned_data['custom_restrictions']

    def clean_is_redeemed_by_sms(self):
        self.cleaned_data['is_redeemed_by_sms'] = \
            bool(int(self.cleaned_data.get('is_redeemed_by_sms', 1)))
        return self.cleaned_data['is_redeemed_by_sms']

def get_restrictions_initial_data(this_coupon):
    """ Get the initial data for the restrictions form. """
    if not this_coupon['is_redeemed_by_sms']:
        is_redeemed_by_sms = 0
    else:
        is_redeemed_by_sms = 1
    default_restrictions_list = \
        COUPON_RESTRICTIONS.get_default_restrictions_list(
            this_coupon['coupon_id'],
            this_coupon['custom_restrictions'])
    initial_dict = {
                'is_redeemed_by_sms':is_redeemed_by_sms,
                'custom_restrictions':this_coupon['custom_restrictions'],
                'default_restrictions':default_restrictions_list
                }
    return initial_dict

class ValidDaysForm(forms.Form):
    """ The Valid Days Form holds the 7 days of the week checkboxes to build
    the valid days string when certain checkboxes are check and unchecked.
    """
    is_valid_monday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'monfri'}), required=False)
    is_valid_tuesday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'monfri'}), required=False)
    is_valid_wednesday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'monfri'}), required=False)
    is_valid_thursday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'monfri'}), required=False)
    is_valid_friday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'monfri'}), required=False)
    is_valid_saturday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'weekend'}), required=False)
    is_valid_sunday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'weekend'}), required=False)

def get_valid_days_initial_data(this_coupon):
    """ Build the initial_dict for the ValidDaysForm() """
    initial_dict = {
        'is_valid_monday': this_coupon['is_valid_monday'],
        'is_valid_tuesday': this_coupon['is_valid_tuesday'],
        'is_valid_wednesday': this_coupon['is_valid_wednesday'],
        'is_valid_thursday': this_coupon['is_valid_thursday'],
        'is_valid_friday': this_coupon['is_valid_friday'],
        'is_valid_saturday': this_coupon['is_valid_saturday'],
        'is_valid_sunday': this_coupon['is_valid_sunday'],
    }
    return initial_dict

class EditCouponForm(forms.Form):
    """ The Coupon Edit form.  Used originally for the preview edit coupon. """
    def __init__(self, *args, **kwargs):
        """ Dynamically create 10 sets of location fields. """
        super(EditCouponForm, self).__init__(*args, **kwargs)
        count = 1
        while count <= 10:
            self.fields['location_address1_' + str(count)] = forms.CharField(
                widget=forms.TextInput(attrs={'size':'25', 'maxlength':'50'}),
                required=False)
            self.fields['location_address2_' + str(count)] = forms.CharField(
                widget=forms.TextInput(attrs={'size':'25', 'maxlength':'50'}),
                required=False)
            self.fields['location_city_' + str(count)] = forms.CharField(
                widget=forms.TextInput(attrs={'size':'25', 'maxlength':'50'}),
                required=False)
            self.fields['location_state_province_' + str(count)] = USStateField(
                widget=USStateSelect(attrs={}), required=False)
            self.fields['location_zip_postal_' + str(count)] = forms.CharField(
                widget=forms.TextInput(attrs={'size':'6', 'maxlength':'9'}),
                required=False)
            self.fields['location_description_' + str(count)] = forms.CharField(
                widget=forms.TextInput(attrs={'size':'25', 'maxlength':'50'}),
                required=False)
            self.fields['location_area_code_' + str(count)] = forms.CharField(
                widget=forms.TextInput(attrs={'size':'3', 'maxlength':'3'}),
                required=False)
            self.fields['location_exchange_' + str(count)] = forms.CharField(
                widget=forms.TextInput(attrs={'size':'3', 'maxlength':'3'}),
                required=False)
            self.fields['location_number_' + str(count)] = forms.CharField(
                widget=forms.TextInput(attrs={'size':'4', 'maxlength':'4'}),
                required=False)
            count += 1

    business_name = forms.CharField(widget=forms.TextInput(
        attrs={'size':'25', 'maxlength':'50'}),
        error_messages={'required': 'Please supply a Business Name'}
        )
    slogan = forms.CharField(widget=forms.TextInput(
        attrs={'size':'25', 'maxlength':'40'}),
        required=False
        )
    web_url = forms.CharField(widget=forms.TextInput(
        attrs={'size':'25', 'maxlength':'255'}),
        required=False
        )
    headline = forms.CharField(widget=forms.TextInput(
        attrs={'size':'25', 'maxlength':'25'}),
        error_messages={'required': 'Please supply a Coupon Offer'}
        )
    qualifier = forms.CharField(widget=forms.TextInput(
        attrs={'size':'25', 'maxlength':'40'}),
        required=False
        )

    default_restrictions = forms.ModelMultipleChoiceField(
        widget=CheckboxSelectMultiple,
        queryset=DefaultRestrictions.objects.all().order_by('sort_order'),
        required=False)
    custom_restrictions = forms.CharField(widget=forms.Textarea(attrs={
        'onkeypress' : "return enforceMaxLength(this,1500,event);",
        'onblur' : "return enforceMaxLength(this,1500,event);"
        }), required=False)

    is_valid_monday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'monfri'}), required=False)
    is_valid_tuesday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'monfri'}), required=False)
    is_valid_wednesday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'monfri'}), required=False)
    is_valid_thursday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'monfri'}), required=False)
    is_valid_friday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'monfri'}), required=False)
    is_valid_saturday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'weekend'}), required=False)
    is_valid_sunday = forms.BooleanField(
        widget=CheckboxInput(attrs={'class':'weekend'}), required=False)

    is_redeemed_by_sms = forms.ChoiceField(
        widget=RadioSelect, choices=IS_REDEEMED_BY_SMS_CHOICES)

    expiration_date = forms.CharField(
        widget=forms.HiddenInput(attrs={'maxlength':'10'}))

    def clean(self):
        """ Clean EditCouponForm fields. """
        self.cleaned_data = trim_fields_in_form(self)
        web_url = self.cleaned_data.get('web_url', None)
        if web_url:
            business = Business(web_url=web_url)
            is_url_good = business.clean_web_url()
            if not is_url_good:
                self._errors['web_url'] = ErrorList(["URL not valid"])
        # Clean location fields.
        count = 1
        while count <= 10:
            # Do not use default state if no other address information is
            # present.
            if not self.cleaned_data['location_address1_' + str(count)] and \
                not self.cleaned_data['location_address2_' + str(count)] and \
                not self.cleaned_data['location_city_' + str(count)] and \
                not self.cleaned_data['location_zip_postal_' + str(count)]:
                self.cleaned_data['location_state_province_' + str(count)] = ""
            count += 1
        return self.cleaned_data

    def clean_custom_restrictions(self):
        """ Clean custom restrictions. """
        self.cleaned_data['custom_restrictions'] = \
            self.cleaned_data.get(
                'custom_restrictions', None).strip()[:1500]
        return self.cleaned_data['custom_restrictions']

    def clean_web_url(self):
        """ Clean web_url field in form. """
        self.cleaned_data['web_url'] = self.cleaned_data.get(
            'web_url', None).strip()
        if self.cleaned_data['web_url'] != '' \
        and self.cleaned_data['web_url'][:7] != 'http://':
            self.cleaned_data['web_url'] = 'http://%s' % (
                self.cleaned_data['web_url'])
        return self.cleaned_data['web_url']

class SearchCouponForm(SearchForm):
    """ Search form for coupons with category filter. """
    category_choices = [ ('0', 'Search all categories')]
    category_choices.extend(
        [(category.id, category.name) for category in Category.objects.all()])

    cat = forms.ChoiceField(
        required=False,
        label=_('Category'),
        choices=category_choices,
        widget=forms.Select(attrs={'class':'dropdown'})
        )

    def __init__(self, *args, **kwargs):
        self.selected_categories = kwargs.pop("selected_categories", [])
        # These two vars are used by the template:
        self.query_string_not_found = False
        self.category_not_found = False
        self.suggestion = None
        self.sqs = [] # This is the result set that will be returned.
        super(SearchCouponForm, self).__init__(*args, **kwargs)

    def clean_cat(self):
        """ Clean user submitted categories. """
        if not self.cleaned_data.get('cat', None) \
        or self.cleaned_data['cat'] == '0':
            self.cleaned_data['cat'] = ''
        return self.cleaned_data['cat']

    def process_search(self, request):
        """ Perform search query from form. """
        cat = self.cleaned_data['cat']
        search_query = self.cleaned_data['q']
        if cat != '' or search_query != '':
            self.set_search_query_set(request)
            if cat != '' and search_query != '':
                self.search_category_and_query()
            elif cat != '':
                self.search_category_only()
            else:
                self.search_query_string_only()
            coupons = self.intersect_index_and_db_results(request)
        else:
            coupons = self.no_query_found(request)
        return coupons, self.suggestion

    def set_search_query_set(self, request):
        """ Set searchqueryset, a QuerySet from solr, defaulting to all coupons
        for this site. If there was a previous search with valid results,
        set it to that.
        """
        self.searchqueryset = request.POST.get('searchqueryset', None)
        if not self.searchqueryset:
            self.searchqueryset = SearchQuerySet().filter(
                site_id=get_current_site(request).id)
        return

    def search_category_and_query(self):
        """ Search both the category and the query string. """
        self.search_category()
        if self.category_not_found:
            self.query_string_not_found = True
            self.sqs = self.searchqueryset
            self.suggestion = self.grab_suggestion()
        else:
            self.search_query_string()
            if self.query_string_not_found:
                self.sqs = self.searchqueryset
                self.suggestion = self.grab_suggestion()
        return

    def search_category_only(self):
        """ Search the category only. """
        self.search_category()
        if self.category_not_found:
            self.sqs = self.searchqueryset
            self.suggestion = self.grab_suggestion()
        return

    def search_query_string_only(self):
        """ Search the query string only. """
        self.search_query_string()
        if self.query_string_not_found:
            self.sqs = self.searchqueryset
            self.suggestion = self.grab_suggestion()
        return

    def search_query_string(self):
        """ Search against the query string. """
        self.sqs = self.search()
        if not len(self.sqs):
            self.query_string_not_found = True
        else:
            self.searchqueryset = self.sqs
        return

    def search_category(self):
        """ Search against the selected category. """
        self.sqs = self.searchqueryset.filter(
            categories=self.cleaned_data['cat'])
        if not len(self.sqs):
            self.category_not_found = True
        else:
            self.searchqueryset = self.sqs
        return

    def intersect_index_and_db_results(self, request):
        """ Take the searchqueryset results after searching against category and
        query_string and intersect those results with the db """
        LOG.debug('searchqueryset: %s' % self.searchqueryset)
        searchqueryset_ids = [
            int(result.pk) for result in self.sqs if result is not None]
        LOG.debug('searchqueryset_ids: %s' % searchqueryset_ids)
        # Filter results against coupons that are eligible for display on
        # the site.
        coupon_ids = ALL_COUPONS.get_all_coupons(get_current_site(request))[1]
        LOG.debug('coupon_ids: %s' % coupon_ids)
        good_ids = set(coupon_ids).intersection(set(searchqueryset_ids))
        LOG.debug('good_ids: %s' % good_ids)
        sorted_coupon_ids, coupons = SORT_COUPONS.sorted_coupons(good_ids)
        ALL_COUPONS.join_coupon_with_locations(sorted_coupon_ids, coupons)
        LOG.debug('coupons: %s' % coupons)
        return coupons

    def no_query_found(self, request):
        """ Determines the behavior when no query was found. """
        all_coupons, coupon_ids = ALL_COUPONS.get_all_coupons(
            get_current_site(request))
        record_action_multiple_coupons.delay(action_id=1,
            coupon_ids=tuple(coupon_ids))
        return all_coupons

    def grab_suggestion(self):
        """  Return a suggestion since these results did not return anything. """
        if getattr(settings, 'HAYSTACK_INCLUDE_SPELLING', False):
            return self.get_suggestion()

class AddFlyerDatesForm(forms.Form):
    """ The Add Flyer Dates Form. """

    subdivision_consumer_count = forms.IntegerField(widget=forms.HiddenInput(),
        required=False, initial=0)

    def __init__(self, available_flyer_dates_list,
        subdivision_consumer_count=None, checked_data=None, *args, **kwargs):
        """ Dynamically create 10 sets of location fields. """
        super(AddFlyerDatesForm, self).__init__(*args, **kwargs)
        if checked_data:
            self.fields['subdivision_consumer_count'].initial = \
            checked_data.get('subdivision_consumer_count', 0)
        else:
            self.fields['subdivision_consumer_count'].initial = \
                subdivision_consumer_count
        for flyer_month in available_flyer_dates_list:
            for week in flyer_month['weeks']:
                attrs = {'value': week['send_date']}
                if not week['date_is_available']:
                    attrs['disabled'] = 'disabled'
                if checked_data:
                    if '%s' % date_filter(week['send_date'], 'F j'
                            ) in checked_data:
                        attrs['checked'] = 'checked'
                else:
                    if week['checked'] and week['date_is_available']:
                        attrs['checked'] = 'checked'
                self.fields['%s' % date_filter(
                    week['send_date'], 'F j')] = forms.ChoiceField(
                        widget=CheckboxInput(
                            attrs=attrs,
                            check_test=True),
                        initial=week['send_date'],
                        label = '%s' % date_filter(week['send_date'], 'F j'),
                        required=False)

    def clean_dynamic_fields(self, post_data):
        """ Clean method for this form. """
        selected_flyer_list = []
        self.cleaned_data = {}
        self._errors = ErrorDict()
        for field in self.fields:
            if field in post_data and field != 'subdivision_consumer_count':
                try:
                    strptime(post_data[field], "%Y-%m-%d")
                    selected_flyer_list.append(post_data[field])
                except ValueError:
                    pass
        try:
            if int(self.fields['subdivision_consumer_count'].initial) < 1:
                # Abort transaction.
                raise forms.ValidationError(
                    _("Flyer Purchases are currently unavailable."))
        except (TypeError, ValueError):
            raise forms.ValidationError(
                    _("Flyer Purchase unavailable."))
        if not selected_flyer_list:
            self._errors['non_field_error'] = ErrorList(
                    ["You must choose at least one date to send out a flyer."])
        else:
            self.cleaned_data = {'flyer_dates_list':selected_flyer_list}
        return self

    def custom_is_valid(self, post_data):
        """ Custom is_valid form method to build cleaned_data and errors then
        return a boolean deeming the validity of the form.
        """
        self.clean_dynamic_fields(post_data)
        is_valid = True
        if self._errors or not self.cleaned_data:
            is_valid = False
        return is_valid

class AddFlyerByMapForm(forms.Form):
    """ The Add Flyer By Map Form. """
    def __init__(self, county_dict, *args, **kwargs):
        super(AddFlyerByMapForm, self).__init__(*args, **kwargs)

        for county in county_dict:
            county_underscore = county['county'].replace(" ", "_")
            attrs = {
                'class': "county county_%s" % county_underscore,
                'id': "id_%s_%s" % (county['county_id'], county['county_count'])
                }
            self.fields['county_%s' % county_underscore] = forms.ChoiceField(
                widget=CheckboxInput(attrs=attrs, check_test=True),
                initial=county_underscore,
                label = county['county'],
                required=False)
            for city in county['cities']:
                city_underscore = city['city'].replace(" ", "_")
                for _zip in city['zips']:
                    self.fields['zip_%s' % _zip['zip']] = forms.IntegerField(
                        widget=forms.HiddenInput(
                        attrs={'class': "zip region_%s region_%s zip_%s" % (
                                county_underscore,
                                city_underscore,
                                _zip['zip']),
                            'id': "id_%s_%s" % (
                                _zip['zip_id'], _zip['zip_count'])}),
                    required=False, initial=_zip['zip'])

        self.fields['county_array'] = forms.CharField(widget=forms.HiddenInput(),
            required=False)
        self.fields['zip_array'] = forms.CharField(widget=forms.HiddenInput(),
            required=False)
        self.fields['subdivision_consumer_count'] = forms.IntegerField(
            widget=forms.HiddenInput(
                attrs={'class':"subdivision_consumer_count"}),
        required=False, initial=0)

    def clean_dynamic_fields(self, post_data):
        """ Clean method for this form. """
        self.cleaned_data = {}
        self._errors = ErrorDict()
        county_array = post_data['county_array'].split(",")
        zip_array = post_data['zip_array'].split(",")
        if county_array[0] is u'':
            county_array.pop(0)
        if zip_array[0] is u'':
            zip_array.pop(0)
        county_array = [int(county) for county in county_array]
        zip_array = [int(_zip) for _zip in zip_array]
        subdivision_consumer_count = post_data['subdivision_consumer_count']
        self.cleaned_data = {
            'subdivision_consumer_count':subdivision_consumer_count,
            'zip_array':tuple(zip_array),
            'county_array':tuple(county_array)}
        return self

    def custom_is_valid(self, post_data):
        """ Custom is_valid form method to build cleaned_data and errors, then
        return a boolean deeming the validity of the form.
        """
        self.clean_dynamic_fields(post_data)
        is_valid = True
        if self._errors or not self.cleaned_data:
            is_valid = False
        return is_valid

class AddFlyerByListForm(forms.Form):
    """ The Add Flyer By List Form. """
    def __init__(self, county_dict, *args, **kwargs):
        super(AddFlyerByListForm, self).__init__(*args, **kwargs)

        for county in county_dict:
            county_underscore = county['county'].replace(" ", "_")
            attrs = {'class':"county county_%s" % county_underscore,
                     'id':"id_%s_%s" % (county['county_id'],
                                        county['county_count'])}
            self.fields['county_%s' % county_underscore] = forms.ChoiceField(
                widget=CheckboxInput(
                    attrs=attrs,
                    check_test=True),
                initial=county_underscore,
                label = '%s' % (county['county']),
                required=False)

            for city in county['cities']:
                if len(city['zips']) is 1:
                    city_underscore = city['city'].replace(" ", "_")
                    self.fields['city_%s' % city_underscore] = \
                        forms.ChoiceField(
                            widget=forms.CheckboxInput(
                                attrs={'class': "city region_%s city_%s" % (
                                        county_underscore,
                                        city_underscore),
                                   'id': "id_%s_%s" % (city['city_id'],
                                        city['city_count'])},
                                check_test=True),
                            required=False,
                            label = '%s %s' % (city['city'],
                                city['zips'][0]['zip']),
                            initial=city_underscore)
                else:
                    city_underscore = city['city'].replace(" ", "_")
                    self.fields['city_%s' % city_underscore] = \
                        forms.ChoiceField(
                            widget=forms.CheckboxInput(
                                attrs={'class': "city region_%s city_%s" % (
                                        county_underscore,
                                        city_underscore),
                                    'id': "id_%s_%s" % (city['city_id'],
                                        city['city_count'])},
                                check_test=True),
                            required=False,
                            label = '%s' % (city['city']),
                            initial=city_underscore)
                    for _zip in city['zips']:
                        self.fields['zip_%s' % _zip['zip']] = forms.ChoiceField(
                            widget=forms.CheckboxInput(
                                attrs={'class':
                                    "zip region_%s region_%s zip_%s" % (
                                        county_underscore,
                                        city_underscore,
                                        _zip['zip']),
                                   'id':"id_%s_%s" % (_zip['zip_id'],
                                        _zip['zip_count'])},
                                check_test=True),
                            required=False,
                            label = '%s' % (_zip['zip']),
                            initial=_zip['zip'])
        self.fields['county_array'] = forms.CharField(
            widget=forms.HiddenInput(), required=False)
        self.fields['zip_array'] = forms.CharField(widget=forms.HiddenInput(),
            required=False)
        self.fields['subdivision_consumer_count'] = forms.IntegerField(
            widget=forms.HiddenInput(
                attrs={'class':"subdivision_consumer_count"}),
        required=False, initial=0)

    def clean_dynamic_fields(self, post_data):
        """ Clean method for this form. """
        self.cleaned_data = {}
        self._errors = ErrorDict()
        county_array = post_data['county_array'].split(",")
        zip_array = post_data['zip_array'].split(",")
        if county_array[0] is u'':
            county_array.pop(0)
        if zip_array[0] is u'':
            zip_array.pop(0)
        county_array = [int(county) for county in county_array]
        zip_array = [int(_zip) for _zip in zip_array]
        subdivision_consumer_count = post_data['subdivision_consumer_count']
        self.cleaned_data = {
            'subdivision_consumer_count':subdivision_consumer_count,
            'zip_array':tuple(zip_array),
            'county_array':tuple(county_array)}
        return self

    def custom_is_valid(self, post_data):
        """ Custom is_valid form method to build cleaned_data and errors, then
        return a boolean deeming the validity of the form.
        """
        self.clean_dynamic_fields(post_data)
        is_valid = True
        if self._errors or not self.cleaned_data:
            is_valid = False
        return is_valid


import subprocess

import argparse

def main():

    parser = argparse.ArgumentParser(description='Grab a Hardware Component from GitHub and place it in ScopeFoundryHW using git subtree add/pull.')

    parser.add_argument('name', type=str,
                    help='name of hardware')

    parser.add_argument('action', help='add or pull')

    parser.add_argument('--squash', action='store_true',
                            required=False, help='')

    args = parser.parse_args()
    print(args)
    print("-->", args['name'])

if __name__ == "__main__":
    main()


#! /usr/bin/env python3

import os.path
import argparse
import fitparse
import pandas as pd
import math
import matplotlib
import matplotlib.cm as cm
import folium
from folium.features import DivIcon
from datetime import datetime, timedelta
import io
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from jinja2 import Template
import base64
import logging

AVAILABLE_METRICS = {
    "enhanced_altitude": {
        "color": "rgb(200, 155, 155)",
        "pretty_name": "Altitude",
        "unit": "m"
    },
    "heart_rate": {
        "color": "rgb(255, 50, 50)",
        "pretty_name": "Heart rate",
        "unit": "bpm"
    },
    "speed": {
        "color": "rgb(0, 0, 109)",
        "pretty_name": "Speed",
        "unit": "km/h"
    }
}

HTML_TEMPLATE_FNAME = "templates/activity.html"

logger = logging.getLogger("watchmap")
logger.addHandler(logging.StreamHandler())

def normalize_value(varmin, varmax, value):
    return float(varmax - value) / float(varmax - varmin)

def add_to_layer(layer, pt, varname, minmax):
    norm = matplotlib.colors.Normalize(
        vmin=minmax[varname]["min"], vmax=minmax[varname]["max"], clip=True
    )
    mapper = cm.ScalarMappable(norm=norm, cmap=cm.plasma)
    tooltip = f"Speed: {pt.speed:0.1f}kph
Heart rate: {pt.heart_rate}bpm
Altitude: {pt.enhanced_altitude:0.1f}m
Time: {pt.timestamp}"
    folium.CircleMarker(
        location=(pt.position_lat, pt.position_long),
        radius=10 + 1.5 * normalize_value(minmax[varname]["min"], minmax[varname]["max"], pt[varname]),
        tooltip=tooltip,
        fill_color=matplotlib.colors.to_hex(mapper.to_rgba(pt[varname])),
        fill=True,
        fill_opacity=0.2,
        weight=0,
    ).add_to(layer)

def get_session_details(fitfile):
    session = list(fitfile.get_messages("session"))
    if len(session) != 1:
        raise Exception("Unsupported session type")
    return {d.name: d.value for d in session[0] if d.value is not None}

def plot_map(track):
    minmax = {
        colname: {"min": min(track[colname]), "max": max(track[colname])}
        for colname in track.columns if len(track[colname].dropna())
    }

    m = folium.Map(
        location=[track["position_lat"].mean(), track["position_long"].mean()],
        zoom_start=15,
    )
    track_duration = track.iloc[-1].timestamp - track.iloc[0].timestamp

    feat_group_speed = folium.FeatureGroup(name="Speed")
    feat_group_hr = folium.FeatureGroup(name="Heart Rate", show=False)
    feat_group_alt = folium.FeatureGroup(name="Altitude", show=False)

    folium.Marker(
        [track.iloc[0]["position_lat"], track.iloc[0]["position_long"]],
        tooltip=f"Start
Time: {track.iloc[0].timestamp}",
        icon=folium.Icon(icon="home", color="green"),
    ).add_to(m)
    folium.Marker(
        [track.iloc[-1]["position_lat"], track.iloc[-1]["position_long"]],
        tooltip=f"End
Length: {track.iloc[-1].distance/1000:0.1f}km
Duration: {track_duration}
Time: {track.iloc[-1].timestamp}",
        icon=folium.Icon(icon="flag", color="red"),
    ).add_to(m)

    for _, pt in track.iterrows():
        if pt.speed == 0:
            pt.speed = 0.01
        add_to_layer(feat_group_speed, pt, "speed", minmax)
        add_to_layer(feat_group_hr, pt, "heart_rate", minmax)
        add_to_layer(feat_group_alt, pt, "enhanced_altitude", minmax)

    m.add_child(feat_group_speed)
    m.add_child(feat_group_hr)
    m.add_child(feat_group_alt)
    m.add_child(folium.LayerControl())
    mapbuff = io.BytesIO()
    m.save(mapbuff, close_file=False)
    return mapbuff

def plot_charts(track):
    metrics = sorted(list(set(AVAILABLE_METRICS).intersection(set(track.columns))))
    nb_rows = len(metrics)
    fig = make_subplots(rows=nb_rows, cols=1)
    current_row = 1

    for metric in metrics:
        fig.add_trace(
            go.Scatter(
                x=track["timestamp"],
                y=track[metric],
                name=AVAILABLE_METRICS[metric]["pretty_name"],
                text="{pretty_name} ({unit})".format(**AVAILABLE_METRICS[metric]),
                hoverinfo="y+text",
                marker_color=AVAILABLE_METRICS[metric]["color"],
            ),
            row=current_row,
            col=1,
        )
        current_row += 1
    chartsbuff = io.StringIO()
    fig.write_html(chartsbuff, full_html=False, default_height="700px", default_width="100%")
    return chartsbuff

def build_html(input_path, output, map=True, embed_fit=False):
    fitfile = fitparse.FitFile(input_path)
    track = fitrecords_to_track(fitfile.get_messages("record"))
    mapbuff = None
    b64fit = None

    if embed_fit:
        with open(input_path, "rb") as input_file:
            b64fit = os.path.basename(input_path), base64.b64encode(input_file.read()).decode('utf-8')

    if "position_long" not in track.columns:
        logger.warn("No GPS coordinates found in the FIT file, not plotting the map")
        map = False

    if map:
        mapbuff = plot_map(track)
    chartsbuff = plot_charts(track)
    track_duration = track.iloc[-1].timestamp - track.iloc[0].timestamp

    session_info = get_session_details(fitfile)

    with open(os.path.join(os.path.dirname(__file__), HTML_TEMPLATE_FNAME), "r") as html_template:
        tpl = Template(html_template.read())

    with open(output, "w") as f:
        f.write(
            tpl.render(
                **{
                    "track_duration": track_duration,
                    "map_iframe": mapbuff.getvalue()
                    .decode("utf-8")
                    .replace('"', """)
                    if mapbuff
                    else None,
                    "charts_iframe": chartsbuff.getvalue(),
                    "session_info": session_info,
                    "fit_file": b64fit,
                }
            )
        )
        logger.info("Output written to %s" % output)

def fitrecords_to_track(fitrecords):
    track = []
    for record in fitrecords:
        track.append({d.name: d.value for d in record})
    df = pd.DataFrame(track)
    if 'enhanced_speed' in df.columns:
        df["speed"] = df.enhanced_speed * 3.6
    if "position_long" in df.columns and "position_lat" in df.columns:
        df["position_long"] = df["position_long"] * 180 / math.pow(2, 31)
        df["position_lat"] = df["position_lat"] * 180 / math.pow(2, 31)
        return df.dropna(subset=["position_long", "position_lat"])
    return df

def run():
    parser = argparse.ArgumentParser(description="Plot Garmin Activity on a map")
    parser.add_argument("-i", "--input", help="Input FIT file", required=True, type=str)
    parser.add_argument(
        "-o",
        "--output_dir",
        help="Output directory (output will be written in output_dir/{input}.html)",
        type=str,
        required=True,
    )
    parser.add_argument("-v", "--verbose", action='store_true')
    parser.add_argument("-f", "--force", help="Overwrite output file if it exists", action='store_true')
    parser.add_argument("--embed-fit", dest="embed_fit", help="Embed FIT file into the generated HTML page", action='store_true')
    args = parser.parse_args()

    if args.verbose:
        logger.setLevel(logging.INFO)

    if not os.path.exists(args.output_dir):
        os.makedirs(args.output_dir)

    output = '/'.join([
        e for e in (
            args.output_dir.split('/')
            + [f"{'.'.join(args.input.split('/')[-1].split('.')[:-1])}.html"]
        )
        if e != ''
        ])

    logger.info(f"Processing {args.input}")

    if os.path.exists(output) and not args.force:
        logger.warn(f"Output file '{output}' already exists, skipping.")
        return

    build_html(args.input, output, embed_fit=args.embed_fit)


from django.utils.deprecation import MiddlewareMixin
from users.models import Users
from django.shortcuts import render, redirect
from django.urls import reverse, resolve
from django.http import HttpResponse, JsonResponse
import constant

REQUIRE_LIOGIN_JSON = ["/users/createBookList/", "/users/getUserBookLists/"]
REQUIRE_LIOGIN = ["/users/mine/"]

class LoginMiddleware(MiddlewareMixin):
    def process_request(self, request):

        if request.path in REQUIRE_LIOGIN_JSON:

            user_id = request.session.get("user_id")

            if user_id:
                try:
                    user = Users.objects.get(id=user_id)
                    request.user = user
                except:
                    data = {
                        "status": constant.HTTP_REDIRECT,
                        "msg": "user not available",
                    }

                    return JsonResponse(data=data)

            else:
                data = {"status": constant.HTTP_REDIRECT, "msg": "user not log in"}
                return JsonResponse(data=data)

        if request.path in REQUIRE_LIOGIN:

            user_id = request.session.get("user_id")

            if user_id:
                try:
                    user = Users.objects.get(id=user_id)
                    request.user = user
                except:
                    data = {
                        "status": constant.HTTP_REDIRECT,
                        "msg": "user not available",
                    }

                    return redirect(reverse("users:login"))

            else:
                data = {"status": constant.HTTP_REDIRECT, "msg": "user not log in"}
                return redirect(reverse("users:login"))


# -*- coding: UTF-8 -*-

from output_class import OutputClass
from db_entities.conf import DBConf
from db_entities.conf_question import DBConfQuestion
from google.appengine.ext import db

class ConfReply(OutputClass):

    url_handler = '/conf/reply/.*'
    access = 0

    def get(self):

        super(ConfReply, self).get()

        q_id = int(self.get_url_part(1))
        name = self.get_url_part(2)

        conf = 0

        try:
            conf = DBConf.gql("where name = :name", name = name)[0]
        except:
            self.showMessage("К сожалению, такой конференции не найдено!")
            return

        if conf.userid != self.Session['userid']:
            self.showMessage("Нет доступа")
            return

        question = DBConfQuestion.get_by_id(q_id)

        self.insertTemplate("conf/tpl_conf_reply.html", {
                                              'name' : name,
                                              'cap' : conf.cap,
                                              'question' : question,
                                              })

        self.drawPage()

    def post(self):

        super(ConfReply, self).get()

        q_id = int(self.get_url_part(1))
        name = self.get_url_part(2)

        conf = 0

        try:
            conf = DBConf.gql("where name = :name", name = name)[0]
        except:
            self.showMessage("К сожалению, такой конференции не найдено!")
            return

        if conf.userid != self.Session['userid']:
            self.showMessage("Нет доступа")
            return

        question = DBConfQuestion.get_by_id(q_id)

        question.answer = self.request.get("answer")
        question.moderated = True
        question.put()

        conf.updated = db.datetime.datetime.now()
        conf.put()

        self.showMessage("Готово!")


"""Helper Functions for the Controllers Module"""
import os
import xml.etree.ElementTree as ET
from collections import defaultdict
import calendar
import numpy as np
import shapely.geometry
import shapely
import netCDF4
from tethysapp.aqx_india.config import THREDDS_CATALOG, THREDDS_wms, DATA_DIR, LOG_DIR, GIF_DIR
from shapely.geometry import Polygon
import logging
from datetime import datetime,timedelta
import psycopg2
import json
import requests
from PIL import Image,ImageFile,ImageFont,ImageDraw,ImageChops,ImageOps
import imageio
from django.views.decorators.csrf import csrf_exempt
import tethysapp.aqx_india.config as cfg
from geopy.distance import great_circle
from geopy.distance import geodesic
from itertools import *
import logging

log = logging.getLogger(__name__)

logger = logging.getLogger('utils.py')
logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(LOG_DIR+'/AQX_India.log', maxBytes=104857600, backupCount=5)
logger.addHandler(handler)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('"%(asctime)s" , "%(name)s" , "%(levelname)s" , "%(message)s"')
ch.setFormatter(formatter)
handler.setFormatter(formatter)
logger.addHandler(ch)

def generate_variables_meta():
    """Generate Variables Metadata from the Var Info text"""
    db_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'public/data/var_info.txt')
    variable_list = []
    with open(db_file, mode='r') as f:
        f.readline()  # Skip first line

        lines = f.readlines()

    for line in lines:
        if line != '':
            line = line.strip()
            linevals = line.split('|')
            variable_id = linevals[0]
            category = linevals[1]
            display_name = linevals[2]
            units = linevals[3]
            vmin = linevals[4]
            vmax = linevals[5]

            try:
                variable_list.append({
                    'id': variable_id,
                    'category': category,
                    'display_name': display_name,
                    'units': units,
                    'min': vmin,
                    'max': vmax,
                })
            except Exception:
                continue
    print('vmax =',vmax)
    return variable_list

def get_styles():
    """Returns a list of style tuples"""
    date_obj = {}

    color_opts = [
        ('Rainbow', 'rainbow'),
        ('TMP 1', 'tmp_2maboveground'),
        ('TMP 2', 'dpt_2maboveground'),
        ('SST-36', 'sst_36'),
        ('Greyscale', 'greyscale'),

        ('OCCAM', 'occam'),
        ('OCCAM Pastel', 'occam_pastel-30'),
        ('Red-Blue', 'redblue'),
        ('NetCDF Viewer', 'ncview'),
        ('ALG', 'alg'),
        ('ALG 2', 'alg2'),
        ('Ferret', 'ferret'),
        ('Reflectivity', 'enspmm-refc'),
        ('PM25', 'pm25_india'),
        ('PM25 RAMP', 'pm25_india_ramp'),
        # ('Probability', 'prob'),
        # ('White-Blue', whiteblue'),
        # ('Grace', 'grace'),
    ]

    date_obj["colors"] = color_opts

    return date_obj

def gen_style_legend(style):
    style_f = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'public/data/palettes/'+str(style)+'.pal')
    scale = []
    if os.path.exists(style_f):
        with open(style_f, mode='r') as f:
            lines = f.readlines()
        for line in lines:
            lval = line.split()
            if len(lval)>0:
                rgb = (lval[0], lval[1], lval[2])
                scale.append(rgb)
    return scale

def gen_thredds_options():
    """Generate THREDDS options for the dropdowns"""
    catalog_url = THREDDS_CATALOG

    catalog_wms = THREDDS_wms
    tinf = defaultdict()
    json_obj = {}

    if catalog_url[-1] != "/":
        catalog_url = catalog_url + '/'

    if catalog_wms[-1] != "/":
        catalog_wms = catalog_wms + '/'
    catalog_xml_url = catalog_url + 'catalog.xml'
    cat_response = requests.get(catalog_xml_url, verify=False)
    cat_tree = ET.fromstring(cat_response.content)
    currentDay = datetime.now().strftime('%d')
    currentMonth = datetime.now().strftime('%m')
    currentYear = datetime.now().strftime('%Y')
    d=currentYear+currentMonth+currentDay
    for elem in cat_tree.iter():
        for k, v in elem.attrib.items():
            if 'title' in k and ("geos" in v or "fire" in v or "aod" in v):
                run_xml_url = catalog_url + str(v) +'/catalog.xml'
                run_response = requests.get(run_xml_url, verify=False)
                run_tree = ET.fromstring(run_response.content)
                for ele in run_tree.iter():
                    for ke, va in ele.attrib.items():
                        if 'urlPath' in ke:
                            if va.endswith('.nc') and d in va  and "geos" in va:
                                tinf.setdefault(v, {}).setdefault('3daytoday', []).append(va)
                                tinf.setdefault(v, {}).setdefault('3dayrecent', []).append(va)
                            elif va.endswith('.nc') and d not in va and "geos" in va:
                                tinf.setdefault(v, {}).setdefault('3dayrecent', []).append(va)
                            elif va.endswith('.nc') and "geos" not in va:
                                tinf.setdefault(v, {}).setdefault('monthly', []).append(va)
                        if 'title' in ke and ("combined" in va):
                            mo_xml_url = catalog_url + str(v) + '/'+str(va)+'/catalog.xml'
                            print(mo_xml_url)
                            mo_response = requests.get(mo_xml_url, verify=False)
                            mo_tree = ET.fromstring(mo_response.content)
                            for el in mo_tree.iter():
                                for key, val in el.attrib.items():
                                    if 'urlPath' in key:
                                        tinf.setdefault(v, {}).setdefault(va, []).append(val)
    json_obj['catalog'] = tinf
    return json_obj

def get_time(freq, run_type, run_date):
    # Empty list to store the timeseries values
    ts = []
    json_obj = {}

    """Make sure you have this path for all the run_types(/home/tethys/aq_dir/fire/combined/combined.nc)"""
    infile = os.path.join(DATA_DIR, run_type, run_date)
    nc_fid = netCDF4.Dataset(infile, 'r')  # Reading the netCDF file
    lis_var = nc_fid.variables
    time = nc_fid.variables['time'][:]
    for timestep, v in enumerate(time):
        dt_str = netCDF4.num2date(lis_var['time'][timestep], units=lis_var['time'].units,
                                  calendar=lis_var['time'].calendar)
        #time_stamp = calendar.timegm(dt_str.utctimetuple()) * 1000
        dtt=dt_str.strftime('%Y-%m-%dT%H:%M:%SZ')
        dt=datetime.strptime(dtt,'%Y-%m-%dT%H:%M:%SZ')
        ts.append(datetime.strftime(dt, '%Y-%m-%dT%H:%M:%SZ'))
    ts.sort()
    json_obj["times"] = ts
    return json_obj

@csrf_exempt
def get_pt_values(s_var, geom_data, freq, run_type, run_date):
    """Helper function to generate time series for a point"""
    logger.info("PARAMETERS : ['" + s_var + "','" + geom_data + "','" + freq + "','" + run_type + "','" + run_date+"']")
    # Empty list to store the timeseries values
    ts_plot = []
    ts_plot_pm25 = []
    ts_plot_bcpm25 = []
    ts_plot_geospm25 = []
    s_var1 = 'PM25'
    s_var2 = 'BC_MLPM25'
    s_var3 = 'GEOSPM25'

    json_obj = {}

    # Defining the lat and lon from the coords string
    coords = geom_data.split(',')
    stn_lat = float(coords[1])
    stn_lon = float(coords[0])
    st_point=(stn_lat,stn_lon)
    """Make sure you have this path for all the run_types(/home/tethys/aq_dir/fire/combined/combined.nc)"""
    try:
        if "geos" in run_type:
            infile = os.path.join(DATA_DIR, run_type, run_date)
        else:
            infile = os.path.join(DATA_DIR, run_type, freq, run_date)
        nc_fid = netCDF4.Dataset(infile, 'r',)  # Reading the netCDF file
        lis_var = nc_fid.variables
        if "geos" == run_type and "PM25" in s_var:
            field = nc_fid.variables[s_var][:]
            lats = nc_fid.variables['lat'][:]
            lons = nc_fid.variables['lon'][:]  # Defining the longitude array
            time = nc_fid.variables['time'][:]
            abslat = np.abs(lats - stn_lat)  # Finding the absolute latitude
            abslon = np.abs(lons - stn_lon)  # Finding the absolute longitude
            lat_idx = (abslat.argmin())
            lon_idx = (abslon.argmin())
            for timestep, v in enumerate(time):
                val = field[lat_idx, lon_idx][timestep]
                if np.isnan(val) == False:
                    dt_str = netCDF4.num2date(lis_var['time'][timestep], units=lis_var['time'].units,
                                              calendar=lis_var['time'].calendar)
                    dtt = dt_str.strftime('%Y-%m-%dT%H:%M:%SZ')
                    dt = datetime.strptime(dtt, '%Y-%m-%dT%H:%M:%SZ')
                    time_stamp = calendar.timegm(dt.utctimetuple()) * 1000
                    ts_plot.append([time_stamp, float(val)])
            field1 = nc_fid.variables[s_var1][:]
            lats = nc_fid.variables['lat'][:]
            lons = nc_fid.variables['lon'][:]  # Defining the longitude array
            time = nc_fid.variables['time'][:]
            abslat = np.abs(lats - stn_lat)  # Finding the absolute latitude
            abslon = np.abs(lons - stn_lon)  # Finding the absolute longitude
            lat_idx = (abslat.argmin())
            lon_idx = (abslon.argmin())
            for timestep, v in enumerate(time):

                val = field1[lat_idx, lon_idx][timestep]
                if np.isnan(val) == False:
                    dt_str = netCDF4.num2date(lis_var['time'][timestep], units=lis_var['time'].units,
                                              calendar=lis_var['time'].calendar)
                    test=dt_str+timedelta(hours=7)
                    time_stamp = calendar.timegm(test.timetuple()) * 1000
                    ts_plot_pm25.append([time_stamp, float(val)])
            field2 = nc_fid.variables[s_var2][:]
            lats = nc_fid.variables['lat'][:]
            lons = nc_fid.variables['lon'][:]  # Defining the longitude array
            time = nc_fid.variables['time'][:]
            # Defining the variable array(throws error if variable is not in combined.nc)
            #new way to cal dist
            coordinates=list(product(lats, lons))
            dist=[]
            for val in coordinates:
                distance=great_circle(val, st_point).kilometers
                dist.append(distance)
            index = np.argmin(np.array(dist))
            lat=coordinates[index][0]
            lon = coordinates[index][1]
            for l in range(len(lats)):
                if lat==lats[l]:
                    lat_idx=l
            for l in range(len(lons)):
                if lon == lons[l]:
                    lon_idx = l

            # print("nearest index of lat and lon")

            # abslat = np.abs(lats - stn_lat)  # Finding the absolute latitude
            # abslon = np.abs(lons - stn_lon)  # Finding the absolute longitude
            # lat_idx = (abslat.argmin())
            # lon_idx = (abslon.argmin())
        #new way end
            for timestep, v in enumerate(time):
                val = field2[lat_idx, lon_idx][timestep]
                if np.isnan(val) == False:
                    dt_str = netCDF4.num2date(lis_var['time'][timestep], units=lis_var['time'].units,
                                              calendar=lis_var['time'].calendar)
                    test=dt_str+timedelta(hours=7)
                    dtt = test.strftime('%Y-%m-%dT%H:%M:%SZ')
                    dt = datetime.strptime(dtt, '%Y-%m-%dT%H:%M:%SZ')
                    time_stamp = calendar.timegm(dt.timetuple()) * 1000
                    ts_plot_bcpm25.append([time_stamp, float(val)])
            field3 = nc_fid.variables[s_var3][:]
            lats = nc_fid.variables['lat'][:]
            lons = nc_fid.variables['lon'][:]  # Defining the longitude array
            time = nc_fid.variables['time'][:]
            coordinates = list(product(lats, lons))
            dist = []
            for val in coordinates:
                distance = great_circle(val, st_point).kilometers
                dist.append(distance)
            index = np.argmin(np.array(dist))
            lat = coordinates[index][0]
            lon = coordinates[index][1]
            for l in range(len(lats)):
                if lat == lats[l]:
                    lat_idx = l
            for l in range(len(lons)):
                if lon == lons[l]:
                    lon_idx = l
            for timestep, v in enumerate(time):

                val = field3[lat_idx, lon_idx][timestep]
                if np.isnan(val) == False:
                    dt_str = netCDF4.num2date(lis_var['time'][timestep], units=lis_var['time'].units,
                                              calendar=lis_var['time'].calendar)
                    test=dt_str+timedelta(hours=5)  # adding local time hours
                    test=test+timedelta(minutes=30)  #  local min
                    dtt = test.strftime('%Y-%m-%dT%H:%M:%SZ')
                    dt = datetime.strptime(dtt, '%Y-%m-%dT%H:%M:%SZ')
                    time_stamp = calendar.timegm(dt.timetuple()) * 1000
                    ts_plot_geospm25.append([time_stamp, float(val)])
        else:
            field = nc_fid.variables[s_var][:]
            lats = nc_fid.variables['Latitude'][:]
            lons = nc_fid.variables['Longitude'][:]  # Defining the longitude array
            time = nc_fid.variables['time'][:]
            coordinates = list(product(lats, lons))
            dist = []
            for val in coordinates:
                distance = great_circle(val, st_point).kilometers
                dist.append(distance)
            index = np.argmin(np.array(dist))
            lat = coordinates[index][0]
            lon = coordinates[index][1]
            for l in range(len(lats)):
                if lat == lats[l]:
                    lat_idx = l
            for l in range(len(lons)):
                if lon == lons[l]:
                    lon_idx = l
            for timestep, v in enumerate(time):

                val = field[timestep,lat_idx,lon_idx]
                if np.isnan(val) == False:
                    dt_str = netCDF4.num2date(lis_var['time'][timestep], units=lis_var['time'].units,
                                              calendar=lis_var['time'].calendar)
                    dtt = dt_str.strftime('%Y-%m-%dT%H:%M:%SZ')
                    dt = datetime.strptime(dtt, '%Y-%m-%dT%H:%M:%SZ')
                    time_stamp = calendar.timegm(dt.utctimetuple()) * 1000
                    ts_plot.append([time_stamp, float(val)])

        ts_plot.sort()
        ts_plot_pm25.sort()
        ts_plot_bcpm25.sort()
        ts_plot_geospm25.sort()
        point = [round(stn_lat, 2), round(stn_lon, 2)]
        json_obj["plot"] = ts_plot

        if freq == "station":
            json_obj["bc_mlpm25"] = ts_plot_bcpm25
            json_obj["geos_pm25"] = ts_plot_geospm25
            json_obj["ml_pm25"] = ts_plot_pm25
        json_obj["geom"] = point
        if len(ts_plot) == 0:
            logger.warn("The selected point has no data")
        else:
            pass
            # logger.info("PLOT POINT OBJECT : " + json.dumps(json_obj["plot"]))
        logger.info(json.dumps(json_obj["geom"]))
    except Exception as e:
        return json_obj
    return json_obj

@csrf_exempt
def get_poylgon_values(s_var, geom_data, freq, run_type, run_date):
    """Helper function to generate time series for a polygon"""
    logger.info("PARAMETERS : ['" + s_var +"','"+ geom_data +"','"+ freq +"','"+ run_type +"','"+ run_date+"']")
    # Empty list to store the timeseries values
    ts_plot = []

    json_obj = {}
    # Defining the lat and lon from the coords string
    poly_geojson = Polygon(json.loads(geom_data))
    shape_obj = shapely.geometry.asShape(poly_geojson)
    bounds = poly_geojson.bounds
    miny = float(bounds[0])
    minx = float(bounds[1])
    maxy = float(bounds[2])
    maxx = float(bounds[3])

    """Make sure you have this path for all the run_types(/home/tethys/aq_dir/fire/combined/combined.nc)"""
    if "geos" in run_type:
        infile = os.path.join(DATA_DIR, run_type, run_date)
    else:
        infile = os.path.join(DATA_DIR, run_type, freq, run_date)
    nc_fid = netCDF4.Dataset(infile, 'r')
    lis_var = nc_fid.variables

    if "geos" == run_type:
        field = nc_fid.variables[s_var][:]
        lats = nc_fid.variables['lat'][:]
        lons = nc_fid.variables['lon'][:]  # Defining the longitude array
        time = nc_fid.variables['time'][:]
        # Defining the variable array(throws error if variable is not in combined.nc)

        latli = np.argmin(np.abs(lats - minx))
        latui = np.argmin(np.abs(lats - maxx))

        lonli = np.argmin(np.abs(lons - miny))
        lonui = np.argmin(np.abs(lons - maxy))
        for timestep, v in enumerate(time):
            val = field[latli:latui,lonli:lonui,timestep]
            val = np.mean(val)
            if np.isnan(val) == False:
                dt_str = netCDF4.num2date(lis_var['time'][timestep], units=lis_var['time'].units,
                                          calendar=lis_var['time'].calendar)
                test = dt_str + timedelta(hours=5)  # local time hour
                test=test+timedelta(minutes=30)   #local time min
                dtt = test.strftime('%Y-%m-%dT%H:%M:%SZ')
                dt = datetime.strptime(dtt, '%Y-%m-%dT%H:%M:%SZ')
                time_stamp = calendar.timegm(dt.timetuple()) * 1000
                ts_plot.append([time_stamp, float(val)])
    else:
        """Reading variables from combined.nc"""
        lats = nc_fid.variables['Latitude'][:]  # Defining the latitude array
        lons = nc_fid.variables['Longitude'][:]  # Defining the longitude array
        field = nc_fid.variables[s_var][:]  # Defning the variable array(throws error if variable is not in combined.nc)
        time = nc_fid.variables['time'][:]

        latli = np.argmin(np.abs(lats - minx))
        latui = np.argmin(np.abs(lats - maxx))

        lonli = np.argmin(np.abs(lons - miny))
        lonui = np.argmin(np.abs(lons - maxy))
        for timestep, v in enumerate(time):
            vals = field[timestep, latli:latui, lonli:lonui]
            if run_type == 'fire':
                val = np.sum(vals)
            else:
                val = np.mean(vals)
            if np.isnan(val) == False:
                dt_str = netCDF4.num2date(lis_var['time'][timestep], units=lis_var['time'].units,
                                          calendar=lis_var['time'].calendar)
                dtt = dt_str.strftime('%Y-%m-%dT%H:%M:%SZ')
                dt = datetime.strptime(dtt, '%Y-%m-%dT%H:%M:%SZ')
                time_stamp = calendar.timegm(dt.utctimetuple()) * 1000
                ts_plot.append([time_stamp, float(val)])

    ts_plot.sort()

    geom = [round(minx, 2), round(miny, 2), round(maxx, 2), round(maxy, 2)]

    json_obj["plot"] = ts_plot
    json_obj["geom"] = geom
    if len(ts_plot) == 0:
        logger.warn("The selected polygon has no data")
    else:
        logger.info("PLOT POLYGON OBJECT : " + json.dumps(json_obj["plot"]))
    logger.info(json.dumps(json_obj["geom"]))
    return json_obj

def get_station_data(init_date):
    try:
        print("Getting ready to connect db")
        conn = psycopg2.connect(
            "dbname={0} user={1} host={2} password={3} port={4}".format(cfg.connection['dbname'], cfg.connection['user'], cfg.connection['host'],
                                                               cfg.connection['password'],cfg.connection['port']))
        cur = conn.cursor()
        print("Getting ready to query db")
        sql = "SELECT  DISTINCT ON (s.location) s.location, s.parameter, s.latitude, s.longitude, s.value, s.local FROM indiagrounddata s WHERE   parameter='pm25' and local like '"+init_date+"%' "
        print(sql)
        cur.execute(sql)
        print("out from query")
        data = cur.fetchall()
        stations=[]
        for row in data:
            location = row[0]
            print("lcation ",location)
            parameter = row[1]
            latitude = row[2]
            longitude = row[3]
            pm25 = row[4]
            local = row[5]
            stations.append({
                'location': location,
                'parameter': parameter,
                'latitude': latitude,
                'longitude': longitude,
                'pm25': pm25,
                'local': local
            })
        conn.close()
        return stations
    except Exception as e:
        return ["error"]

def get_pm25_data(s_var, run_type, run_date, station, lat, lon):
    try:
        geom_data = lon+',' + lat
        print("getting ready to get pt values")
        geos_pm25_data = get_pt_values(s_var, geom_data, "station", "geos", run_date)
        print("pt values returned")
        conn = psycopg2.connect(
            "dbname={0} user={1} host={2} password={3} port={4}".format(cfg.connection['dbname'], cfg.connection['user'],
                                                               cfg.connection['host'], cfg.connection['password'],cfg.connection['port']))
        cur = conn.cursor()
        print("connected to db")
        # "2019-08-01 03:00:00"
        #print("run_date is ", run_date)
        #print(run_date.split('.')[0])
        date_obj = datetime.strptime(run_date.split('.')[0],"%Y%m%d")
        end_date = date_obj+timedelta(days=3)
        sd = date_obj.strftime("%Y-%m-%d %H:%M:%S")
        ed = end_date.strftime("%Y-%m-%d %H:%M:%S")

        sql="SELECT  local,value from indiagrounddata where location = '"+station+"' and value is not null \
                      and parameter='pm25' \
                      and substring(local,12,2)  in ('01','04','07','10','13','16','19','22') \
                      and substring(local,1,19)  between '"+sd+"' and '" +ed+"' "
        print(sql)

        cur.execute(sql)
        '''
        cur.execute(("SELECT  local,value from testindia where location = '%s' and value is not null \
                      and substring(local,12,2)  in ('02','05','08','11','14','17','20','23') \
                      and substring(local,1,19)  between '%s' and '%s'"), (str(station), sd, ed,))   # station is location,ed=end date,sd=start date
        '''
        data = cur.fetchall()
        pm25_data = {}
        ts_plot = []
        print("getting into for loop 519")
        for row in data:
            dt = row[0][0:19]

            pm25 = row[1]
            print("this is pm25 ", pm25)
            dtts=datetime.strptime(dt, '%Y-%m-%dT%H:%M:%S')

            time_stamp = calendar.timegm(dtts.timetuple()) * 1000

            ts_plot.append([time_stamp, float(str(pm25))])

        ts_plot.sort()
        pm25_data["field_data"] = ts_plot
        pm25_data["ml_pm25"] = geos_pm25_data["ml_pm25"]
        pm25_data["bc_mlpm25"] = geos_pm25_data["bc_mlpm25"]

        pm25_data["geos_pm25"] = geos_pm25_data["geos_pm25"]
        pm25_data["geom"] = geos_pm25_data["geom"]
        conn.close()
        return pm25_data
    except Exception as e:
        return ""

def generate_gif(date, variable, fps, cds):
    try:
        if fps == 'Fast':
            frames = 3
        else:
            frames = 1
        ImageFile.LOAD_TRUNCATED_IMAGES = True
        if cds == "":
            coords=[[6653078.941942, -19567.879241],[12955974.216254, 4970241.327215]]
        else:
            coords=json.loads(cds)
        times = ['01', '04', '07', '10', '13', '16', '19', '22']
        date_obj = datetime.strptime(date.split('.')[0], "%Y%m%d")
        d1 = date_obj.strftime("%Y-%m-%d")
        d2 = (date_obj+timedelta(days=1)).strftime("%Y-%m-%d")
        d3 = (date_obj + timedelta(days=2)).strftime("%Y-%m-%d")
        dt = date_obj.strftime("%Y%m%d")
        timevar = []
        imagedata = []
        for d in [d1, d2, d3]:
            for time in times:
                timevar.append(d+' '+time+':30')  # 6653078.941942,-19567.879241,12955974.216254,4970241.327215
                image_url = THREDDS_wms + '/mk_aqx/geos/' +dt+'.nc?service=WMS&request=GetMap&layers='+variable+'&styles=boxfill%2Frainbow&format=image%2Fpng&transparent=true&version=1.3.0&time='+d+'T'+time+'%3A30%3A00.000Z&colorscalerange=0%2C5&ABOVEMAXCOLOR=0x00ffff&width=700&height=700&crs=EPSG%3A3857&bbox='+str(coords[0][0])+','+str(coords[0][1])+','+str(coords[1][0])+','+str(coords[1][1])
                image_content = requests.get(image_url, verify=False).content
                imagedata.append(image_content)

        images = []
        i = 0
        if variable == 'BC_MLPM25':
            variable = 'PM 2.5'
        for filename in imagedata:
            with open(GIF_DIR+dt+'.png', 'wb') as f:
                f.write(filename)
            img = Image.open(GIF_DIR+dt+'.png').convert('RGBA')
            bg = Image.new(img.mode, img.size, img.getpixel((0, 0)))
            diff = ImageChops.difference(img, bg)
            diff = ImageChops.add(diff, diff, 2.0, -100)
            box = diff.getbbox()
            if box:
                img = img.crop(box)
            img = ImageOps.expand(img, border=20, fill='black')
            draw = ImageDraw.Draw(img)
            font = ImageFont.truetype(os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                                   'public/data/agane.ttf'), 20)
            x, y = 40, 560
            draw.text((x - 1, y), variable, font=font, fill='black')
            draw.text((x + 1, y), variable, font=font, fill='black')
            draw.text((x, y - 1), variable, font=font, fill='black')
            draw.text((x, y + 1), variable, font=font, fill='black')
            x, y = 140, 560
            draw.text((x - 1, y), str(timevar[i]), font=font, fill='black')
            draw.text((x + 1, y), str(timevar[i]), font=font, fill='black')
            draw.text((x, y - 1), str(timevar[i]), font=font, fill='black')
            draw.text((x, y + 1), str(timevar[i]), font=font, fill='black')
            draw.text((40, 560), variable, (255, 255, 255), font=font)
            draw.text((140, 560), str(timevar[i]), (255, 255, 255), font=font)
            adpc_logo = Image.open(os.path.join(os.path.dirname(os.path.realpath(__file__)),'public/images/adpc.png'))
            adpc_logo = adpc_logo.convert("RGBA")
            img.paste(adpc_logo, (100, 40), adpc_logo)
            nasa_logo = Image.open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'public/images/nasa.png'))
            nasa_logo = nasa_logo.convert("RGBA")
            img.paste(nasa_logo, (40, 40), nasa_logo)
            images.append(img)
            i = i + 1
            images.append(img)

        imageio.mimsave(GIF_DIR + dt + '.gif', images, fps=frames)
        anim = ""
        with open(GIF_DIR + dt + '.gif', "rb") as f:
            data = f.read()
            anim=data.encode("base64")
        os.remove(GIF_DIR + dt + '.gif')
        os.remove(GIF_DIR + dt + '.png')
        return anim
    except Exception as e:
        return e


# Alunos : Ana denicoli e  Julio Cesar
# turma : T2
# função : Programa que gera 10 valores aleatórios para o usuario jogar na Mega Sena

import random

for x in range (0,10) :
    valor = random.randint(0,100)
    print ('Os valores para a Mega Sena são: ', valor)