from __future__ import division

import librosa, pydub
import numpy as np
from tempfile import TemporaryFile
import pickle, json, os

class mash:

    def __init__(self, json_, cached=False):
        self.sr = 22050  # new Sampling Rate for the audio files

        self.songs = json_
        self.Yin = []
        self.Yout = []
        self.pathIn = []
        self.pathOut = []
        self.beats = {'in': [], 'out': []}
        self.tempo = {'in': 0, 'out': 0}

        self._setup()
        self._load(cached=cached)
        self._extract()
        self._segment()
        self._speedUp()
        out = self._mix()

        print("Exporting...")
        out.export(out_f="final.mp3", format="mp3")
        print("[SUCCESS] Export as `final.mp3`")

    def _setup(self):
        if not os.path.exists('cache'):
            os.makedirs('cache')

    def _load(self, cached=True):
        for song in self.songs:
            if os.path.exists("cache/%s.pkl"%song['name']):
                print("\nLoading", song['name'], "from cache")
                with open("cache/%s.pkl"%song['name'], 'rb') as f:
                    if song['mixin']:
                        print("Yin=", song['name'])
                        self.Yin = pickle.load(f)
                        self.pathIn = song['path']
                    else:
                        print("Yout=", song['name'])
                        self.Yout.append(pickle.load(f))
                        self.pathOut.append(song['path'])
                continue

            print("\nLoading", song['name'])
            y, sr = librosa.load(song['path'], sr=self.sr)
            if song['mixin']:
                self.Yin = y
                self.pathIn = song['path']
            else:
                self.Yout.append(y)
                self.pathOut.append(song['path'])
            print("[SUCCESS] Loaded", song['name'])

            if cached:
                try:
                    with open('cache/%s.pkl'%song['name'], 'wb') as f:
                        pickle.dump(y, f)
                        print("[SUCCESS] Cached", song['name'])
                except Exception as e:
                    print("[FAILED] Caching", song['name'])
                    print(e)

    def _extract(self):
        # TODO: Add cosine distance similarity to choose the best mixout
        self.Yout = self.Yout[0] # NOTE: considering 1mixin & 1mixout
        self.pathOut = self.pathOut[0]

        self.tempo['in'], self.beats['in'] = librosa.beat.beat_track(y=self.Yin, sr=self.sr)
        self.tempo['out'], self.beats['out'] = librosa.beat.beat_track(y=self.Yout, sr=self.sr)

        print("TempoIn=", self.tempo['in'])
        print("TempoOut=", self.tempo['out'])

        self._OTAC()
        self._crossFadeRegion()

    def _OTAC(self): # Optimal Tempo Adjustment Coefficient Computation
        C = [-2, -1, 0, 1, 2]

        if self.tempo['in'] == self.tempo['out']:
            self.tempo['tgt'] = self.tempo['in']
            return

        Tin_ = [(2**c)*self.tempo['in'] for c in C]
        TinIndex_ = np.argmin(np.absolute(Tin_ - self.tempo['out']))
        Copt = C[TinIndex_]
        Bopt = (2**Copt)*self.tempo['in']

        Tlow = min(Bopt, self.tempo['out'])
        Thigh = max(Bopt, self.tempo['out'])

        a, b = 0.765, 1
        Ttgt = (a-b)*Tlow + np.sqrt( ((a-b)**2)*(Tlow**2) + 4*a*b*Thigh*Tlow )
        Ttgt = Ttgt/(2*a)

        print("FoptIn=", Ttgt/Bopt)
        print("FoptOut=", Ttgt/self.tempo['out'])
        print("Ttgt=", Ttgt)

        self.tempo['tgt'] = Ttgt

    def _crossFadeRegion(self): # Computes the cross fade region for the mixed song
        Na = self.beats['in'].shape[0]-1

        scores = [self._score(i, Na) for i in range(2, int(Na/4))]
        noBeats = np.argmax(scores)+2

        inDuration = librosa.get_duration(y=self.Yin, sr=self.sr)
        fadeInStart = librosa.frames_to_time(self.beats['in'], sr=self.sr)[-int(noBeats/2)]
        fadeIn = inDuration - fadeInStart

        fadeOut = librosa.frames_to_time(self.beats['out'], sr=self.sr)[int(noBeats/2)]

        print("Best Power Corelation Scores=", np.max(scores))
        print("Number of beats in cross fade region=", noBeats)
        print("fadeInStart=", fadeInStart)
        print("fadeOutEnd=", fadeOut)
        print("Cross Fade Time=", fadeIn+fadeOut)

        self.crossFade = [fadeInStart*1000, fadeOut*1000] # In milliseconds

    def _score(self, T, Na):
        cr = 0
        for i in range(1, T+1):
            cr += self.beats['in'][Na-i+1]*self.beats['out'][i]
        return cr/T

    def _segment(self):
        print("Started Segmentation")

        sIn = pydub.AudioSegment.from_file(self.pathIn, format="mp3")
        sOut = pydub.AudioSegment.from_file(self.pathOut, format="mp3")

        print("[SUCCESS] Segmented audio files")

        self.segments = {
            'in': [ sIn[:self.crossFade[0]], sIn[self.crossFade[0]:] ],
            'out': [ sOut[:self.crossFade[1]], sOut[self.crossFade[1]:] ],
        }
        del sIn, sOut

    def _speedUp(self):
        s1 = self.segments['in'][1]
        s2 = self.segments['out'][0]

        speed1 = self.tempo['tgt']/self.tempo['in']
        speed2 = self.tempo['tgt']/self.tempo['out']

        print("Playback Speed of in end segment=",speed1,'X')
        print("Playback Speed of out start segment=",speed2,'X')

        s1 = s1.speedup(playback_speed=speed1)
        s2 = s1.speedup(playback_speed=speed2)

    def _mix(self):
        xf = self.segments['in'][1].fade(to_gain=-120, start=0, end=float('inf'))
        xf *= self.segments['out'][0].fade(from_gain=-120, start=0, end=float('inf'))

        out = TemporaryFile()

        out.write(self.segments['in'][0]._data)
        out.write(xf._data)
        out.write(self.segments['out'][1]._data)

        out.seek(0)

        print("[SUCCESS] Mixed 4 audio segment to 1")
        return self.segments['in'][0]._spawn(data=out)

if __name__ == '__main__':
    with open('songs.json', 'r') as f:
        j = json.loads(f.read())
        obj = mash(j, cached=True)


import matplotlib
matplotlib.use("Agg")

import matplotlib.pyplot as plt
import numpy as np
import os

import experiments_xdr as ex

from matplotlib.markers import MarkerStyle

output_filename = "price_comparison_graph.tex"

import seaborn as sns

sns.set(rc={'text.usetex' : True})

#input_lines = [
#	("Tâtonnement 10 assets", "sosp_tat_results", "o"),
#	("Convex Solver 10 assets", "cvxpy_results", "+")
#	]

def times_mean(times):
	acc = 0.0
	for i in range(0, times.size()):
		acc = acc + times[i].runtime
	return acc / times.size()

def plot_one_experiment_line(line_name, results_filename, mark, fill, color):
	print(results_filename)
	results = ex.PriceComputationExperiment.new()
	results.load_from_file(os.fsencode(results_filename))
	meanx = []
	meany = []

	xvals = []
	yvals = []
	for i in range(0, results.experiments.size()):
	#for key in data.keys():
		num_txs = results.experiments[i].num_txs
		res = results.experiments[i].results
		if (res.size() > 0):
			meanx.append(num_txs)
			meany.append(times_mean(res))
		if (res.size() != results.experiments[i].num_trials):
			print ("timeouts:", (results.experiments[i].num_trials - res.size()))
		for j in range(0, res.size()):
			xvals.append(num_txs)
			yvals.append(res[j].runtime)
		#	print(key, vals[i])
	#plt.scatter(xvals, yvals, marker=MarkerStyle(mark, fillstyle=fill), color=color)
	sns.lineplot(meanx, meany, marker=MarkerStyle(mark, fillstyle=fill), color=color, label=line_name, markersize=10, edgecolor="black")

	#plt.scatter(meanx, meany, mark=mark)

plot_one_experiment_line("CVXPY, 10 Assets", "pricecomp_measurements/cvxpy_10", "D", "left", "tab:blue")
#plot_one_experiment_line("cvxpy 20", "pricecomp_measurements/cvxpy_20", "D", "right", "tab:blue")
#plot_one_experiment_line("cvxpy 50", "pricecomp_measurements/cvxpy_50", "D", "full", "tab:blue")
plot_one_experiment_line("T\^atonnement, 10 Assets", "pricecomp_measurements/tatonnement_10", "o", "left", "tab:red")
plot_one_experiment_line("T\^atonnement, 20 Assets", "pricecomp_measurements/tatonnement_20", "o", "right", "tab:red")
plot_one_experiment_line("T\^atonnement, 50 Assets", "pricecomp_measurements/tatonnement_50", "o", "full", "tab:red")
#for (legend_name, filename, mark) in input_lines:
#	plot_one_experiment_line(legend_name, filename, mark)

plt.xscale('log')
plt.yscale('log')
plt.axis([500,20000000,0.001, 300])
plt.xlabel("Number of Offers")
plt.ylabel("Time (s)")

plt.legend()

import tikzplotlib
tikzplotlib.save(output_filename)

plt.savefig("out.png")


from typing import Optional

from .graphics import (
    ConnectionDirection,
    DominoBoardGraphic,
    DominoGraphic,
    DominoOrientation,
)

class DominoSide:
    def __init__(self, val, domino, connection_direction):
        self.value = val
        self.is_endpoint = False
        self.connection = None
        self.connection_direction = connection_direction
        self.parent_domino: Domino = domino

    def __repr__(self):
        return "{}-Side({})".format(self.parent_domino, self.connection_direction.name)

    def get_playable_value(self):
        return self.value

    def rotate(self, intervals):
        rotations = [
            ConnectionDirection.Left,
            ConnectionDirection.Up,
            ConnectionDirection.Right,
            ConnectionDirection.Down,
        ]
        if self.connection_direction == ConnectionDirection.Left:
            self.connection_direction = rotations[intervals]
        elif self.connection_direction == ConnectionDirection.Down:
            self.connection_direction = rotations[intervals - 1]
        elif self.connection_direction == ConnectionDirection.Right:
            self.connection_direction = rotations[intervals - 2]
        elif self.connection_direction == ConnectionDirection.Up:
            self.connection_direction = rotations[intervals - 3]

class DominoMidSide(DominoSide):
    def __init__(self, domino, connection_direction):
        super().__init__(None, domino, connection_direction)

    def get_playable_value(self):
        return self.parent_domino.side1.value

class Domino:
    def __init__(self, side1_val, side2_val):
        self.side1 = DominoSide(side1_val, self, ConnectionDirection.Left)
        self.side2 = DominoSide(side2_val, self, ConnectionDirection.Right)
        self.orientation = DominoOrientation.Side1Left

        self.graphic = DominoGraphic(side1_val, side2_val, self.orientation, None, None)

    def __repr__(self):
        return "Domino({},{})".format(self.side1.value, self.side2.value)

    def get_playable_sides(self):
        playable_sides = []
        if self.side1.connection is None:
            playable_sides.append(self.side1)
        if self.side2.connection is None:
            playable_sides.append(self.side2)
        return playable_sides

    def get_value_in_play(self):
        return sum([x.value for x in self.get_playable_sides()])

    def rotate(self, intervals):
        # Rotations done clockwise in 90deg intervals
        self.rotate_orientation(intervals)
        self.side1.rotate(intervals)
        self.side2.rotate(intervals)

    def rotate_orientation(self, intervals):
        rotations = [
            DominoOrientation.Side1Left,
            DominoOrientation.Side1Up,
            DominoOrientation.Side1Right,
            DominoOrientation.Side1Down,
        ]
        if self.orientation == DominoOrientation.Side1Left:
            self.orientation = rotations[intervals]
            self.graphic.orientation = rotations[intervals]
        elif self.orientation == DominoOrientation.Side1Down:
            self.orientation = rotations[intervals - 1]
            self.graphic.orientation = rotations[intervals - 1]
        elif self.orientation == DominoOrientation.Side1Right:
            self.orientation = rotations[intervals - 2]
            self.graphic.orientation = rotations[intervals - 2]
        elif self.orientation == DominoOrientation.Side1Up:
            self.orientation = rotations[intervals - 3]
            self.graphic.orientation = rotations[intervals - 3]

    @staticmethod
    def get_rotation_interval(direction1, direction2):
        # we want to align connection directions so:
        # Left -> Right,
        # Find correct alignment with direction1
        alignments = {
            ConnectionDirection.Left: ConnectionDirection.Right,
            ConnectionDirection.Up: ConnectionDirection.Down,
            ConnectionDirection.Right: ConnectionDirection.Left,
            ConnectionDirection.Down: ConnectionDirection.Up,
        }
        goal_alignment = alignments[direction1]

        alignment_map = {
            ConnectionDirection.Left: 1,
            ConnectionDirection.Up: 2,
            ConnectionDirection.Right: 3,
            ConnectionDirection.Down: 4,
        }

        current_alignment = alignment_map[direction2]
        goal_alignment = alignment_map[goal_alignment]
        diff = goal_alignment - current_alignment
        if diff < 0:
            diff += 4

        return diff

class DoubleDomino(Domino):
    def __init__(self, side):
        super().__init__(side, side)
        self.mid_side1 = DominoMidSide(self, ConnectionDirection.Up)
        self.mid_side2 = DominoMidSide(self, ConnectionDirection.Down)

        # Set initial orientation to be vertical
        self.rotate(1)

    def end_sides_available(self):
        return (
            self.mid_side1.connection is not None
            and self.mid_side2.connection is not None
        )

    def get_playable_sides(self):
        playable_sides = []
        if self.end_sides_available():
            if self.side1.connection is None:
                playable_sides.append(self.side1)
            if self.side2.connection is None:
                playable_sides.append(self.side2)
        else:
            if self.mid_side1.connection is None:
                playable_sides.append(self.mid_side1)
            if self.mid_side2.connection is None:
                playable_sides.append(self.mid_side2)
        return playable_sides

    def get_value_in_play(self):
        return 0 if self.end_sides_available() else 2 * self.side1.value

    def rotate(self, intervals):
        self.rotate_orientation(intervals)
        self.side1.rotate(intervals)
        self.side2.rotate(intervals)
        self.mid_side1.rotate(intervals)
        self.mid_side2.rotate(intervals)

class DominoBoard:
    def __init__(self, board_size=100):
        self.root_domino = None
        self.dominoes = []
        self.endpoints = set()

        self.board_graphic = DominoBoardGraphic(board_size)
        self.root_x = int(board_size / 2)
        self.root_y = int(board_size / 2)

    def add_root_domino(self, domino: Domino):
        self.root_domino = domino
        self.dominoes.append(domino)
        new_endpoints = domino.get_playable_sides()
        self.endpoints = self.endpoints.union(set(new_endpoints))

        # Update graphics
        self.root_domino.graphic.x_position = self.root_x
        self.root_domino.graphic.y_position = self.root_y

    def add_leaf_domino(
        self, domino: Domino, endpoint: DominoSide, attachpoint: DominoSide
    ):
        self.dominoes.append(domino)
        self.endpoints.remove(endpoint)
        endpoint_domino = endpoint.parent_domino

        endpoint.connection = attachpoint
        attachpoint.connection = endpoint

        new_endpoints = endpoint_domino.get_playable_sides()
        self.endpoints = self.endpoints.union(set(new_endpoints))
        new_endpoints = domino.get_playable_sides()
        self.endpoints = self.endpoints.union(set(new_endpoints))

        # Update graphics
        endpoint_position = (
            endpoint_domino.graphic.x_position,
            endpoint_domino.graphic.y_position,
        )
        endpoint_direction = endpoint.connection_direction.value
        new_position = (
            endpoint_position[0] + endpoint_direction[0],
            endpoint_position[1] + endpoint_direction[1],
        )
        domino.graphic.x_position = new_position[0]
        domino.graphic.y_position = new_position[1]
        # rotate incoming domino
        rotation_intervals = Domino.get_rotation_interval(
            endpoint.connection_direction, attachpoint.connection_direction
        )
        domino.rotate(rotation_intervals)

    def add_domino(
        self,
        domino: Domino,
        endpoint: Optional[DominoSide] = None,
        attachpoint: Optional[DominoSide] = None,
    ):
        if not self.root_domino:
            self.add_root_domino(domino)
        else:
            if endpoint is None or attachpoint is None:
                assert False, "Need endpoint and attachpoint if not root domino"
            assert endpoint in self.endpoints, "Not a valid endpoint"
            assert (
                endpoint.get_playable_value() == attachpoint.get_playable_value()
            ), "Not a valid move"
            self.add_leaf_domino(domino, endpoint, attachpoint)

        self.board_graphic.add_domino(domino.graphic)

    def get_score(self):
        in_play_dominoes = set([endpoint.parent_domino for endpoint in self.endpoints])
        score = sum([domino.get_value_in_play() for domino in in_play_dominoes])

        return score


import xml.dom.minidom
import os
from rumboot.testing.test_desc import *

class JUintReport:

    def __init__(self, log_file_path):
        self._log_file_path = log_file_path
        self._tests = 0
        self._failures = 0
        self._root = xml.dom.minidom.Document()
        self._testsuites = self._root.createElement("testsuites")
        self._root.appendChild(self._testsuites)
        self._testsuite = self._root.createElement("testsuite")
        self._testsuite.setAttribute("name", "Testing result") # ???
        self._testsuites.appendChild(self._testsuite)

    def add_test_result(self, test_desc):
        self._tests += 1
        testcase = self._root.createElement("testcase")
        testcase.setAttribute("name", test_desc.full_name)
        if test_desc.status == TEST_STATUS_NOT_EXECUTED:
            skipped = self._root.createElement("skipped")
            skipped.setAttribute("message", "Skipped")
            testcase.appendChild(skipped)
        elif test_desc.status == TEST_STATUS_FAULT:
            self._failures += 1
            failure = self._root.createElement("failure")
            failure.setAttribute("message", "Failed")
            testcase.appendChild(failure)
        if test_desc.status != TEST_STATUS_NOT_EXECUTED:
            std_out = self._root.createElement("system-out")
            text_value = self._root.createTextNode(test_desc.log_text)
            std_out.appendChild(text_value)
            testcase.appendChild(std_out)
        self._testsuite.appendChild(testcase)

    def flush(self):
        self._testsuite.setAttribute("tests", str(self._tests))
        self._testsuite.setAttribute("errors", "0")
        self._testsuite.setAttribute("failures", str(self._failures))

        file_path = os.path.join(self._log_file_path)
        with open(file_path, "w") as file:
            self._root.writexml(file, addindent="  ", newl="\n", encoding="UTF-8")


from flask import Flask, render_template, redirect, request
from forms import LoginForm
from database import Database
from forms import PlaceForm
from forms import CityForm
from forms import StateForm
from forms import PlacetagForm
from forms import states_detailsForm
from forms import city_detailsForm
from forms import place_detailsForm
from forms import InputForm
from forms import RegisterForm
from client import getRecommendations
from forms import UserLoginForm

app = Flask(__name__,
            static_url_path='',
            static_folder='static')
app.config['SECRET_KEY'] = 'you-will-never-guess'

#from app import route

@app.route('/hello')
def hello():
    return "Hello universe"

#loops
# making list of pokemons
Pokemons =["Pikachu", "Charizard", "Squirtle", "Jigglypuff",
           "Bulbasaur", "Gengar", "Charmander", "Mew", "Lugia", "Gyarados"]

@app.route('/sample1')
def sample1():
    return render_template("sample1.html", len = len(Pokemons), Pokemons = Pokemons)
    app.run(use_reloader = True, debug = True)

@app.route('/sample')
def sample():
    return render_template('sample.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    print('login')
    message = ''
    form = LoginForm()
    if form.validate_on_submit():
        # print('Login requested for username {}, password {}'.format(form.username.data, form.password.data))
        # return redirect('/index')
        db = Database()
        id = db.checkLogin(form.username.data, form.password.data)
        db.close()
        print('id', id)
        if id != -1:
            return redirect('/states')
        else:
            message = 'Invalid username or password'
    return render_template('login.html', form=form, message=message)

@app.route('/userlogin', methods=['GET', 'POST'])
def userlogin():
    print('userlogin')
    message = ''
    form = UserLoginForm()
    if form.validate_on_submit():
        # print('Login requested for username {}, password {}'.format(form.username.data, form.password.data))
        # return redirect('/index')
        db = Database()
        result = db.userlogin(form.username.data, form.password.data)
        db.close()
        print(result)
        if len(result)>0:
            return redirect('/input')
        else:
            message = 'Invalid username or password'
    return render_template('userlogin.html', form=form, message=message)

@app.route('/register', methods=['GET', 'POST'])
def register():
    print('register')
    message = ''
    form = RegisterForm()
    if form.validate_on_submit():
        db = Database()
        id = db.register(form.username.data, form.fname.data, form.lname.data, form.password.data)
        db.close()
        print('id', id)
        if id != -1:
            return redirect('/userlogin')
        else:
            message = 'Invalid username or password'
    return render_template('register.html', form=form, message=message)

@app.route('/')
@app.route('/index')
def index():
    return render_template('index.html')

@app.route('/service')
def service():
    return render_template('service.html')

@app.route('/contact')
def contact():
    return render_template('contact.html')

@app.route('/about')
def about():
    return render_template('about.html')

@app.route('/states',methods=['GET', 'POST'])
def states():
    message = ''
    form = StateForm()
    db = Database()
    if form.validate_on_submit():
        # print('Input requested for state{}, ' .format(form.state.data))
        # return redirect('/index')
        db.addState(form.name.data)
        db.commit()
        #print('id', id)
        #if id != -1:
        return redirect('/states')
        # else:
        #     message = 'Invalid state'

    States=db.getStates()
    db.close()
    return render_template('states.html',form=form, message=message,States=States,len=len(States))

# @app.route('/city', methods=['GET', 'POST'])
# def city():
#     message = ''
#     form = CityForm()
#     placeid=request.args.get('placeid')
#     form = states_detailsForm()
#     db = Database()
#     if form.validate_on_submit():
#         # print('Input requested for state{}, city{}, ' .format(form.state.data, form.city.data))
#         # return redirect('/index')

#         id = db.addCity(form.name.data)
#         db.commit()
#         # print('id', id)
#         # if id != -1:
#         return redirect('/place?placeid='+placeid)
#         # else:
#         #    message = 'Invalid state or city'

#     Cities=db.getCities()
#     db.close()
#     return render_template('city.html', form=form, message=message,city=Cities,len=len(Cities))

@app.route('/place', methods=['GET', 'POST'])
def place():
    message = ''
    form = states_detailsForm()
    form = PlaceForm()
    if form.is_submitted():
        # return redirect('/index')
        db = Database()
        cityid=request.args.get('cityid')
        print('cityid',cityid)
        id = db.addPlace(form.place.data, form.desc.data,form.longitude.data,form.latitude.data,cityid)
        db.close()
        print('id', id)
        if id != -1:
            return redirect('/index')
        else:
            message = 'Invalid place'
    return render_template('place.html', form=form, message=message)

@app.route('/placetag', methods=['GET', 'POST'])
def placetag():
    message = ''
    form = PlacetagForm()
    if form.is_submitted():
        # return redirect('/index')
        db = Database()
        cityid=request.args.get('cityid')
        print('cityid',cityid)
        id = db.addPlacetag(form.placetag.data, form.tag.data)
        db.close()

        print('id', id)
        if id != -1:
            return redirect('/index')
        else:
            message = 'Invalid place'
    return render_template('placetag.html', form=form, message=message)

@app.route('/states_details', methods=['GET', 'POST'])
def states_details():
    message = ''
    stateid=request.args.get('stateid')
    form = states_detailsForm()
    db = Database()
    if form.is_submitted():
        if(form.add.data):
            db.addCity(form.name.data,stateid,form.desc.data, form.longitude.data, form.latitude.data)
        else:
            db.executeUpdate("update state set name='"+form.newstate.data+"' where stateid="+stateid)
        db.close()
        print('id', id)
        return redirect('/states_details?stateid='+stateid)
    cities=db.getCities(stateid)
    state=db.getStateById(stateid)
    return render_template('states_details.html', form=form, message=message, len=len(cities),cities=cities,state=state)

@app.route('/citydetails', methods=['GET', 'POST'])
def citydetails():
    message = ''
    id=request.args.get('id')
    form = city_detailsForm()
    db=Database()
    if form.is_submitted():
        # return redirect('/index')
        #cityid=request.args.get('cityid')
        #print('cityid',cityid)
        if(form.add.data):
            db.addPlace(form.name.data,form.desc.data, form.longitude.data, form.latitude.data,id)
        else:
            db.executeUpdate("update city set name='"+form.newcity.data+"' where id="+id)
        db.close()
        print('id', id)

        return redirect('/citydetails?id='+id)
    places=db.getplaces(id)
    city=db.getCityById(id)
    return render_template('citydetails.html', form=form, message=message,len=len(places),places=places, city=city)

@app.route('/placedetails', methods=['GET', 'POST'])
def placedetails():
    placeid=request.args.get('placeid')
    form=place_detailsForm()
    db=Database()
    if form.is_submitted():
        print('form.add.data',form.add.data,form.placetag.data)
        if(form.add.data):
            db.executeUpdate('insert into place_tag values ('+placeid+",'"+form.placetag.data+"')")
            db.close()
        return redirect('/placedetails?placeid='+placeid)

    place=db.executeQuery('select * from place where placeid='+str(placeid))[0]
    placetags=db.executeQuery('select * from place_tag where placeid='+placeid)
    db.close()

    return render_template('placedetails.html',place=place,placetags=placetags,taglen=len(placetags))

@app.route('/removeplacetag',methods=['GET','POST'])
def removeplacetag():
    placeid=request.args.get('placeid')
    tag=request.args.get('tag')
    db=Database()
    db.executeUpdate('delete from place_tag where placeid='+placeid+" and name='"+tag+"'")
    db.close()
    return redirect('/placedetails?placeid='+placeid)

@app.route('/distancetest')
def distancetest():
    db=Database()
    distance=db.getdistance(7,8)
    print('distance'+str(distance))

@app.route('/input', methods=['GET','POST'])
def input():
    db=Database()
    form = InputForm()
    if form.is_submitted():
        homecity=form.homecity.data
        selectedcities=request.form.getlist('selectedcities')
        locationtags=request.form.getlist('location_tag')
        minbudget=form.minbudget.data
        maxbudget=form.maxbudget.data
        print(homecity)
        print(selectedcities)
        print(locationtags)
        print(minbudget)
        print(maxbudget)

        itineraries=db.getItineraries(homecity,selectedcities,locationtags,minbudget,maxbudget)
        recommendations=getRecommendations(1,selectedcities)

        recom_cities=[]
        db=Database()
        c=db.getCursor()

        for x in recommendations:
            c.execute('select * from city where id='+str(x))
            city=c.fetchall()
            recom_cities.append(city[0])

        return render_template('result.html',itineraries=itineraries,recom_cities=recom_cities)

    cities=db.executeQuery("select * from city order by name")
    tags=db.executeQuery("select distinct(name) as name from place_tag order by name")
    return render_template('input.html',cities=cities,len=len(cities),tags=tags,tagslen=len(tags))

# @app.route('/input')
# def input():
#     db=Database()
#     cities=db.executeQuery("select * from city order by name")
#     tags=db.executeQuery("select distinct(name) as name from place_tag order by name")
#     return render_template('input.html',cities=cities,len=len(cities),tags=tags,tagslen=len(tags))


from __future__ import annotations

from collections.abc import Sequence
import functools

import numpy as np
import probnum as pn
from probnum.typing import ArrayLike, DTypeLike, FloatLike, ScalarType, ShapeLike

from ._domain import Domain
from ._point import Point

class Interval(Domain, Sequence[np.ndarray]):
    def __init__(
        self,
        lower_bound: FloatLike,
        upper_bound: FloatLike,
        dtype: DTypeLike = np.double,
    ) -> None:
        self._lower_bound = pn.utils.as_numpy_scalar(lower_bound, dtype=dtype)
        self._upper_bound = pn.utils.as_numpy_scalar(upper_bound, dtype=dtype)

        if self._lower_bound > self._upper_bound:
            raise ValueError("The lower bound must not be larger than the upper bound")

        assert self._lower_bound.dtype == self._upper_bound.dtype

        super().__init__(shape=(), dtype=self._lower_bound.dtype)

    def __len__(self) -> int:
        return 2

    def __getitem__(self, idx: int) -> np.ndarray:
        if idx in (0, -2):
            return self._lower_bound

        if idx in (1, -1):
            return self._upper_bound

        return KeyError(f"Index {idx} is out of range")

    def __iter__(self):
        yield self._lower_bound
        yield self._upper_bound

    @functools.cached_property
    def boundary(self) -> Point:
        return (Point(self._lower_bound), Point(self._upper_bound))

    @property
    def volume(self) -> ScalarType:
        return self._upper_bound - self._lower_bound

    def __repr__(self) -> str:
        return (
            f"<Interval {[self._lower_bound, self._upper_bound]} with "
            f"shape={self.shape} and "
            f"dtype={str(self.dtype)}>"
        )

    def __contains__(self, item: ArrayLike) -> bool:
        arr = np.asarray(item, dtype=self.dtype)

        if arr.shape != self.shape:
            return False

        return self._lower_bound <= arr <= self._upper_bound

    def __eq__(self, other: object) -> bool:
        return isinstance(other, Interval) and tuple(self) == tuple(other)

    def uniform_grid(self, shape: ShapeLike, inset: ArrayLike = 0.0) -> np.ndarray:
        shape = pn.utils.as_shape(shape)
        inset = np.asarray(inset)

        assert len(shape) == 1 and inset.ndim == 0

        return np.linspace(
            self._lower_bound + inset,
            self._upper_bound - inset,
            shape[0],
        )


from contextlib import contextmanager
from io import StringIO
from streamlit.report_thread import REPORT_CONTEXT_ATTR_NAME
from threading import current_thread
import streamlit as st
import pandas as pd
import time
from detect_steamlit import detect
import os
import sys
import argparse
from PIL import Image
import PIL
import base64
import torch
import cv2
import imageio
import sys
# set the matplotlib backend so figures can be saved in the background
import matplotlib
# import the necessary packages
from sklearn.metrics import classification_report
from skimage import transform
from skimage import exposure
from skimage import io
import matplotlib.pyplot as plt
import numpy as np
import argparse
import random
import os
import pandas as pd
from imageio import imread
import keras
import cv2
from torch.autograd import Variable
import torch.nn as nn
import torch
import torch.nn.functional as F
from gtts import gTTS
import math
import gdown

# url = 'https://drive.google.com/uc?id=1kznuazx4fO8starp_JONzAeAtWjRnZ3A'
# output = 'D:/best(4).pt'
# gdown.download(url, output, quiet=True)

def download_file_from_google_drive(id, destination):
    URL = "https://docs.google.com/uc?export=download"

    session = requests.Session()

    response = session.get(URL, params = { 'id' : id }, stream = True)
    token = get_confirm_token(response)

    if token:
        params = { 'id' : id, 'confirm' : token }
        response = session.get(URL, params = params, stream = True)

    save_response_content(response, destination)

def get_confirm_token(response):
    for key, value in response.cookies.items():
        if key.startswith('download_warning'):
            return value

    return None

def save_response_content(response, destination):
    CHUNK_SIZE = 32768

    with open(destination, "wb") as f:
        for chunk in response.iter_content(CHUNK_SIZE):
            if chunk: # filter out keep-alive new chunks
                f.write(chunk)
def copy_attr(a, b, include=(), exclude=()):
    # Copy attributes from b to a, options to only include [...] and to exclude [...]
    for k, v in b.__dict__.items():
        if (len(include) and k not in include) or k.startswith('_') or k in exclude:
            continue
        else:
            setattr(a, k, v)

class View(nn.Module):
    def __init__(self):
        super(View, self).__init__()

    def forward(self, x):
        numel = x.numel() / x.shape[0]
        return x.view(-1, int(numel))

def convNoutput(convs, input_size):  # predict output size after conv layers
    input_size = int(input_size)
    input_channels = convs[0][1].weight.shape[1]  # input channel
    output = torch.Tensor(1, input_channels, input_size, input_size)
    with torch.no_grad():
        for conv in convs:
            output = conv(output)
    return output.numel(), output.shape

class stn(nn.Module):
    def __init__(self, input_channels, input_size, params):
        super(stn, self).__init__()

        self.input_size = input_size

        self.maxpool = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv1 = nn.Sequential(
            nn.ReplicationPad2d(2),
            nn.Conv2d(input_channels, params[0], kernel_size=5, stride=1),
            nn.ReLU(True),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        self.conv2 = nn.Sequential(
            nn.ReplicationPad2d(2),
            nn.Conv2d(params[0], params[1], kernel_size=5, stride=1),
            nn.ReLU(True),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )

        self.conv3 = nn.Sequential(
            nn.ReplicationPad2d(2),
            nn.Conv2d(params[1], params[2], kernel_size=3, stride=1),
            nn.ReLU(True),
            nn.MaxPool2d(kernel_size=2, stride=2)
        )

        out_numel, out_size = convNoutput([self.conv1, self.conv2, self.conv3], input_size / 2)
        # set fc layer based on predicted size
        self.fc = nn.Sequential(
            View(),
            nn.Linear(out_numel, params[3]),
            nn.ReLU()
        )
        self.classifier = classifier = nn.Sequential(
            View(),
            nn.Linear(params[3], 6)  # affine transform has 6 parameters
        )
        # initialize stn parameters (affine transform)
        self.classifier[1].weight.data.fill_(0)
        self.classifier[1].bias.data = torch.FloatTensor([1, 0, 0, 0, 1, 0])

    def localization_network(self, x):
        x = self.maxpool(x)
        x = self.conv1(x)
        x = self.conv2(x)
        x = self.conv3(x)
        x = self.fc(x)
        x = self.classifier(x)
        return x

    def forward(self, x):
        theta = self.localization_network(x)
        theta = theta.view(-1, 2, 3)
        grid = F.affine_grid(theta, x.size())
        x = F.grid_sample(x, grid)
        return x

class SillNet(nn.Module):
    def __init__(self, nc, input_size, class_train, class_test, extract_chn=None, classify_chn=None, param1=None, param2=None, param3=None, param4=None, param_mask=None):
        super(SillNet, self).__init__()

        self.extract_chn = extract_chn
        self.classify_chn = classify_chn
        self.param1 = param1
        self.param2 = param2
        self.param3 = param3
        self.param4 = param4
        self.input_size = input_size
        self.nc = nc
        self.class_train = class_train
        self.class_test = class_test

        # extracter
        self.ex_pd1 = nn.ReplicationPad2d(2)
        self.ex1 = nn.Conv2d(nc, self.extract_chn[0], 5, 1)  # inchn, outchn, kernel, stride, padding, dilation, groups
        self.ex_bn1 = nn.InstanceNorm2d(self.extract_chn[0])

        self.ex_pd2 = nn.ReplicationPad2d(2)
        self.ex2 = nn.Conv2d(self.extract_chn[0], self.extract_chn[1], 5, 1)  # 1/1
        self.ex_bn2 = nn.InstanceNorm2d(self.extract_chn[1])

        self.ex_pd3 = nn.ReplicationPad2d(1)
        self.ex3 = nn.Conv2d(self.extract_chn[1], self.extract_chn[2], 3, 1)  # 1/1
        self.ex_bn3 = nn.InstanceNorm2d(self.extract_chn[2])

        self.ex_pd4 = nn.ReplicationPad2d(1)
        self.ex4 = nn.Conv2d(self.extract_chn[2], self.extract_chn[3], 3, 1)  # 1/1
        self.ex_bn4 = nn.InstanceNorm2d(self.extract_chn[3])

        self.ex_pd5 = nn.ReplicationPad2d(1)
        self.ex5 = nn.Conv2d(self.extract_chn[3], self.extract_chn[4], 3, 1)  # 1/1
        self.ex_bn5 = nn.InstanceNorm2d(self.extract_chn[4])

        self.ex_pd6 = nn.ReplicationPad2d(1)
        self.ex6 = nn.Conv2d(self.extract_chn[4], self.extract_chn[5], 3, 1)  # 1/1
        self.ex_bn6 = nn.InstanceNorm2d(self.extract_chn[5])

        self.leakyrelu = nn.LeakyReLU(0.2)
        self.relu = nn.ReLU()
        self.sigmoid = nn.Sigmoid()

        # decoder
        self.up1 = nn.UpsamplingNearest2d(scale_factor=2)
        self.de_pd1 = nn.ReplicationPad2d(1)
        self.de1 = nn.Conv2d(int(self.extract_chn[5] / 2), self.extract_chn[4], 3, 1)
        self.de_bn1 = nn.InstanceNorm2d(self.extract_chn[4], 1.e-3)

        self.de_pd2 = nn.ReplicationPad2d(1)
        self.de2 = nn.Conv2d(self.extract_chn[4], self.extract_chn[3], 3, 1)
        self.de_bn2 = nn.InstanceNorm2d(self.extract_chn[3], 1.e-3)

        self.de_pd3 = nn.ReplicationPad2d(1)
        self.de3 = nn.Conv2d(self.extract_chn[3], self.extract_chn[2], 3, 1)
        self.de_bn3 = nn.InstanceNorm2d(self.extract_chn[2], 1.e-3)

        self.de_pd4 = nn.ReplicationPad2d(1)
        self.de4 = nn.Conv2d(self.extract_chn[2], self.extract_chn[1], 3, 1)
        self.de_bn4 = nn.InstanceNorm2d(self.extract_chn[1], 1.e-3)

        self.de_pd5 = nn.ReplicationPad2d(1)
        self.de5 = nn.Conv2d(self.extract_chn[1], nc, 3, 1)

        # warping
        if param1 is not None:
            self.stn1 = stn(nc, self.input_size, param1)
        if param2 is not None:
            self.stn2 = stn(self.extract_chn[1], self.input_size, param2)
        if param3 is not None:
            self.stn3 = stn(self.extract_chn[3], self.input_size, param3)
        if param4 is not None:
            self.stn4 = stn(int(self.extract_chn[5] / 2), self.input_size, param4)

        # classifier 1
        # inchn, outchn, kernel, stride, padding, dilation, groups
        self.cls1 = nn.Conv2d(int(self.extract_chn[5]), self.classify_chn[0], 5, 1, 2)
        self.cls_bn1 = nn.BatchNorm2d(self.classify_chn[0])

        self.cls2 = nn.Conv2d(self.classify_chn[0], self.classify_chn[1], 5, 1, 2)  # 1/2
        self.cls_bn2 = nn.BatchNorm2d(self.classify_chn[1])

        self.cls3 = nn.Conv2d(self.classify_chn[1], self.classify_chn[2], 5, 1, 2)  # 1/4
        self.cls_bn3 = nn.BatchNorm2d(self.classify_chn[2])

        self.cls4 = nn.Conv2d(self.classify_chn[2], self.classify_chn[3], 3, 1, 1)  # 1/4
        self.cls_bn4 = nn.BatchNorm2d(self.classify_chn[3])

        self.cls5 = nn.Conv2d(self.classify_chn[3], self.classify_chn[4], 3, 1, 1)  # 1/8
        self.cls_bn5 = nn.BatchNorm2d(self.classify_chn[4])

        self.cls6 = nn.Conv2d(self.classify_chn[4], self.classify_chn[5], 3, 1, 1)  # 1/8
        self.cls_bn6 = nn.BatchNorm2d(self.classify_chn[5])

        self.fc1 = nn.Linear(int(self.input_size / 8 * self.input_size / 8) * self.classify_chn[5], self.class_train)
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=1)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.dropout = nn.Dropout(p=0.5)

        # classifier 2
        # inchn, outchn, kernel, stride, padding, dilation, groups
        self.cls21 = nn.Conv2d(int(self.extract_chn[5]), self.classify_chn[0], 5, 1, 2)
        self.cls2_bn1 = nn.BatchNorm2d(self.classify_chn[0])

        self.cls22 = nn.Conv2d(self.classify_chn[0], self.classify_chn[1], 5, 1, 2)  # 1/2
        self.cls2_bn2 = nn.BatchNorm2d(self.classify_chn[1])

        self.cls23 = nn.Conv2d(self.classify_chn[1], self.classify_chn[2], 5, 1, 2)  # 1/4
        self.cls2_bn3 = nn.BatchNorm2d(self.classify_chn[2])

        self.cls24 = nn.Conv2d(self.classify_chn[2], self.classify_chn[3], 3, 1, 1)  # 1/4
        self.cls2_bn4 = nn.BatchNorm2d(self.classify_chn[3])

        self.cls25 = nn.Conv2d(self.classify_chn[3], self.classify_chn[4], 3, 1, 1)  # 1/8
        self.cls2_bn5 = nn.BatchNorm2d(self.classify_chn[4])

        self.cls26 = nn.Conv2d(self.classify_chn[4], self.classify_chn[5], 3, 1, 1)  # 1/8
        self.cls2_bn6 = nn.BatchNorm2d(self.classify_chn[5])

        self.fc2 = nn.Linear(int(self.input_size / 8 * self.input_size / 8) * self.classify_chn[5], self.class_test)

    def extract(self, x, is_warping):
        if is_warping and self.param1 is not None:
            x = self.stn1(x)
        h1 = self.leakyrelu(self.ex_bn1(self.ex1(self.ex_pd1(x))))
        h2 = self.leakyrelu(self.ex_bn2(self.ex2(self.ex_pd2(h1))))

        if is_warping and self.param2 is not None:
            h2 = self.stn2(h2)
        h3 = self.leakyrelu(self.ex_bn3(self.ex3(self.ex_pd3(h2))))
        h4 = self.leakyrelu(self.ex_bn4(self.ex4(self.ex_pd4(h3))))

        if is_warping and self.param3 is not None:
            h4 = self.stn3(h4)
        h5 = self.leakyrelu(self.ex_bn5(self.ex5(self.ex_pd5(h4))))
        h6 = self.sigmoid(self.ex_bn6(self.ex6(self.ex_pd6(h5))))

        feat_sem, feat_illu = torch.chunk(h6, 2, 1)
        feat_sem_nowarp = feat_sem

        if is_warping and self.param4 is not None:
            feat_sem = self.stn4(feat_sem)

        return feat_sem, feat_illu, feat_sem_nowarp

    def decode(self, x):
        h1 = self.leakyrelu(self.de_bn1(self.de1(self.de_pd1(x))))
        h2 = self.leakyrelu(self.de_bn2(self.de2(self.de_pd2(h1))))
        h3 = self.leakyrelu(self.de_bn3(self.de3(self.de_pd3(h2))))
        h4 = self.leakyrelu(self.de_bn4(self.de4(self.de_pd4(h3))))
        out = self.sigmoid(self.de5(self.de_pd5(h4)))
        return out

    def classify(self, x):
        h1 = self.pool2(self.leakyrelu(self.cls_bn1(self.cls1(x))))
        h2 = self.leakyrelu(self.cls_bn2(self.cls2(h1)))
        h3 = self.pool2(self.leakyrelu(self.cls_bn3(self.cls3(h2))))
        h4 = self.leakyrelu(self.cls_bn4(self.cls4(h3)))
        h5 = self.pool2(self.leakyrelu(self.cls_bn5(self.cls5(h4))))
        h6 = self.leakyrelu(self.cls_bn6(self.cls6(h5)))
        h7 = h6.view(-1, int(self.input_size / 8 * self.input_size / 8 * self.classify_chn[5]))
        out = self.fc1(h7)
        return out

    def classify2(self, x):
        h1 = self.pool2(self.leakyrelu(self.cls2_bn1(self.cls21(x))))
        h2 = self.leakyrelu(self.cls2_bn2(self.cls22(h1)))
        h3 = self.pool2(self.leakyrelu(self.cls2_bn3(self.cls23(h2))))
        h4 = self.leakyrelu(self.cls2_bn4(self.cls24(h3)))
        h5 = self.pool2(self.leakyrelu(self.cls2_bn5(self.cls25(h4))))
        h6 = self.leakyrelu(self.cls2_bn6(self.cls26(h5)))
        h7 = h6.view(-1, int(self.input_size / 8 * self.input_size / 8 * self.classify_chn[5]))
        out = self.fc2(h7)
        return out

    def init_params(self, net):
        print('Loading the model from the file...')
        net_dict = self.state_dict()
        if isinstance(net, dict):
            pre_dict = net
        else:
            pre_dict = net.state_dict()
        # 1. filter out unnecessary keys
        pre_dict = {k: v for k, v in pre_dict.items() if (k in net_dict)}
        net_dict.update(pre_dict)
        # 3. load the new state dict
        self.load_state_dict(net_dict)

class SillNet_gtsrb(nn.Module):
    def __init__(self, nc, input_size, class_train, class_test, extract_chn=None, classify_chn=None, param1=None, param2=None, param3=None, param4=None, param_mask=None):
        super(SillNet_gtsrb, self).__init__()

        self.extract_chn = extract_chn
        self.classify_chn = classify_chn
        self.param1 = param1
        self.param2 = param2
        self.param3 = param3
        self.param4 = param4
        self.input_size = input_size
        self.nc = nc
        self.class_train = class_train
        self.class_test = class_test

        # extracter
        self.ex_pd1 = nn.ReplicationPad2d(2)
        self.ex1 = nn.Conv2d(nc, self.extract_chn[0], 5, 1)  # inchn, outchn, kernel, stride, padding, dilation, groups
        self.ex_bn1 = nn.InstanceNorm2d(self.extract_chn[0])

        self.ex_pd2 = nn.ReplicationPad2d(2)
        self.ex2 = nn.Conv2d(self.extract_chn[0], self.extract_chn[1], 5, 1)  # 1/1
        self.ex_bn2 = nn.InstanceNorm2d(self.extract_chn[1])

        self.ex_pd3 = nn.ReplicationPad2d(1)
        self.ex3 = nn.Conv2d(self.extract_chn[1], self.extract_chn[2], 3, 1)  # 1/1
        self.ex_bn3 = nn.InstanceNorm2d(self.extract_chn[2])

        self.ex_pd4 = nn.ReplicationPad2d(1)
        self.ex4 = nn.Conv2d(self.extract_chn[2], self.extract_chn[3], 3, 1)  # 1/1
        self.ex_bn4 = nn.InstanceNorm2d(self.extract_chn[3])

        self.ex_pd5 = nn.ReplicationPad2d(1)
        self.ex5 = nn.Conv2d(self.extract_chn[3], self.extract_chn[4], 3, 1)  # 1/1
        self.ex_bn5 = nn.InstanceNorm2d(self.extract_chn[4])

        self.ex_pd6 = nn.ReplicationPad2d(1)
        self.ex6 = nn.Conv2d(self.extract_chn[4], self.extract_chn[5], 3, 1)  # 1/1
        self.ex_bn6 = nn.InstanceNorm2d(self.extract_chn[5])

        self.leakyrelu = nn.LeakyReLU(0.2)
        self.relu = nn.ReLU()
        self.sigmoid = nn.Sigmoid()

        # decoder
        self.up1 = nn.UpsamplingNearest2d(scale_factor=2)
        self.de_pd1 = nn.ReplicationPad2d(1)
        self.de1 = nn.Conv2d(int(self.extract_chn[5] / 2), self.extract_chn[4], 3, 1)
        self.de_bn1 = nn.InstanceNorm2d(self.extract_chn[4], 1.e-3)

        self.de_pd2 = nn.ReplicationPad2d(1)
        self.de2 = nn.Conv2d(self.extract_chn[4], self.extract_chn[3], 3, 1)
        self.de_bn2 = nn.InstanceNorm2d(self.extract_chn[3], 1.e-3)

        self.de_pd3 = nn.ReplicationPad2d(1)
        self.de3 = nn.Conv2d(self.extract_chn[3], self.extract_chn[2], 3, 1)
        self.de_bn3 = nn.InstanceNorm2d(self.extract_chn[2], 1.e-3)

        self.de_pd4 = nn.ReplicationPad2d(1)
        self.de4 = nn.Conv2d(self.extract_chn[2], self.extract_chn[1], 3, 1)
        self.de_bn4 = nn.InstanceNorm2d(self.extract_chn[1], 1.e-3)

        self.de_pd5 = nn.ReplicationPad2d(1)
        self.de5 = nn.Conv2d(self.extract_chn[1], nc, 3, 1)

        # warping
        if param1 is not None:
            self.stn1 = stn(nc, self.input_size, param1)
        if param2 is not None:
            self.stn2 = stn(self.extract_chn[1], self.input_size, param2)
        if param3 is not None:
            self.stn3 = stn(self.extract_chn[3], self.input_size, param3)
        if param4 is not None:
            self.stn4 = stn(int(self.extract_chn[5] / 2), self.input_size, param4)
            #self.rotate = rotate(int(self.extract_chn[5]/2), self.input_size, param4)

        # classifier 1
        # inchn, outchn, kernel, stride, padding, dilation, groups
        self.cls1 = nn.Conv2d(int(0.5 * self.extract_chn[5]), self.classify_chn[0], 5, 1, 2)
        self.cls_bn1 = nn.BatchNorm2d(self.classify_chn[0])

        self.cls2 = nn.Conv2d(self.classify_chn[0], self.classify_chn[1], 5, 1, 2)  # 1/2
        self.cls_bn2 = nn.BatchNorm2d(self.classify_chn[1])

        self.cls3 = nn.Conv2d(self.classify_chn[1], self.classify_chn[2], 5, 1, 2)  # 1/4
        self.cls_bn3 = nn.BatchNorm2d(self.classify_chn[2])

        self.cls4 = nn.Conv2d(self.classify_chn[2], self.classify_chn[3], 3, 1, 1)  # 1/4
        self.cls_bn4 = nn.BatchNorm2d(self.classify_chn[3])

        self.cls5 = nn.Conv2d(self.classify_chn[3], self.classify_chn[4], 3, 1, 1)  # 1/8
        self.cls_bn5 = nn.BatchNorm2d(self.classify_chn[4])

        self.cls6 = nn.Conv2d(self.classify_chn[4], self.classify_chn[5], 3, 1, 1)  # 1/8
        self.cls_bn6 = nn.BatchNorm2d(self.classify_chn[5])

        self.fc1 = nn.Linear(int(self.input_size / 8 * self.input_size / 8) * self.classify_chn[6], self.class_train)
        #self.glbpool = nn.MaxPool2d(kernel_size=int(self.input_size/8), stride=1)
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=1)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.dropout = nn.Dropout(p=0.5)

        # classifier 2
        # inchn, outchn, kernel, stride, padding, dilation, groups
        self.cls21 = nn.Conv2d(int(0.5 * self.extract_chn[5]), self.classify_chn[0], 5, 1, 2)
        self.cls2_bn1 = nn.BatchNorm2d(self.classify_chn[0])

        self.cls22 = nn.Conv2d(self.classify_chn[0], self.classify_chn[1], 5, 1, 2)  # 1/2
        self.cls2_bn2 = nn.BatchNorm2d(self.classify_chn[1])

        self.cls23 = nn.Conv2d(self.classify_chn[1], self.classify_chn[2], 5, 1, 2)  # 1/4
        self.cls2_bn3 = nn.BatchNorm2d(self.classify_chn[2])

        self.cls24 = nn.Conv2d(self.classify_chn[2], self.classify_chn[3], 3, 1, 1)  # 1/4
        self.cls2_bn4 = nn.BatchNorm2d(self.classify_chn[3])

        self.cls25 = nn.Conv2d(self.classify_chn[3], self.classify_chn[4], 3, 1, 1)  # 1/8
        self.cls2_bn5 = nn.BatchNorm2d(self.classify_chn[4])

        self.cls26 = nn.Conv2d(self.classify_chn[4], self.classify_chn[5], 3, 1, 1)  # 1/8
        self.cls2_bn6 = nn.BatchNorm2d(self.classify_chn[5])

        self.fc2 = nn.Linear(int(self.input_size / 8 * self.input_size / 8) * self.classify_chn[6], self.class_test)

    def extract(self, x, is_warping):
        if is_warping and self.param1 is not None:
            x = self.stn1(x)
        h1 = self.leakyrelu(self.ex_bn1(self.ex1(self.ex_pd1(x))))
        h2 = self.leakyrelu(self.ex_bn2(self.ex2(self.ex_pd2(h1))))

        if is_warping and self.param2 is not None:
            h2 = self.stn2(h2)
        h3 = self.leakyrelu(self.ex_bn3(self.ex3(self.ex_pd3(h2))))
        h4 = self.leakyrelu(self.ex_bn4(self.ex4(self.ex_pd4(h3))))

        if is_warping and self.param3 is not None:
            h4 = self.stn3(h4)
        h5 = self.leakyrelu(self.ex_bn5(self.ex5(self.ex_pd5(h4))))
        h6 = self.sigmoid(self.ex_bn6(self.ex6(self.ex_pd6(h5))))
        h6_nowarp = h6
        f_nowarp, noise = torch.chunk(h6_nowarp, 2, 1)

        feature, _ = torch.chunk(h6, 2, 1)

        if is_warping and self.param4 is not None:
            #feature = self.rotate(feature)
            feature = self.stn4(feature)

        return feature, noise, f_nowarp

    def decode(self, x):
        h1 = self.leakyrelu(self.de_bn1(self.de1(self.de_pd1(x))))
        h2 = self.leakyrelu(self.de_bn2(self.de2(self.de_pd2(h1))))
        h3 = self.leakyrelu(self.de_bn3(self.de3(self.de_pd3(h2))))
        h4 = self.leakyrelu(self.de_bn4(self.de4(self.de_pd4(h3))))
        out = self.sigmoid(self.de5(self.de_pd5(h4)))
        return out

    def classify(self, x):
        h1 = self.pool2(self.leakyrelu(self.cls_bn1(self.cls1(x))))
        h2 = self.leakyrelu(self.cls_bn2(self.cls2(h1)))
        h3 = self.pool2(self.leakyrelu(self.cls_bn3(self.cls3(h2))))
        h4 = self.leakyrelu(self.cls_bn4(self.cls4(h3)))
        h5 = self.pool2(self.leakyrelu(self.cls_bn5(self.cls5(h4))))
        h6 = self.leakyrelu(self.cls_bn6(self.cls6(h5)))
        h7 = h6.view(-1, int(self.input_size / 8 * self.input_size / 8 * self.classify_chn[6]))
        out = self.fc1(h7)
        #out = self.dropout(out)
        return out

    def classify2(self, x):
        h1 = self.pool2(self.leakyrelu(self.cls2_bn1(self.cls21(x))))
        h2 = self.leakyrelu(self.cls2_bn2(self.cls22(h1)))
        h3 = self.pool2(self.leakyrelu(self.cls2_bn3(self.cls23(h2))))
        h4 = self.leakyrelu(self.cls2_bn4(self.cls24(h3)))
        h5 = self.pool2(self.leakyrelu(self.cls2_bn5(self.cls25(h4))))
        h6 = self.leakyrelu(self.cls2_bn6(self.cls26(h5)))
        h7 = h6.view(-1, int(self.input_size / 8 * self.input_size / 8 * self.classify_chn[6]))
        out = self.fc2(h7)
        #out = self.dropout(out)
        return out

    def init_params(self, net):
        print('Loading the model from the file...')
        net_dict = self.state_dict()
        if isinstance(net, dict):
            pre_dict = net
        else:
            pre_dict = net.state_dict()
        # 1. filter out unnecessary keys
        pre_dict = {k: v for k, v in pre_dict.items() if (k in net_dict)}  # for fs net
        net_dict.update(pre_dict)
        # 3. load the new state dict
        self.load_state_dict(net_dict)

def transform(img, img_size):
    img = img.astype(np.float64)
    #img -= self.mean
    if img_size is not None:
        img = cv2.resize(img, (img_size[1], img_size[0]), interpolation=cv2.INTER_AREA)
    # Resize scales images from 0 to 255, thus we need
    # to divide by 255.0
    img = img.astype(float) / 255.0

    # NHWC -> NCHW
    img = img.transpose(2, 0, 1)
    img = np.reshape(img, (1, 3, 64, 64))
    img = torch.from_numpy(img).float().to(torch.device('cpu'))
    return img

def predict_sign_class(molel, img):
    class_gt = {0: 'Speed limit (20 km/h)',
                1: 'Speed limit (30 km/h)',
                2: 'Speed limit (50 km/h)',
                3: 'Speed limit (60 km/h)',
                4: 'Speed limit (70km/h)',
                5: 'Speed limit (80km/h)',
                6: 'End of speed limit (80 km/h)',
                7: 'Speed limit (100 km/h)',
                8: 'Speed limit (120 km/h)',
                9: 'No passing',
                10: 'No passing veh over 3.5 tons',
                11: 'Right-of-way at intersection',
                12: 'Priority road',
                13: 'Yield',
                14: 'Stop',
                15: 'No vehicles',
                16: 'Veh > 3.5 tons prohibited',
                17: 'No entry',
                18: 'General caution',
                19: 'Dangerous curve left',
                20: 'Dangerous curve right',
                21: 'Double curve',
                22: 'Bumpy road',
                23: 'Slippery road',
                24: 'Road narrows on the right',
                25: 'Road work',
                26: 'Traffic signals',
                27: 'Pedestrians',
                28: 'Children crossing',
                29: 'Bicycles crossing',
                30: 'Beware of ice/snow',
                31: 'Wild animals crossing',
                32: 'End speed + passing limits',
                33: 'Turn right ahead',
                34: 'Turn left ahead',
                35: 'Ahead only',
                36: 'Go straight or right',
                37: 'Go straight or left',
                38: 'Keep right',
                39: 'Keep left',
                40: 'Roundabout mandatory',
                41: 'End of no passing',
                42: 'End no passing veh > 3.5 tons'}

    if isinstance(img, str):
        img = m.imread(img)
    # plt.imshow(img)
    img = np.array(img, dtype=np.uint8)
    img = transform(img, (64, 64))
    feat_sem, feat_illu, feat_nowarp = molel.extract(img, is_warping=True)
    feature_exc = torch.cat((feat_sem, feat_illu), 1)
    # class for dataset GTSRB
    prob, pred_sup = torch.max(molel.classify(feature_exc), 1)
    result = class_gt[pred_sup.tolist()[0]]
    # print(pred_sup)
    return result

def load_sillnet(weights):
    model_sillnet = SillNet(nc=3, input_size=64, class_train=43, class_test=43, extract_chn=[100, 150, 200, 150, 100, 6], classify_chn=[
                            100, 150, 200, 250, 300, 100], param1=None, param2=None, param3=None, param4=[150, 150, 150, 150])
    model_sillnet.init_params(torch.load(weights, map_location=torch.device('cpu')))
    return model_sillnet

def make_prediction(model_1, model, img_path='', save_path='main/data/predicted'):
    im = imageio.imread(img_path)
    path = img_path.split('.')[0]
    img_name = img_path.split('.')[-1] + "_predicted.jpg"
    if not os.path.isdir(save_path):
        mode = 0o777
        os.makedirs(save_path, mode)
    predict_path = os.path.join(save_path, img_name)
    pred = model_1(im)
    pred_df = pred.pandas().xyxy[0]
    pred_df = pred_df.loc[pred_df.confidence > 0.4]
    results = []
    i=10
    for idx, row in pred_df.iterrows():
        # a = (int(row['xmin']), int(row['ymin']))
        # b = (int(row['xmax']), int(row['ymax']))
        # c = (int(row['xmin']), int(row['ymin']) - 10)
        # print(a,b)
        # 150:225, 410:485
        ymin = math.ceil(row['ymin'])
        ymax = math.ceil(row['ymax'])
        xmin = math.ceil(row['xmin'])
        xmax = math.ceil(row['xmax'])

        a = (xmin, ymin)
        b = (xmax, int(row['ymax']))
        c = (int(row['xmin']), ymax - i)
        print(f'{ymin}:{ymax},{xmin}:{xmax}')
        if (ymax) >150 and (xmax)>150:
            crop_img = im[ymin:ymax, xmin:xmax]
        else:
            crop_img = im
        #try to sharpen img
        kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
        crop_img = cv2.filter2D(crop_img, -1, kernel)
        #crop_img = im[151:223, 519:602]
        result = predict_sign_class(model, crop_img)
        results.append(result)
        # print(result)
        cv2.putText(im, result, c, cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36, 255, 12), 2)
        im = cv2.rectangle(im, a, b, (0, 255, 0), 1)
        # plt.figure(figsize=(100,100))
        i+=15
    imageio.imwrite(predict_path, im)
    final_result = ','.join(results)
    return predict_path, final_result
@st.cache(suppress_st_warning=True)
def load_models():
    dir_path = os.path.dirname(os.path.realpath(__file__))
    f_checkpoint = "best(4).pt"
    f_checkpoint_1 = "gtsrb2gtsrb_2021-11-27-144458_best.pth"
    listfile = os.listdir(dir_path)

    if f_checkpoint not in listfile:
        with st.spinner("Downloading model... this may take awhile! \n Don't stop it!"):
            url = 'https://drive.google.com/uc?id=1kznuazx4fO8starp_JONzAeAtWjRnZ3A'
            output = 'best(4).pt'
            gdown.download(url, output, quiet=True)
    if f_checkpoint_1 not in listfile:
        with st.spinner("Downloading model2... this may take awhile! \n Don't stop it!"):
            #download_file_from_google_drive('1i2E951VghoPQn-N742n8zE0_i3jPO-yy', f_checkpoint_1)
            url = 'https://drive.google.com/uc?id=1i2E951VghoPQn-N742n8zE0_i3jPO-yy'
            output = "gtsrb2gtsrb_2021-11-27-144458_best.pth"
            gdown.download(url, output, quiet=True)
    model_1 = torch.hub.load('ultralytics/yolov5', 'custom', path=f_checkpoint, force_reload=True) # default
    model = load_sillnet(f_checkpoint_1)
    return model_1,model

st.set_page_config(
    page_title="Traffic Sign DetectionðŸš¦",
)

@contextmanager
def st_redirect(src, dst):
    '''
        Redirects the print of a function to the streamlit UI.
    '''
    placeholder = st.empty()
    output_func = getattr(placeholder, dst)

    with StringIO() as buffer:
        old_write = src.write

        def new_write(b):
            if getattr(current_thread(), REPORT_CONTEXT_ATTR_NAME, None):
                buffer.write(b)
                output_func(buffer.getvalue())
            else:
                old_write(b)

        try:
            src.write = new_write
            yield
        finally:
            src.write = old_write

@contextmanager
def st_stdout(dst):
    '''
        Sub-implementation to redirect for code redability.
    '''
    with st_redirect(sys.stdout, dst):
        yield

@contextmanager
def st_stderr(dst):
    '''
        Sub-implementation to redirect for code redability in case of errors.
    '''
    with st_redirect(sys.stderr, dst):
        yield

def _all_subdirs_of(b='.'):
    '''
        Returns all sub-directories in a specific Path
    '''
    result = []
    for d in os.listdir(b):
        bd = os.path.join(b, d)
        if os.path.isdir(bd):
            result.append(bd)
    return result

def _get_latest_folder():
    '''
        Returns the latest folder in a runs\detect
    '''
    return max(_all_subdirs_of(os.path.join('runs', 'detect')), key=os.path.getmtime)

parser = argparse.ArgumentParser()
parser.add_argument('--weights', nargs='+', type=str, default='yolov5m.pt', help='model.pt path(s)')
parser.add_argument('--source', type=str, default='data\images', help='source')  # file/folder, 0 for webcam
parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')
parser.add_argument('--conf-thres', type=float, default=0.25, help='object confidence threshold')
parser.add_argument('--iou-thres', type=float, default=0.45, help='IOU threshold for NMS')
parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
parser.add_argument('--view-img', action='store_true', help='display results')
parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
parser.add_argument('--save-crop', action='store_true', help='save cropped prediction boxes')
parser.add_argument('--nosave', action='store_true', help='do not save images/videos')
parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3')
parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
parser.add_argument('--augment', action='store_true', help='augmented inference')
parser.add_argument('--update', action='store_true', help='update all models')
parser.add_argument('--project', default='runs/detect', help='save results to project/name')
parser.add_argument('--name', default='exp', help='save results to project/name')
parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
parser.add_argument('--line-thickness', default=3, type=int, help='bounding box thickness (pixels)')
parser.add_argument('--hide-labels', default=False, action='store_true', help='hide labels')
parser.add_argument('--hide-conf', default=False, action='store_true', help='hide confidences')
opt = parser.parse_args()
opt.weights = 'best(4).pt'
CHOICES = {0: "Image Upload"}

def _save_uploadedfile(uploadedfile):
    '''
        Saves uploaded videos to disk.
    '''
    with open(os.path.join("data", "videos", uploadedfile.name), "wb") as f:
        f.write(uploadedfile.getbuffer())

def _format_func(option):
    '''
        Format function for select Key/Value implementation.
    '''
    return CHOICES[option]

inferenceSource = str(st.sidebar.selectbox('Select Source to detect:',
                      options=list(CHOICES.keys()), format_func=_format_func))

if inferenceSource == '0':
    uploaded_file = st.sidebar.file_uploader("Upload Image", type=['jpg'])
    if uploaded_file is not None:
        is_valid = True
        with st.spinner(text='In progress'):
            st.sidebar.image(uploaded_file)
            picture = Image.open(uploaded_file)
            picture = picture.save(f'data/images/{uploaded_file.name}')
            opt.source = f'data/images/{uploaded_file.name}'
    else:
        is_valid = False
# else:
#     uploaded_file = st.sidebar.file_uploader("Upload Video", type=['mp4'])
#     if uploaded_file is not None:
#         is_valid = True
#         with st.spinner(text='In progress'):
#             st.sidebar.video(uploaded_file)
#             _save_uploadedfile(uploaded_file)
#             opt.source = f'data/videos/{uploaded_file.name}'
#     else:
#         is_valid = False

st.title('Welcome to Traffic Sign DetectionðŸš¦')

inferenceButton = st.empty()

if is_valid:
    if inferenceButton.button('Launch the Detection!'):
        # model_1 = torch.hub.load('ultralytics/yolov5', 'custom', path='best(4).pt', force_reload=True) # default
        # model = load_sillnet('sillnet/gtsrb2gtsrb_2021-11-27-144458_best.pth')
        with st_stdout("info"):
            model_1,model = load_models()
            predicted_img, results = make_prediction(model_1, model, opt.source)
            i=0
            speech = f"Please Attend a head Traffic Sign {results}"
            #print(speech)
            tts = gTTS(speech)
            filename = opt.source.split('.')[0]+'.mp3'
            filename =  'data/audio/'+filename.split('/')[-1]

            print(filename)
            tts.save(filename)
        if inferenceSource != '0':
            st.warning('Video playback not available on deployed version due to licensing restrictions. ')
            with st.spinner(text='Preparing Video'):
                for vid in os.listdir(_get_latest_folder()):
                    st.video(f'{_get_latest_folder()}/{vid}')
                st.balloons()
        else:
            with st.spinner(text='Preparing Images'):
                st.text(results)
                st.audio(filename)
                st.image(predicted_img)
                st.balloons()


class Solution:
    def findRestaurant(self, list1: List[str], list2: List[str]) -> List[str]:
        ans = []
        set1 = set(list1)&set(list2)
        leastSum = 1000000
        for word in set1:
            currentSum = list1.index(word)+list2.index(word)
            if currentSum<leastSum:
                ans.clear()
                ans.append(word)
                leastSum = currentSum
            elif currentSum==leastSum:
                ans.append(word)
        return ans

Minimum Index Sum of Two Lists/findRestaurant.py3


for i in range (1,100):
 iMod5 = i % 5 == 0
 if i % 3 == 0:
  if iMod5:
   print("FizzBuzz")
  else:
   print("Fizz")
 elif iMod5:
  print("Buzz")
 else:
  print(i)

#golf:

#BEGIN#
def e(i):
  f=i%5==0;p=print
  if i%3==0:
   if f:p("FizzBuzz")
   else:p("Fizz")
  elif f:p("Buzz")
  else:p(i)
i=1;exec("e(i);i+=1;"*100)
#END#


"""
Base for implementations of document classes alike to revtex.
"""

from .abstract_formatter import AbstractFormatter
from .fontsizes import DEFAULT_FONTSIZES

class RevtexLikeFormatter(AbstractFormatter):
    """
    A generic Formatter for revtex-like journals.

    Inherited classes should set the following:
      self._columnwidths
      self._wide_columnwidths

    """

    _columnwidths = {}
    _wide_columnwidths = {}

    def __init__(self, columns, paper, fontsize):
        """Sets up the plot with the fitting arguments so that the font sizes of the plot
        and the font sizes of the document are well aligned.

        Args:
            columns (str, optional):  the columns you used to set up your quantumarticle,
                either "onecolumn" or "twocolumn". Defaults to "twocolumn".
            paper (str, optional): the paper size you used to set up your quantumarticle,
                either "a4paper" or "letterpaper". Defaults to "a4paper".
            fontsize (int, optional): the fontsize you used to set up your quantumarticle,
                either 10, 11 or 12. Defaults to 10.
        """
        self.columns = columns
        self.paper = paper
        self.fontsize = fontsize

        super().__init__()

    @property
    def columnwidth(self):
        """columnwidth of the document."""
        return self._columnwidths[self.columns][self.paper]

    @property
    def wide_columnwidth(self):
        """Wide columnwidth of the document."""
        return self._wide_columnwidths[self.columns][self.paper]

    @property
    def fontsizes(self):
        """Fontsizes as specified by the underlying document."""
        return DEFAULT_FONTSIZES[self.fontsize]

    def __eq__(self, other):
        return (
            self.fontsize == other.fontsize
            and self.columns == other.columns
            and self.paper == other.paper
        )

class RevtexLikeParser:
    """Generic parser for revtex-like document classes.

    Args:
        documentclass_identifiers (List[string]): Strings identifying the supported document class.
        formatter_class (class): Class object describing the formatter.
    """

    # pylint: disable=too-few-public-methods

    def __init__(self, documentclass_identifiers, formatter_class):
        self.documentclass_identifiers = documentclass_identifiers
        self.formatter_class = formatter_class

    def __call__(self, preamble):
        """Parse the given preamble and extract the formatter.

        Args:
            preamble (string): Preamble of the target document.

        Returns:
            Union[NoneType,Formatter]: Either a formatter if the target document has the given
                document class or None.
        """
        # IDEA: Add support for regexes to support things like \documentclass[rmp,aps]{revtex4-1}
        for documentclass_identifier in self.documentclass_identifiers:
            if documentclass_identifier in preamble:
                return self.formatter_class(**self._extract_kwargs(preamble))

        return None

    @staticmethod
    def _extract_kwargs(preamble):
        r"""Parse the preamble to extract the informations relevant for plot style.

        Args:
            preamble (str): The preamble, containing at least the \documentclass command.

        Returns:
            Dict: formatter_kwargs (columns, paper, fontsize)
        """
        formatter_kwargs = {}

        if "onecolumn" in preamble:
            formatter_kwargs["columns"] = "onecolumn"
        else:
            formatter_kwargs["columns"] = "twocolumn"

        if "letterpaper" in preamble:
            formatter_kwargs["paper"] = "letterpaper"
        else:
            formatter_kwargs["paper"] = "a4paper"

        if "11pt" in preamble:
            formatter_kwargs["fontsize"] = 11
        elif "12pt" in preamble:
            formatter_kwargs["fontsize"] = 12
        else:
            formatter_kwargs["fontsize"] = 10

        return formatter_kwargs


from flask import Blueprint, jsonify, request, redirect
from flask_login import login_required, current_user
from datetime import datetime
from app.models import Comment, db
from app.forms.edit_comment_form import EditCommentForm

comment_routes = Blueprint('comments', __name__)

@comment_routes.route('/<int:id>', methods=['DELETE'])
@login_required
def delete_comment(id):
    comment = Comment.query.get(id)
    if not comment:
        return jsonify({"message": "Comment not found"}), 404
    if (current_user.id != comment.user_id):
        return redirect('/api/auth/unauthorized')
    db.session.delete(comment)
    db.session.commit()
    return {"id": comment.id}

@comment_routes.route("/<int:id>", methods=["PUT"])
@login_required
def update_comment_for_pin(id):
    form = EditCommentForm()
    form['csrf_token'].data = request.cookies['csrf_token']
    target_comment = Comment.query.get(id)
    if not target_comment:
        return jsonify({"message": "Comment not found"}), 404
    if (current_user.id != target_comment.user_id):
        return redirect('/api/auth/unauthorized')
    if form.validate_on_submit():
        target_comment.message = form.data["message"]
        db.session.commit()
        response = target_comment.to_dict()
        response["commenter"] = {
            "photo_url": target_comment.user.photo_url, "first_name": target_comment.user.first_name
        }
        return response
    if form.errors:
        print(form.errors)
        return form.errors


import math

class Pda:
    def __init__(self, model, **args):
        # initialize the super class
        super().__init__()

        # independent properties
        self.length = 10.0              # in mm
        self.diameter = 5.1            # in mm
        self.viscosity = 3.5          # in cP (Pa * s)
        self.velocity = 0
        self.velocity10 = 0

        # set the independent properties
        for key, value in args.items():
            setattr(self, key, value)

        # dependent properties
        self.res = 1.0                 # resistance in mmHg * s * l-1
        self.raw_flow = 0.0                # in l/s
        self.flow = 0.0            # in m/s

        # get a reference to the whole model
        self.model = model

        self.initialized = False
        self.delta_p = 0.0
        self.pda = {}

    def initialize(self):
        # get a reference to the ductus arteriosus blood connector
        self.pda = self.model.components['DA']

        # initialization is now complete
        self.initialized = True

    def model_step(self):
        # enable or disable the DA connector depending on the state of the pda model
        self.model.components['DA'].is_enabled = self.is_enabled

        # if the Pda model is enabled then initialize the model if not done before, otherwise calculate the resistance of the duct.
        if self.is_enabled:
            if self.initialized:
                self.calculate_resistance()
            else:
                self.initialize()

    def calculate_resistance(self):
        # calculate the resistance of the ductus arteriousus where
        # the duct is modeled as a perfect tube with a diameter and a length in millimeters
        # the viscosity is in centiPoise

        # resistance is calculated using Poiseuille's Law : R = (8 * n * L) / (PI * r^4)

        # we have to watch the units carefully where we have to make sure that the units in the formula are
        # resistance is in mmHg * s / l
        # L = length in meters from millimeters
        # r = radius in meters from millimeters
        # n = viscosity in mmHg * s from centiPoise

        # convert viscosity from centiPoise to mmHg * s
        n_mmhgs = self.viscosity * 0.001 * 0.00750062

        # convert the length to meters
        length_meters = self.length / 1000.0

        # calculate the radius in meters
        radius_meters = (self.diameter / 2) / 1000.0

        # calculate the resistance using Poiseuille's Law, the resistance is now in mmHg * s/mm^3
        self.res = (8.0 * n_mmhgs * length_meters) / (math.pi * math.pow(radius_meters, 4))

        # convert resistance of mmHg * s / mm^3 to mmHg *s / l
        self.res = self.res / 1000.0

        # transfer the resistance to the ductus arteriosus blood connector and enable flow
        self.pda.no_flow = not self.is_enabled
        self.pda.r_for = self.res
        self.pda.r_back = self.res

        # store the pda flow in l / s
        self.flow = self.pda.flow

        # calculate the velocity in m/s, for that we have to convert the flow to mm^3/sec
        # velocity = flow_rate (in mm^3/s) / (pi * radius^2)     in m/s
        self.velocity = (self.pda.flow / 1000.0) / (math.pi * math.pow(radius_meters, 2.0))
        self.velocity10 = self.velocity * 10.0


import wx.lib.ogl as ogl
from myhdl import Signal, always
from MyHDLSim.combinational import Or
from MyHDLSim.Wrappers.GenericGateWrapper import GenericGateWrapper

class OrGateShape(ogl.PolygonShape):
    """ This shape is used exclusively to contruct the OR Gate main shape.
        The shape is initially based within an 80x80 square, centered """
    def __init__(self):
        ogl.PolygonShape.__init__(self)

        points = [ (-40, 40),
                   (20, 40),
                   (40, 0),
                   (20, -40),
                   (-40, -40),
                   (-30,-20),
                   (-30,20) ]

        self.Create(points)
        self.CalculatePolygonCentre
        self.AddText("Or")
        self.SetRegionName("Or")

class OrGateWrapper(GenericGateWrapper):
    """ This class wraps a MyHDLSim.combinational.OR function for drawing """

    def __init__(self, drawManager, x, y, out, a, b, c = None, d = None):
        GenericGateWrapper.__init__(self, drawManager, x, y, [a,b,c,d], OrGateShape(), out)
        self._CreateInstance(Or, out, a, b, c, d)

        GenericGateWrapper._connectWires(self, drawManager)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import session, jsonify, render_template, request

import math
from random import randint
import random

from bson.objectid import ObjectId

from classroom import app
from classroom import db

@app.route("/classroom/quiz/tests/<test_id>/", methods=["GET"])
def get_test_to_add_questions(test_id):
    test = db.tests.find_one({"_id": ObjectId(test_id)})

    questions = []
    for id in test["questions"]:
        question = db.questions.find_one({"_id": ObjectId(id)})
        questions.append(question)

    return render_template("quiz/tests/add_questions_to_test.html", test=test, questions=questions)

#Redirecionando para dashboard
@app.route("/classroom/quiz/tests/", methods=["GET"])
def dashboard():
        if "_id" in session:
            return render_template("quiz/tests/create_test.html")
        else:
            return render_template("errors/403.html")

#removendo um teste
@app.route("/quiz/tests/<test_id>/", methods=["DELETE"])
def remove_test(test_id):
    db.tests.remove( {"_id": ObjectId(test_id)} )
    #removendo respostas relacionadas ao teste
    db.answers.remove( {"test._id": ObjectId(test_id)} )

    return "OK"

#Retornando todas as questões por tópico
@app.route("/quiz/tests/<course>/<topic>/", methods=["POST"])
def create_test(course, topic):
    number = int(request.form.get("number")) #Número de questões
    type = request.form.get("type"); #Tipo de questão
    #Esta pode ser melhorada
    level = [{ "name" : "easy", "percentage" : float(request.form.get("easy")) },
            { "name" : "medium", "percentage" : float(request.form.get("medium")) },
            { "name" : "difficult", "percentage" : float(request.form.get("hard")) }]

    questions = []

    i = 0
    while(i < 3):
        amount = int((level[i]["percentage"] / 100) * number)

        print(amount)

        if amount != 0:

            result = db.questions.find({
                "topic._id" : ObjectId(topic),
                "level" : level[i]["name"],
                "type": type,
                "private": "false"
            }).limit(amount)

            for item in result:
                if item["_id"]:
                    item["_id"] = str(item["_id"])
                    item["topic"]["_id"] = str(item["topic"]["_id"])
                    item["topic"]["course"]["_id"] = str(item["topic"]["course"]["_id"])
                questions.append(item)

        i = i + 1

    return jsonify(questions)

#Criando teste
@app.route("/quiz/tests/", methods=["POST"])
def save_test():
    name = request.form.get("name")
    description = request.form.get("description")
    num_attempts = request.form.get("numAttempts")
    time = request.form.get("ntime")

    questions = request.form.getlist("questions[]")

    creator = db.users.find_one(
              {
                "email" : session["email"]
              })

    db.tests.insert_one({
        "name": name,
        "description": description,
        "creator": creator,
        "classes": [],
        "questions": questions,
        "numAttempts": num_attempts,
        "time": time
    })

    return "OK"

#Compartilhando teste
@app.route("/quiz/tests/<test_id>/classes/", methods=["PUT"])
def share_test(test_id):
    title = request.form.get("title")
    description = request.form.get("description")
    deadline = request.form.get("deadline")
    classe_id = request.form.get("classe")

    classe = db.classes.find_one( {"_id": ObjectId(classe_id)} )

    db.tests.update({"_id" : ObjectId(test_id)},{"$addToSet": {"classes": classe}})

    test = db.tests.find_one( {"_id": ObjectId(test_id)} )

    db.tasks.insert({
        "title": title,
        "description": description,
        "deadline": deadline,
        "class": classe,
        "test": test
    })

    return "OK"

#atualizando as informações do teste
@app.route("/quiz/tests/<test_id>/", methods=["PUT"])
def update_test(test_id):
    name = request.form.get("name")
    description = request.form.get("description")
    num_attempts = request.form.get("numAttempts")
    time = request.form.get("ntime")

    questions = request.form.getlist("questions[]")

    db.tests.update({"_id": ObjectId(test_id)},
    {"$set": {
        "name": name,
        "description": description,
        "classes": [],
        "questions": questions,
        "numAttempts": num_attempts,
        "time": time
            }
    })

    return "OK"

#Retornando um teste pelo ID
@app.route("/classroom/quiz/tests/<test_id>/answers/", methods=["GET"])
def test(test_id):
    try:
        test = db.tests.find_one(
               {
                    "_id" : ObjectId(test_id)
               })

        if str(test["creator"]["_id"]) == session["_id"]:
            test["_id"] = str(test["_id"])
            test["creator"]["_id"] = str(test["creator"]["_id"])

            questions = []

            for id in test["questions"]:
                question = db.questions.find_one({"_id": ObjectId(id)})

                if question["type"] == "multipleChoice":
                    questions.append({
                        "_id": str(question["_id"]),
                        "title": question["title"],
                        "type": question["type"],
                        "correctAnswer": question["correctAnswer"],
                        "choices": question["choices"]
                    })
                else:
                    questions.append({
                        "_id": str(question["_id"]),
                        "title": question["title"],
                        "type": question["type"],
                        "correctAnswer": question["correctAnswer"]
                    })

            answers = db.answers.find(
                      {
                        "test._id" : ObjectId(test_id)
                      })

            return render_template("quiz/tests/verify_test.html", test=test, answers=answers, questions=questions)
    except Exception as e:
        return render_template("errors/403.html")

#enviando uma nova answer
@app.route("/quiz/tests/<test_id>/answers/", methods=["POST"])
def send_answer(test_id):
    #verificando se existir uma resposta anterior
    last_answer = db.answers.find_one({
        "test._id": ObjectId(test_id),
        "user._id": ObjectId(session["_id"])
    })

    if last_answer:
        num_attempts = int(last_answer["numAttempts"]) + 1
        db.answers.update({"_id": last_answer["_id"]}, {"$inc": {"numAttempts": 1}})

    else:
        num_attempts = 1

    answers = request.form.getlist("answers[]")
    values = request.form.getlist("values[]")

    test = db.tests.find_one(
           {
                "_id" : ObjectId(test_id)
           })

    user = db.users.find_one(
           {
                "_id" : ObjectId(session["_id"])
           })

    num_questions = len(test["questions"])
    num_correct_questions = 0

    questions = []

    #analisando se a questão está certa
    for answer, value in zip(answers, values):
        for id in test["questions"]:
            question = db.questions.find_one({"_id": ObjectId(id)})

            if value == str(question["_id"]):
                question["answer"] = answer
                questions.append(question)

                if question["type"] == "trueOrFalse" or question["type"] == "multipleChoice":
                    if question["correctAnswer"] == question["answer"]:
                        num_correct_questions += 1

    if num_questions == 0:
        grade = 0
    else:
        grade = num_correct_questions / num_questions * 10

    if last_answer:
        if last_answer["grade"] > grade:
            return "OK"
        else:
            #apagando resposta anterior
            db.answers.remove({"_id": last_answer["_id"]})

    #salvando resposta no BD
    db.answers.insert({
        "user": user,
        "test": test,
        "grade": grade,
        "numAttempts": num_attempts,
        "answers": questions
    })

    return "OK"

'''
#Retornando um teste pelo ID
@app.route("/classroom/quiz/classes/<class_id>/tests/<test_id>/", methods=["GET"])
def get_test_by_id(class_id, test_id):
    try:
        turma = db.classes.find_one( {"_id": ObjectId(class_id)} )
        test = db.tests.find_one( {"_id": ObjectId(test_id)} )

    except:
        return render_template("errors/404.html"), 404

    user = db.users.find_one({"_id": ObjectId(session["_id"])})

    classe = db.classes.find_one( {"_id": ObjectId(turma["_id"]), "participants": {"$in": [ObjectId(user["_id"])]}} )

    if classe == None:
        return render_template("errors/403.html"), 403

    answer = db.answers.find_one({"user._id": ObjectId(session["_id"]), "test._id": test["_id"]})

    num_attempts = int(test["numAttempts"])

    if answer:
        num_attempts -= int(answer["numAttempts"])

        if num_attempts == 0:
            return render_template("errors/403.html"), 403

    test["_id"] = str(test["_id"])
    test["creator"]["_id"] = str(test["creator"]["_id"])

    questions = []
    for id in test["questions"]:
        item = db.questions.find_one({"_id": ObjectId(id)})

        if item["_id"]:
            item["_id"] = str(item["_id"])
            item["topic"]["_id"] = str(item["topic"]["_id"])
            item["topic"]["course"]["_id"] = str(item["topic"]["course"]["_id"])
            if item["type"] == "multipleChoice" or item["type"] == "trueOrFalse":
                random.shuffle(item["choices"])
        questions.append(item)

    test["questions"] = questions

    return render_template("quiz/tests/answer_test.html", test=test, num_attempts=num_attempts)
'''

#Retornando um teste pelo ID
@app.route("/classroom/quiz/classes/<class_id>/tests/<test_id>/", methods=["GET"])
def get_test_by_id(class_id, test_id):
    try:
        user = db.users.find_one({"_id": ObjectId(session["_id"])})
        classe = db.classes.find_one( {"_id": ObjectId(class_id), "participants": {"$in": [ObjectId(user["_id"])]}} )
        test = db.tests.find_one( {"_id": ObjectId(test_id)} )

    except:
        return render_template("errors/404.html"), 404

    if classe == None:
        return render_template("errors/403.html"), 403

    attempt = db.attempts.find_one({"user": user["_id"], "test": test["_id"]})

    print(attempt)

    if attempt:
        db.attempts.update(
            {"_id": attempt["_id"]},
            { "$inc": { "number": 1}
        })
        print(test["numAttempts"])
        if(( attempt["number"] + 1 ) > int(test["numAttempts"])):
            return render_template("errors/403.html")

        num_attempts=(int(test["numAttempts"]) - attempt["number"])

    else:
        db.attempts.insert({"user": user["_id"], "test": test["_id"], "number": 1})
        num_attempts=(int(test["numAttempts"]) - 1)

    answer = db.answers.find_one({"user._id": ObjectId(session["_id"]), "test._id": test["_id"]})

    test["_id"] = str(test["_id"])
    test["creator"]["_id"] = str(test["creator"]["_id"])

    questions = []
    for id in test["questions"]:
        item = db.questions.find_one({"_id": ObjectId(id)})

        if item["_id"]:
            item["_id"] = str(item["_id"])
            item["topic"]["_id"] = str(item["topic"]["_id"])
            item["topic"]["course"]["_id"] = str(item["topic"]["course"]["_id"])
            if item["type"] == "multipleChoice" or item["type"] == "trueOrFalse":
                random.shuffle(item["choices"])
        questions.append(item)

    test["questions"] = questions

    return render_template("quiz/tests/answer_test.html", test=test, num_attempts=num_attempts)

#retornando testes criados
@app.route("/classroom/tests/", methods=["GET"])
def get_all_tests():
    result = db.tests.find({"creator._id": ObjectId(session["_id"])})

    tests = []

    for t in result:
        tests.append({"_id": str(t["_id"]), "name": t["name"]})

    return jsonify(tests)


from django.urls import path
from .views import WebsiteList, ReScrape, ArticleList, ScrapingHistoryList

urlpatterns = [
    path('websites/', WebsiteList.as_view()),
    path('re-scrape/<int:pk>/', ReScrape.as_view()),
    path('articles/', ArticleList.as_view()),
    path('scraping_history/', ScrapingHistoryList.as_view()),

]


# coding=utf-8
from time import mktime
from APISender import APISender
from django.conf import settings
from base.APIConstants import Constants
from base.APIMessage import PushMessage
from biz.constants import APP_JUMP_OBEJCT_NEWS, APP_JUMP_OBEJCT_HOT_VIDEO

if settings.ENVIRONMENT == settings.PRODUCTION:
    Constants.use_official()
else:
    Constants.use_sandbox()

android_sender = APISender(settings.XIAOMI_PUSH_APP_SECRET_ANDROID)
ios_sender = APISender(settings.XIAOMI_PUSH_APP_SECRET_IOS)

def broadcast_news(news):
    return broadcast_message(news.title, f'{APP_JUMP_OBEJCT_NEWS}:{news.id}', start_time=news.start_time,
                             end_time=news.end_time)

def broadcast_hot_video(hot_video):
    return broadcast_message(hot_video.name, f'{APP_JUMP_OBEJCT_HOT_VIDEO}:{hot_video.id}', start_time=hot_video.start_time,
                             end_time=hot_video.end_time)

def push_message(mobile, content, jump_to=None, start_time=None, end_time=None):
    user_alias = mobile

    android_msg = _build_message(content, jump_to, start_time, end_time, 'android')
    android_sender.send_to_alias(android_msg.message_dict(), user_alias)

    ios_msg = _build_message(content, jump_to, start_time, end_time, 'ios')
    ios_sender.send_to_alias(ios_msg.message_dict_ios(), user_alias)

def broadcast_message(content, jump_to=None, start_time=None, end_time=None):
    android_msg = _build_message(content, jump_to, start_time, end_time, 'android')
    android_sender.broadcast_all(android_msg.message_dict())

    ios_msg = _build_message(content, jump_to, start_time, end_time, 'ios')
    ios_sender.broadcast_all(ios_msg.message_dict_ios())

def _build_message(content, jump_to, start_time, end_time, device):
    msg = PushMessage().title('拳城出击').description(content).extra({'jump_to': jump_to}).restricted_package_name(
        settings.ANDROID_PACKAGE_NAME)
    if device == 'android':
        msg.payload(content).notify_type(1)
    else:
        msg.restricted_package_name(
            settings.IOS_PACKAGE_NAME)
    if start_time:
        msg.time_to_send(int(mktime(start_time.timetuple())) * 1000)
    if end_time:
        msg.time_to_live((end_time - start_time).microseconds)
    return msg


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def oddEvenList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if head is None:
            return head

        eh = None
        ep = None

        p = head
        t = None

        while p != None:
            if eh == None:
                eh = p.next
                ep = eh
            else:
                ep.next = p.next
                ep = ep.next

            if p.next is not None:
                p.next = p.next.next

            t = p
            p = p.next

        t.next = eh
        return head

problems/328. Odd Even Linked List/solution.py