import unittest
from random import randint
import os

def preberi(ime_datoteke):
    vhod = open(ime_datoteke, "r")
    slovar = {}
    nov = []
    for b in vhod:
        nov.append(b.split())       #da se znebimo vsega shita, ki ga branje iz txt datoteke namece

    i = 1           #stevc za kljuce slovarja
    for a in nov:
        b = []
        for c in a:                     #vrednosti seznama a, ki so string, shranimo kot int v nov seznam b
            b.append(int(c))

        g = b.index(min(b))         #v g se shrani indeks od najmanjse vrednosti v b (min ne dela s stringi)
        ns = []
        h = 0
        while h < 2:                    #nacin za sortiranje od min naprej:
            while g < len(b):
                if b[g] not in ns:
                    ns.append(b[g])
                g += 1
            h += 1
            g = 0

        slovar[i] = ns
        i += 1
    return slovar

def mozna_pot(pot, zemljevid):
    dolzina = len(pot) -1
    if len(zemljevid[pot[0]]) != 1 or len(zemljevid[pot[dolzina]]) != 1:
        return False

    pot2 = pot[1:-1]        #ce gre vmes ven
    for a in pot2:
        if len(zemljevid[a]) == 1 :
            return False

    c = 1
    for a in pot:               #ce se krizisce ponovi
        if c < len(pot):
            if a == pot[c]:
                return False
            c += 1

    i = 1
    for a in pot:        #ce ni povezave:
        if i<len(pot):
            if pot[i] not in zemljevid[a]:
                return False
        i += 1
    return True

def hamiltonova(pot, zemljevid):
    if not (mozna_pot(pot,zemljevid)):
        return False

    ponovitve = []
    for a in pot:
        if a not in ponovitve:
            ponovitve.append(a)
        else:
            return False

    krozisca = []
    for a in zemljevid:
        if len(zemljevid[a]) != 1:
            krozisca.append(a)

    for a in krozisca:
        if a not in pot:
            return False
    return True

def navodila(pot, zemljevid):
    navodila = []
    for i, a in enumerate(pot[1:-1]):
        seznam = zemljevid[a]
        prejsnja = pot[i]
        if i+1<len(pot[1:]):
            naslednja = pot[1:][i+1]

        i_prejsnje = seznam.index(prejsnja)
        i_naslednje = seznam.index(naslednja)

        razlika = i_naslednje - i_prejsnje
        izvoz = razlika % len(seznam)
        navodila.append(izvoz)
    return navodila

def prevozi(zacetek, navodila, zemljevid):
    pot = []
    pot.append(zacetek)
    a = zemljevid[zacetek]
    for b in a:
        pot.append(b)

    for i, a in enumerate(navodila):
        seznam = zemljevid[pot[i+1]]
        prejsnji = pot[i]

        i_prejsnji = seznam.index(prejsnji)
        i_naslednji = (i_prejsnji + a) - len(seznam)
        naslednji = seznam[i_naslednji]

        pot.append(naslednji)
    return pot

class Test06(unittest.TestCase):
    maxDiff = 100000

    def test_01_preberi(self):
        self.assertEqual(
            preberi("zemljevid.txt"),
            {1: [3],
             2: [4],
             3: [1, 8, 7, 6, 4],
             4: [2, 3, 6, 5],
             5: [4, 11, 10],
             6: [3, 11, 4],
             7: [3, 8, 11],
             8: [3, 16, 9, 7],
             9: [8, 16, 14, 11],
             10: [5, 11, 13],
             11: [5, 6, 7, 9, 14, 10],
             12: [13],
             13: [10, 14, 12],
             14: [9, 16, 13, 11],
             15: [16],
             16: [8, 15, 14, 9]})

        fname = "z{:05}.bla".format(randint(10000, 99999))
        with open(fname, "w") as f:
            f.write("2\n3 1\n2")
        try:
            self.assertEqual(preberi(fname), {1:[2], 2: [1, 3], 3: [2]})
        finally:
            try:
                os.remove(fname)
            except:
                print("Ne morem pobrisati {}. (Je na Dropboxu?) Briši sam(a).".format(fname))

    def test_02_mozna_pot(self):
        zemljevid = preberi("zemljevid.txt")
        self.assertTrue(mozna_pot([1, 3, 7, 3, 4, 2], zemljevid))
        self.assertTrue(mozna_pot([1, 3, 7, 3, 4, 2][::-1], zemljevid))
        self.assertTrue(mozna_pot([1, 3, 7, 3, 4, 5, 4, 3, 1], zemljevid))
        self.assertTrue(mozna_pot([1, 3, 7, 3, 4, 5, 4, 3, 1][::-1], zemljevid))
        self.assertTrue(mozna_pot([1, 3, 8, 16, 15], zemljevid))
        self.assertTrue(mozna_pot([1, 3, 8, 16, 15][::-1], zemljevid))
        self.assertTrue(mozna_pot([15, 16, 15], zemljevid))

        # Ne začne/konča se na vhodih/izhodih
        self.assertFalse(mozna_pot([1, 3, 7, 11, 14, 16], zemljevid))
        self.assertFalse(mozna_pot([3, 7, 11, 14, 16, 15], zemljevid))

        # Vmes gre ven
        self.assertFalse(mozna_pot([1, 3, 6, 4, 2, 4, 5, 11, 14, 13, 12], zemljevid))
        self.assertFalse(mozna_pot([1, 3, 6, 4, 2, 2, 4, 5, 11, 14, 13, 12], zemljevid))

        # Ponovi eno križišče
        self.assertFalse(mozna_pot([1, 3, 8, 8, 16, 15], zemljevid))

        # Ni povezave
        self.assertFalse(mozna_pot([1, 3, 16, 15], zemljevid))
        self.assertFalse(mozna_pot([1, 15], zemljevid))

        zemljevid2 = {1: [2], 2: [1, 3], 3: [2]}
        self.assertTrue(mozna_pot([1, 2, 3], zemljevid2))
        self.assertFalse(mozna_pot([1, 3], zemljevid2))

        zemljevid2 = {1: [2], 2: [1, 3], 3: [2, 4], 4: [3]}
        self.assertTrue(mozna_pot([1, 2, 3, 4], zemljevid2))
        self.assertTrue(mozna_pot([4, 3, 2, 1], zemljevid2))
        self.assertFalse(mozna_pot([1, 3, 4], zemljevid2))
        self.assertFalse(mozna_pot([1, 4], zemljevid2))

    def test_03_hamiltonova(self):
        zemljevid = preberi("zemljevid.txt")
        self.assertTrue(hamiltonova([1, 3, 7, 8, 16, 9, 14, 11, 6, 4, 5, 10, 13, 12], zemljevid))
        self.assertTrue(hamiltonova([1, 3, 7, 8, 16, 9, 14, 11, 6, 4, 5, 10, 13, 12][::-1], zemljevid))

        # Ena manjka
        self.assertFalse(hamiltonova([1, 3, 8, 16, 9, 14, 11, 6, 4, 5, 10, 13, 12], zemljevid))

        # Ni začetka/konca
        self.assertFalse(hamiltonova([3, 8, 16, 9, 14, 11, 6, 4, 5, 10, 13, 12], zemljevid))
        self.assertFalse(hamiltonova([1, 3, 7, 8, 16, 9, 14, 11, 6, 4, 5, 10, 13], zemljevid))

        # Ponavljenje
        self.assertFalse(hamiltonova([1, 3, 8, 16, 9, 14, 11, 6, 4, 5, 10, 11, 14, 13, 12], zemljevid))
        self.assertFalse(hamiltonova([1, 3, 7, 8, 16, 9, 14, 11, 6, 3, 4, 5, 10, 13, 12], zemljevid))

        zemljevid2 = {1: [2], 2: [1, 3], 3: [2, 4], 4: [3]}
        self.assertTrue(hamiltonova([1, 2, 3, 4], zemljevid2))
        self.assertTrue(hamiltonova([4, 3, 2, 1], zemljevid2))
        self.assertFalse(hamiltonova([1, 2, 4], zemljevid2))

class Test07(unittest.TestCase):
    maxDiff = 100000

    def test_01_navodila(self):
        zemljevid = preberi("zemljevid.txt")
        self.assertEqual(navodila([1, 3, 8, 16, 15], zemljevid), [1, 1, 1])
        self.assertEqual(navodila([1, 3, 6, 4, 2], zemljevid), [3, 2, 2])
        self.assertEqual(navodila([1, 3, 6, 11, 14, 16, 15], zemljevid), [3, 1, 3, 2, 3])
        self.assertEqual(navodila([12, 13, 14, 11, 9, 8, 7, 3, 4, 2], zemljevid), [2, 1, 5, 1, 1, 2, 2, 3])
        self.assertEqual(navodila([2, 4, 2], zemljevid), [0])
        self.assertEqual(navodila([15, 16, 14, 11, 9, 16, 14, 11, 9, 16, 15], zemljevid), [1, 2, 5, 2, 3, 2, 5, 2, 2])

class Test08(unittest.TestCase):
    maxDiff = 100000

    def test_01_prevozi(self):
        zemljevid = preberi("zemljevid.txt")
        self.assertEqual(prevozi(1, [1, 1, 1], zemljevid), [1, 3, 8, 16, 15])
        self.assertEqual(prevozi(1, [3, 2, 2], zemljevid), [1, 3, 6, 4, 2])
        self.assertEqual(prevozi(1, [3, 1, 3, 2, 3], zemljevid), [1, 3, 6, 11, 14, 16, 15])
        self.assertEqual(prevozi(12, [2, 1, 5, 1, 1, 2, 2, 3], zemljevid), [12, 13, 14, 11, 9, 8, 7, 3, 4, 2])
        self.assertEqual(prevozi(2, [0], zemljevid), [2, 4, 2])
        self.assertEqual(prevozi(15, [1, 2, 5, 2, 3, 2, 5, 2, 2], zemljevid), [15, 16, 14, 11, 9, 16, 14, 11, 9, 16, 15])

class Test09(unittest.TestCase):
    maxDiff = 100000

    def test_01_sosedi(self):
        zemljevid = preberi("zemljevid.txt")
        self.assertEqual(sosedi({15}, zemljevid), {16})
        self.assertEqual(sosedi({15, 16}, zemljevid), {14, 9, 8})
        self.assertEqual(sosedi({15, 16, 14, 9, 8}, zemljevid), {3, 7, 11, 13})
        self.assertEqual(sosedi({15, 16, 14, 9, 8, 3, 7, 11, 13}, zemljevid), {1, 4, 6, 5, 10, 12})
        self.assertEqual(sosedi({15, 16, 14, 9, 8, 3, 7, 11, 13, 1, 4, 6, 5, 10, 12}, zemljevid), {2})
        self.assertEqual(sosedi({15, 16, 14, 9, 8, 3, 7, 11, 13, 1, 4, 6, 5, 10, 12, 2}, zemljevid), set())

        self.assertEqual(sosedi({6}, zemljevid), {4, 3, 11})
        self.assertEqual(sosedi({6, 4, 3, 11}, zemljevid), {2, 5, 1, 7, 8, 9, 14, 10})

    def test_02_razdalja(self):
        zemljevid = preberi("zemljevid.txt")
        self.assertEqual(razdalja(15, 16, zemljevid), 1)

        self.assertEqual(razdalja(15, 14, zemljevid), 2)
        self.assertEqual(razdalja(15, 9, zemljevid), 2)
        self.assertEqual(razdalja(15, 8, zemljevid), 2)

        self.assertEqual(razdalja(15, 7, zemljevid), 3)
        self.assertEqual(razdalja(15, 13, zemljevid), 3)

        self.assertEqual(razdalja(15, 5, zemljevid), 4)
        self.assertEqual(razdalja(15, 10, zemljevid), 4)

        self.assertEqual(razdalja(15, 2, zemljevid), 5)

        self.assertEqual(razdalja(6, 4, zemljevid), 1)
        self.assertEqual(razdalja(6, 5, zemljevid), 2)
        self.assertEqual(razdalja(6, 10, zemljevid), 2)
        self.assertEqual(razdalja(6, 13, zemljevid), 3)
        self.assertEqual(razdalja(6, 12, zemljevid), 4)

class Test10(unittest.TestCase):
    maxDiff = 100000

    def test_01_najkrajsa_pot(self):
        zemljevid = preberi("zemljevid.txt")
        self.assertEqual(najkrajsa_navodila(1, 15, zemljevid), [1, 1, 1])
        self.assertEqual(najkrajsa_navodila(1, 2, zemljevid), [4, 3])
        self.assertEqual(najkrajsa_navodila(2, 15, zemljevid), [1, 2, 1, 1])
        self.assertEqual(najkrajsa_navodila(2, 12, zemljevid), [3, 2, 2, 2])
        self.assertEqual(najkrajsa_navodila(15, 12, zemljevid), [1, 1, 1])

        self.assertEqual(najkrajsa_navodila(15, 1, zemljevid), [3, 3, 4])
        self.assertEqual(najkrajsa_navodila(2, 1, zemljevid), [1, 1])
        self.assertEqual(najkrajsa_navodila(15, 2, zemljevid), [3, 3, 3, 3])
        self.assertEqual(najkrajsa_navodila(12, 2, zemljevid), [1, 1, 1, 1])
        self.assertEqual(najkrajsa_navodila(12, 15, zemljevid), [2, 3, 3])

        navodila = najkrajsa_navodila(1, 12, zemljevid)
        self.assertEqual(len(navodila), 5)
        self.assertEqual(prevozi(1, navodila, zemljevid)[-1], 12)

        navodila = najkrajsa_navodila(12, 1, zemljevid)
        self.assertEqual(len(navodila), 5)
        self.assertEqual(prevozi(12, navodila, zemljevid)[-1], 1)

if __name__ == "__main__":
    unittest.main()


"""
13. Write a program that lets the user play Rock-Paper-Scissors against the computer. There
should be five rounds, and after those five rounds, your program should print out who won
and lost or that there is a tie.
"""
import random

rsp = ['r','s','p']

player_win = 0

computer_win= 0

for i in range(5):
 p = input('Enter <r>ock,<s>cissor or <p>aper:')
 c = rsp[random.randint(0,2)]

 if(  ( (p=='r')and(c=='r') ) or ( (p=='s')and(c=='s') ) or ( (p=='p')and(c=='p') )):
  print('You:',p,' Computer:',c,' Is a draw',sep='')

 elif(  ( (p=='r')and(c=='s') ) or ( (p=='s')and(c=='p') ) or ( (p=='p')and(c=='r') )):
  print('You:',p,' Computer:',c,' You win!',sep='')
  player_win += 1

 else:
  print('You:',p,' Computer:',c,' You lose',sep='')
  computer_win += 1

print()

if(player_win > computer_win):print("You're a winner!","Total win:",player_win,"Computer total win:",computer_win)

elif(computer_win > player_win ):print("You lose!","Total win:",player_win,"Computer total win:",computer_win)

else:print("Is a draw game","Total win:",player_win,"Computer total win:",computer_win)


from PIL import Image
import streamlit as st

st.title('Manitoba Lottery App :chart_with_downwards_trend:')

image = Image.open('images/649.png')
st.image(image, width=256)

options, actual, costs = st.columns(3)
choices = ('Bi-weekly', 'Weekly', 'Monthly')

# first column
with options:
    frequency = st.selectbox(
    'How often do you play the lottery?', choices)
    num_tickets = st.slider('How many tickets do you buy?', 1, 24, 1)
    num_years = st.slider('How many years have you played?', 1, 100, 1)
    plays_extra = st.checkbox('Do you play Extra?')

# second column
with actual:
    st.subheader('Realistic Loss')
    weekly_loss = -3.9928 if plays_extra else -2.9928

    if frequency == 'Bi-weekly':
        weekly_loss *= 2 * num_tickets
        st.metric(label="Bi-weekly Loss", value=f"${weekly_loss:.2f}", delta=f"-${weekly_loss*0.9184:.2f}")
    elif frequency == 'Weekly':
        weekly_loss *= num_tickets * num_tickets
        st.metric(label="Weekly Loss", value=f"${weekly_loss:.2f}", delta=f"-${weekly_loss*0.9184:.2f}")
    else:
        weekly_loss *= 0.25 * num_tickets
        st.metric(label="Monthly Loss", value=f"${weekly_loss:.2f}", delta=f"-${weekly_loss*0.9184:.2f}")

    yearly_loss = weekly_loss * 52
    st.metric(label="Yearly Loss", value=f"${yearly_loss:.2f}", delta=f"-${yearly_loss*0.9184:.2f}")
    term_loss = weekly_loss*52*num_years
    st.metric(label=f"{num_years} Year Loss", value=f"${term_loss:.2f}", delta=f"-${term_loss*0.9184:.2f}")

with costs:
    st.subheader('What did I Miss?')
    st.metric(label="Cups of Cofee", value=f"{weekly_loss / 2:.2f} â˜•",
                delta=f"{weekly_loss/2*0.9184:.2f}")
    st.metric(label="Iphone SE", value=f"{yearly_loss / 600:.2f} ðŸ“±",
                delta=f"{yearly_loss/600*0.9184:.2f}")
    st.metric(label="Used Cars ", value=f"{term_loss / 8000:.2f} ðŸš—",
                delta=f"{term_loss/8000*0.9184:.2f}")

caption = '''
Realistic Losses are based on the average cost of a ticket and the average chance of winning
over a typical persons lifespan of 85 years. This assumes that you play the lottery from the age of
18 to 85, and that you play the lottery bi-weekly and buy the maximum number of tickets allowed my MB lottery
which is 25 tickets per draw. Theoretical losses are shown in red underneath the values.
These values are based on the average cost of a ticket and the average chance of winning over billions of
iterations, unrealistic for us but takes into account winning the jackpot multiple times and the payout.
'''
st.caption(caption)
st.markdown("***")

st.subheader('Source Code')
with open('code/lottery.py', 'r') as f:
    code = f.read()

st.code(code, language='python')


import os
import subprocess
from tqdm import tqdm
import shutil

def get_rna_ss_fea(rnaID, rna_seq, out_prefix):
    '''to compute structure features of rnas and proteins'''

    rna_out = os.path.join(out_prefix, "lncRNA_Structure_features")
    if os.path.exists(rna_out):
        os.remove(rna_out)

    features_workdir = os.path.join(out_prefix, "features_workdir")
    if os.path.exists(features_workdir):
        shutil.rmtree(features_workdir)
    os.mkdir(features_workdir)
    #####################
    # lncRNA structure
    rna_file_part = os.path.join(features_workdir, "tmp.rna.file.")
    rna_file_list = os.path.join(features_workdir, "tmp.filelist")

    rna_Seq = []
    for seq in rna_seq:
        seq = seq.replace('U', 'T')
        rna_Seq.append(seq)
    i = 0
    for rnaid, rnaseq in zip(rnaID, rna_Seq):
        f_tmp = open(rna_file_part + str(i), "w")
        i += 1
        f_tmp.write(">" + rnaid + "\n")
        f_tmp.write(rnaseq + "\n")
        f_tmp.close()

    file_list_cmd = "ls " + features_workdir + " |grep tmp.rna.file > " + rna_file_list
    #print file_list_cmd
    subprocess.call(file_list_cmd, shell=True)

    RNAScore2 = "./data/tools/RNAScore2"

    with open(rna_file_list, "r") as fr:
        bar = tqdm(fr.readlines())
        for tmp in bar:
            tmp = tmp.strip()
            tmpfile = os.path.join(features_workdir, tmp)
            tmpout = os.path.join(features_workdir, tmp + ".r_score")
            rna_cmd = RNAScore2 + " -i " + tmpfile + " -o " + tmpout + " -l 250 -r -noPS"
            #print rna_cmd
            subprocess.call(rna_cmd, shell=True)

            combine_cmd = "cat " + tmpout + " >> " + rna_out
            #print combine_cmd
            subprocess.call(combine_cmd, shell=True)
            os.remove(tmpfile)
            os.remove(tmpout)
            bar.set_description("Extract lncRNA Struct Features:")
        fr.close()
    #####################

    os.remove(rna_file_list)
    os.rmdir(features_workdir)
    print("Extract lncRNA struct features has finished.")
    return rna_out

def get_pro_ss_fea(proID, proSeq, out_prefix):
    '''to compute structure features of rnas and proteins'''

    protein_out = os.path.join(out_prefix, "protein_Structure_features")
    if os.path.exists(protein_out):
        os.remove(protein_out)

    #####################
    # protein structure
    features_workdir = os.path.join(out_prefix, "features_workdir")
    if os.path.exists(features_workdir):
        shutil.rmtree(features_workdir)
    os.mkdir(features_workdir)
    protein_file_part = os.path.join(features_workdir, "tmp.protein.file.")
    protein_file_list = os.path.join(features_workdir, "tmp.filelist")

    stride_dat = "./data/tools/stride.dat"
    stride_cmd = "cp " + stride_dat + " " + os.path.abspath('.')
    tmp_stride_dat = os.path.join(os.path.abspath('.'), "stride.dat")
    subprocess.call(stride_cmd, shell=True)

    i = 0
    for proid, proseq in zip(proID, proSeq):
        f_tmp = open(protein_file_part + str(i), "w")
        i += 1
        f_tmp.write(">" + proid + "\n")
        f_tmp.write(proseq + "\n")
        f_tmp.close()

    file_list_cmd = "ls " + features_workdir + \
        " |grep tmp.protein.file > " + protein_file_list
    #print file_list_cmd
    subprocess.call(file_list_cmd, shell=True)

    RNAScore2 = "./data/tools/RNAScore2"

    with open(protein_file_list, "r") as fp:
        bar = tqdm(fp.readlines())
        for tmp in bar:
            tmp = tmp.strip()
            tmpfile = os.path.join(features_workdir, tmp)
            tmpout = os.path.join(features_workdir, tmp + ".pro_score")
            protein_cmd = RNAScore2 + " -i " + tmpfile + " -o " + tmpout + " -p"
            #print protein_cmd
            subprocess.call(protein_cmd, shell=True)

            combine_cmd = "cat " + tmpout + " >> " + protein_out
            #print combine_cmd
            subprocess.call(combine_cmd, shell=True)
            os.remove(tmpfile)
            os.remove(tmpout)
            bar.set_description("Extract protein Struct Features:")

        fp.close()
    #####################

    os.remove(protein_file_list)
    os.remove(tmp_stride_dat)
    os.rmdir(features_workdir)
    print("Extract protein struct features has finished.")

    return protein_out


import numpy as np
import FNS.Archimedean
from FNS.Archimedean import *

class FFN:
    '''
        Intuitionistic Fuzzy Number
        MD denotes menbership degree, NMD denotes non-membership
    '''
    qrung=3
    def __init__(self,MD,NMD):
        MD = np.asarray(MD)
        NMD = np.asarray(NMD)
        assert ((MD.size==0 or MD.size==1) and (NMD.size==0 or NMD.size==1) and 0<=MD<=1 and 0<=NMD<=1) and 0<=MD**3+NMD**3<=1, \
        'ERROR: Both of MD and NMD and MD^3+NMD^3 must have be in the interval[0,1] and the number of MD or NMD must have be 1.'
        self.MD = MD
        self.NMD = NMD

    def __repr__(self):
        return 'FFN:('+str(np.around(self.MD,4))+','+str(np.around(self.NMD,4))+')'

    ## Algebraic Basic Operations
    def Algebraic_Power(self,l):
        '''
            FFN Algebraic power operation
            l: parameter, denote the power of FFN
            return: new FFN
        '''
        newFFN =FFN(0,0)
        newFFN.MD = in_algebraic_tau(l*algebraic_tau(self.MD**3))**(1/3)
        newFFN.NMD = in_algebraic_s(l*algebraic_s(self.NMD**3))**(1/3)
        return newFFN
    def Algebraic_Times(self,l):
        '''
            FFN Algebraic times operation
            l: parameter, denote the times of FFN
            return: new FFN
        '''
        newFFN =FFN(0,0)
        newFFN.MD = in_algebraic_s(l*algebraic_s(self.MD**3))**(1/3)
        newFFN.NMD = in_algebraic_tau(l*algebraic_tau(self.NMD**3))**(1/3)
        return newFFN

    ## Einstein Basic Operations
    def Einstein_Power(self,l):
        '''
            FFN Einstein power operation
            l: parameter, denote the Einstein power of FFN
            return: new FFN
        '''
        newFFN =FFN(0,0)
        newFFN.MD = in_einstein_tau(l*einstein_tau(self.MD**3))**(1/3)
        newFFN.NMD = in_einstein_s(l*einstein_s(self.NMD**3))**(1/3)
        return newFFN
    def Einstein_Times(self,l):
        '''
            FFN Einstein times operation
            l: parameter, denote the Einstein times of FFN
            return: new FFN
        '''
        newFFN =FFN(0,0)
        newFFN.MD = in_einstein_s(l*einstein_s(self.MD**3))**(1/3)
        newFFN.NMD = in_einstein_tau(l*einstein_tau(self.NMD**3))**(1/3)
        return newFFN

    def Fast_Algebraic_Power(self,l):
        '''
           Fast FFN Algebraic power operation
        '''
        newFFN=FFN(0,0)
        newFFN.MD=self.MD**l
        newFFN.NMD=(1-(1-self.NMD**3)**l)**(1/3)
        return newFFN
    def Fast_Algebraic_Times(self,l):
        '''
            Fast FFN Algebraic times operation
        '''
        newFFN=FFN(0,0)
        newFFN.MD = (1-(1-self.MD**3)**l)**(1/3)
        newFFN.NMD = self.NMD**l
        return newFFN

    def Fast_Einstein_Power(self,l):
        '''
             Fast FFN Einstein power operation
        '''
        newFFN=FFN(0,0)
        newFFN.MD = ((2*(self.MD**3)**l)/((2-self.MD**3)**l+(self.MD**3)**l))**(1/3)
        newFFN.NMD = (((1+self.NMD**3)**l-(1-self.NMD**3)**l)/((1+self.NMD**3)**l+(1-self.NMD**3)**l))**(1/3)
        return newFFN

    def Fast_Einstein_Times(self,l):
        '''
            Fast FFN Einstein times operation
        '''
        newFFN=FFN(0,0)
        newFFN.MD = (((1+self.MD**3)**l-(1-self.MD**3)**l)/((1+self.MD**3)**l+(1-self.MD**3)**l))**(1/3)
        newFFN.NMD = ((2*(self.NMD**3)**l)/((2-self.NMD**3)**l+(self.NMD**3)**l))**(1/3)
        return newFFN

########### Intersection and Union ###########
## Intersection
def FFN_Intersection(ifn1,ifn2):
    '''
        毕达哥拉斯模糊数交运算
    '''
    assert ifn1.qrung == ifn2.qrung and ifn1.qrung==3, 'ERROR:the two FFNs are not the same FFN or they are not FFN!'
    newFFN = FFN(0,0)
    newFFN.MD = min(ifn1.MD, ifn2.MD)
    newFFN.NMD = max(ifn1.NMD, ifn2.NMD)
    return newFFN

def FFN_Union(ifn1,ifn2):
    '''
        毕达哥拉斯模糊数并运算
    '''
    assert ifn1.qrung == ifn2.qrung and ifn1.qrung==3, 'ERROR:the two FFNs are not the same FFN or they are not FFN!'
    newFFN = FFN(0,0)
    newFFN.MD = max(ifn1.MD, ifn2.MD)
    newFFN.NMD = min(ifn1.NMD, ifn2.NMD)
    return newFFN

##########  Basic multiplication and addition operations #################
def FFN_Algebraic_Multiply(ifn1,ifn2):
    assert ifn1.qrung == ifn2.qrung and ifn1.qrung==3, 'ERROR:the two FFNs are not the same FFN or they are not FFN!'
    newFFN = FFN(0,0)
    newFFN.MD = pithy_algebraic_T(ifn1.MD**3,ifn2.MD**3)**(1/3)
    newFFN.NMD = pithy_algebraic_S(ifn1.NMD**3,ifn2.NMD**3)**(1/3)
    return newFFN

def FFN_Algebraic_Plus(ifn1,ifn2):
    assert ifn1.qrung == ifn2.qrung and ifn1.qrung==3, 'ERROR:the two FFNs are not the same FFN or they are not FFN!'

    newFFN = FFN(0,0)
    newFFN.MD = pithy_algebraic_S(ifn1.MD**3,ifn2.MD**3)**(1/3)
    newFFN.NMD = pithy_algebraic_T(ifn1.NMD**3,ifn2.NMD**3)**(1/3)
    return newFFN

## Einstein Basic Operations
def FFN_Einstein_Multiply(ifn1,ifn2):
    assert ifn1.qrung == ifn2.qrung and ifn1.qrung==3, 'ERROR:the two FFNs are not the same FFN or they are not FFN!'

    newFFN = FFN(0,0)
    newFFN.MD = pithy_einstein_T(ifn1.MD**3,ifn2.MD**3)**(1/3)
    newFFN.NMD = pithy_einstein_S(ifn1.NMD**3,ifn2.NMD**3)**(1/3)
    return newFFN
def FFN_Einstein_Plus(ifn1,ifn2):
    assert ifn1.qrung == ifn2.qrung and ifn1.qrung==3, 'ERROR:the two FFNs are not the same FFN or they are not FFN!'

    newFFN = FFN(0,0)
    newFFN.MD = pithy_einstein_S(ifn1.MD**3,ifn2.MD**3)**(1/3)
    newFFN.NMD = pithy_einstein_T(ifn1.NMD**3,ifn2.NMD**3)**(1/3)
    return newFFN


import argparse
import os
import time
import pandas as pd
import torch
from sklearn.metrics import precision_recall_fscore_support
from torch.optim import AdamW
from torch.utils.data import DataLoader
from peft import (
    get_peft_config,
    get_peft_model,
    get_peft_model_state_dict,
    set_peft_model_state_dict,
    PeftType,
    PrefixTuningConfig,
    PromptEncoderConfig,
    LoraConfig
)
from datasets import Dataset, DatasetDict
from transformers import AutoModelForSequenceClassification, AutoTokenizer, get_linear_schedule_with_warmup, set_seed, \
    InputExample
from tqdm import tqdm

# ------------------------init parameters----------------------------
parser = argparse.ArgumentParser(description='P-tuning v2')
parser.add_argument('--plm', type=str, default="bert-large", help='choose plm: bert or roberta or ernie')
parser.add_argument('--type', type=str, default="ptuningv2", help='choose model: ptuningv1, ptuningv2, lora')
parser.add_argument('--rank', type=int, default=4, help='LORA rank')
parser.add_argument('--lr', type=float, default=3e-4, help='learning rate')
parser.add_argument('--soft_tokens', type=int, default=10, help='soft tokens')
parser.add_argument('--train_file', type=str, default='datasets/preprocessed/train.json', help='train set')
parser.add_argument('--valid_file', type=str, default='datasets/preprocessed/dev.json', help='validation set')
parser.add_argument('--test_file', type=str, default='datasets/preprocessed/test.json', help='test set')
parser.add_argument('--train', action="store_true", help='If train or not')
parser.add_argument('--eval', action="store_true", help='If evaluate or not')
args = parser.parse_args()

if args.plm == 'bert':
    model_name_or_path = "bert-base-chinese"
elif args.plm == 'roberta':
    model_name_or_path = "uer/chinese_roberta_L-12_H-768"
elif args.plm == 'ernie':
    model_name_or_path = "nghuyong/ernie-3.0-base-zh"
elif args.plm == 'bert-large':
    model_name_or_path = "yechen/bert-large-chinese"
elif args.plm == 'bert-large':
    model_name_or_path = "yechen/bert-large-chinese"
elif args.plm == 'roberta-large':
    model_name_or_path = "hfl/chinese-roberta-wwm-ext-large"

device = "cuda"
batch_size = 4
num_epochs = 8
lr = args.lr

if args.type=='ptuningv2':
    peft_type = PeftType.PREFIX_TUNING
    peft_config = PrefixTuningConfig(task_type="SEQ_CLS", num_virtual_tokens=args.soft_tokens)
elif args.type=='lora':
    peft_type = PeftType.LORA
    # target: Q, K, V, Dense
    peft_config = LoraConfig(task_type="SEQ_CLS", inference_mode=False, r=args.rank,
                             lora_alpha=16, lora_dropout=0.1, target_modules=['query', 'key', 'value', 'output.dense'])
    # target: Q, K, V
    # peft_config = LoraConfig(task_type="SEQ_CLS", inference_mode=False, r=args.rank,
    #                          lora_alpha=16, lora_dropout=0.1, target_modules=['query', 'key', 'value'])
elif args.type=='ptuningv1':
    peft_type = PeftType.P_TUNING
    peft_config = PromptEncoderConfig(task_type="SEQ_CLS", num_virtual_tokens=args.soft_tokens)

# if any(k in model_name_or_path for k in ("gpt", "opt", "bloom")):
#     padding_side = "left"
# else:
#     padding_side = "right"

tokenizer = AutoTokenizer.from_pretrained(model_name_or_path)
if getattr(tokenizer, "pad_token_id") is None:
    tokenizer.pad_token_id = tokenizer.eos_token_id

# Load Dataset
train_path = args.train_file # 'datasets/preprocessed/train.json'
dev_path = args.valid_file # 'datasets/preprocessed/dev.json'
test_path = args.test_file # 'datasets/preprocessed/test.json'
datasets = DatasetDict.from_json({'train': train_path, 'dev': dev_path, 'test': test_path})

def tokenize_function(examples):
    # max_length=None => use the model max length (it's actually the default
    outputs = tokenizer(examples["claim"], examples["evidences"], truncation=True, max_length=256)
    return outputs

tokenized_datasets = datasets.map(
    tokenize_function,
    batched=True,
    remove_columns=["claimId", "claim", "evidences"],
)
tokenized_datasets = tokenized_datasets.rename_column("label", "labels")

def collate_fn(examples):
    return tokenizer.pad(examples, return_tensors="pt")

# Instantiate dataloaders.
train_dataloader = DataLoader(
    tokenized_datasets["train"], shuffle=True, collate_fn=collate_fn, batch_size=batch_size)
dev_dataloader = DataLoader(
    tokenized_datasets["dev"], shuffle=False, collate_fn=collate_fn, batch_size=batch_size
)
test_dataloader = DataLoader(
    tokenized_datasets["test"], shuffle=False, collate_fn=collate_fn, batch_size=batch_size
)

model = AutoModelForSequenceClassification.from_pretrained(model_name_or_path, return_dict=True, num_labels=3)
# model_sd = model.state_dict()
# for k in list(model_sd.keys()):
#       print('module:', k)
model = get_peft_model(model, peft_config)
model.print_trainable_parameters()
model.to(device)

optimizer = AdamW(params=model.parameters(), lr=lr)
# Instantiate scheduler
lr_scheduler = get_linear_schedule_with_warmup(
    optimizer=optimizer,
    num_warmup_steps=0,
    num_training_steps=(len(train_dataloader) * num_epochs),
)

total_time = 0
for epoch in range(num_epochs):
    model.train()
    total_loss = 0
    best_microf1 = 0
    best_macrof1 = 0
    best_recall = 0
    best_precision = 0
    start_time = time.time()
    # ========================================
    #               Training
    # ========================================
    if args.train:
        for step, batch in enumerate(tqdm(train_dataloader)):
            batch.to(device)
            outputs = model(**batch)
            loss = outputs.loss
            total_loss += loss.sum()
            loss.sum().backward()
            optimizer.step()
            lr_scheduler.step()
            optimizer.zero_grad()
        end_time = time.time()
        training_time = end_time - start_time
        total_time += training_time

        # ========================================
        #               Validation
        # ========================================
        model.eval()
        valid_y_pred = []
        valid_y_true = []
        for step, batch in enumerate(tqdm(dev_dataloader)):
            batch.to(device)
            with torch.no_grad():
                outputs = model(**batch)
            predictions = outputs.logits.softmax(dim=-1)
            predictions = torch.argmax(predictions, dim=-1)
            labels = batch['labels']
            valid_y_true.extend(labels.cpu().tolist())
            valid_y_pred.extend(predictions.cpu().tolist())
        pre, recall, f1, _ = precision_recall_fscore_support(valid_y_true, valid_y_pred, average='micro')
        microf1 = f1
        pre, recall, f1, _ = precision_recall_fscore_support(valid_y_true, valid_y_pred, average='macro')
        if f1 > best_macrof1:
            best_microf1 = microf1
            best_macrof1 = f1
            torch.save(model.state_dict(), f"./checkpoint/lora_model.ckpt")
        print("Epoch {}, f1 {}".format(epoch, f1), flush=True)
    print('Training complete in {:.0f}m {:.0f}s'.format(total_time // 60, total_time % 60))

# ========================================
#               Test
# ========================================
if args.eval:
    model.load_state_dict(torch.load(f"./checkpoint/lora_model.ckpt"))
    model = model.to(device)
    model.eval()
    test_y_pred = []
    test_y_true = []
    for step, batch in enumerate(tqdm(test_dataloader)):
        batch.to(device)
        with torch.no_grad():
            outputs = model(**batch)
        predictions = outputs.logits.softmax(dim=-1)
        predictions = torch.argmax(predictions, dim=-1)
        # predictions = torch.argmax(predictions)
        # class_labels = ['SUP', 'REF', 'NEI']
        # predicted_label = class_labels[predictions]
        # print("預測的 label 為:", predicted_label)
        labels = batch['labels']
        test_y_true.extend(labels.cpu().tolist())
        test_y_pred.extend(predictions.cpu().tolist())
    pre, recall, f1, _ = precision_recall_fscore_support(test_y_true, test_y_pred, average='micro')
    print("       F1 (micro): {:.2%}".format(f1))
    pre, recall, f1, _ = precision_recall_fscore_support(test_y_true, test_y_pred, average='macro')
    print("Precision (macro): {:.2%}".format(pre))
    print("   Recall (macro): {:.2%}".format(recall))
    print("       F1 (macro): {:.2%}".format(f1))


import os
import viagens_modulo_1 as viagem
from time import sleep

def addPacote ():
  pacoteAdd = int(input('Qual Serviço deseja adicionar?\n[1]-Aluguel de Carros\n[2]-Seguro Viagem\n[3]-Passeios não inclusos no pacote\n[4]-Sair\n'))
  #OPIÇÃO 1
  if (pacoteAdd == 1):
    print ('Com mais de 400 agências, uma das maiores frota de carros do Brasil.\n Faça sua reserva!')
    opcaocarro =  int(input('Para mais informações acesse o site: https://www.revi.com/alugueis?\nEsta informacao foi util ?\n[1]-Sim\n[2]-Não\n'))
    if (opcaocarro == 1 or opcaocarro == 2):
      print('Obrigado por sua opinião\n')
      sleep(1)
      if viagem.finalizar() == False:
        return False
    else:
      print('Insira uma opção válida!')
      sleep(1)
      os.system("cls")
      if addPacote() == False:
        return False

  #OPIÇÃO 2
  elif (pacoteAdd == 2):
    print ('No Brasil, os planos de Seguro Viagem são regulamentados e supervisionados pela SUSEP - Superitendencia de Seguros Privados\n O seguro de viagem é disponibilizado sob a forma de apólices ou bilhetes e pode ser contratado no momento da reserva de um pacote de viagem para cobrir exatamente a duração dessa viagem\n')
    opcaoSeguro = int(input('Para mais informações acesse o site: https://revi.com/seguros\nEsta informacao foi util ?\n[1]-Sim\n[2]-Não\n'))
    if (opcaoSeguro == 1 or opcaoSeguro == 2):
      print('Obrigado por sua opinião\n')
      sleep(1)
      if viagem.finalizar() == False:
        return False
    else:
      print('Insira uma opção válida!')
      sleep(1)
      os.system("cls")
      if addPacote() == False:
        return False
  #OPIÇÃO 3
  elif (pacoteAdd == 3):
    #direcionar para o site ficticio
    print ('Com diversos serviços adcionais, para incrementar o seu pacote, veja nossa lista e escolha o serviço para tonar sua viagem ainda mais inesquecíves')
    opcaoPacotesA = int(input('Para mais informações acesse o site: https://revi.com/passeios-adicionais\nEsta informacao foi util ?\n[1]-Sim\n[2]-Não\n'))
    if (opcaoPacotesA == 1 or opcaoPacotesA == 2):
      print('Obrigado por sua opinião\n')
      sleep(1)
      if viagem.finalizar() == False:
        return False
    else:
      print('Insira uma opção válida!')
      sleep(1)
      os.system("cls")
      if addPacote() == False:
        return False
  #OPIÇÃO 4
  elif (pacoteAdd == 4):
    print('Obrigado pelo contato\n')
    sleep(1)
    if viagem.finalizar() == False:
      return False
  #tratativa de erros de pacoteAdd
  else:
    print('Insira uma opção válida!')
    sleep(1)
    os.system("cls")
    if addPacote() == False:
      return False


import pandas as pd
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import bs4 as bs
import pickle
import requests
import datetime as dt

pd.plotting.register_matplotlib_converters()

def set_dates():
    """
    asks for user input regarding start and end dates
    :return: start,end dates as datatime library objects
    """
    syear, smonth, sday = (
        input('provide starting year,month,day:').split(','))
    syear, smonth, sday = int(syear), int(smonth), int(sday)
    eyear, emonth, eday = input('provide ending year,month,day:').split(',')
    eyear, emonth, eday = int(eyear), int(emonth), int(eday)
    start = dt.datetime(syear, smonth, sday)
    end = dt.datetime(eyear, emonth, eday)
    return start, end

def read_data(csv_format, stock, source, start, end):
    """

    :param csv_format:
    :param stock:
    :param source:
    :param start:
    :param end:
    :return:
    """
    all_data = web.DataReader(stock, source, start, end)
    all_data.to_csv(csv_format)
    all_data = pd.read_csv(csv_format, parse_dates=True, index_col=0)
    return all_data

def plot_graph(df, information):
    """

    :param df:
    :param information:
    :return:
    """
    name = information[0]
    ticker = information[1][0]
    info = information[1][1]
    df[['Open']].plot()
    title = name + ' (' + ticker + ') -' + info
    plt.title(title)
    plt.ylabel('USD $')
    plt.xlabel('Date')
    plt.grid()
    plt.show()

def get_sp500():
    """

    :return:
    """
    resp = requests.get('https://en.wikipedia.org/wiki/List_of_S%26P_500_'
                        'companies')
    soup = bs.BeautifulSoup(resp.text, features='lxml')
    table = soup.find('table', {'class': 'wikitable sortable'})
    tickers = []
    for row in table.findAll('tr')[1:]:
        ticker = row.findAll('td')[0].text
        name = row.findAll('td')[1].text.replace(' Inc', '') \
            .replace(',', '').replace('.', '').lower()
        sector = row.findAll('td')[4].text
        tickers.append([name,ticker[:-1], sector])
    with open('sp500tickers.pickle', 'wb') as f:
        pickle.dump(tickers, f)
    return tickers

def get_TA35():
    """

    :return:
    """
    resp = requests.get('https://en.wikipedia.org/wiki/TA-35_Index')
    soup = bs.BeautifulSoup(resp.text, features='lxml')
    table = soup.find('table', {'class': 'wikitable'})
    tickers = []
    for row in table.findAll('tr')[2:]:
        ticker = row.findAll('td')[2].text[6:-1] + ".TA"
        name = row.findAll('td')[1].text.replace(' Ltd', '') \
                   .replace('.', '').replace('.', '').lower()[:-1]
        sector = row.findAll('td')[3].text[:-1]
        tickers.append([name,ticker,sector])
    with open('TA35tickers.pickle', 'wb') as f:
        pickle.dump(tickers, f)
    return tickers

def scrape_stock_data(ticker):
    """

    :param ticker:
    :return:
    """
    all_data = dict()
    webpage = f"https://finance.yahoo.com/quote/{ticker}?p={ticker}"
    resp = requests.get(webpage)
    soup = bs.BeautifulSoup(resp.text, features='lxml')
    stock_data = soup.find_all("table")
    for table in stock_data:
        tds = table.findAll('td')
        for i in range(1, len(tds), 2):
            name = str(tds[i]).split('test=\"')[1].split("-value")[0]
            try:
                value = str(tds[i]).split('</')[0].split('>', 2)[2]
            except IndexError:
                value = str(tds[i]).split('</')[0].split('>')[1]
            all_data[name] = value
    return all_data

def sort_according_to(lst,value):
    tickers = [item[1] for item in lst]
    if str(value).lower()=='tickers':
        return tickers.sort()

print(sort_according_to(get_sp500(),1))
#
# for item in get_sp500()[:10]:
#     ticker = item[1]
#     data = scrape_stock_data(ticker)
#     print(ticker)
#     print(data)

def main():
    """

    :return:
    """
    source = 'yahoo'
    sp = get_sp500()
    stock_name = 'apple'
    # stock_name = input('Which stock to show?').lower()

    if stock_name in sp:
        symbol_sector = sp[stock_name]
    else:
        symbol_sector = stock_name, None
    csv_format = stock_name + '.csv'
    # start, end = set_dates()
    start = dt.datetime(2020, 1, 1)
    end = dt.datetime(2020, 3, 1)
    data_to_plot = read_data(csv_format, symbol_sector[0], source, start, end)
    plot_graph(data_to_plot, [stock_name, symbol_sector])

# main()

# start = dt.datetime(2020,1,1)
# end = dt.datetime(2020,3,1)
# all_data =[]
# names_lst = []
# for item in get_TA35()[:10]:
#     name = item[0]
#     names_lst.append(name)
#     ticker = item[1]
#     info = item[2]
#     csv_format = name +'.csv'
#     data = read_data(csv_format,ticker,'yahoo',start,end)
#     all_data.append(data)
#     print("Finished loading data of:",name)
#     print("plotting graph for:",name)
# for stock in all_data:
#     plt.plot(stock[['Open']])
#
# plt.legend(names_lst)
# plt.show()


import argparse
import ast
import os

import librosa

import paddlehub as hub
from paddlehub.datasets import ESC50

parser = argparse.ArgumentParser(__doc__)
parser.add_argument("--wav", type=str, required=True, help="Audio file to infer.")
parser.add_argument("--sr", type=int, default=44100, help="Sample rate of inference audio.")
parser.add_argument("--model_type", type=str, default='panns_cnn14', help="Select model to to inference.")
parser.add_argument("--topk", type=int, default=1, help="Show top k results of prediction labels.")
parser.add_argument(
    "--checkpoint", type=str, default='./checkpoint/best_model/model.pdparams', help="Checkpoint of model.")
args = parser.parse_args()

if __name__ == '__main__':
    label_map = {idx: label for idx, label in enumerate(ESC50.label_list)}

    model = hub.Module(
        name=args.model_type,
        version='1.0.0',
        task='sound-cls',
        num_class=ESC50.num_class,
        label_map=label_map,
        load_checkpoint=args.checkpoint)

    data = [librosa.load(args.wav, sr=args.sr)[0]]
    result = model.predict(data, sample_rate=args.sr, batch_size=1, feat_type='mel', use_gpu=True)

    msg = f'[{args.wav}]\n'
    for label, score in list(result[0].items())[:args.topk]:
        msg += f'{label}: {score}\n'
    print(msg)


import gym
import numpy as np
import cityflow

class TSCEnv(gym.Env):
    """
    Environment for Traffic Signal Control task.

    Parameters
    ----------
    world: World object
    agents: list of agent, corresponding to each intersection in world.intersections
    metric: Metric object, used to calculate evaluation metric
    """
    def __init__(self, world, agents, metric):
        self.world = world

        self.eng = self.world.eng
        self.n_agents = len(self.world.intersection_ids)
        self.n = self.n_agents

        assert len(agents) == self.n_agents

        self.agents = agents
        action_dims = [agent.action_space.n for agent in agents]
        self.action_space = gym.spaces.MultiDiscrete(action_dims)

        if isinstance(metric, list):
            self.metric = metric
        else:
            self.metric = [metric]

    def update_metric(self):
        if self.world.eng.get_current_time()%5 == 0:
            for metric in self.metric:
                metric.update(done=False)

    def reset_metric(self):
        for metric in self.metric:
            metric.reset()

    def step(self, actions):
        assert len(actions) == self.n_agents

        self.world.step(actions)
        self.update_metric()

        obs = [agent.get_ob() for agent in self.agents]
        rewards = [agent.get_reward() for agent in self.agents]
        num_vehicles = self.world.count_vehicles()

        if num_vehicles == 0 and self.world.eng.get_current_time() > 20:
            dones = [True] * self.n_agents
        else:
            dones = [False] * self.n_agents

        infos = {"count_vehicles":num_vehicles}

        return obs, rewards, dones, infos

    def reset(self):
        self.world.reset()
        self.reset_metric()
        obs = [agent.get_ob() for agent in self.agents]
        return obs


import copy
import math
from typing import Any, Callable, cast, Dict, Optional, Union, TYPE_CHECKING, Tuple

import torch
import torch.distributed as dist
import torch.nn as nn
import torch.nn.functional as F
from torch import Tensor
from torch.nn import Module, ModuleList
from torch.distributed import ProcessGroup

from oslo.torch.distributed import ParallelMode
from oslo.torch.nn.parallel.expert_parallel.experts import Experts
from oslo.torch.nn.parallel.expert_parallel._ops import AllToAll, EPDispatch, EPCombine

if TYPE_CHECKING:
    Base = Module[Tensor]
else:
    Base = Module

uniform_map: Dict[torch.device, Callable] = dict()
gumbel_map: Dict[torch.device, Callable] = dict()
exp_selection_uniform_map: Dict[torch.device, Callable] = dict()

USE_EINSUM = True

def multiplicative_jitter(x, device: torch.device, epsilon=1e-2):
    if epsilon == 0:
        return x

    uniform = uniform_map.get(device, None)
    if uniform is None:
        low = torch.tensor(1.0 - epsilon, device=device)
        high = torch.tensor(1.0 + epsilon, device=device)
        uniform = torch.distributions.uniform.Uniform(low=low, high=high).rsample
        uniform_map[device] = uniform

    return x * uniform(x.shape)

def gumbel_rsample(shape: Tuple, device: torch.device) -> Tensor:
    gumbel = gumbel_map.get(device, None)
    if gumbel is None:
        one = torch.tensor(1.0, device=device)
        zero = torch.tensor(0.0, device=device)
        gumbel = torch.distributions.gumbel.Gumbel(zero, one).rsample
        gumbel_map[device] = gumbel

    return gumbel()

# paper : https://arxiv.org/pdf/2006.16668.pdf
# Einseutine Sum Dimensions
#     - g = group
#     - s = sequence
#     - e = expert
#     - m = model
#     - c = capacity
def einsum(rule, a, b):
    if USE_EINSUM:
        return torch.einsum(rule, a, b)
    elif rule == "s,se->se":
        return a.reshape(a.shape[0], -1) * b
    elif rule == "se,sc->sec":
        return a.unsqueeze(2) * b.unsqueeze(1)
    elif rule == "se,se->s":
        return torch.bmm(a.unsqueeze(1), b.unsqueeze(2)).reshape(-1)
    elif rule == "sec,sm->ecm":
        s, e, c = a.shape[:3]
        m = b.shape[1]
        return torch.matmul(a.reshape(s, -1).t(), b).reshape(e, c, m)
    elif rule == "sec,ecm->sm":
        return torch.matmul(a.reshape(a.shape[0], -1), b.reshape(-1, b.shape[-1]))
    elif rule == "ks,ksm->sm":
        k, s, m = b.shape[:3]

        a = a.t().unsqueeze(1)
        # |a| = (k, s) -> |a.t()| = (s, k) -> |a.t().unsqueeze(1)| = (s, 1, k)
        b = b.reshape(k, -1).t().reshape(s, m, k)
        # |b| = (k, s, m) -> |b.reshape(k, -1)| = (k, s*m) -> |b.reshape(k, -1).t()| = (s*m, k)
        # -> |b.reshape(k, -1).t().reshape(s, m, k)| = (s, m, k)

        return torch.bmm(a, b.transpose(1, 2)).squeeze(2)
    else:
        return torch.einsum(rule, a, b)

# The following functions are extracted and scripted
# because otherwise during a torch.jit.trace, the non-Tensor
# values used in the calculations get recorded as constants.
# torch.jit.script coerces them into Tensors and preserves
# their dynamic shapes. This enables ONNX export.
# We can't script the entire top1gating function because it
# includes stateful caching logic which is incompatible with ONNX.
@torch.jit.script
def _capacity(gates: Tensor, capacity_factor: Tensor, min_capacity: Tensor) -> Tensor:
    # |gates| = (S, E)
    num_tokens, num_experts = gates.shape[:2]

    # to(torch.int64) works around a bug in torch.onnx.export:
    # it should cast k to int 64 when converting torch.topk but it doesn't
    capacity = torch.ceil((num_tokens / num_experts) * capacity_factor).to(torch.int64)
    if capacity < min_capacity:
        capacity = min_capacity.to(torch.int64)

    return capacity

@torch.jit.script
def _top_idx(source, k):
    return torch.topk(source, k=k, dim=0)[1]

@torch.jit.script
def _one_hot_to_float(x, num_classes):
    return F.one_hot(x, num_classes=num_classes).float()

def top1_gating(
    logits: Tensor,
    capacity_factor: float,
    min_capacity: int,
    noisy_gate_policy: Optional[str] = None,
    drop_tokens: bool = True,
    use_rts: bool = True,
    use_kernel: bool = False,
) -> Tuple[Tensor, Tensor, Tensor, Tensor]:
    # |logits| = (num_tokens, num_experts)

    # For exploration, add noise to logits.
    # In this case, since noisy_gate_policy is different,
    # do not multiply noise with inputs in the gate.
    if noisy_gate_policy == "RSample":
        logits_w_noise = logits + gumbel_rsample(logits.shape, device=logits.device)
        # |logits_w_noise| = (num_tokens, num_experts)

    # Calculate conditional probability for each token to be dispatched to experts
    gates = F.softmax(logits, dim=1)
    # |gates| = (num_tokens, num_experts)

    # Calculate the number of tokens that each expert can contain
    capacity = _capacity(
        gates, torch.tensor(capacity_factor), torch.tensor(min_capacity)
    )

    # Get the index of expert for each token to be dispatched
    indices = torch.argmax(
        logits_w_noise if noisy_gate_policy == "RSample" else gates, dim=1
    )
    # |indices| = (num_tokens, )

    # Binarize the index of expert for each token to be dispatched
    num_experts = int(gates.shape[1])
    mask = F.one_hot(indices, num_classes=num_experts)
    # |mask| = (num_tokens, num_experts)

    # Calculate the number of tokens dispatched to each expert
    exp_counts = torch.sum(mask, dim=0).detach().to("cpu")
    # |exp_counts| = (num_experts, )

    # Share the maximum capacity across all devices in the world
    if not drop_tokens:
        new_capacity = torch.max(exp_counts).to(logits.device)
        dist.all_reduce(new_capacity, op=dist.ReduceOp.MAX, group=dist.group.WORLD)
        capacity = new_capacity

    # Calculate loss for training
    me = torch.mean(gates, dim=0)
    ce = torch.mean(mask.float(), dim=0)
    l_aux = torch.sum(me * ce) * num_experts

    # For exploration of token selection, multiply noise with mask
    if use_rts:
        uniform = exp_selection_uniform_map.get(logits.device, None)
        if uniform is None:
            low = torch.tensor(0.0, device=logits.device)
            high = torch.tensor(1.0, device=logits.device)
            uniform = torch.distributions.uniform.Uniform(low=low, high=high).rsample
            exp_selection_uniform_map[logits.device] = uniform
        mask_rand = mask * uniform(mask.shape)
    else:
        mask_rand = mask
    # |mask_rand| = (num_tokens, num_experts)

    assert (
        logits.shape[0] >= min_capacity
    ), "No, of tokens (batch-size) should be greater than min_capacity. Either set min_capacity to 0 or increase your batch size"

    top_idx = _top_idx(mask_rand, capacity)
    # |top_idx| = (num_tokens, 1)

    mask = mask * torch.zeros_like(mask).scatter_(0, top_idx, 1)
    # |mask| = (num_tokens, num_experts)

    locations = torch.cumsum(mask, dim=0) - 1
    # |locations| = (num_tokens, )

    # Get the location of token in the buffer allocated to each expert
    # If some tokens drop out, then clear all values of that token
    locations_s = torch.sum(locations * mask, dim=1)
    # |locations_s| = (num_tokens, )

    # Only leave the conditional probability for the token to be dispatched
    # and clear other conditional probabilities for that token
    mask_float = mask.float()
    gates = gates * mask_float
    # |mask_float| = (num_tokens, num_experts)
    # |gates| = (num_tokens, num_experts)

    # Binarize the location of token in the buffer allocated to each expert
    locations_sc = _one_hot_to_float(locations_s, capacity)
    # |location_sc| = (num_tokens, num_experts)

    combine_weights = einsum("se,sc->sec", gates, locations_sc)
    dispatch_mask = combine_weights.bool()
    # |combine_weights| = (num_tokens, num_experts, capacity)
    # |dispatch_mask| = (num_tokens, num_experts, capacity)

    return l_aux, combine_weights, dispatch_mask, exp_counts

def top2_gating(
    logits: Tensor, capacity_factor: float, min_capacity: int, use_kernel: bool
) -> Tuple[Tensor, Tensor, Tensor, Tensor]:
    # |logits| = (num_tokens, num_experts)

    # Calculate conditional probability for each token to be dispatched to experts
    gates = F.softmax(logits, dim=1)
    # |gates| = (num_tokens, num_experts)

    # Calculate the number of tokens that each expert can contain
    capacity = _capacity(
        gates, torch.tensor(capacity_factor * 2), torch.tensor(min_capacity)
    )

    # Create a mask for 1st's expert per token
    indices1_s = torch.argmax(gates, dim=1)
    num_experts = int(gates.shape[1])
    mask1 = F.one_hot(indices1_s, num_classes=num_experts)
    # |indices1_s| = (token_num, )
    # |mask1| = (token_num, num_experts)

    # Create a mask for 2nd's expert per token using Gumbel-max trick
    # https://timvieira.github.io/blog/post/2014/07/31/gumbel-max-trick/
    logits_w_noise = logits + gumbel_rsample(logits.shape, device=logits.shape)
    logits_except1 = logits_w_noise.masked_fill(mask1.bool(), float("-inf"))
    # |logits_w_noise| = (num_tokens, num_experts)
    # |logits_except1| = (num_tokens, num_experts)

    indices2_s = torch.argmax(logits_except1, dim=1)
    mask2 = F.one_hot(indices2_s, num_classes=num_experts)
    # |indices2_s| = (num_tokens, 1)
    # |mask2| = (num_tokens, num_experts)

    # Get the location of token in the buffer allocated to each expert
    # If some tokens drop out, then clear all values of that token
    locations1 = torch.cumsum(mask1, dim=0) - 1
    locations2 = torch.cumsum(mask2, dim=0) - 1
    locations2 += torch.sum(mask1, dim=0, keepdim=True)
    # |locations1| = (num_tokens, num_experts)
    # |locations2| = (num_tokens, num_experts)

    # Calculate the number of tokens dispatched to each expert
    exp_counts = torch.sum(mask1, dim=0)
    # |exp_counts| = (num_experts, )

    # Calculate loss for training
    me = torch.mean(gates, dim=0)
    ce = torch.mean(mask1.float(), dim=0)
    l_aux = torch.mean(me * ce) * num_experts * num_experts

    # Drop out tokens spilling out from the buffer
    mask1 *= torch.lt(locations1, capacity)
    mask2 *= torch.lt(locations2, capacity)
    # |mask1| = (num_tokens, num_experts)
    # |mask2| = (num_tokens, num_experts)

    # Get the location of token in the buffer allocated to each expert
    # If some tokens drop out, then clear all values of that token
    locations1_s = torch.sum(locations1 * mask1, dim=1)
    locations2_s = torch.sum(locations2 * mask2, dim=1)
    # |locations1_s| = (num_tokens, num_experts)
    # |locations2_s| = (num_tokens, num_experts)

    mask1_float = mask1.float()
    mask2_float = mask2.float()

    gates1_s = einsum("se,se->s", gates, mask1_float)
    gates2_s = einsum("se,se->s", gates, mask2_float)
    # |gates1_s| = (num_tokens, )
    # |gates2_s| = (num_tokens, )

    # Normalize conditional probabilities for tokens to be dispatched
    denom_s = gates1_s + gates2_s
    denom_s = torch.clamp(denom_s, min=torch.finfo(denom_s.dtype).eps)
    gates1_s /= denom_s
    gates2_s /= denom_s
    # |denom_s| = (num_tokens, )

    gates1 = einsum("s,se->se", gates1_s, mask1_float)
    gates2 = einsum("s,se->se", gates2_s, mask2_float)
    # |gates1| = (num_tokens, num_experts)
    # |gates2| = (num_tokens, num_experts)

    # Binarize the location of token in the buffer allocated to each expert
    locations1_sc = _one_hot_to_float(locations1_s, capacity)
    locations2_sc = _one_hot_to_float(locations2_s, capacity)
    # |locations1_sc| = (num_tokens, capacity)
    # |locations2_sc| = (num_tokens, capacity)

    # Calculate combine weights and dispatch mask for output of different experts but of same tokens
    combine1_sec = einsum("se,sc->sec", gates1, locations1_sc)
    combine2_sec = einsum("se,sc->sec", gates2, locations2_sc)
    # |combine1_sec| = (num_tokens, num_experts, capacity)
    # |combine2_sec| = (num_tokens, num_experts, capacity)

    combine_weights = combine1_sec + combine2_sec
    dispatch_mask = combine_weights.bool()
    # |combine_weights| = (num_tokens, num_experts, capacity)
    # |dispatch_mask| = (num_tokens, num_experts, capacity)

    return l_aux, combine_weights, dispatch_mask, exp_counts

class TopKGate(Module):

    wg: torch.nn.Linear

    def __init__(
        self,
        model_dim: int,
        num_experts: int,
        k: int = 1,
        capacity_factor: float = 1.0,
        eval_capacity_factor: float = 1.0,
        min_capacity: int = 8,
        noisy_gate_policy: Optional[str] = None,
        drop_tokens: bool = True,
        use_rts: bool = True,
    ) -> None:
        super().__init__()

        if k != 1 and k != 2:
            raise ValueError("Only top-1 and top-2 gatings are supported")
        self.wg = torch.nn.Linear(model_dim, num_experts, bias=False)
        self.k = k

        self.capacity_factor = capacity_factor
        self.eval_capacity_factor = eval_capacity_factor
        self.min_capacity = min_capacity

        self.noisy_gate_policy = noisy_gate_policy

        self.drop_tokens = drop_tokens
        self.use_rts = use_rts

    def forward(
        self, inputs: torch.Tensor, use_kernel: bool = False
    ) -> Tuple[Tensor, Tensor, Tensor]:
        # |inputs| = (token_num = batch_size * sent_len, d_model)

        # For stability of training process, make tensor 32 bit float type
        # of gate's weights and input
        if self.wg.weight.dtype != torch.float32:
            self.wg = self.wg.float()
        input_fp32 = inputs.float()

        # For exploration, multiply noise with input
        if self.noisy_gate_policy == "Jitter" and self.training:
            input_fp32 = multiplicative_jitter(input_fp32, device=inputs.device)

        # Calculate gating score for each token
        logits = self.wg(input_fp32)
        # |logits| = (tokens_num, experts_num)

        if self.k == 1:
            gate_output = top1_gating(
                logits,
                self.capacity_factor if self.training else self.eval_capacity_factor,
                self.min_capacity,
                self.noisy_gate_policy if self.training else None,
                self.drop_tokens,
                self.use_rts,
                use_kernel,
            )
        else:
            gate_output = top2_gating(
                logits,
                self.capacity_factor if self.training else self.eval_capacity_factor,
                self.min_capacity,
            )
        # gate_output
        #   gate_output[0] = auxiliary loss
        #   gate_output[1] = weights to combine the outputs of different experts but based on same token
        #   gate_output[2] = mask to dispatch tokens for each expert
        #   gate_output[3] = number of tokens to be dispatched for each expert

        return gate_output

class ExpertParallelFrontResidual(Module):
    def __init__(self, base_module, in_features):
        super(ExpertParallelFrontResidual, self).__init__()
        self.residual = copy.deepcopy(base_module)
        self.residual_mix = nn.Linear(in_features, 2)

    def forward(self, inputs):
        residual_inter = self.residual(inputs)
        # |residual_inter| = (sent_len, batch_size, out_features)

        residual_weight = self.residual_mix(inputs)
        residual_weight = F.softmax(residual_weight, dim=-1)
        # |residual_weight| = (sent_len, batch_size, 2)

        return residual_inter, residual_weight

class ExpertParallelBehindResidual(Module):
    def __init__(self, base_module):
        super(ExpertParallelBehindResidual, self).__init__()
        self.residual = copy.deepcopy(base_module)

    def forward(self, inputs):
        outputs = self.residual(inputs)

        return outputs

class ExpertParallelFrontBlock(Module):
    def __init__(
        self,
        link_info: dict,
        in_features: int,
        out_features: int,
        gate: Module,
        experts: Experts,
        ep_size: int,
        num_local_experts: int,
        use_residual: bool = False,
        residual: Optional[nn.Module] = None,
    ):
        super().__init__()

        self.link_info = link_info

        self.gate = gate

        self.in_features = in_features
        self.out_features = out_features

        self.front_experts = experts
        self.ep_group = None
        self.ep_size = ep_size
        self.num_local_experts = num_local_experts

        # Create Residual
        self.use_residual = use_residual
        self.residual, self.residual_mix = None, None
        if use_residual:
            assert (
                residual is not None
            ), "If you want to use residual moe, then you must give residual instance"
            self.residual = ExpertParallelFrontResidual(residual, in_features)
            # self.residual = residual

            # self.residual_mix = nn.Linear(in_features, 2)

    def _set_ep_group(self, ep_group):
        self.ep_group = ep_group

    # def residual_forward(self, inputs: Tensor):
    #    residual_inter = self.residual(inputs)
    #    # |residual_inter| = (sent_len, batch_size, out_features)
    #
    #    residual_weight = self.residual_mix(inputs)
    #    residual_weight = F.softmax(residual_weight, dim=-1)
    #    # |residual_weight| = (sent_len, batch_size, 2)
    #
    #    return residual_inter, residual_weight

    def forward(self, inputs: Tensor):
        # |inputs| = (batch_size, sent_len, d_model)
        #         or (sent_len, batch_size, d_model)

        # Implement Algorithm 2 from GShard Paper
        d_model = inputs.shape[-1]

        # Initial Implementation -> Reshape into S tokens by dropping sequence dimension.
        # Reshape into G groups so that each group can distribute tokens equally
        # group_size = kwarg['group_size'] if 'group_size' in kwargs.size() else 1
        # -> this is not valid for oslo's context because we cannot manipulate inputs of each intra-modules
        self.link_info["inputs_shape"] = inputs.shape
        reshaped_input = inputs.reshape(-1, d_model)
        # |reshaped_input| = (num_tokens = batch_size * sent_len, d_model)

        # Calculate information to dispatch tokens
        l_aux, combine_weights, dispatch_mask, self.exp_counts = self.gate(
            reshaped_input
        )
        self.link_info["combine_weights"] = combine_weights
        # |combine_weights| = (num_tokens, num_experts, capacity)
        # |dispatch_mask| = (num_tokens, num_experts, capacity)

        dispatched_input = einsum(
            "sec,sm->ecm", dispatch_mask.type_as(inputs), reshaped_input
        )
        # |dispatched_input| = (num_experts, capacity, d_model)

        # Dispatch tokens to each expert
        dispatched_input = AllToAll.apply(self.ep_group, dispatched_input)
        self.link_info["a2a_shape"] = dispatched_input.shape
        # |dispatched_input| = (num_experts, capacity, in_features)

        # Reshape tokens for convenience of experts' forward operation
        dispatched_input = dispatched_input.reshape(
            self.ep_size, self.num_local_experts, -1, self.in_features
        )
        # |dispatched_input| = (ep_size, num_local_experts, capacity, in_features)

        expert_output = self.front_experts(dispatched_input)
        # |expert_output| = (ep_size, num_local_experts, capacity, out_features)

        self.link_info["front_output_shape"] = expert_output.shape
        output = expert_output.reshape(-1, self.link_info["front_output_shape"][-1])
        # |output| = (ep_size * num_local_experts * capacity, out_features)

        if self.use_residual:
            # residual_inter, self.link_info["residual_weight"] = self.residual_forward(
            #    inputs
            # )
            residual_inter, self.link_info["residual_weight"] = self.residual(inputs)

            self.link_info["residual_inter_shape"] = residual_inter.shape
            residual_inter = residual_inter.reshape(
                -1, self.link_info["residual_inter_shape"][-1]
            )
            # |residual_inter| = (sent_len * batch_size, out_features)

            output = torch.cat([output, residual_inter], dim=0)
            # |output| = (ep_size * num_local_experts * capacity + sent_len * batch_size, out_features)

        return output

# TODO: implement tutel for efficient communication
class ExpertParallelBehindBlock(Module):
    def __init__(
        self,
        link_info: dict,
        in_features: int,
        out_features: int,
        experts: Experts,
        ep_size: int,
        num_local_experts: int,
        use_residual: bool = False,
        residual: Optional[nn.Module] = None,
    ):
        super().__init__()

        self.link_info = link_info

        self.in_features = in_features
        self.out_features = out_features

        self.behind_experts = experts
        self.ep_group = None
        self.ep_size = ep_size
        self.num_local_experts = num_local_experts

        self.use_residual = use_residual
        self.residual = None
        if use_residual:
            assert (
                residual is not None
            ), "If you want to use residual moe, then you must give residual instance"
            # self.residual = residual
            self.residual = ExpertParallelBehindResidual(residual)

    def _set_ep_group(self, ep_group):
        self.ep_group = ep_group

    def forward(self, inputs):
        # |inputs| =  (ep_size * num_local_experts * capacity, in_features) if not use_residual
        #         or (ep_size * num_local_experts * capacity + sent_len * batch_size, out_features) if use_residual

        dim0, dim1, dim2, _ = self.link_info["front_output_shape"]
        front_output = inputs[: dim0 * dim1 * dim2].reshape(
            self.link_info["front_output_shape"]
        )
        # |front_output| = (ep_size, num_local_experts, capacity, out_features)

        expert_output = self.behind_experts(front_output)
        expert_output = AllToAll.apply(self.ep_group, expert_output)
        # |expert_output| = (ep_size, num_local_experts, capacity, out_features)

        expert_output = expert_output.reshape(
            self.ep_size * self.num_local_experts, -1, self.out_features
        )
        # |expert_output| = (ep_size * num_local_experts, capacity, out_features)

        # Combine
        combined_output = einsum(
            "sec,ecm->sm",
            self.link_info["combine_weights"].type_as(front_output),
            expert_output,
        )
        # |combined_output| = (token_num = batch_size * sent_len, out_features)

        output = combined_output.reshape(self.link_info["inputs_shape"])
        # |output| = (sent_len, batch_size, out_features)
        #         or (batch_size, sent_len, out_features)

        # Resiudal
        if self.use_residual:
            residual_inter = inputs[dim0 * dim1 * dim2 :].reshape(
                self.link_info["residual_inter_shape"]
            )
            # |residual_inter| = (sent_len, batch_size, in_features)
            #                 or (batch_size, sent_len, in_features)

            residual_output = self.residual(residual_inter)
            # |residual_output| = (sent_len, batch_size, out_features)

            output = (
                output * self.link_info["residual_weight"][..., 0:1]
                + residual_output * self.link_info["residual_weight"][..., 1:]
            )
            # |output| = (sent_len, batch_size, out_features)

        return output


import config
import parser

import notifier
import vegetableCheck
from scraper import Scraper

def main():
    scraper = Scraper(cache_name=__name__, cache_expiry=36000)
    scrapedHtml = scraper.get(url=config.riverfordUrl)

    allBoxesInfo = parser.parseBoxContentsPage(scrapedHtml)

    message = getMessage(allBoxesInfo)
    if message:
        notifier.sendSlackNotification(message)

def getMessage(allBoxesInfo):
    if vegetableCheck.containsVegetable(config.unwantedVegetable,
                                        allBoxesInfo[config.preferredBox]):
        altBoxes = vegetableCheck.findAlternativeBoxes(
                                                    config.unwantedVegetable,
                                                    allBoxesInfo,
                                                    config.allowedBoxes)
        if len(altBoxes):
            return ("Your preferred box has %s in it this week. "
                    "But fear not, there are "
                    "%s free alternatives: %s" % (config.unwantedVegetable,
                                                  ', '.join(altBoxes)))
        else:
            return ("Alas, *all your box options contain %s* this week. "
                    "Bad luck.\n\n*Contents:*\n%s" % (
                                config.unwantedVegetable,
                                '\n'.join(allBoxesInfo[config.preferredBox])))
    else:
        return ("*You are free from %s this week.*\n\n*Contents:*"
                "\n%s" % (config.unwantedVegetable,
                          '\n'.join(allBoxesInfo[config.preferredBox])))

if __name__ == '__main__':
    main()


from sqlalchemy import func, desc
from sqlalchemy.orm import aliased

from src.models import Follow
from src.utils.db_session import get_db_read_replica
from src.queries import response_name_constants
from src.queries.query_helpers import populate_user_metadata, add_query_pagination
from src.queries.get_unpopulated_users import get_unpopulated_users

def get_followees_for_user(args):
    users = []
    follower_user_id = args.get('follower_user_id')
    current_user_id = args.get('current_user_id')
    limit = args.get('limit')
    offset = args.get('offset')

    db = get_db_read_replica()
    with db.scoped_session() as session:
        # correlated subquery sqlalchemy code:
        # https://groups.google.com/forum/#!topic/sqlalchemy/WLIy8jxD7qg
        inner_follow = aliased(Follow)
        outer_follow = aliased(Follow)

        # subquery to get a user's follower count
        inner_select = (
            session.query(
                func.count(inner_follow.followee_user_id)
            )
            .filter(
                inner_follow.followee_user_id == outer_follow.followee_user_id,
                inner_follow.is_current == True,
                inner_follow.is_delete == False
            )
            .correlate(outer_follow)
        )

        # get all users followed by input user, sorted by their follower count desc
        outer_select = (
            session.query(
                outer_follow.followee_user_id,
                inner_select.as_scalar().label(response_name_constants.follower_count)
            )
            .filter(
                outer_follow.follower_user_id == follower_user_id,
                outer_follow.is_current == True,
                outer_follow.is_delete == False
            )
            .group_by(outer_follow.followee_user_id)
            .order_by(desc(response_name_constants.follower_count))
        )
        followee_user_ids_by_follower_count = add_query_pagination(
            outer_select, limit, offset).all()

        user_ids = [user_id for (user_id, follower_count)
                    in followee_user_ids_by_follower_count]

        # get all users for above user_ids
        users = get_unpopulated_users(session, user_ids)

        # bundle peripheral info into user results
        users = populate_user_metadata(
            session, user_ids, users, current_user_id)

        # order by follower_count desc
        users.sort(
            key=lambda user: user[response_name_constants.follower_count],
            reverse=True
        )

    return users


#!/usr/bin/python
import rospy, cv2, cv_bridge, numpy
from sensor_msgs.msg import Image
from geometry_msgs.msg import Twist

rospy.init_node('follower')

last_time=rospy.Time.now()
time=rospy.Time.now()
e_last=0
time_diff=0
cy_last=0
cy_total=0

class Follower:
    def __init__(self):
        self.bridge = cv_bridge.CvBridge()
        cv2.namedWindow("window", 1)
        self.image_sub = rospy.Subscriber('camera/rgb/image_raw',Image, self.image_callback)
        #certain bots like turtlebot 2 has this same publisher, while some have it as only 'cmd_vel'
        self.cmd_vel_pub = rospy.Publisher('cmd_vel_mux/input/teleop',Twist, queue_size=1)
        self.twist = Twist()
        # kp and kd may vary according to the bot used, so tune accordingly
        self.kp=0.1
        self.kd=0.5
        self.time=rospy.Time.now()
    def image_callback(self, msg):
        self.image = self.bridge.imgmsg_to_cv2(msg,desired_encoding='bgr8') #using HSV for the robot to work in varied lighting
        hsv = cv2.cvtColor(self.image, cv2.COLOR_BGR2HSV)
        lower_yellow = numpy.array([10, 10, 10])  #lower limit of yellow line
        upper_yellow = numpy.array([255, 255, 250]) #upper limit of yellow line
        mask = cv2.inRange(hsv, lower_yellow, upper_yellow)
        h, w, d = self.image.shape
        search_bot = 3*h/4 + 50
        #limiting the image feed so as to decrease proccesing and lag
        mask[search_bot:h, 0:w]=0
        M = cv2.moments(mask)
        if M['m00'] != 0:
            self.cx = int(M['m10']/M['m00'])
            self.cy = int(M['m01']/M['m00'])
            cv2.circle(self.image, (self.cx, self.cy), 20, (0,0,255), -1)
            err =self.cx - w/2
            self.pd(err)
        #robot may stop few cms befor the end of staright line, so this following code helps in traversing it
        else:
            self.twist.angular.z=0
            if rospy.Time.now().to_sec()<=(self.time.to_sec()+30): #this number i.e '30' may change according to bot used, so tune accordingly
                self.twist.linear.x=0.2
                self.cmd_vel_pub.publish(self.twist)
                cv2.imshow("window", self.image)
                cv2.waitKey(3)
            else:
                self.twist.linear.x=0
                self.cmd_vel_pub.publish(self.twist)
                cv2.imshow("window", self.image)
                cv2.waitKey(3)

    def pd(self, e):
        #this is the code for the pd controller
        global e_last
        global last_time
        global time_diff
        global time
        global cy_last
        global cy_total
        if e_last==0:
            last_time=rospy.Time.now()
            self.twist.angular.z=-((self.kp*e)/100)

        else:
            self.time=rospy.Time.now()
            time_diff=self.time-last_time
            last_time=self.time
            self.twist.angular.z=-((self.kp*e-abs(self.kd*((e-e_last)/(time_diff.to_sec()))))/100)
        #linear velocity shd be low when angular velocity is high and vice versa, so the following code is used
        self.twist.linear.x=abs(0.2-abs(self.twist.angular.z)/40)
        self.cmd_vel_pub.publish(self.twist)
        cv2.imshow("window", self.image)
        cv2.waitKey(3)

follower = Follower()
rospy.spin()


from cegispro2.synthesis.TemplateRefinement.TemplateRefiner import TemplateRefiner
from pysmt.shortcuts import TRUE, And, GE, LT, Int, Implies, Real, Symbol, INT, ToReal
from cegispro2.synthesis.synthesis_utils import *
from cegispro2.expectations.Expectation import Expectation
import itertools

logger = logging.getLogger("cegispro2")

class VariablePartitionTemplateRefiner(TemplateRefiner):
    """
    Fixed-partition.
    Refinement strategy that obtains a new template by splitting the last instance of the current template into inductive and non-inductive parts.
    """
    def __init__(self, variables, char_fun, property, options, statistics):
        super(VariablePartitionTemplateRefiner, self).__init__(variables,char_fun,property,options, statistics)

        self.instantiate_parameters = Expectation.instantiate
        self.synthesize_parameter_valuation = get_model
        if options.optimizing_synthesizer:
            raise Exception("Optimizing synthesizer is not supported for the variable template refiner.")

    def get_next_counterexample_state(self, f, phi_f, exp_temp, phi_exp_temp, last_cti, guard_of_last_cti, distance):
        """

        :param f:
        :param phi_f:
        :param last_cti:
        :param guard_index_of_last_cti:
        :param distance:
        :return: A tupel (new_distance, (s, *additional_info)) with s a state such that Phi(f)[s] > f[s] or f[s] < 0 or f[s] > property[s], or None if there is no such s.
        """
        # we have to check inductivity, safety, and non-negativity
        while True:
            double_distance_constraint = None
            if distance > 1:
                double_distance_constraint = get_double_distance_constraint(self.variables, last_cti, distance)

            last_cti_constraint = None
            # if guard_of_last_cti != None:
            #    last_cti_constraint = guard_of_last_cti.pysmt_expression

            self.statistics.inductivity_check_time.start_timer()

            # check for inductivity
            was_inductivity = False
            state_and_info = self.inductivity_check(phi_f, f, double_distance_constraint)
            if state_and_info == True:
                # if no cti, check for safety
                state_and_info = self.check_safety(f, self.property, double_distance_constraint)
                if state_and_info == True:
                    # check non-negativity
                    state_and_info = f.check_non_negativity(double_distance_constraint)

                    if not state_and_info == True:
                        logger.debug("cex type: non-negativity")
                    pass
                else:
                    logger.debug("cex type: safety")
            else:
                was_inductivity = True
                logger.debug("cex type: cti")

            self.statistics.inductivity_check_time.stop_timer()

            if state_and_info == True:
                # If there is no cti ...
                if double_distance_constraint == None:
                    # ... and there was no distance constraint, then we have an inductive invariant
                    if guard_of_last_cti == None:
                        return None
                    else:
                        logger.debug("No counterexample state. Reset guard_index_constraint.")
                        guard_of_last_cti = None
                        continue
                else:
                    # .... otherwise, we search for a cti with less distance
                    logger.debug("no counterexample state. Divide distance")
                    distance = distance // self.distance_constant
                    continue

            if was_inductivity:
                (cti, index_guard_linexp_phi_f, index_guard_linexp_f) = state_and_info
                logger.debug("Guard index f= %s" % index_guard_linexp_f)
                return (distance, (cti, phi_f.guard_linexp_pairs[index_guard_linexp_phi_f], f.guard_linexp_pairs[
                    index_guard_linexp_f]))  # we do not need the additional information for this type of template refinement
            else:
                (cex, _) = state_and_info
                return (distance, (cex, None, None))

    def get_constraint_from_counterexample_state(self, cti, exp_temp, phi_exp_temp, guard_linexp_phi_exp_temp,
                                                 guard_linexp_exp_temp):

        # Check whether we have a full model
        # for var in self.variables:
        #     if var not in cti:
        #         raise Exception("We need full solver models.")

        formulae = []
        var_to_val = {var: cti[var] for var in self.variables}

        state_formula = And([Equals(var, cti[var]) for var in self.variables])

        for (guard, linexp) in exp_temp.guard_templatelinexp_pairs:

            if is_sat([guard.pysmt_expression, state_formula] + self.template_var_constraint):
                # inductivity
                for (guard2, linexp2) in phi_exp_temp.guard_linexp_pairs:
                    if is_sat([guard2.pysmt_expression, state_formula] + self.template_var_constraint):
                        lhs = And(guard.pysmt_expression, guard2.pysmt_expression).substitute(var_to_val).simplify()
                        rhs = self.constraint_inequality(linexp2, linexp).pysmt_expression.substitute(
                            var_to_val).simplify()
                        formulae.append(Implies(lhs, rhs))

                # non-negativity
                lhs = guard.pysmt_expression.substitute(var_to_val).simplify()
                rhs = LinearInequality.LEQ(LinearExpression.get_constant_expression(self.variables, Real(0)),
                                           linexp).pysmt_expression.substitute(var_to_val).simplify()
                formulae.append(Implies(lhs, rhs))

                # safety
                for (guard2, linexp2) in self.property.guard_linexp_pairs:
                    if is_sat([guard2.pysmt_expression, state_formula]):
                        lhs = guard.pysmt_expression.substitute(var_to_val).simplify()
                        rhs = self.constraint_inequality(linexp, linexp2).pysmt_expression.substitute(
                            var_to_val).simplify()
                        formulae.append(Implies(lhs, rhs))

        # logger.debug('Constraint: %s' % new_constraint.serialize())

        return formulae

    def get_constraints_from_existing_ctis(self, ctis, phi_exp_temp, exp_temp):
        res = []
        for cti in ctis:
            res += self.get_constraint_from_counterexample_state(cti, exp_temp, phi_exp_temp, None, None)
        return res


from itertools import count

def countFreq(arr, n):

   visited = [False for i in range(n)]
   count=0

   for i in range(n):

     if (visited[i] == True):
        continue

     for j in range(i + 1, n, 1):
        if (arr[i] == arr[j]):
          visited[j] = True
     count += 1

   print("The Count is ",count)

arr = [10, 30, 10, 20, 10, 20, 30, 10,46,44,44]
n = len(arr)
countFreq(arr, n)


"""
# -*- coding:utf-8 -*-
@Project : SmartKartRider
@File : PosDetection.py
@Author : Johan
@Time : 10/27/2022 11:07 PM

"""
import math
import cv2
import imutils
import numpy as np

from Utils.CVTools import cvDebugOut
from Vision.Detector import ShapeDetector
from Utils.Geometry import angle_between_vectors, direction_of_traingle
from KartriderKit.__init__ import ROOTPATH, RAW_DATA_PATH
import glob

from Vision.Filter import hsvFilter

class PosDetection:
    def __init__(self):
       self.up_norm = np.array([0, -1])
    def PosEstimationOnSmallMap(self, img_path, region = (80, 110, 85, 115), target_size = (100, 100), OutPutPath = ROOTPATH + "/Data/Debug/ArrowInSmallMap"):
        img = cv2.imread(img_path)
        img = cv2.resize(img[region[0]:region[1], region[2]:region[3]], target_size)
        lower = np.array([80, 80, 120])  # BGR
        upper = np.array([120, 255, 255])
        _, mask, _ = hsvFilter(img, lower, upper)
        cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL,
                                cv2.CHAIN_APPROX_SIMPLE)
        cnts = imutils.grab_contours(cnts)
        sd = ShapeDetector()
        if len(cnts) == 1:
            c = cnts[0]
            shape, train_points = sd.detect(c)
            train_points = train_points.reshape(len(train_points), -1)
            if len(train_points) == 3:
                k_dir_vet = direction_of_traingle(train_points)

                print(shape)
                result = angle_between_vectors(k_dir_vet, self.up_norm)
            else:
                print("No Triangle Detection! "+ img_path)
                cvDebugOut(OutPutPath, img)
                result = 0.0
        else:
            print("No Triangle Detection! " + img_path)
            cvDebugOut(OutPutPath, img)
            result = 0.0
        return result

if __name__ == "__main__":
    img_path_list = glob.glob(ROOTPATH+ '/raw_data/US/SmallMap/*.*', recursive=True)
    # print(img_path_list)
    pd = PosDetection()
    for i in range(len(img_path_list)):
        print(img_path_list[i])
        # img = cv2.imread(img_path_list[i])
        print(pd.PosEstimationOnSmallMap(img_path_list[i]))


import functools

def load_data(fun=None):
    res = []
    with open('input') as input:
        res = input.read().splitlines()
    if fun is not None:
        res = [fun(line) for line in res]
    return res

def load_list_of_ints():
    res = []
    with open('input') as input:
        res = [int(i) for line in
               input.read().splitlines() for i in line.split(',')]
    return res

def load_lists_of_strings():
    data = [line.rstrip('\r\n').split(',') for line in open('input')]
    return data

def trace_fn(fn):
    @functools.wraps(fn)
    def wrapper_debug(*args, **kargs):
        args_repr = [repr(a) for a in args]
        kargs_repr = [f'{k}={v!r}' for k,v in kargs.items()]
        sig = ', '.join(args_repr + kargs_repr)
        print(f'Calling {fn.__name__}({sig})')
        res = fn(*args, **kargs)
        print(f'{fn.__name__!r} returned {res!r}')
        return res
    return wrapper_debug


"""
This plugin searches for AWS key IDs
"""
import hashlib
import hmac
import re
import string
import textwrap
from datetime import datetime

import requests

from detect_secrets.core.constants import VerifiedResult
from detect_secrets.plugins.base import classproperty
from detect_secrets.plugins.base import RegexBasedDetector

class AWSKeyDetector(RegexBasedDetector):
    """Scans for AWS keys."""
    secret_type = 'AWS Access Key'

    denylist = (
        re.compile(r'AKIA[0-9A-Z]{16}'),
    )

    @classproperty
    def disable_flag_text(cls):
        return 'no-aws-key-scan'

    def verify(self, token, context):
        secret_access_key_candidates = get_secret_access_keys(context)
        if not secret_access_key_candidates:
            return VerifiedResult.UNVERIFIED

        for candidate in secret_access_key_candidates:
            if verify_aws_secret_access_key(token, candidate):
                return VerifiedResult.VERIFIED_TRUE

        return VerifiedResult.VERIFIED_FALSE

def get_secret_access_keys(content):
    # AWS secret access keys are 40 characters long.
    # e.g. some_function('AKIA...', '[secret key]')
    # e.g. secret_access_key = '[secret key]'
    regex = re.compile(
        r'(=|,|\() *([\'"]?)([%s]{40})(\2)(\))?' % (
            re.escape(string.ascii_letters + string.digits + '+/=')
        ),
    )

    return [
        match[2]
        for line in content.splitlines()
        for match in regex.findall(line)
    ]

def verify_aws_secret_access_key(key, secret):  # pragma: no cover
    """
    Using requests, because we don't want to require boto3 for this one
    optional verification step.

    Loosely based off:
    https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html

    :type key: str
    :type secret: str
    """
    now = datetime.utcnow()
    amazon_datetime = now.strftime('%Y%m%dT%H%M%SZ')

    headers = {
        # This is a required header for the signing process
        'Host': 'sts.amazonaws.com',
        'X-Amz-Date': amazon_datetime,
    }
    body = {
        'Action': 'GetCallerIdentity',
        'Version': '2011-06-15',
    }

    # Step #1: Canonical Request
    signed_headers = ';'.join(
        map(
            lambda x: x.lower(),
            headers.keys(),
        ),
    )
    canonical_request = textwrap.dedent("""
        POST
        /

        {headers}

        {signed_headers}
        {hashed_payload}
    """)[1:-1].format(

        headers='\n'.join([
            '{}:{}'.format(header.lower(), value)
            for header, value in headers.items()
        ]),
        signed_headers=signed_headers,

        # Poor man's method, but works for this use case.
        hashed_payload=hashlib.sha256(
            '&'.join([
                '{}={}'.format(header, value)
                for header, value in body.items()
            ]).encode('utf-8'),
        ).hexdigest(),
    )

    # Step #2: String to Sign
    region = 'us-east-1'
    scope = '{request_date}/{region}/sts/aws4_request'.format(
        request_date=now.strftime('%Y%m%d'),

        # STS is a global service; this is just for latency control.
        region=region,
    )

    string_to_sign = textwrap.dedent("""
        AWS4-HMAC-SHA256
        {request_datetime}
        {scope}
        {hashed_canonical_request}
    """)[1:-1].format(
        request_datetime=amazon_datetime,
        scope=scope,
        hashed_canonical_request=hashlib.sha256(
            canonical_request.encode('utf-8'),
        ).hexdigest(),
    )

    # Step #3: Calculate signature
    signing_key = _sign(
        _sign(
            _sign(
                _sign(
                    'AWS4{}'.format(secret).encode('utf-8'),
                    now.strftime('%Y%m%d'),
                ),
                region,
            ),
            'sts',
        ),
        'aws4_request',
    )

    signature = _sign(
        signing_key,
        string_to_sign,
        hex=True,
    )

    # Step #4: Add to request headers
    headers['Authorization'] = (
        'AWS4-HMAC-SHA256 '
        'Credential={access_key}/{scope}, '
        'SignedHeaders={signed_headers}, '
        'Signature={signature}'
    ).format(
        access_key=key,
        scope=scope,
        signed_headers=signed_headers,
        signature=signature,
    )

    # Step #5: Finally send the request
    response = requests.post(
        'https://sts.amazonaws.com',
        headers=headers,
        data=body,
    )

    if response.status_code == 403:
        return False

    return True

def _sign(key, message, hex=False):  # pragma: no cover
    value = hmac.new(key, message.encode('utf-8'), hashlib.sha256)
    if not hex:
        return value.digest()

    return value.hexdigest()