from abc import ABCMeta, abstractmethod
from contextlib import asynccontextmanager

__all__ = ["get_backend", "Backend"]

class Backend(metaclass=ABCMeta):
    def __init__(self, tg):
        self._tg = tg

    @abstractmethod
    @asynccontextmanager
    async def connect(self, *a, **k):
        """
        This async context manager returns a connection.
        """

    async def aclose(self):
        """
        Force-close the connection.
        """
        await self._tg.cancel_scope.cancel()

    def spawn(self, *a, **kw):
        return self._tg.spawn(*a, **kw)

    @abstractmethod
    @asynccontextmanager
    async def monitor(self, *topic):
        """
        Return an async iterator that listens to this topic.
        """

    @abstractmethod
    async def send(self, *topic, payload):
        """
        Send this payload to this topic.
        """

def get_backend(name):
    from importlib import import_module
    if '.' not in name:
        name = "distkv.backend."+name
    return import_module(name).connect


from flask import render_template,request,redirect,url_for,abort
from ..models import User,Blog,Comment
from .forms import UpdateProfile,BlogForm,CommentForm,SubscriberForm
from . import main
from .. import db,photos
from flask_login import login_required,current_user
from ..models import User,Blog,Comment,Subscriber
from datetime import datetime
from ..requests import get_quotes
from ..email import mail_message

@main.route('/user/<uname>')
def profile(uname):
    user = User.query.filter_by(username = uname).first()

    if user is None:
        abort(404)

    return render_template("profile/profile.html", user = user)

@main.route('/quotes', methods=['GET','POST'])
def quotes():
   quotes = get_quotes()
   print (quotes)

   return render_template('quotes.html',quotes = quotes)

@main.route('/user/<uname>/update',methods = ['GET','POST'])
@login_required
def update_profile(uname):
    user = User.query.filter_by(username = uname).first()
    if user is None:
        abort(404)

    form = UpdateProfile()

    if form.validate_on_submit():
        user.bio = form.bio.data
        db.session.add(user)
        db.session.commit()
        return redirect(url_for('.profile',uname=user.username))
    return render_template('profile/update.html',form =form)

@main.route('/user/<uname>/update/pic',methods= ['POST'])
@login_required
def update_pic(uname):
    user = User.query.filter_by(username = uname).first()
    if 'photo' in request.files:
        filename = photos.save(request.files['photo'])
        path = f'photos/{filename}'
        user.profile_pic_path = path
        db.session.commit()
    return redirect(url_for('main.profile',uname=uname))

@main.route('/detail', methods=['GET','POST'])
@login_required
def detail():
    blog_form=BlogForm()
    if blog_form.validate_on_submit():
        detail = Blog(category=blog_form.category.data,title = blog_form.title.data)
        db.session.add(detail)
        db.session.commit()
    subscribers = Subscriber.query.all()
    for email in subscribers:
        mail_message("Hey Welcome To My Blog ","email/welcome_post",email.email,subscribers=subscribers)
    return render_template('detail.html',blog_form=blog_form)

@main.route('/', methods=['GET','POST'])
def subscriber():
    subscriber_form=SubscriberForm()
    if subscriber_form.validate_on_submit():
        subscriber= Subscriber(email=subscriber_form.email.data,title = subscriber_form.title.data)
        db.session.add(subscriber)
        db.session.commit()
        mail_message("Hey Welcome To My Blog ","email/welcome_subscriber",subscriber.email,subscriber=subscriber)
    subscriber = Blog.query.all()
    detail = Blog.query.all()
    return render_template('index.html',subscriber=subscriber,subscriber_form=subscriber_form,detail=detail)

@main.route('/comments/<int:id>', methods=['GET','POST'])
def comment(id):
    comment_form=CommentForm()
    if comment_form.validate_on_submit():
        new_comment = Comment(description=comment_form.description.data,blog_id=id)
        db.session.add(new_comment)
        db.session.commit()
    comments = Comment.query.filter_by(blog_id=id)
    return render_template('comment.html',comment_form=comment_form,comments=comments)

@main.route('/delete/<int:id>', methods=['GET','POST'])
def delete(id):
    try:
        if current_user.is_authenticated:
            blog = Blog.query.filter_by(id=id).all()
            for blogs in blog:
                db.session.delete(blogs)
                db.session.commit()
            return redirect(url_for('main.detail'))
        return ''
    except Exception as e:
        return(str(e))

@main.route('/delete1/<int:id>', methods=['GET','POST'])
def delete1(id):
    try:
        if current_user.is_authenticated:
            comment_form=CommentForm()
            comment = Comment.query.filter_by(comment_id=id).first()
            for comments in comment:
                db.session.delete(comment)
                db.session.commit()
            return redirect(url_for('main.comment'))
        return ''
    except Exception as e:
        return(str(e))


import cv2

image = cv2.imread("images/shapes_d.png")
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Get the thresholds
thresh = cv2.Canny(gray_image, 200, 255)

# Get the contours
contours, _ = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
print("Contours found", len(contours))

# Get approximate polygons -> in a loop
for (index, contour) in enumerate(contours):
    # The cv2 function used to approximate the number of sides in a contour
    poly_count = cv2.approxPolyDP(contour, .01 * cv2.arcLength(contour, True), True)
    # Compute the centers of the contour
    x, y, h, w = cv2.boundingRect(contour)
    center = cv2.moments(contour)
    cx = int(center['m10'] / center['m00']) - int(w / 4)
    cy = int(center['m01'] / center['m00']) - int(w / 4)
    print("Index {} -> polygon count -> {}", index, len(poly_count))

    # Calculate the dimensions

    cv2.putText(image, "{}".format(index), (cx, cy + 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0))

    if len(poly_count) == 3:
        shape_name = "Triangle"
        cv2.putText(image, shape_name, (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0))
    if len(poly_count) == 4:
        if w / h == 1:
            shape_name = "Square"
            cv2.putText(image, shape_name, (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 1, 0), 1)
        else:
            shape_name = "Rectangle"
            cv2.putText(image, shape_name, (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 100, 0), 1)
    if len(poly_count) > 20:
        shape_name = "Circle"
        cv2.putText(image, shape_name, (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 100, 0), 1)

cv2.imshow("Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()


#!/usr/bin/python

import xml.dom.minidom

cyclists = [("Cyclist Name", 0, 0, "59:59", "0.0")]

filePath = str(input("Enter File Name:\t"))
print(filePath)

DomTree = xml.dom.minidom.parse(filePath)
collection = DomTree.documentElement

eventParticipants = collection.getElementsByTagName("event_participant")

for eventParticipant in eventParticipants:
    participant = eventParticipant.getElementsByTagName("participant")[0]
    print(participant)
    if participant.hasAttribute("name"):
        participantName = participant.getAttribute("name")
    else:
        particpantName = "None"

    if participant.hasAttribute("id"):
        participantID = int(participant.getAttribute("id"))
        print(participantID)
    else:
        participantID = -1

    rank = -1
    duration = "+59:59"
    rankTwo = "99.99"
    results = eventParticipant.getElementsByTagName("result")

    i = 0
    for entry in results:
        #result = entry.getElementsByTagName("result")[0]
        result = entry
        i = i+1
        if result.hasAttribute("result_code"):
            result_code = result.getAttribute("result_code")
            print(result_code)
            if result_code == "rank":
                if result.hasAttribute("value"):
                    rank = int(result.getAttribute("value"))
                    rankTwo = result.getAttribute("value")
            if result_code == "duration":
                if result.hasAttribute("value"):
                    duration = result.getAttribute("value")

    cyclists.append((participantName, participantID, rank, duration, rankTwo))

for cyclist in sorted(cyclists, key=lambda contestents: contestents[2]):
    print(cyclist[0] + "\t\t|" + str(cyclist[1]) + "\t|" + str(cyclist[2]) + "\t|" + cyclist[3])


# coding: utf-8
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
from devtools_testutils import AzureTestCase
from azure.communication.rooms.aio import RoomsClient

class RoomsAsyncTest(AzureTestCase):
    def __init__(self, method_name, **kwargs):
        super(RoomsAsyncTest, self).__init__(method_name, **kwargs)

    def create_client(self, endpoint):
        credential = self.get_credential(RoomsClient, is_async=True)
        return self.create_client_from_credential(
            RoomsClient,
            credential=credential,
            endpoint=endpoint,
        )


#!/usr/bin/python3.6

"""
                --- Web Scrapper ---
This module when executed, scrappes the defined website for jokes and stores them in a list in jokes.py.
When the list becomes empty, i;e all the jokes are posted, this script is automatically executed and stores
the  jokes in the list.
"""

import bs4 as bs
import urllib.request
import re
import config
import url
import time

# Link to be parsed
URL = url.getUrl(0)

# Fake user agaent
user_agent = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36'

# List stores all the parsed text
all_content = []

# Function to extract jokes from the current page
def parsePage():

    request = urllib.request.Request(URL, headers={'User-Agent': user_agent})
    response = urllib.request.urlopen(request)

    # Bs4 Object
    soup = bs.BeautifulSoup(response, 'lxml')
    for div in soup.find_all('div', class_ = 'post-text'):
        all_content.append(str(div.text))

# Find the maximum number of pages in the url
def findMaxPages():
    request = urllib.request.Request(URL, headers={'User-Agent': user_agent})
    response = urllib.request.urlopen(request)

    # Bs4 Object
    soup = bs.BeautifulSoup(response, 'lxml')
    pages = []
    for div in soup.find_all('span', class_ = 'item'):
        pages.append(int(div.text))
    maxPages = pages[-1]
    return maxPages

parsePage()

currentPage = 2
# Use this in case you want to parse the whole site

#maxPages = findMaxPages()
maxPages = 15

resetUrl = URL
URL += "/page"

# Looping each page and parsing content
while currentPage <= maxPages:
    URL += "/"+str(currentPage)
    parsePage()
    URL = URL.split("/")
    del URL[-1]
    URL = "/".join(URL)
    currentPage += 1

#print(all_content)


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

import hashlib
import os
import re
import tempfile
from typing import Dict

import requests

__author__ = "Sascha Greuel"
__copyright__ = "Copyright 2020, Sascha Greuel"
__license__ = "MIT"
__maintainer__ = "Sascha Greuel"
__email__ = "hello@1-2.dev"
__status__ = "Production"

root = os.getcwd() + os.path.sep

def get_versions() -> Dict[str, str]:
    """ Returns a list of version numbers for imagemagick, libaom & libheif """
    api_base = "https://api.github.com/repos"
    file_base = "https://github.com"

    if "GITHUB_TOKEN" in os.environ:
        headers = {"Authorization": "Bearer " + os.environ['GITHUB_TOKEN']}
    else:
        headers = {}

    # Get version information for ImageMagick and write it to file
    data = requests.get(
        api_base + '/ImageMagick/ImageMagick/tags',
        headers=headers
    ).json()
    imagemagick_ver = re.sub(r'[^0-9.\-]', r'', data[1]['name'])
    open(root + 'versions' + os.path.sep + 'imagemagick.version', 'w+').write(imagemagick_ver)

    # Download ImageMagick tarball, calculate it's hash and write it to file
    open(root + 'versions' + os.path.sep + 'imagemagick.hash', 'w+').write(get_hash(
        file_base + '/ImageMagick/ImageMagick/archive/' + imagemagick_ver + '.tar.gz'
    ))

    # Get version information for aom and write it to file
    data = requests.get(
        api_base + '/jbeich/aom/tags',
        headers=headers
    ).json()
    libaom_ver = re.sub(r'[^0-9.]', r'', data[0]['name'])
    open(root + 'versions' + os.path.sep + 'aom.version', 'w+').write(libaom_ver)

    # Download aom tarball, calculate it's hash and write it to file
    open(root + 'versions' + os.path.sep + 'aom.hash', 'w+').write(get_hash(
        file_base + '/jbeich/aom/archive/v' + libaom_ver + '.tar.gz'
    ))

    # Get version information for libheif and write it to file
    data = requests.get(
        api_base + '/strukturag/libheif/tags',
        headers=headers
    ).json()
    libheif_ver = re.sub(r'[^0-9.]', r'', data[0]['name'])
    open(root + 'versions' + os.path.sep + 'libheif.version', 'w+').write(libheif_ver)

    # Download aom tarball, calculate it's hash and write it to file
    open(root + 'versions' + os.path.sep + 'libheif.hash', 'w+').write(get_hash(
        file_base + '/strukturag/libheif/releases/download/v' + libheif_ver + '/libheif-' + libheif_ver + '.tar.gz'
    ))

    # Return version information for README updates
    return {
        'imagemagick': imagemagick_ver,
        'libaom': libaom_ver,
        'libheif': libheif_ver
    }

def get_hash(url):
    """ Returns the SHA1 hash for the given file from URL """
    if "GITHUB_TOKEN" in os.environ:
        headers = {"Authorization": "Bearer " + os.environ['GITHUB_TOKEN']}
    else:
        headers = {}

    sha1 = hashlib.sha1()
    tf = tempfile.NamedTemporaryFile()

    with open(tf.name, "wb") as f:
        response = requests.get(url, headers=headers)
        f.write(response.content)

    with open(tf.name, "rb") as f:
        while True:
            chunk = f.read(sha1.block_size)
            if not chunk:
                break
            sha1.update(chunk)

    return sha1.hexdigest()

if __name__ == '__main__':
    readme_path = root + "README.md"
    readme = open(readme_path, "r").read()
    versions = get_versions()
    replacement = "\n* ImageMagick version: `" + versions['imagemagick'] + "`\n"
    replacement += "* libaom version: `" + versions['libaom'] + "`\n"
    replacement += "* libheif version: `" + versions['libheif'] + "`"

    r = re.compile(
        r'<!-- versions start -->.*<!-- versions end -->'.format(),
        re.DOTALL,
    )

    replacement = '<!-- versions start -->{}<!-- versions end -->'.format(replacement)

    open(readme_path, "w").write(r.sub(replacement, readme))


import pytest
from django.urls import reverse
from rest_framework import status

pytestmark = pytest.mark.django_db

def test_quiz_list(admin_client):
    url = reverse('api-quiz:list_quiz')
    response = admin_client.get(url, content_type="application/json")
    assert response.status_code == status.HTTP_200_OK

def test_quiz_api_detail(admin_client, quiz):
    url = reverse('api-quiz:retrieve_quiz', args=[quiz.id])
    response = admin_client.get(url)
    assert response.status_code == status.HTTP_200_OK
    assert response.json()['id'] == quiz.id

def test_quiz_api_update(admin_client, quiz):
    url = reverse('api-quiz:update_quiz', args=[quiz.id])
    response = admin_client.patch(url, data={'title': 'new_title'})
    assert response.status_code == status.HTTP_200_OK

def test_quiz_api_delete(admin_client, quiz):
    url = reverse('api-quiz:delete_quiz', args=[quiz.id])
    response = admin_client.delete(url)
    assert response.status_code == status.HTTP_204_NO_CONTENT


from core.preprocessor import processor
import dill as dpickle
import numpy as np

class TextToNumber:

    @staticmethod
    def create_number_vector(raw_text_array, append_indicators=True, max_uniqie_words_size=8000, padding_maxlen=70, padding_position='post', output_file='nummerical_text'):
        body_pp = processor(append_indicators=append_indicators, keep_n=max_uniqie_words_size, padding_maxlen=padding_maxlen, padding=padding_position)
        vecs = body_pp.fit_transform(raw_text_array)

        if output_file is not None:
            # Save the preprocessor
            with open(output_file + '_pp.dpkl', 'wb') as f:
                dpickle.dump(body_pp, f)

            # Save the processed data
            np.save(output_file + '_vecs.npy', vecs)

        return vecs

    @staticmethod
    def load_text_processor(fname='title_pp.dpkl'):
        """
        Load preprocessors from disk.
        Parameters
        ----------
        fname: str
            file name of ktext.proccessor object
        Returns
        -------
        num_tokens : int
            size of vocabulary loaded into ktext.processor
        pp : ktext.processor
            the processor you are trying to load
        Typical Usage:
        -------------
        num_decoder_tokens, title_pp = load_text_processor(fname='title_pp.dpkl')
        num_encoder_tokens, body_pp = load_text_processor(fname='body_pp.dpkl')
        """
        # Load files from disk
        with open(fname, 'rb') as f:
            pp = dpickle.load(f)

        num_tokens = max(pp.id2token.keys()) + 1
        # print(f'Size of vocabulary for {fname}: {num_tokens:,}')
        return num_tokens, pp

    @staticmethod
    def load_decoder_inputs(decoder_np_vecs='train_title_vecs.npy'):
        """
        Load decoder inputs.
        Parameters
        ----------
        decoder_np_vecs : str
            filename of serialized numpy.array of decoder input (issue title)
        Returns
        -------
        decoder_input_data : numpy.array
            The data fed to the decoder as input during training for teacher forcing.
            This is the same as `decoder_np_vecs` except the last position.
        decoder_target_data : numpy.array
            The data that the decoder data is trained to generate (issue title).
            Calculated by sliding `decoder_np_vecs` one position forward.
        """
        vectorized_text = np.load(decoder_np_vecs)
        # For Decoder Input, you don't need the last word as that is only for prediction
        # when we are training using Teacher Forcing.
        decoder_input_data = vectorized_text[:, :-1]

        # Decoder Target Data Is Ahead By 1 Time Step From Decoder Input Data (Teacher Forcing)
        decoder_target_data = vectorized_text[:, 1:]

        # print(f'Shape of decoder input: {decoder_input_data.shape}')
        # print(f'Shape of decoder target: {decoder_target_data.shape}')
        return decoder_input_data, decoder_target_data

    @staticmethod
    def load_encoder_inputs(encoder_np_vecs='train_body_vecs.npy'):
        """
        Load variables & data that are inputs to encoder.
        Parameters
        ----------
        encoder_np_vecs : str
            filename of serialized numpy.array of encoder input (issue title)
        Returns
        -------
        encoder_input_data : numpy.array
            The issue body
        doc_length : int
            The standard document length of the input for the encoder after padding
            the shape of this array will be (num_examples, doc_length)
        """
        vectorized_body = np.load(encoder_np_vecs)
        # Encoder input is simply the body of the issue text
        encoder_input_data = vectorized_body
        doc_length = encoder_input_data.shape[1]
        # print(f'Shape of encoder input: {encoder_input_data.shape}')
        return encoder_input_data, doc_length


"""resolute URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('power/', views.power, name='power'),
    path('last_read/', views.last_read, name='last_read'),
    path('get_last_read/', views.get_last_read, name='get_last_read'),
    path('score_card/', views.score_card, name='score_card'),
    path('voltage/', views.voltage, name='voltage'),
    path('current/', views.current, name='current'),
    path('readings/', views.readings, name='readings'),
    path('get_line_readings/', views.get_line_readings, name='get_line_readings'),
    path('max_demand/', views.max_demand, name='max_demand'),
    path('fetch_vals_period/', views.fetch_vals_period, name='fetch_vals_period'),
    path('fetch_device_vals/', views.fetch_vals_period_per_device, name='fetch_vals_period_per_device'),
    path('load_datalogs/', views.load_datalogs, name='load_datalogs'),
    path('consumption/', views.consumption, name='consumption'),
    path('power_quality/', views.power_quality, name='power_quality'),
    path('load_readings/', views.load_readings, name='load_readings'),
    path('get_yesterday_today_usage/', views.get_yesterday_today_usage, name='get_yesterday_today_usage'),
    path('get_line_readings_log/', views.get_line_readings_log, name='get_line_readings_log'),
    path('get_energy_consumption_readings/', views.get_energy_consumption_readings, name='get_energy_consumption_readings'),
    path('get_capacity_factors/', views.get_capacity_factors, name='get_capacity_factors'),
    path('messaging/', views.messaging, name='messaging'),
    path('fetch_messages/', views.fetch_messages, name='fetch_messages'),
    path('check_new_message/', views.check_new_message, name='check_new_message'),
    path('send_message/', views.send_message, name='send_message'),
    path('simple_upload/', views.simple_upload, name='simple_upload'),
    path('upload_cdd/', views.upload_cdd, name='upload_cdd'),
    path('all_customers/', views.all_customers, name='all_customers'),
    path('view_customer/<int:id>', views.view_customer, name='view_customer'),
    path('view_profile/', views.view_profile, name='view_profile'),
    path('upload_image/', views.upload_image, name='upload_image'),
    path('update_details/', views.update_details, name='update_details'),
    path('add_user/', views.add_user, name='add_user'),
    path('edit_user/', views.edit_user, name='edit_user'),
    path('update_branch/', views.update_branch, name='update_branch'),
    path('update_device/', views.update_device, name='update_device'),
    path('create_branch/', views.create_branch, name='create_branch'),
    path('create_device/', views.create_device, name='create_device'),
    path('update_historic_scores/', views.update_historic_scores, name='update_historic_scores'),
    path('get_total_energy/', views.get_total_energy, name='get_total_energy'),
    path('get_stats/', views.get_stats, name='get_stats'),
    # path('detail_view', views.detail_view, name='detail_view'),
    # path('locationpost', views.locationpost, name='locationpost'),
    # path('incidents', views.incidents, name='incidents'),
    # path('table', views.table, name='table'),
    # path('logs', views.logs, name='logs'),
    # # path('track', views.track, name='track')
    # path('check/<slug:slug>/', views.check, name='check'),
    # path('collection_check/<int:id>/', views.collection_check, name='collection_check'),
    # path('track/<slug:slug>/', views.track, name='track'),
    # path('trail/<slug:slug>/', views.trail, name='trail'),
    # path('mapping/<slug:slug>/', views.mapping, name='mapping'),
    # path('get_lat_lng/<slug:id>', views.get_lat_lng, name='get_lat_lng'),# FOR PROFILE REALTIME MAP
    # path('get_latlng/<slug:username>', views.get_latlng, name='get_latlng'),
    # path('get_latlng_incident/<slug:username>/<slug:incident>/', views.get_latlng_incident, name='get_latlng_incident'),
    # path('post_latlng', views.post_latlng, name='post_latlng'),
    # path('check_panic', views.check_panic, name='check_panic'),
    # path('create_panic', views.create_panic, name='create_panic'),
    # path('resolve_panic_mobile', views.resolve_panic_mobile, name='resolve_panic_mobile'),
    # path('resolve_panic', views.resolve_panic, name='resolve_panic'),
    # path('recurring_gps_post', views.recurring_gps_post, name='recurring_gps_post'),
    # path('farmers', views.farmers, name='farmers'),
    # path('herdsmen', views.herdsmen, name='herdsmen'),
    # path('get_client_data', views.get_client_data, name='get_client_data'),
    # path('profile_page/<int:target_id>/<slug:is_farmer>', views.profile_page, name='profile_page')

    # path('test', views.test, name='test'),
]


import datetime
import math

def countdown(due_date='2000/01/01', days_only=False):
    """
    :param due_date: year/month/day/hour   hour is optional
    :return: string denoting time left
    """
    # create countdown timer
    future = [int(s) for s in due_date.split('/')]
    f = future
    future = datetime.datetime(year=f[0], month=f[1], day=f[2])
    current = datetime.datetime.now()

    time_left = future - current
    time_left = time_left.days

    if days_only:
        print('time left:', time_left, 'days')
        return time_left

    def year(days):
        if days % 365 != days:
            return int(days / 365)
        else: return 0

    def month(days):
        years = year(days)
        if years >= 1:
            days = days - (years * 365)
        if days % 30 != days:
            return int(days / 30)
        else: return 0

    def day(days):
        months = month(days)
        years = year(days)
        if months >= 1:
            days = days - (years * 365) - (months * 30)
        return days

    t = time_left
    return '{0}yr {1}mth {2}dy left.'.format(year(t), month(t), day(t))

print(countdown('2019/05/22'))


from django.shortcuts import render
from django.contrib.auth.decorators import login_required

from .utils import get_metrics_alerts

# Application Views

# Home

@login_required
def home_page(request):
	context = {
		'page_title': "Homepage"
	}
	return render(request, 'website/home_page.html', context)

@login_required
def rms_homepage(request):
	context = {
		'page_title': "RMS Homepage"
	}
	return render(request, 'website/rms_employee_homepage.html', context)

@login_required
def item_lookup_homepage(request):
	context = {
		'page_title': "Item Lookup Homepage"
	}
	return render(request, 'website/item_lookup_homepage.html', context)

@login_required
def metrics_homepage(request):
	context = {
		'page_title': "Metrics Homepage"
	}
	return render(request, 'website/metrics_homepage.html', context)

@login_required
def notifications_page(request):
	context = {
		'page_title': "Notifications Page",
		'metrics_alerts': get_metrics_alerts()
	}
	return render(request, 'website/notifications_page.html', context)

@login_required
def item_management_homepage(request):
	context = {
		'page_title': "Items Management Homepage",
	}
	return render(request, 'website/item_management_homepage.html', context)


#!/usr/bin/python

# This script gets interface info such as bytes, packets and drops
# The use case this was developed for was gigamon testing with security onion but it could be used in a variety of ways
# Run example:
# ./check_int.py eno6 eno7
# List interfaces after filename with spaces
# it then writes out the result to a file initial.txt with bytes first then packets then drops.
# this will be analyzed in the check_int_dif script

import sys
import subprocess
import time
import calendar
import datetime

interfaces = sys.argv[1:]
prev_info = []
new_info = []
diff_info = []

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

def interface_diff(count):
        global interfaces
        global prev_info
        global new_info
        global diff_info

        headers = ["Interface", "Bytes", "Packets", "Drops"]
        new_info = []
        diff_info = [headers]
        line = []
        numInt=1
        # Run command and get interface information
        for interface in interfaces:
            # Testing with file
            #command = "cat test_check_rx.txt | grep -A 3 " + interface + " | tail -n 1"
            command = "ip -s link | grep -A 3 " + interface + " | tail -n 1"
            process = subprocess.Popen(command, shell = True, stdout = subprocess.PIPE)
            output, error = process.communicate()

            formatted = []

            # Remove empty space junk to standardize data locations
            for item in output.split(" "):
                if is_number(item):
                    formatted.append(item)

            line = [interface, formatted[0], formatted[1], formatted[3]]
            new_line = [formatted[0], formatted[1], formatted[3]]
            new_info.append(line)
            # write files to use for analysis
            if numInt==1:
                operation="w"
            else:
                operation="a"
            with open("initial.txt", operation) as initialOutput:
                initialOutput.write("%s %s %s\n" % (formatted[0], formatted[1], formatted[3]))
            numInt+=1

        # write out info to stdout
        print("")
        print("Run: " + str(count))
        print(datetime.datetime.fromtimestamp(calendar.timegm(time.gmtime())).isoformat())

        # Print interface information in data table
        if count == 1:
            initial = new_info[:]
            initial.insert(0, headers)
        print("Initial run:")
        print("-------------------------------------------------------------------")
        for i, d in enumerate(initial):
            line = '|'.join(str(x).ljust(16) for x in d)
            print(line)
            if i == 0:
                print('-' * len(line))
        print("-------------------------------------------------------------------")
       # ignore this
       # with open("initial.txt", "w") as initialOutput:
            #initialOutput.write("%s %s %s\n" % (formatted[0], formatted[1], formatted[3]))

interface_diff(1)


# -*- coding: utf-8 -*-
"""
Created on Tue Oct 22 14:44:21 2019

@author: IST_1
"""

import pandas as pd
import op_models
from matplotlib import pyplot as plt

intrepid_data = pd.read_excel('ISASM CustCare 2019 r2.xlsx')

intrepid_data['dayofyear'] = intrepid_data.Timestamp.dt.dayofyear

dayahead_2018_lbmp = pd.read_csv('OASIS_Day-Ahead_Market_Zonal_LBMP_NYC_2018.csv')
dayahead_2018_lbmp['total'] = (dayahead_2018_lbmp['DAM Zonal LBMP']+dayahead_2018_lbmp['DAM Zonal Losses']-dayahead_2018_lbmp['DAM Zonal Congestion'])
dayahead_2017_lbmp = pd.read_csv('OASIS_Day-Ahead_Market_Zonal_LBMP_NYC_2017.csv')
dayahead_2017_lbmp['total'] = (dayahead_2017_lbmp['DAM Zonal LBMP']+dayahead_2017_lbmp['DAM Zonal Losses']-dayahead_2017_lbmp['DAM Zonal Congestion'])
dayahead_2016_lbmp = pd.read_csv('OASIS_Day-Ahead_Market_Zonal_LBMP_NYC_2016.csv')
dayahead_2016_lbmp['total'] = (dayahead_2016_lbmp['DAM Zonal LBMP']+dayahead_2016_lbmp['DAM Zonal Losses']-dayahead_2016_lbmp['DAM Zonal Congestion'])
dayahead_2016_lbmp = dayahead_2016_lbmp.drop(dayahead_2016_lbmp.index[1416:1440])
dayahead_2015_lbmp = pd.read_csv('OASIS_Day-Ahead_Market_Zonal_LBMP_NYC_2015.csv')
dayahead_2015_lbmp['total'] = (dayahead_2015_lbmp['DAM Zonal LBMP']+dayahead_2015_lbmp['DAM Zonal Losses']-dayahead_2015_lbmp['DAM Zonal Congestion'])

total_dayahead_lbmp = pd.DataFrame(columns=['date','2015','2016','2017','2018','average'])
total_dayahead_lbmp = pd.DataFrame(pd.date_range(start='1/1/2018', end='1/1/2019',freq='H'))
total_dayahead_lbmp = total_dayahead_lbmp.drop(total_dayahead_lbmp.index[-1],axis=0)
total_dayahead_lbmp = total_dayahead_lbmp.rename(columns={0:'date'})
total_dayahead_lbmp['2015'] = dayahead_2015_lbmp.total
total_dayahead_lbmp['2016'] = dayahead_2016_lbmp.total
total_dayahead_lbmp['2017']= dayahead_2017_lbmp.total
total_dayahead_lbmp['2018'] = dayahead_2018_lbmp.total

total_dayahead_lbmp['average'] = total_dayahead_lbmp[['2015','2016','2017','2018']].sum(axis=1)/4
lbmp = total_dayahead_lbmp['average'].repeat(4).shift(-1)[0:24817].reset_index(drop=True)

intrepid_data['lbmp'] = lbmp/4/1000

intrepid_data = intrepid_data.drop(columns={'Period','Datehour'})
intrepid_data = intrepid_data.rename(columns={'Timestamp':'date','Con Ed kW':'original_building_power_kw'})
intrepid_data['energy_rate'] = 0.0079
#intrepid_data['energy_rate'] = intrepid_data.lbmp

intrepid_data["demand_rate1"] = [0] * len(intrepid_data.index)
intrepid_data["demand_rate_category1"] = [0] * len(intrepid_data.index)
intrepid_data["demand_rate2"] = [0] * len(intrepid_data.index)
intrepid_data["demand_rate_category2"] = [0] * len(intrepid_data.index)

demand_tariff_type = "SC9 Rate 2"
# conditions
intermediate_peak = ((intrepid_data['date'].dt.month <= 5) | (intrepid_data['date'].dt.month >= 10)) & (
        (intrepid_data['date'].dt.weekday >= 0) &
        (intrepid_data['date'].dt.weekday <= 5)) & \
          ((intrepid_data['date'].dt.hour >= 8) & (intrepid_data['date'].dt.hour < 22))

on_peak1 = ((intrepid_data['date'].dt.month >= 6) & (intrepid_data['date'].dt.month <= 9)) & (
        (intrepid_data['date'].dt.weekday >= 0) &
        (intrepid_data['date'].dt.weekday <= 5)) & \
          ((intrepid_data['date'].dt.hour >= 8) & (intrepid_data['date'].dt.hour < 18))

on_peak2 = ((intrepid_data['date'].dt.month >= 6) & (intrepid_data['date'].dt.month <= 9)) & (
        (intrepid_data['date'].dt.weekday >= 0) &
        (intrepid_data['date'].dt.weekday <= 5)) & \
          ((intrepid_data['date'].dt.hour >= 8) & (intrepid_data['date'].dt.hour < 22))

# intermediate Demand_Rate is set for the entire column,
# and other Demand_Rates overwrite it when the conditions are met
intrepid_data.loc[intermediate_peak,"demand_rate1"] = 11.48
intrepid_data.loc[intermediate_peak,"demand_rate2"] = 11.48
intrepid_data.loc[on_peak1, "demand_rate1"] = 8.33
intrepid_data.loc[on_peak2, "demand_rate2"] = 15.56
# finding cost for all data points, then assigning categories

intrepid_data.loc[intrepid_data["demand_rate1"] == 8.33, "demand_rate_category1"] = "on_peak1"
intrepid_data.loc[intrepid_data["demand_rate2"] == 15.56, "demand_rate_category2"] = "on_peak2"
intrepid_data.loc[intrepid_data["demand_rate1"] == 11.48, "demand_rate_category1"] = "intermediate"
intrepid_data.loc[intrepid_data["demand_rate2"] == 11.48, "demand_rate_category2"] = "intermediate"
intrepid_data.loc[intrepid_data["demand_rate1"] == 0, "demand_rate_category1"] = "off_peak"
intrepid_data.loc[intrepid_data["demand_rate2"] == 0, "demand_rate_category2"] = "off_peak"

#suggest 250kW/500kWh battery here
power = 250

df2 = pd.DataFrame(columns=['intervals','solar','Ein','Eout','charge_state','system_out'])
test_dates_df = pd.DataFrame(columns=['date','dayofyear','lbmp','demand_rate1','demand_rate_category1','demand_rate2','demand_rate_category2',
                                          'original_building_power_kw','output','energy_rate'])
demand_expenses = list()
energy_expenses = list()

for i in set(intrepid_data.date.dt.month):
    test_dates = intrepid_data.loc[(intrepid_data.date.dt.month == i)]#&(data.date.dt.dayofyear <= (i+1))]
    test_dates = test_dates.reset_index(drop=True)
    df,model = op_models.peak_shave(test_dates, power=power, capacity=power*2, eff=.8, itc=False, project_type='storage only', export=False)
    df2 = pd.concat([df2,df])
    test_dates_df = pd.concat([test_dates_df,test_dates])
    demand_expenses.append((model.demand_expenses()))
    energy_expenses.append((model.energy_expenses()))

df2 = df2.reset_index(drop=True)

intrepid_data['Ein'] = df2.Ein
intrepid_data['Eout'] = df2.Eout
intrepid_data['charge_state'] = df2.charge_state
intrepid_data['system_out'] = df2.system_out

demand_expenses_total = sum(demand_expenses)
energy_expenses_total = sum(energy_expenses)
expenses = demand_expenses_total + energy_expenses_total
battery_cost = power*2*340*0.7*0.8

print('Yearly Expenses with no energy storage system: $152095.67')
print('Yearly savings with storage system of size',power,': $',152095.67-expenses)
print('Years to payback: ', battery_cost/(152095.67-expenses))

graph_beginning = 19199
graph_end = 19294
plt.figure(figsize=(15,5))
plt.plot(intrepid_data.index,intrepid_data.original_building_power_kw,intrepid_data.system_out)
plt.figure(figsize=(15,5))
plt.plot(intrepid_data.index[graph_beginning:graph_end],intrepid_data.original_building_power_kw[graph_beginning:graph_end],intrepid_data.system_out[graph_beginning:graph_end])
plt.figure(figsize=(15,5))
plt.plot(intrepid_data.index[graph_beginning:graph_end],intrepid_data.system_out[graph_beginning:graph_end])

#print(intrepid_data.loc[intrepid_data.demand_rate_category1=='off_peak'].system_out.max())
#print(intrepid_data.loc[intrepid_data.demand_rate_category1=='on_peak1'].system_out.max())
#print(intrepid_data.loc[intrepid_data.demand_rate_category2=='on_peak2'].system_out.max())
#print(intrepid_data.loc[intrepid_data.demand_rate_category1=='intermediate'].system_out.max())

#intrepid_data['lbmp'] = total_dayahead_lbmp.loc[(intrepid_data.Timestamp.dt.hour == total_dayahead_lbmp.date.dt.hour)&
#        (intrepid_data.Timestamp.dt.day == total_dayahead_lbmp.date.dt.day)&(intrepid_data.Timestamp.dt.month == total_dayahead_lbmp.date.dt.month)]


from django.shortcuts import render_to_response, redirect
from django.urls import reverse
import os
import urllib.request
import urllib.parse
from urllib.parse import urlencode
from app.settings import BUS_STATION_CSV
import csv
from django.core.paginator import Paginator

def index(request):
    return redirect(reverse(bus_stations))

def bus_stations(request):
    page = request.GET.get('page')
    bus_station = []
    x = 0
    y = 0
    if page==None:
        page = 1
    with open(BUS_STATION_CSV, newline='') as csvfile:
        reader = csv.DictReader(csvfile)
        for line in reader:
            bus_station.append({'Name' : line['Name'], 'Street' : line['Street'], 'District' : line['District']})
    p = Paginator(bus_station, 10)
    object = p.get_page(page)
    if object.has_next():
        query_arg_next = {'page': object.next_page_number()}
        query_arg_next = f'bus_stations?{urllib.parse.urlencode(query_arg_next)}'
    else:
        query_arg_next = None
    if object.has_previous():
        query_arg_prev = {'page': object.previous_page_number()}
        query_arg_prev = f'bus_stations?{urllib.parse.urlencode(query_arg_prev)}'
    else:
        query_arg_prev = None

    return render_to_response('index.html', context={
        'bus_stations': object,
        'current_page': page,
        'prev_page_url': query_arg_prev,
        'next_page_url': query_arg_next,
    })


#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Copyright © 2012 Johannes S. Mueller-Roemer. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

import re
import datetime
import os
import urllib.request as urllib
import codecs
import subprocess

if not os.path.exists('gl3.h'):
    print('Downloading gl3.h...')
    web = urllib.urlopen('http://www.opengl.org/registry/api/gl3.h')
    with open('gl3.h', 'wb') as f:
        f.writelines(web.readlines())
else:
    print('Using existing gl3.h...')

gl3hf = open('gl3.h', 'r')
gl3h = gl3hf.read()
gl3hf.close()

print('Parsing gl3.h...')
defReg = re.compile(r'#define\s+GL_([A-Z0-9_]+)\s+([0-9a-fA-Fx]+)')
verReg = re.compile(r'VERSION_(\d)_(\d)')
procReg = re.compile(r'GLAPI\s+(\w+)\s+APIENTRY\s+gl(\w+)\s*\((.*)\)')

vers = []
defs = []

for defn in defReg.finditer(gl3h):
    ver = verReg.match(defn.group(1))
    if ver:
        vers.append([int(defn.start()), int(ver.group(1)), int(ver.group(2))])
    else:
        defs.append([defn.group(1), defn.group(2)])

for i in range(len(vers)-1):
    vers[i][0] = vers[i+1][0]
vers[-1][0] = len(gl3h)

procs = []

for proc in procReg.finditer(gl3h):
    procs.append([proc.start(), proc.group(1), proc.group(2), proc.group(3)])

print('Writing gl3.go...')
gl3go = codecs.open('gl3.go', 'w', 'utf-8')

gl3go.write(r'''/******************************************************************************
 * Copyright © %s Johannes S. Mueller-Roemer. All rights reserved.          *
 *                                                                            *
 * Redistribution and use in source and binary forms, with or without         *
 * modification, are permitted provided that the following conditions         *
 * are met:                                                                   *
 * 1. Redistributions of source code must retain the above copyright          *
 *    notice, this list of conditions and the following disclaimer.           *
 * 2. Redistributions in binary form must reproduce the above copyright       *
 *    notice, this list of conditions and the following disclaimer in the     *
 *    documentation and/or other materials provided with the distribution.    *
 * 3. The names of the authors may not be used to endorse or promote products *
 *    derived from this software without specific prior written permission.   *
 *                                                                            *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR      *
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  *
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.    *
 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,          *
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT   *
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  *
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY      *
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT        *
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF   *
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.          *
 ******************************************************************************/

package gl

import (
    "github.com/lxn/go-winapi"
    "syscall"
    "unsafe"
)

const (
''' % (datetime.date.today().year))

for defn in defs:
    gl3go.write('%s = %s\n' % tuple(defn))

gl3go.write(r''')

var (
''')

for proc in procs:
    gl3go.write('gl%s uintptr\n' % (proc[2]))

gl3go.write(r''')

func Init() {
    lib := syscall.Handle(winapi.MustLoadLibrary("opengl32.dll"))

    var err error
    supported := true
    var _ = supported
''')

ver = 0
gl3go.write('// GL %d.%d\n' % tuple(vers[ver][1::]))
for proc in procs:
    if proc[0] >= vers[ver][0]:
        ver += 1
        gl3go.write('// GL %d.%d\n' % tuple(vers[ver][1::]))
    gl3go.write('''gl%(1)s = winapi.WglGetProcAddress(syscall.StringToUTF16Ptr("gl%(1)s"))
if gl%(1)s == 0 {
    gl%(1)s, err = syscall.GetProcAddress(lib, "gl%(1)s")
    if err != nil {
        supported = false
    }
}

''' % { '1' : proc[2] })

gl3go.write(r'''}
''')

typemap = {
    'GLenum' : 'uint32',
    'GLboolean' : 'uint8',
    'GLbitfield' : 'uint32',
    'GLbyte' : 'int8',
    'GLshort' : 'int16',
    'GLint' : 'int32',
    'GLsizei' : 'int32',
    'GLubyte' : 'uint8',
    'GLushort' : 'uint16',
    'GLuint' : 'uint32',
    'GLuint64' : 'uint64',
    'GLhalf' : 'uint16',
    'GLfloat' : 'float32',
    'GLclampf' : 'float32',
    'GLdouble' : 'float64',
    'GLclampd' : 'float64',
    'GLintptr' : 'uintptr',
    'GLsizeiptr' : 'uintptr',

    'GLenum *' : '[]uint32',
    'const GLenum *' : '[]uint32',
    'GLboolean *' : '[]uint8',
    'const GLboolean *' : '[]uint8',
    'GLbyte *' : '[]int8',
    'const GLbyte *' : '[]int8',
    'GLshort *' : '[]int16',
    'const GLshort *' : '[]int16',
    'GLint *' : '[]int32',
    'const GLint *' : '[]int32',
    'GLint64 *' : '[]int64',
    'const GLint64 *' : '[]int64',
    'GLuint64 *' : '[]uint64',
    'GLsizei *' : '[]int32',
    'const GLsizei *' : '[]int32',
    'GLubyte *' : '[]uint8',
    'const GLubyte *' : '[]uint8',
    'GLushort *' : '[]uint16',
    'const GLushort *' : '[]uint16',
    'GLuint *' : '[]uint32',
    'const GLuint *' : '[]uint32',
    'GLfloat *' : '[]float32',
    'const GLfloat *' : '[]float32',
    'GLdouble *' : '[]float64',
    'const GLdouble *' : '[]float64',
    'GLchar *' : '[]uint8',
    'const GLchar *' : '[]uint8',
    'const GLchar* *' : '[][]uint8',
    'const GLchar* const *' : '[][]uint8',

    'GLDEBUGPROCARB' : 'uintptr',
    'GLsync' : 'uintptr',
    'struct _cl_context *' : 'uintptr',
    'struct _cl_event *' : 'uintptr',
    'GLvoid *' : 'uintptr',
    'const void *' : 'uintptr',
    'const GLvoid *' : 'uintptr',

    'const GLvoid* const *' : '[]uintptr',
    'GLvoid* *' : '*uintptr'
}

keywords = {
    'type' : 'type_',
    'func' : 'func_',
    'range' : 'range_',
    'map' : 'map_'
}

for proc in procs:
    ret = proc[1]
    params = []
    if proc[3] != 'void':
        for param in proc[3].split(','):
            p = re.match('(.*?)(\w+)$', param.strip())
            params.append([typemap.get(p.group(1).strip(), None), keywords.get(p.group(2).strip(), p.group(2).strip())])
            if not params[-1][0]:
                print("Unknown type: '%s' (gl%s)" % (p.group(1).strip(), proc[2]))
    gl3go.write('\nfunc %s(\n' % proc[2])
    for param in params:
        gl3go.write('%s %s,\n' % (param[1], param[0]))
    if ret != 'void':
        ret_ = ret
        ret = typemap.get(ret_, None)
        if not ret:
            print("Unknown type: '%s' (gl%s)" % (ret_, proc[2]))
            ret = 'void'
        gl3go.write(') %s {\nret, _, _ := ' % (ret))
    else:
        gl3go.write(') {\n')
    nRound = ((len(params)+2)//3)*3
    nRound = 3 if nRound < 3 else nRound
    gl3go.write('syscall.Syscall%s(\ngl%s,\n%d,\n' % ('' if nRound == 3 else nRound, proc[2], len(params)))
    for p in params:
        if re.match('\[\]', p[0]):
            gl3go.write('uintptr(unsafe.Pointer(&%s[0])),\n' % (p[1]))
        elif re.match('\*', p[0]):
            gl3go.write('uintptr(unsafe.Pointer(%s)),\n' % (p[1]))
        else:
            gl3go.write('uintptr(%s),\n' % (p[1]))
    for i in range(nRound-len(params)):
        gl3go.write('0,\n')
    if ret != 'void':
        gl3go.write(')\nreturn %s(ret)\n}\n\n' % (ret))
    else:
        gl3go.write(')\n}\n\n')

#for proc in procs:
#    """
#    match = re.match(r'(.*?)u?[bsifd]v?(?:ARB)?$', proc[1])
#    if match:
#        print(match.group(1))
#    """
#    print("%s gl%s(%s)" % proc)

gl3go.close()

print('Formatting gl3.go...')
subprocess.call(['gofmt', '-w=true', 'gl3.go'])


# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

"""
Commands for storage file share operations
"""

#pylint: disable=too-many-arguments

import os.path
from azure.cli.core._logging import get_az_logger

def storage_file_upload_batch(client, destination, source, pattern=None, dryrun=False,
                              validate_content=False, content_settings=None, max_connections=1,
                              metadata=None):
    """
    Upload local files to Azure Storage File Share in batch
    """

    from .files_helpers import glob_files_locally
    source_files = [c for c in glob_files_locally(source, pattern)]

    if dryrun:
        logger = get_az_logger(__name__)
        logger.warning('upload files to file share')
        logger.warning('    account %s', client.account_name)
        logger.warning('      share %s', destination)
        logger.warning('      total %d', len(source_files or []))
        logger.warning(' operations')
        for f in source_files or []:
            logger.warning('  - %s => %s', *f)

        return []

    # TODO: Performance improvement
    # 1. Avoid create directory repeatedly
    # 2. Upload files in parallel
    def _upload_action(source_pair):
        dir_name = os.path.dirname(source_pair[1])
        file_name = os.path.basename(source_pair[1])
        if dir_name and len(dir_name) > 0:
            client.create_directory(share_name=destination,
                                    directory_name=dir_name,
                                    fail_on_exist=False)

        client.create_file_from_path(share_name=destination,
                                     directory_name=dir_name,
                                     file_name=file_name,
                                     local_file_path=source_pair[0],
                                     content_settings=content_settings,
                                     metadata=metadata,
                                     max_connections=max_connections,
                                     validate_content=validate_content)

        return client.make_file_url(destination, dir_name, file_name)

    return list(_upload_action(f) for f in source_files)

def storage_file_download_batch(client, source, destination, pattern=None, dryrun=False,
                                validate_content=False, max_connections=1):
    """
    Download files from file share to local directory in batch
    """

    from .files_helpers import glob_files_remotely, mkdir_p

    source_files = glob_files_remotely(client, source, pattern)

    if dryrun:
        source_files_list = list(source_files)

        logger = get_az_logger(__name__)
        logger.warning('upload files to file share')
        logger.warning('    account %s', client.account_name)
        logger.warning('      share %s', source)
        logger.warning('destination %s', destination)
        logger.warning('    pattern %s', pattern)
        logger.warning('      total %d', len(source_files_list))
        logger.warning(' operations')
        for f in source_files_list:
            logger.warning('  - %s/%s => %s', f[0], f[1], os.path.join(destination, *f))

        return []

    def _download_action(pair):
        destination_dir = os.path.join(destination, pair[0])
        mkdir_p(destination_dir)
        client.get_file_to_path(source,
                                directory_name=pair[0],
                                file_name=pair[1],
                                file_path=os.path.join(destination, *pair),
                                validate_content=validate_content,
                                max_connections=max_connections)
        return client.make_file_url(source, *pair)

    return list(_download_action(f) for f in source_files)


from src.data.meta import Meta
from src.filtering.scene import SceneHeuristic

import collections
import bisect
import json
import ast

class Content(Meta):
  def __init__(self, id, connector):
    super().__init__(id, connector)
    raw = self.run(f"""SELECT media_id, title, date_added , release_date
                    FROM media
                    WHERE media_id = {self.id};
                    """)[0]

    self.title = raw[1]
    self.date_added = raw[2]
    self.release_date = raw[3]

  def getResults(self, resultType = 'EMOJI', topScenes=False):
    res = self.run(f"""SELECT user_id, media_time_secs, challenge_key
                    FROM results
                    WHERE code='{resultType}' AND media_item_id = {self.id};""")

    data = []
    for i in res:
        data.append([i[0], self.getSceneIdx(i[1]), i[2]])

    if topScenes:
      new = []
      top = SceneHeuristic(data).getTopScenes(topScenes)
      for i in data:
        if i[1] in top:
          new.append(i)
      data = new

    self.results = data
    return self.results

  def getScenes(self):
    scenes = ast.literal_eval(self.run(f"""SELECT scenes FROM media_items_meta WHERE media_id = {self.id} ;""")[0][0])
    temp = collections.OrderedDict()
    for idx, i in enumerate(scenes):
      temp[i['end']] = idx
    self.scenes = temp
    return temp

  def getSceneIdx(self, timestamp):
    return bisect.bisect_left(list(self.scenes.keys()), timestamp)


import gdal
import csv
from osgeo import ogr, osr
import numpy as np

def reproject(x, y):
    source = osr.SpatialReference()
    source.ImportFromEPSG(28992)
    target = osr.SpatialReference()
    target.ImportFromEPSG(4326)
    text = "POINT({0} {1})".format(x, y)
    point = ogr.CreateGeometryFromWkt(text)
    transform = osr.CoordinateTransformation(source, target)
    point.Transform(transform)
    return [point.GetX(), point.GetY()]

def extractSingleData(tif, x, y, numband):
    geotransform = tif.GetGeoTransform()
    originX = geotransform[0]
    originY = geotransform[3]
    pixel_width = geotransform[1]
    pixel_height = geotransform[5]

    xoffset = int(np.divide(x - originX, pixel_width))
    yoffset = int(np.divide(y - originY, pixel_height))

    band = tif.GetRasterBand(numband)
    data = band.ReadAsArray(xoffset, yoffset, 1, 1)

    if data == None:
        return -99
    else:
        return data[0][0]

################
# Main program #
################

path_raster = r"D:/UTwente/IGM_PhD_Materials/data/geo/raster/Beleving_Reclass_RD_New.tif"
path_points = r"D:/UTwente/IGM_PhD_Materials/data/geo/vector/1km_clipped/1km_clipped_centroids_text.csv"
path_out = r"D:/PycharmProjects/IGM_PhD_Materials/data/P04/out/features/country_features/Centroids_NR_BL.csv"

tif = gdal.Open(path_raster)

with open(path_points, "r", newline="") as r:
    with open(path_out, "w", newline="") as w:
        reader = csv.reader(r, delimiter=";")
        writer = csv.writer(w, delimiter=";")
        next(reader)
        i = 0
        for row in reader:
            rowid = int(row[2])
            latitude = float(row[1])
            longitude = float(row[0])
            value = extractSingleData(tif, longitude, latitude, 1)
            writer.writerow([i, value])
            i += 1


import csv
import hashlib
import logging
import shutil
from datetime import datetime, timedelta
from ntpath import basename
from typing import Dict

from colorama import Fore
from dateutil import parser

from sauronx import append_log_to_submission_log, stamp

from .alive import SauronxAlive, StatusValue
from .configuration import config
from .submission import CompletedRunInfo

def make_dirs_perm(pathname):
    make_dirs(pathname)
    os.chmod(pathname, 0o777)

class Results:
    """
    Keeps track of frames and metadata in a SauronX submission.
    Also uploads the data and notifies if requested.
    The recommended usage is:
            with Results() as results:
                    # let the camera write
                    results.upload()
    """

    def __init__(
        self, sx_alive: SauronxAlive, keep_raw_frames: bool = False, assume_clean: bool = False
    ) -> None:
        self.coll = config.get_coll(sx_alive.submission_hash)
        self.sx_alive = sx_alive
        self.submission_hash = self.sx_alive.submission_hash
        self.upload_params = config["connection.upload"]
        self.notify_params = config["connection.notification"]
        self.output_dir = self.coll.output_dir()
        self.raw_frames_output_dir = self.coll.outer_frames_dir()
        self.fps = config["sauron.hardware.camera.frames_per_second"]
        plate_type_id = sx_alive.submission_obj.experiment.template_plate.plate_type.id
        roi = config.camera_roi(plate_type_id)
        self.frame_width = roi.x1 - roi.x0
        self.frame_height = roi.y1 - roi.y0
        # this gets uploaded to a 'pending' dir on valinor for notification
        self.video_file = self.coll.avi_file()
        self.qp = config["sauron.data.video.qp"]
        self.x265_params = None
        self.keyframe_interval = config["sauron.data.video.keyframe_interval"]
        self.extra_x265_options = config["sauron.data.video.extra_x265_params"]
        self.submission_log_file = append_log_to_submission_log(self.submission_hash)
        self.file_hasher = FileHasher(algorithm=hashlib.sha256, extension=".sha256")
        self.keep_raw_frames = keep_raw_frames
        self.assume_clean = assume_clean

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb) -> None:
        pass

    def initialize_dir(self) -> None:
        def change_perm(action, name, exc):
            os.chmod(name, 0o777)

        tmp_webcam_snap = ".{}.snap.tmp.jpg".format(self.submission_hash)
        if os.path.exists(self.output_dir):
            warn_user(
                "Refusing to initialize output directory:",
                self.output_dir,
                "The path already exists.",
            )
            print(Fore.RED + "Overwrite? [yes/no]", end="")
            if prompt_yes_no(""):
                # a little weird, but copy webcam file first
                # this is useful if --dark and --override are both set
                if pexists(self.coll.webcam_snapshot()):
                    shutil.copy(self.coll.webcam_snapshot(), tmp_webcam_snap)
                print("")
                shutil.rmtree(self.output_dir, onerror=change_perm)
                if os.path.exists(self.raw_frames_output_dir):
                    logging.info("Deleting raw frames at {}".format(self.raw_frames_output_dir))
                    if self.assume_clean:
                        logging.warning(
                            "Since --assume-clean is set, will not delete previous frames."
                        )
                    else:
                        shutil.rmtree(self.raw_frames_output_dir, onerror=change_perm)
            else:
                raise RefusingRequestException(
                    "The path {} already exists; refusing to proceed.".format(self.output_dir)
                )
            logging.info("Finished deleting")

        make_dirs_perm(self.output_dir)
        make_dirs_perm(self.raw_frames_output_dir)
        make_dirs_perm(pjoin(self.output_dir, "timing"))
        make_dirs_perm(pjoin(self.output_dir, "sensors"))
        if pexists(tmp_webcam_snap) and os.path.getsize(tmp_webcam_snap) > 0:
            logging.warning(
                "Keeping webcam snapshot from previous run. It will be overwritten if a new capture is taken."
            )
            shutil.move(tmp_webcam_snap, self.coll.webcam_snapshot())

        with open(pjoin(self.output_dir, "submission_hash.txt"), "w", encoding="utf8") as f:
            f.write(self.sx_alive.submission_hash)
        shutil.copyfile(os.environ["SAURONX_CONFIG_PATH"], self.coll.toml_file())

        # copy os info, git hash, etc.
        with open(self.coll.env_file(), "w", encoding="utf8") as f:
            for key, value in config.environment_info.items():
                f.write(key + "=" + value + "\n")

        logging.info("Prepared output directory {}".format(self.output_dir))

        if pexists(self.coll.log_file()):
            logging.warning("The log file at {} already exists".format(self.coll.log_file()))
        else:
            os.symlink(self.submission_log_file, self.coll.log_file())

    def finalize(self, run_info: CompletedRunInfo) -> None:
        import valarpy.model as model

        with open(self.coll.env_file(), "a", encoding="utf8") as f:

            def write(key: str, value: str) -> None:  # TODO strip control chars, etc, too
                f.write(key + "=" + escape_for_properties(value) + "\n")

            sub_obj = self.sx_alive.submission_obj
            exp = sub_obj.experiment
            # this is the critical start time, which is used to fill in runs.datetime_run
            write("datetime_started", stamp(run_info.datetime_acclimation_started))
            # and this end time is critical too
            write("datetime_capture_finished", stamp(run_info.datetime_capture_finished))
            write("original:experiment_id", exp.id)
            write("original:experiment_name", exp.name)
            write("original:description", sub_obj.description)
            write("original:continuing_id", sub_obj.continuing_id)
            write("original:datetime_plated", sub_obj.datetime_plated)
            write("original:datetime_dosed", sub_obj.datetime_dosed)
            write("original:notes", sub_obj.notes)
            write("original:person_submitted", sub_obj.user_id)
            write("original:battery", exp.battery_id)
            write("original:template_plate", exp.template_plate_id)
            for param in model.SubmissionParams.select(model.SubmissionParams).where(
                model.SubmissionParams.submission == sub_obj.id
            ):
                write("param:" + param.param_type + ":" + param.name, param.value)
            write("datetime_environment_written", stamp(datetime.now()))
            write("ffmpeg_version", self.find_ffmpeg_version())
        try:
            if os.path.exists(run_info.preview_path):
                shutil.copyfile(run_info.preview_path, self.coll.preview_snapshot())
            else:
                logging.error("Missing preview snapshot {}".format(run_info.preview_path))
        except:
            logging.exception("Failed to copy preview frame at {}".format(run_info.preview_path))
        success_to_user("Finalized run. All of the necessary data is now present.")

    def find_ffmpeg_version(self):
        out, err = wrap_cmd_call(["ffmpeg", "-version"])
        return out

    def upload(self) -> None:
        try:
            self.sx_alive.update_status(StatusValue.UPLOADING)
            # noinspection PyTypeChecker
            for i in range(0, int(self.upload_params["max_attempts"])):
                try:
                    self._attempt_upload()
                    break
                except (SCPException, ExternalCommandFailed) as e:
                    # noinspection PyTypeChecker
                    if i < int(self.upload_params["max_attempts"]) - 1:
                        logging.error("Upload failed (attempt {})".format(i), e)
                        warn_user("Upload failed (attempt {})".format(i))
                    else:
                        raise e
            self.sx_alive.update_status(StatusValue.UPLOADED)
        except Exception:
            self.sx_alive.update_status(StatusValue.FAILED_DURING_UPLOAD)
            raise

    def copy_raw_to(self, path: str) -> None:
        msg = "Moving raw frames to {}".format(path)
        logging.warning(msg)
        warn_user(msg, "==DO NOT INTERRUPT OR CANCEL==")
        try:
            shutil.move(self.raw_frames_output_dir, path)
        except:
            logging.fatal(
                "Moving raw frames stopped partway. They are split between {} and {}".format(
                    self.raw_frames_output_dir, path
                )
            )
            raise
        warn_user(
            "Moved raw frames to {}.".format(path, self.submission_hash),
            "You will need to copy them back and",
            "finish the submission with `sauronx continue {}`.",
        )

    def make_video(self) -> None:
        try:
            self._parse_frame_timing_file()
            self._trim_frames()
            logging.info(
                "Making primary video with ffmpeg. At high framerates, this should take about as long as the duration of the run"
            )
            self._run_ffmpeg(self.raw_frames_output_dir, self.video_file)
            logging.info("Compressing microphone recording.")
            self._convert_microphone()
        except Exception:
            self.sx_alive.update_status(StatusValue.FAILED_DURING_POSTPROCESSING)
            raise

    def _run_ffmpeg(self, path, output_video):
        make_dirs_perm(os.path.dirname(output_video))
        if not pdir(path):
            raise ValueError("Directory {} does not exist".format(path))
        first_real_frame = self._first_frame(path)
        # TODO change log level back to info
        stream_cmd_call(
            [
                "ffmpeg",
                "-loglevel",
                "warning",
                "-hwaccel",
                "qsv",
                "-f",
                "image2",
                "-nostdin",
                "-c:v",
                "rawvideo",
                "-framerate",
                str(self.fps),
                "-video_size",
                "{}x{}".format(self.frame_width, self.frame_height),
                "-pixel_format",
                "gray",
                "-start_number",
                str(first_real_frame),
                "-i",
                pjoin(path, "%08d.raw"),
                "-y",
                "-c:v",
                "hevc_qsv",
                "-g",
                str(self.keyframe_interval),
                "-q:v",
                str(self.qp),
                "-preset",
                config["sauron.data.video.preset"],
                "-load_plugin",
                "2",
                "-r",
                str(self.fps),
                output_video,
            ]
        )

        self.file_hasher.add_hash(output_video)
        if not self.keep_raw_frames:
            slow_delete(path, 3)

    def _first_frame(self, path: str):
        assert pexists(path), "The frame directory does not exist"
        prop_files = list(sorted(scan_for_proper_files(path)))
        if len(prop_files) == 0:
            warn_user("No frames were found in {}".format(path))
            raise ValueError("No frames were found in {}".format(path))
        return basename(prop_files[0].rstrip(".raw"))

    def _x265_params(self):
        if self.x265_params is not None:
            return self.x265_params
        self.x265_params = "qp={}:keyint={}:min-keyint={}".format(
            str(self.qp), self.keyframe_interval, self.keyframe_interval
        )
        if self.extra_x265_options is not None and len(self.extra_x265_options) > 0:
            self.x265_params += ":" + ":".join(
                [
                    str(k) + "=" + config.parse_path_format(v, self.output_dir)
                    for k, v in self.extra_x265_options.items()
                ]
            )
        logging.info(
            "Encoding with framerate {} and x265 params '{}'".format(self.fps, self.x265_params)
        )
        return self.x265_params

    def _convert_microphone(self) -> None:
        microphone_input = self.coll.microphone_wav_path()
        microphone_output = self.coll.microphone_flac_path()
        if pexists(microphone_input):
            logging.info("Compressing microphone data.")
            stream_cmd_call(
                [
                    "ffmpeg",
                    "-i",
                    microphone_input,
                    "-compression_level",
                    config["sauron.data.audio.flac_compression_level"],
                    "-c:a",
                    "flac",
                    microphone_output,
                ]
            )
            self.file_hasher.add_hash(microphone_output)
            os.remove(microphone_input)

    def _trim_frames(self) -> None:
        """Trims the frames that were captured before the first stimulus or after the last.
        This works because StimulusTimeLog is defined to have its head be the start of the run and its tail be the end of the run, regardless of the stimuli.
        To fulfill this definition, Board.run_scheduled_and_wait appends a stimulus for ID 0 at the beginning, and another at the end.
        """
        if not self.coll.stimulus_timing_exists():
            raise MissingResourceException(
                "Cannot proceed: the stimulus timing log at {} is missing".format(
                    self.coll.stimulus_timing_log_file()
                )
            )

        # first, check that we didn't fail partway through trimming
        # this could be bad; let's fix that before making the trimming videos or the main video
        def fixit(name: str):
            output_video = pjoin(self.coll.trimmed_dir(), name + ".mkv")
            hash_file = output_video + ".sha256"
            tmpdir = pjoin(self.output_dir, name + "-trimmings")
            if pexists(tmpdir) and not pexists(hash_file):
                warn_user("Moving {} trimmed frames back".format(name))
                logging.warning("Moving {} trimmed frames back".format(name))
                for f in os.listdir(tmpdir):
                    if os.path.isdir(
                        self.coll.outer_frames_dir()
                    ):  # If directory exists, copy overwrites existing files in directory, move does not.
                        shutil.copy(pjoin(tmpdir, f), self.coll.outer_frames_dir())
                        os.remove(pjoin(tmpdir, f))
                    else:
                        shutil.move(pjoin(tmpdir, f), self.coll.outer_frames_dir())
            elif pexists(tmpdir):
                pass

        fixit("start")
        fixit("end")

        stimulus_time_log = self._parse_stimulus_timing_file(self.coll.stimulus_timing_log_file())
        if len(stimulus_time_log) == 0:
            return  # ok; nothing to remove
        snapshots = [
            parse_local_iso_datetime(snap) for snap in lines(self.coll.snapshot_timing_log_file())
        ]
        first_stimulus = stimulus_time_log[0]  # type: datetime
        last_stimulus = stimulus_time_log[-1]  # type: datetime
        trimmings_start = []
        trimmings_end = []
        ran_off_end = 0
        my_files = enumerate(sorted(scan_for_proper_files(self.coll.outer_frames_dir())))
        for i, frame in my_files:
            if i >= len(snapshots):
                ran_off_end += 1
            elif snapshots[i] < first_stimulus:
                trimmings_start.append(frame)
            elif snapshots[i] > last_stimulus:
                trimmings_end.append(frame)
        if ran_off_end > 0:
            logging.error("{} stimuli occurred after the last snapshot!")
            warn_user("{} stimuli occurred after the last snapshot!")

        make_dirs_perm(self.coll.trimmed_dir())
        self._make_trimmings_video(trimmings_start, "start")
        self._make_trimmings_video(trimmings_end, "end")

    def _make_trimmings_video(self, trimmings, name):
        output_video = (
            self.coll.trimmed_start_video() if name == "start" else self.coll.trimmed_end_video()
        )
        hash_file = output_video + ".sha256"
        tmpdir = pjoin(self.output_dir, name + "-trimmings")
        if os.path.exists(hash_file):
            # TODO will fail if interrupted WHILE moving frames
            logging.warning(
                "{} trimmed frames video already exists at {}".format(name, output_video)
            )
            return
        if os.path.exists(output_video) or os.path.exists(tmpdir):
            warn_user(
                "Making {} trimmed frames video failed partway through.".format(name),
                "Deleting and remaking.",
            )
            logging.error(
                "Making {} trimmed frames video failed partway through. Deleting and remaking.".format(
                    name
                )
            )
        if len(trimmings) == 0:
            logging.error("No {} trimmed frames".format(name))
            warn_user(
                "No {} trimmed frames.".format(name),
                "Increase {} in {} to ensure that frames aren't lost.".format(
                    "padding_before_milliseconds"
                    if name == "start"
                    else "padding_after_milliseconds",
                    config.path,
                ),
            )
            return
        # moving to another disk is a little slower
        # but we don't want these deleted if sauronx fails
        # tmpdir = pjoin(config.temp_dir(), name + '-trimmings')
        logging.info("Trimmed {} {} frames. Compressing.".format(len(trimmings), name))
        make_dirs_perm(tmpdir)
        logging.debug("Created temp dir at {}".format(tmpdir))
        for frame in trimmings:
            if not pexists(pjoin(tmpdir, os.path.basename(frame))):
                shutil.move(
                    frame, tmpdir
                )  # we HAVE to move here so they're not seen when making the primary video
        self._run_ffmpeg(tmpdir, output_video)

    def _parse_stimulus_timing_file(self, path: str) -> List[datetime]:
        # datetime,id,intensity
        return [parse_local_iso_datetime(line.split(",")[0]) for line in list(lines(path))[1:]]

    def _parse_frame_timing_file(self):
        strftime_fmt = "%Y-%m-%dT%H:%M:%S.%f"
        raw_timing_file_path = self.coll.raw_snapshot_timing_log_file()
        proc_timing_file_path = self.coll.snapshot_timing_log_file()
        stream_cmd_call(["sudo", "chmod", "777", raw_timing_file_path])
        with open(raw_timing_file_path, "r+", encoding="utf8") as f:
            with open(proc_timing_file_path, "w", encoding="utf8") as o:
                reader = csv.reader(f)
                # get the two header lines?
                prev_datetime = parser.parse(next(reader)[0])
                # o.write("{}\n".format(prev_datetime.strftime(strftime_fmt))) # 20180920 added acquisition of an extra, unsaved frame before main acquisition loop
                prev_us = int(next(reader)[0]) / 1000
                for row in reader:
                    curr_us = int(row[0]) / 1000
                    diff_us = curr_us - prev_us
                    new_datetime = prev_datetime + timedelta(microseconds=diff_us)
                    o.write("{}\n".format(new_datetime.strftime(strftime_fmt)))
                    prev_datetime = new_datetime
                    prev_us = curr_us

    def _attempt_upload(self) -> None:
        logging.info("Uploading data via SSH...")
        self._scp_files()
        logging.info("Finished uploading data via SSH")

    def _scp_files(self) -> None:
        stream_cmd_call(
            [
                "scp",
                "-r",
                "-C",
                os.path.normpath(self.output_dir),
                str(self.upload_params["ssh_username"])
                + "@"
                + str(self.upload_params["hostname"])
                + ":"
                + self._remote_upload_dir(),
            ]
        )
        # noinspection PyBroadException
        try:
            self.sx_alive.notify_finished()
        except:
            warn_user("Failed to notify")
            logging.error("Failed to notify")

    def _remote_upload_dir(self) -> str:
        remote_dir = self.upload_params["remote_upload_path"]  # type: str
        return (
            str(self.upload_params["ssh_username"])
            + "@"
            + str(self.upload_params["hostname"])
            + ":"
            + remote_dir
            if remote_dir.endswith(os.sep)
            else remote_dir + os.sep
        )

__all__ = ["Results"]


from discord.ext import commands
from notbot.context import Context, Module
from typing import Optional
from notbot.cogs.util.formatter import success_message, format_user_name

from notbot.services import get_settings_service

MODULE_NAME = "settings_module"

class SettingsModule(commands.Cog, Module):
    def __init__(self, context: Context):
        self.bot = context.get_bot()
        self.settings_service = get_settings_service(context)

    def get_name(self):
        return MODULE_NAME

    @commands.command(
        name="pprefix",
        description="""
    Sets or removes the personal prefix to interact with the bot.
    If the command is called without arguments, it will display your current personal prefix instead.
    """,
        usage="[personal_prefix|unset]",
    )
    async def pprefix(self, ctx, pprefix: Optional[str] = None):
        if pprefix == "unset":
            await self.settings_service.del_pprefix(ctx.author.id)
            await ctx.send(success_message("PPrefix removed"))
            return

        pprfx = await self.settings_service.get_pprefix(ctx.author.id)
        if pprefix is None and pprfx is None:
            raise commands.BadArgument("You do not have a personal prefix.")
        if pprefix is None and pprfx is not None:
            await ctx.send(
                f":information_source: Your personal prefix is **{'nothing' if pprfx == '' else pprfx}**"
            )
            return
        if pprefix is None:
            raise commands.BadArgument("You should specify a prefix.")
        if len(pprefix) > 5:
            raise commands.BadArgument("Personal prefix must be **1-5** characters.")
        await self.settings_service.set_pprefix(ctx.author.id, pprefix)
        if pprefix == "":
            pprefix = "nothing"
        await ctx.send(
            f"Set **{format_user_name(ctx.author)}**'s personal prefix to **{pprefix}**"
        )

def setup(bot):
    context: Context = bot.context

    module = context.get_module(MODULE_NAME)
    bot.add_cog(module)


from django.db import models

class Organism(models.Model):
    name = models.CharField('Name', max_length=100)

    def __str__(self):
        return self.name

class ConcentrationMethod(models.Model):
    name = models.CharField('Name', max_length=100)

    class Meta:
        verbose_name = 'Concentration Method'
        verbose_name_plural = 'Concentration Methods'

    def __str__(self):
        return self.name

class ReadLength(models.Model):
    name = models.CharField('Name', max_length=50)

    class Meta:
        verbose_name = 'Read Length'
        verbose_name_plural = 'Read Lengths'

    def __str__(self):
        return self.name

class IndexType(models.Model):
    name = models.CharField('Name', max_length=150)
    is_index_i7 = models.BooleanField('Is Index I7?', default=False)
    is_index_i5 = models.BooleanField('Is Index I5?', default=False)

    class Meta:
        verbose_name = 'Index Type'
        verbose_name_plural = 'Index Types'

    def __str__(self):
        return self.name

class GenericIndex(models.Model):
    index_id = models.CharField('Index ID', max_length=50, unique=True)
    index = models.CharField('Index', max_length=8)
    index_type = models.ForeignKey(IndexType, verbose_name='Index Type')

    class Meta:
        abstract = True

    def __str__(self):
        return self.index_id

class IndexI7(GenericIndex):
    class Meta:
        verbose_name = 'Index I7'
        verbose_name_plural = 'Indices I7'

class IndexI5(GenericIndex):
    class Meta:
        verbose_name = 'Index I5'
        verbose_name_plural = 'Indices I5'

class BarcodeSingletonModel(models.Model):
    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        self.pk = 1
        super(BarcodeSingletonModel, self).save(*args, **kwargs)

    def delete(self, *args, **kwargs):
        pass

    @classmethod
    def load(cls):
        obj, created = cls.objects.get_or_create(pk=1)
        return obj

class BarcodeCounter(BarcodeSingletonModel):
    counter = models.PositiveSmallIntegerField(default=0)

    def increment(self):
        self.counter += 1

    def __str__(self):
        return str(self.counter)

class GenericLibrarySample(models.Model):
    name = models.CharField(
        'Name',
        max_length=200,
        unique=True,
    )

    date = models.DateTimeField('Date', auto_now_add=True)

    status = models.SmallIntegerField(default=0)

    organism = models.ForeignKey(
        Organism,
        verbose_name='Organism'
    )

    concentration = models.FloatField('Concentration')

    concentration_method = models.ForeignKey(
        ConcentrationMethod,
        verbose_name='Concentration Method',
    )

    dna_dissolved_in = models.CharField('DNA Dissolved in', max_length=255)

    sample_volume = models.PositiveIntegerField('Sample Volume')

    equal_representation_nucleotides = models.BooleanField(
        'Equal Representation of Nucleotides',
        default=True,
    )

    read_length = models.ForeignKey(
        ReadLength,
        verbose_name='Read Length',
    )

    sequencing_depth = models.PositiveIntegerField('Sequencing Depth')

    comments = models.TextField('Comments', null=True, blank=True)

    is_pooled = models.BooleanField('Is pooled?', default=False)

    barcode = models.CharField('Barcode', max_length=9)

    index_type = models.ForeignKey(
        IndexType,
        verbose_name='Index Type',
        null=True,
        blank=True,
    )

    index_i7 = models.CharField(
        'Index I7',
        max_length=8,
        null=True,
        blank=True,
    )

    index_i5 = models.CharField(
        'Index I5',
        max_length=8,
        null=True,
        blank=True,
    )

    # Quality Control
    dilution_factor = models.PositiveIntegerField(
        'Dilution Factor (facility)',
        null=True,
        blank=True,
    )

    concentration_facility = models.FloatField(
        'Concentration (facility)',
        null=True,
        blank=True,
    )

    concentration_method_facility = models.ForeignKey(
        ConcentrationMethod,
        related_name='+',
        verbose_name='Concentration Method (facility)',
        null=True,
        blank=True,
    )

    date_facility = models.DateTimeField(
        'Date (facility)',
        null=True,
        blank=True,
    )

    sample_volume_facility = models.PositiveIntegerField(
        'Sample Volume (facility)',
        null=True,
        blank=True,
    )

    amount_facility = models.FloatField(
        'Amount (facility)',
        null=True,
        blank=True,
    )

    size_distribution_facility = models.CharField(
        'Size Distribution (facility)',
        max_length=200,
        null=True,
        blank=True,
    )

    comments_facility = models.TextField(
        'Comments (facility)',
        null=True,
        blank=True,
    )

    class Meta:
        abstract = True

    def __str__(self):
        return self.name


from typing import Dict, List, Union

import numpy as np
from maggma.builders import MapBuilder
from maggma.core import Store
from pymatgen import Structure

from emmet.core import SETTINGS
from emmet.core.vasp.calc_types import run_type, task_type
from emmet.core.vasp.task import TaskDocument
from emmet.core.vasp.validation import DeprecationMessage, ValidationDoc

__author__ = "Shyam Dwaraknath"
__email__ = "shyamd@lbl.gov"

class TaskValidator(MapBuilder):
    def __init__(
        self,
        tasks: Store,
        task_validation: Store,
        kpts_tolerance: float = SETTINGS.VASP_KPTS_TOLERANCE,
        **kwargs,
    ):
        """
        Creates task_types from tasks and type definitions

        Args:
            tasks: Store of task documents
            task_validation: Store of task_types for tasks
            input_sets: dictionary of task_type and pymatgen input set to validate against
            kpts_tolerance: the minimum kpt density as dictated by the InputSet to require
            LDAU_fields: LDAU fields to check for consistency
        """
        self.tasks = tasks
        self.task_validation = task_validation
        self.kpts_tolerance = kpts_tolerance

        self.kwargs = kwargs

        super().__init__(
            source=tasks,
            target=task_validation,
            projection=["orig_inputs", "output.structure", "input.parameters"],
            **kwargs,
        )

    def unary_function(self, item):
        """
        Find the task_type for the item

        Args:
            item (dict): a (projection of a) task doc
        """
        task_doc = TaskDocument(**item)
        return ValidationDoc.from_task_doc(task_doc=task_doc).dict()


from django.core.management.base import BaseCommand
from hearthstone import cardxml
from ...models import Card

class Command(BaseCommand):
	def add_arguments(self, parser):
		parser.add_argument("path", nargs="?", help="CardDefs.xml file")
		parser.add_argument("--locale", default="enUS")

	def handle(self, *args, **options):
		path = options["path"]
		db, _ = cardxml.load(path, locale=options["locale"])
		self.stdout.write("%i cards available" % (len(db)))

		qs = Card.objects.all().values_list("id")
		known_ids = [item[0] for item in qs]
		missing = [id for id in db if id not in known_ids]
		self.stdout.write("%i known cards" % (len(known_ids)))

		new_cards = [Card.from_cardxml(db[id]) for id in missing]
		Card.objects.bulk_create(new_cards)
		self.stdout.write("%i new cards" % (len(new_cards)))


# Time:  O(a^2 + n), a is the number of ages,
#                    n is the number of people
# Space: O(a)

# 825
# Some people will make friend requests.
# The list of their ages is given and ages[i] is the age of the ith person.
#
# Person A will NOT friend request person B (B != A)
# if any of the following conditions are true:
#
# age[B] <= 0.5 * age[A] + 7
# age[B] > age[A]
# age[B] > 100 && age[A] < 100
# Otherwise, A will friend request B.
#
# Note that if A requests B, B does not necessarily request A.
# Also, people will not friend request themselves.
#
# How many total friend requests are made?
#
# Example 1:
#
# Input: [16,16]
# Output: 2
# Explanation: 2 people friend request each other.
# Example 2:
#
# Input: [16,17,18]
# Output: 2
# Explanation: Friend requests are made 17 -> 16, 18 -> 17.
# Example 3:
#
# Input: [20,30,100,110,120]
# Output:
# Explanation: Friend requests are made 110 -> 100, 120 -> 110, 120 -> 100.
#
# Notes:
# - 1 <= ages.length <= 20000.
# - 1 <= ages[i] <= 120.

try:
    xrange          # Python 2
except NameError:
    xrange = range  # Python 3

import collections

class Solution(object):
    # answer depends on ages not people, so we should COMPRESS data first by merge people w/ same age.
    # otherwise LTE with repeating calculation of people w/ same ages.
    def numFriendRequests(self, ages): # USE THIS
        """
        :type ages: List[int]
        :rtype: int
        """
        def request(a, b):
            return 0.5*a+7 < b <= a

        c = collections.Counter(ages)
        ans = 0
        for a in c:
            for b in c:
                if request(a, b):
                    ans += c[a]*c[b] if a != b else c[a]*(c[a]-1)
        return ans

    def numFriendRequests_ming(self, ages): # similar to the above, but separate a-a and a-b, more clearly
        cnt = collections.Counter(ages)
        ans = sum(cnt[k]*(cnt[k]-1) for k in cnt if k > 14)

        # sort so only consider one way
        unique = sorted(cnt)
        for i in range(len(unique)):
            for j in range(i):
                ans += int(unique[j] > (0.5*unique[i]+7)) * cnt[unique[i]] * cnt[unique[j]]
        return ans

    def numFriendRequests_bookshadow(self, ages): # 不用看了
        '''
        观察题设条件 1 <= ages[i] <= 120，年龄的范围很小, 统计每一个年龄的人数
        遍历每个人，统计符合其年龄条件约束的人数之和
        '''
        cnt = collections.Counter(ages)
        ans = 0
        for age in ages:
            cnt[age] -= 1
            left, right = age / 2 + 8, age
            ans += sum(cnt[age] for age in range(left, right + 1))
            cnt[age] += 1
        return ans

print(Solution().numFriendRequests([69, 24, 85, 8, 85])) # 4


# Copyright (C) 2020 Google Inc.
# Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
"""Module for Mega mixin"""
from collections import defaultdict

import flask
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declared_attr

from ggrc import db
from ggrc.builder import simple_property
from ggrc.models import relationship
from ggrc.models import reflection
from ggrc.models.inflector import get_model

class Mega(object):
  """Mixin adds methods for Mega objects
  Mega objects can have mapped objects of the same type"""

  _api_attrs = reflection.ApiAttributes(
      reflection.Attribute('is_mega', create=False, update=False),
  )

  @simple_property
  def is_mega(self):
    """Returns True if object have children"""
    return bool(self._child_relationships)

  @declared_attr
  def _child_relationships(cls):  # pylint: disable=no-self-argument
    """Return relationships to children
    used to eagerly query is_mega property"""
    joinstr = (
        "and_(foreign(Relationship.source_id) == {cls_name}.id,"
        "foreign(Relationship.source_type) == '{cls_name}',"
        "foreign(Relationship.destination_type) == '{cls_name}')"
    )
    return db.relationship(
        "Relationship",
        primaryjoin=joinstr.format(cls_name=cls.__name__),
    )

  @classmethod
  def eager_query(cls, **kwargs):
    """Define fields to be loaded eagerly to lower the count of DB queries."""
    query = super(Mega, cls).eager_query(**kwargs)
    return query.options(
        sa.orm.subqueryload('_child_relationships').load_only("id")
    )

  @classmethod
  def get_all_relatives_ids(cls, _id, direction):
    """Returns ids of relatives for all generations

    Args:
        _id: ID of Mega object
        direction: could be 'parents' or 'children'
    Returns:
        set of ids
    """
    visited = set()
    not_visited = {_id, }
    while not_visited:
      visited.update(not_visited)
      not_visited = cls._get_relatives_for(direction, not_visited)
      not_visited -= visited
    return visited - {_id}

  @classmethod
  def get_relatives_ids(cls, _id, direction):
    """Returns ids of relatives for one generation

    Args:
        _id: ID of Mega object
        direction: could be 'parents' or 'children'
    Returns:
        set of ids
    """
    return cls._get_relatives_for(direction, {_id}) - {_id}

  @classmethod
  def _get_relatives_for(cls, direction, nodes):
    """Return set of ids of relatives of nodes in selected direction

    Args:
        direction: could be 'parents' or 'children'
        nodes: set of mega objects to find relatives for in selected direction
    Returns:
        set of ids"""
    rel = relationship.Relationship

    if direction == "children":
      direction_filter = rel.source_id.in_
      next_nodes_attr = "destination_id"
    elif direction == "parents":
      direction_filter = rel.destination_id.in_
      next_nodes_attr = "source_id"
    else:
      raise ValueError("Unknown value for direction attr")

    relationships = rel.query.filter(
        direction_filter(nodes),
        rel.source_type == cls.__name__,
        rel.destination_type == cls.__name__,
    )
    return set(getattr(r, next_nodes_attr) for r in relationships)

  @staticmethod
  def _is_parent_for(parent, obj):
    """Check that 'parent' is parent for 'obj'
    Cache parents ids for mega"""
    if hasattr(flask.g, "mega_parents_cache"):
      mega_parents_cache = flask.g.mega_parents_cache
    else:
      mega_parents_cache = flask.g.mega_parents_cache = defaultdict(dict)

    if obj.id in mega_parents_cache[obj.type]:
      parents_ids = mega_parents_cache[obj.type][obj.id]
    else:
      obj_model = get_model(obj.type)
      parents_ids = obj_model.get_all_relatives_ids(obj.id, "parents")
      mega_parents_cache[obj.type][obj.id] = parents_ids
    return parent.id in parents_ids

  @classmethod
  def skip_automapping(cls, src, dst, dst_related_obj):
    """Skip automappings from Mega to child"""
    # In case we mapped an object to Mega we should skip
    # mapping of the object to not parent Mega objects
    # In case of cycle mapping, one Mega object could be parent and child
    to_not_parent = (
        dst_related_obj.type == dst.type and
        not cls._is_parent_for(dst_related_obj, dst)
    )
    # In case we mapped Mega to Mega we should skip mappings of
    # dst related object to src, if src is not parent of dst
    from_not_parent = (
        src.type == dst.type and
        not cls._is_parent_for(src, dst)
    )
    return bool(to_not_parent or from_not_parent)


# blender script to create big fucking booster
# apply to booster3.blend

import bpy, bmesh
import importlib
import bfs
importlib.reload(bfs)

bfs.deselect()
bfs.deleteObjectNamed("booster top")
bfs.deleteObjectNamed("booster bottom")
bfs.deleteObjectNamed("x1")
bfs.deleteObjectNamed("x2")
bfs.deleteObjectNamed("space1")
bfs.deleteObjectNamed("space2")
bfs.deleteObjectNamed("flag1")
bfs.deleteObjectNamed("flag2")
bfs.deleteObjectNamed("logo1")
bfs.deleteObjectNamed("logo2")

booster = bfs.selectByName("booster5")
booster.hide = True

bpy.ops.object.duplicate()
bpy.context.scene.objects.active = bfs.getSelected()[0]
bpy.context.scene.objects.active.hide = False
bpy.context.scene.objects.active.name = 'booster'
booster = bpy.context.scene.objects.active

xPlug = bfs.findObject('x plug')
x1 = bfs.cookieCut(booster, xPlug, "x1", "BMESH")

bfs.selectActivate(xPlug)
xPlug.location.x *= -1
# rotation applies the location change to matrix_world
bpy.ops.transform.rotate(value=bfs.toRad(180), axis=(0.0, 0.0, 1.0))

x2 = bfs.cookieCut(booster, xPlug, "x2", "BMESH")

bfs.selectActivate(xPlug)
bpy.ops.transform.rotate(value=bfs.toRad(180), axis=(0.0, 0.0, 1.0))
xPlug.location.x *= -1

spacePlug = bfs.findObject('space plug')
space1 = bfs.cookieCut(booster, spacePlug, "space1", "BMESH")

bfs.selectActivate(spacePlug)
bpy.ops.transform.translate(value=(-9.0, 0.0, 0.0))
space2 = bfs.cookieCut(booster, spacePlug, "space2", "BMESH")
bfs.selectActivate(spacePlug)
bpy.ops.transform.translate(value=(9.0, 0.0, 0.0))

flagPlug = bfs.findObject('flag plug')
flag1 = bfs.cookieCut(booster, flagPlug, "flag1", "BMESH")
bfs.selectActivate(flagPlug)
bpy.ops.transform.translate(value=(-9.0, 0.0, 0.0))
flag2 = bfs.cookieCut(booster, flagPlug, "flag2", "BMESH")
bfs.selectActivate(flagPlug)
bpy.ops.transform.translate(value=(9.0, 0.0, 0.0))

logoPlug = bfs.findObject('logo plug')
logo1 = bfs.cookieCut(booster, logoPlug, "logo1", "BMESH")
bfs.selectActivate(logoPlug)
bpy.ops.transform.translate(value=(-9.0, 0.0, 0.0))
logo2 = bfs.cookieCut(booster, logoPlug, "logo2", "BMESH")
bfs.selectActivate(logoPlug)
bpy.ops.transform.translate(value=(9.0, 0.0, 0.0))

# calculate UVs
bfs.cylinderUV(flag1, flipZ=True, flipX=True)
bfs.cylinderUV(flag2, flipZ=True, flipX=True)
bfs.cylinderUV(logo1, flipZ=True, flipX=True)
bfs.cylinderUV(logo2, flipZ=True, flipX=True)
bfs.cylinderUV(space1, flipZ=True, flipX=True)
bfs.cylinderUV(space2, flipZ=True, flipX=True)
bfs.cylinderUV(x1, flipZ=True, flipX=True)
bfs.cylinderUV(x2, flipZ=True, flipX=True)

# split booster in 2
fusePlug = bfs.findObject('fuse plug')
bottom_booster = bfs.cookieCut(booster, fusePlug, "booster bottom", "BMESH")
booster.name = "booster top"