'''
Created on Nov 13 2017

@author: Theodore Jagodits

Pledge: I pledge my honor that I have abided by the Stevens honor system. - tjagodit

CS 115 HW 10
'''
D = {}
file_name = "musicrecplus.txt"

def findUsers():
    '''makes a global user list for functions to use'''
    users = []
    for j in D.keys():
        users.append(j)
    users.sort()
    return users

def findEUsers():
    '''makes a list of eligible users'''
    eUsers = []
    for i in D.keys():
        if i[-1] == '$':
            pass
        else:
            eUsers.append(i)
    eUsers.sort()
    return eUsers

def loadUsers(file_name):
    ''' Reads in a file of stored users' preferences stored
        in the file 'file_name'. Returns a dictionary containing
        user names to a list of preferred artists.'''
    my_File= open(file_name,"r")
    s = my_File.read()
    my_File.close()
    L = s.split("\n")
    L = filter(lambda y: len(y) != 0,L)
    for i in L:
        x = i.split(":")
        name = x[0]
        Artists = x[1].split(",")
        D[name]=Artists

def getPreferences(artistName):
    '''adds user and prefs to dictionary'''
    artists = []
    while(1):
        artist = input('Enter an artist that you like (Enter to finish): ')
        if artist == '':
            break
        artists.append(artist)
    artists.sort()
    D[artistName] = artists

def getRecomendations(eUsers,name):
    ''' Gets recommendations for a user (currUser) based
            on the users in D (a dictionary)
            and the user's preferences in pref (a list).
            Returns a list of recommended artists.  '''
    result = []
    if name in eUsers:
        x = findCloseUsers(name,D[name],eUsers)
        if x == []:
            print( 'No recommendations available at this time')
            return None
        for i in x:
            for j in drop_matches(D[name], D[i]):
                result.append(j)
        result.sort()
        for s in result:
            print (s)
    else:
        print( 'There is no user available named ' + name)

def repeater(p):
    '''Returns the artist repeated the most and the number of times it repeats'''
    E = {}
    for j in p:
        if j in E:
            E[j] += 1
        else:
            E[j] = 1
    x = ''
    n = 0
    for i in E:
        if E[i]> n :
            n = E[i]
            x = i
        elif E[i] == n:
            x += '\n' + i
    return [x,n]

def mostPopular(eUsers):
    ''' Returns the most popular artists, the artist that appears most in\
    everyones lists'''
    p = []
    for i in eUsers:
        p += D[i]
    return repeater(p)[0]

def numPopular(eUsers):
    ''' Returns the number of times the most popular artist repeats'''
    p = []
    for i in eUsers:
        p += D[i]
    return repeater(p)[1]

def userLikes(eUsers):
    ''' Returns the user with the most likes '''
    u = ''
    max_val = 0
    for i in eUsers:
        if len(D[i]) > max_val:
            max_val = len(D[i])
            u = i
        elif len(D[i]) == max_val:
            u += '\n' + i
    return u

def findCloseUsers(currUser,prefs,eUsers):
    '''finds all users that match with 2 or more'''
    result = []
    for i in eUsers:
        if num_matches(D[i],prefs) > 0 and num_matches(D[i],prefs) != len(prefs):
            if i != currUser:
                result.append(i)
    return result

def drop_matches(list1, list2):
    '''Returns a new list that contains only the elements in list2 that are NOT
    in list1.'''
    list1.sort()
    list2.sort()
    result = []
    i = 0
    j = 0
    while i < len(list1) and j < len(list2):
        if list1[i] == list2[j]:
            i += 1
            j += 1
        elif list1[i] < list2[j]:
            i += 1
        else:
            result.append(list2[j])
            j += 1
    while j < len(list2):
        result.append(list2[j])
        j += 1
    return result

def num_matches(list1, list2):
    '''Returns the number of elements that the two lists have in common.'''
    list1.sort()
    list2.sort()
    matches = j = i = 0
    while i < len(list1) and j < len(list2):
        if list1[i] == list2[j]:
            matches += 1
            i += 1
            j += 1
        elif list1[i] < list2[j]:
            i += 1
        else:
            j += 1
    return matches

def saveUserPreferences(users):
    ''' Writes all of the user preferences to the file.
            Returns nothing. '''
    my_File = open(file_name,"w")
    for i in users:
        string = ''
        for j in D[i]:
            string += j + ','
        my_File.write(i+":"+string[:-1]+"\n")
    my_File.close()

def menu():
    '''Returns the menu'''
    print('Enter a letter to choose an option:\ne - Enter Preferences\nr - Get recommendations\np - Show most popular artists\nh - How popular is most popular\nm - Which user has the most likes\nq - Save and quit')

def getInput():
    '''Prompts the user to enter a command until it enters a valid command'''
    x = input()
    while not (x in ['e','r','p','h','m','q']):
        x = input('Invalid entry, enter another command')
    return x

def main():
    ''' The main function
    if users is new, then it asks for name'''
    loadUsers(file_name)
    users = findUsers()
    name = input('Enter your name (put a $ symbol after your name if you wish your preferences to remain private):\n')
    name = name.strip()
    name = name.title()
    if name not in users:
        getPreferences(name)
    while(1):
        loadUsers(file_name)
        menu()
        eUsers = findEUsers()
        users = findUsers()
        Input = getInput()
        if Input == 'e':
            getPreferences(name)
            users = findUsers()
            eUsers = findEUsers()
            saveUserPreferences(users)
        if Input == 'r':
            getRecomendations(eUsers,name)
        if Input == 'p':
            print (mostPopular(eUsers))
        if Input == 'h':
            print (numPopular(eUsers))
        if Input == 'm':
            print (userLikes(eUsers))
        if Input == 'q':
            break
    saveUserPreferences(users)

loadUsers(file_name)
main()


import time
from .MachinePlayerAbstract import MachinePlayerAbstract

class MachinePlayerMinMax(MachinePlayerAbstract):
    """ Computer Player controlled by an IA (MinMax algorithm)
    """
    def __init__(self, color):
        """
        Constructor
        :param color: character entered in the grid for example: `o` or `x`
        :return:
        """
        super(MachinePlayerMinMax, self).__init__(color)
        self._type = "MinMax Player"

    def _get_best_move(self, grid):
        """
        Search and return the best "move" (column index)
        :param grid: the grid of the connect four
        :return best_move: the best "move" (column index)
        """
        # start time
        start_time = int(round(time.time() * 1000))
        # determine opponent's color
        opponent_color = self._determine_color()

        # enumerate all legal moves
        # will map legal move states to their alpha values
        legal_moves = {}
        # check if the move is legal for each column

        for col in range(len(grid)):
            if self._is_legal_move(col, grid):
                # simulate the move in column `col` for the current player
                tmp_grid = self._simulate_move(grid, col, self._color)
                legal_moves[col] = -self._find(self._difficulty - 1, tmp_grid, opponent_color)

        best_alpha = -99999999
        best_move = None
        moves = legal_moves.items()
        # search the best "move" with the highest `alpha` value
        for move, alpha in moves:
            if alpha >= best_alpha:
                best_alpha = alpha
                best_move = move

        end_time = int(round(time.time() * 1000))
        print("response time: {}".format(end_time - start_time))

        return best_move

    def _find(self, depth, grid, curr_player_color):
        """
        Searches in the tree at depth = `depth` till it's not equal to 0. This function is recursive
        :param depth: the current depth of the tree
        :param grid: a grid of the connect four
        :param curr_player_color: the color of the current player
        :return alpha: value calculated with an heuristic. It represent the value of a "move" (column index)
        """
        # enumerate all legal moves from this state
        legal_moves = []
        for i in range(len(grid)):
            if self._is_legal_move(i, grid):
                # simulate the move in column i for curr_player
                tmp_grid = self._simulate_move(grid, i, curr_player_color)
                legal_moves.append(tmp_grid)

        if depth == 0 or len(legal_moves) == 0 or self._game_is_over(grid):
            # return the heuristic value of node
            return self._eval_game(depth, grid, curr_player_color)

        # determine opponent's color
        opp_player_color = self._determine_color()

        alpha = -99999999
        for child in legal_moves:
            if child == None:
                print("child == None (search)")
            alpha = max(alpha, -self._find(depth - 1, child, opp_player_color))
        return alpha

    def _eval_game(self, depth, grid, player_color):
        """
        Evaluate the game with its grid
        :param depth: the depth of the tree
        :param grid: a grid of connect four
        :param player_color: the current player's color
        :return: alpha : value calculated with an heuristic. It represent the value of a "move" (column index)
        """
        if player_color == 'x':
            opp_color = 'o'
        else:
            opp_color = 'x'
        # get scores of human and IA player with theirs streaks
        ia_fours = self._find_streak(grid, player_color, 4)
        ia_threes = self._find_streak(grid, player_color, 3)
        ia_twos = self._find_streak(grid, player_color, 2)
        human_fours = self._find_streak(grid, opp_color, 4)
        human_threes = self._find_streak(grid, opp_color, 3)
        human_twos = self._find_streak(grid, opp_color, 2)
        # calculate and return the alpha
        if human_fours > 0:
            return -100000 - depth
        else:
            return (ia_fours * 100000 + ia_threes * 100 + ia_twos * 10) - (human_threes * 100 + human_twos * 10) + depth


import torch
import os
import json
from tqdm import tqdm
import time

#Load the translation model
#en2de = torch.hub.load('pytorch/fairseq', 'transformer.wmt16.en-de',tokenizer='moses', bpe='subword_nmt')
en2de = torch.hub.load('pytorch/fairseq', 'transformer.wmt19.en-de',tokenizer='moses', bpe='fastbpe',checkpoint_file='model1.pt:model2.pt:model3.pt:model4.pt')
en2de.eval()
en2de.cuda()
print("Loaded the Translation Model")

#Load the original CC data
data_path = "/home/zmykevin/multilingual_VL/data/CC/annotations"
cc_annotation = '/'.join([data_path, "dataset_cc.json"])

with open(cc_annotation, "r") as f:
    cc_data = json.load(f)
print("Loaded CC Original Data. \n")

#Translate the CC
cc_imgs = cc_data['images']

total_elements = len(cc_imgs)
batch_size = 32
cc_data_de = {"images":[], "dataset": cc_data['dataset']}
output_cc_data_path = '/'.join([data_path, "dataset_cc_de.json"])

start_time = time.perf_counter()
for i in tqdm(range(0,total_elements,batch_size)):
    #form the batch of sentences
    captions_en_batch = [x['sentences'][0]['raw'] for x in cc_imgs[i:i+batch_size]]
    #print(captions_en_batch)
    captions_de_batch = en2de.translate(captions_en_batch)
    #print(captions_de_batch)
    for j in range(i,i+batch_size):
        cc_data['images'][j]['sentences'][0]['raw'] = captions_de_batch[j-i]
        cc_data['images'][j]['sentences'][0]['tokens'] = captions_de_batch[j-i].split()
        cc_data_de['images'].append(cc_data['images'][j])
    #save cc_data_de
    if i % 32000 == 0:
        with open(output_cc_data_path, "w") as f_out:
            json.dump(cc_data_de, f_out, indent=4, sort_keys=True)
        #break
    # if i > 64:
    # 	break
#print(cc_data_de["images"][0])
print("Finished Translation in {} seconds. \n".format(time.perf_counter()-start_time))
# cc_data_de = {"images":[], "dataset": cc_data['dataset']}
# for img in tqdm(cc_imgs):
#     img_de = img.copy()
#     #translate the caption
#     caption_en = img_de['sentences'][0]['raw']
#     caption_de = en2de.translate(caption_en)
#     tokens_de = caption_de.split()
#     #update img_de
#     img_de['sentences'][0]['tokens'] = tokens_de
#     img_de['sentences'][0]['raw'] = caption_de
#     cc_data_de['images'].append(img_de)
#     #break

# #save the new data to output file
# output_cc_data_path = '/'.join([data_path, "dataset_cc_de.json"])
# with open(output_cc_data_path, "w") as f_out:
#     json.dump(cc_data_de, f_out, indent=4, sort_keys=True)


#Grab all of the fits, output them as fits
#Suggested use:
#python collateFits.py -o ~/Repos/monoAbundanceMW/monoAbundanceMW/data/monoAbundanceResults.fits ../fits/pixelFitG_DblExp_BigPix0.1.sav ../fits/pixelFitG_DblExp_BigPix0.1_1000samples.sav ../fits/pixelFitG_Mass_DblExp_BigPix0.1_simpleage.sav ../fits/pixelFitG_Mass_DblExp_BigPix0.1_simpleage_100samples.sav ../fits/pixelFitG_Vel_HWR_BigPix0.1.sav ../fits/pixelFitG_Vel_HWR_BigPix0.1_10ksamples.sav ../fits/pixelFitG_VelR_HWR_BigPix0.1.sav ../fits/pixelFitG_VelR_HWR_BigPix0.1_10ksamples.sav
#For K
#python collateFits.py -o ~/Repos/monoAbundanceMW/monoAbundanceMW/data/monoAbundanceResults_k.fits ../fits/pixelFitK_DblExp_BigPix0.1_minndata50.sav ../fits/pixelFitK_DblExp_BigPix0.1_minndata50_1000samples.sav ../fits/pixelFitG_Mass_DblExp_BigPix0.1_simpleage.sav ../fits/pixelFitG_Mass_DblExp_BigPix0.1_simpleage_100samples.sav ../fits/pixelFitK_Vel_HWR_BigPix0.1_minndata50.sav ../fits/pixelFitK_Vel_HWR_BigPix0.1_minndata50_1000samples.sav ../fits/pixelFitK_VelR_HWR_BigPix0.1_minndata50.sav ../fits/pixelFitK_VelR_HWR_BigPix0.1_minndata50_1000samples.sav --sample=k --select=program --minndata=50
import os, os.path
import cPickle as pickle
from optparse import OptionParser
import numpy
import fitsio
from pixelFitDens import pixelAfeFeh
from segueSelect import read_gdwarfs, read_kdwarfs, _gi_gr, _mr_gi, \
    segueSelect, _GDWARFFILE, _KDWARFFILE
from fitSigz import _ZSUN
def collateFits(options,args):
    if options.sample.lower() == 'g':
        if options.select.lower() == 'program':
            raw= read_gdwarfs(_GDWARFFILE,logg=True,ebv=True,sn=True)
        else:
            raw= read_gdwarfs(logg=True,ebv=True,sn=True)
    elif options.sample.lower() == 'k':
        if options.select.lower() == 'program':
            raw= read_kdwarfs(_KDWARFFILE,logg=True,ebv=True,sn=True)
        else:
            raw= read_kdwarfs(logg=True,ebv=True,sn=True)
    #Bin the data
    binned= pixelAfeFeh(raw,dfeh=options.dfeh,dafe=options.dafe)
    #Savefiles
    if os.path.exists(args[0]):#Load density fits
        savefile= open(args[0],'rb')
        densfits= pickle.load(savefile)
        savefile.close()
    else:
        raise IOError("density fits file not included")
    if os.path.exists(args[1]):#Load density fits
        savefile= open(args[1],'rb')
        denssamples= pickle.load(savefile)
        savefile.close()
    else:
        raise IOError("density samples file not included")
    if os.path.exists(args[2]):#Load density fits
        savefile= open(args[2],'rb')
        mass= pickle.load(savefile)
        savefile.close()
    else:
        raise IOError("masses file not included")
    #if os.path.exists(args[3]):#Load density fits
    #    savefile= open(args[3],'rb')
    #    masssamples= pickle.load(savefile)
    #    savefile.close()
    #else:
    #    raise IOError("mass samples file not included")
    if os.path.exists(args[4]):#Load density fits
        savefile= open(args[4],'rb')
        velfits= pickle.load(savefile)
        savefile.close()
    else:
        raise IOError("vertical velocity file not included")
    if os.path.exists(args[5]):#Load density fits
        savefile= open(args[5],'rb')
        velsamples= pickle.load(savefile)
        savefile.close()
    else:
        raise IOError("vertical velocity samples  file not included")
    if os.path.exists(args[6]):#Load density fits
        savefile= open(args[6],'rb')
        velrfits= pickle.load(savefile)
        savefile.close()
    else:
        raise IOError("radial velocity file not included")
    if os.path.exists(args[7]):#Load density fits
        savefile= open(args[7],'rb')
        velrsamples= pickle.load(savefile)
        savefile.close()
    else:
        raise IOError("radial velocity samples  file not included")
    nrecs= len([r for r in densfits if not r is None])
    out= numpy.recarray(nrecs,dtype=[('feh',float),
                                     ('afe',float),
                                     ('hz',float),
                                     ('hr',float),
                                     ('bc',float),
                                     ('mass',float),
                                     ('sz',float),
                                     ('hsz',float),
                                     ('p1',float),
                                     ('p2',float),
                                     ('sr',float),
                                     ('hsr',float),
                                     ('zmin',float),
                                     ('zmax',float),
                                     ('zmedian',float),
                                     ('hz_err',float),
                                     ('hr_err',float),
                                     ('mass_err',float),
                                     ('sz_err',float),
                                     ('hsz_err',float),
                                     ('p1_err',float),
                                     ('p2_err',float),
                                     ('szp1_corr',float),
                                     ('szp2_corr',float),
                                     ('szhsz_corr',float),
                                     ('p1hsz_corr',float),
                                     ('p2hsz_corr',float),
                                     ('p1p2_corr',float),
                                     ('sr_err',float)])

    nout= 0
    #Start filling it up
    for ii in range(binned.npixfeh()):
        for jj in range(binned.npixafe()):
            data= binned(binned.feh(ii),binned.afe(jj))
            fehindx= binned.fehindx(binned.feh(ii))#Map onto regular binning
            afeindx= binned.afeindx(binned.afe(jj))#Unnecessary here
            if afeindx+fehindx*binned.npixafe() >= len(densfits):
                continue
            thisdensfit= densfits[afeindx+fehindx*binned.npixafe()]
            thisdenssamples= denssamples[afeindx+fehindx*binned.npixafe()]
            thismass= mass[afeindx+fehindx*binned.npixafe()]
            #thismasssamples= masssamples[afeindx+fehindx*binned.npixafe()]
            thisvelfit= velfits[afeindx+fehindx*binned.npixafe()]
            thesevelsamples= velsamples[afeindx+fehindx*binned.npixafe()]
            thisvelrfit= velrfits[afeindx+fehindx*binned.npixafe()]
            thesevelrsamples= velrsamples[afeindx+fehindx*binned.npixafe()]
            if thisdensfit is None:
                continue
            if len(data) < options.minndata:
                continue
            out['feh'][nout]= binned.feh(ii)
            out[nout]['afe']= binned.afe(jj)
            if options.densmodel.lower() == 'hwr' \
                    or options.densmodel.lower() == 'dblexp':
                out[nout]['hz']= numpy.exp(thisdensfit[0])*1000.
                if options.densmodel.lower() == 'dblexp':
                    out[nout]['hr']= numpy.exp(-thisdensfit[1])
                else:
                    out[nout]['hr']= numpy.exp(thisdensfit[1])
                out[nout]['bc']= thisdensfit[2]
                theseerrors= []
                xs= numpy.array([s[0] for s in thisdenssamples])
                theseerrors.append(0.5*(-numpy.exp(numpy.mean(xs)-numpy.std(xs))+numpy.exp(numpy.mean(xs)+numpy.std(xs))))
                out[nout]['hz_err']= theseerrors[0]*1000.
                if options.densmodel.lower() == 'dblexp':
                    xs= numpy.array([-s[1] for s in thisdenssamples])
                else:
                    xs= numpy.array([s[1] for s in thisdenssamples])
                theseerrors.append(0.5*(-numpy.exp(numpy.mean(xs)-numpy.std(xs))+numpy.exp(numpy.mean(xs)+numpy.std(xs))))
                out[nout]['hr_err']= theseerrors[1]
            #mass
            if options.sample.lower() == 'k':
                out[nout]['mass']= numpy.nan
            else:
                out[nout]['mass']= thismass/10.**6.
            #out[nout]['mass_err']= numpy.std(numpy.array(thismasssamples)/10.**6.)
            #Velocities
            if options.velmodel.lower() == 'hwr':
                out[nout]['sz']= numpy.exp(thisvelfit[1])
                out[nout]['hsz']= numpy.exp(thisvelfit[4])
                out[nout]['sr']= numpy.exp(thisvelrfit[1])
                out[nout]['hsr']= numpy.exp(thisvelrfit[4])
                out[nout]['p1']= thisvelfit[2]
                out[nout]['p2']= thisvelfit[3]
                zsorted= sorted(numpy.fabs(data.zc+_ZSUN))
                out[nout]['zmin']= zsorted[int(numpy.ceil(0.16*len(zsorted)))]*1000.
                out[nout]['zmax']= zsorted[int(numpy.floor(0.84*len(zsorted)))]*1000.
                out[nout]['zmedian']= numpy.median(numpy.fabs(data.zc)-_ZSUN)*1000.
                #Errors
                xs= numpy.array([s[1] for s in thesevelsamples])
                out[nout]['sz_err']= 0.5*(-numpy.exp(numpy.mean(xs)-numpy.std(xs))+numpy.exp(numpy.mean(xs)+numpy.std(xs)))
                xs= numpy.array([s[4] for s in thesevelsamples])
                out[nout]['hsz_err']= 0.5*(-numpy.exp(numpy.mean(xs)-numpy.std(xs))+numpy.exp(numpy.mean(xs)+numpy.std(xs)))
                xs= numpy.array([s[2] for s in thesevelsamples])
                out[nout]['p1_err']= numpy.std(xs)
                xs= numpy.array([s[3] for s in thesevelsamples])
                out[nout]['p2_err']= numpy.std(xs)
                xs= numpy.exp(numpy.array([s[1] for s in thesevelsamples]))
                ys= numpy.array([s[2] for s in thesevelsamples])
                out[nout]['szp1_corr']= numpy.corrcoef(xs,ys)[0,1]
                ys= numpy.array([s[3] for s in thesevelsamples])
                out[nout]['szp2_corr']= numpy.corrcoef(xs,ys)[0,1]
                xs= numpy.array([s[2] for s in thesevelsamples])
                out[nout]['p1p2_corr']= numpy.corrcoef(xs,ys)[0,1]
                xs= numpy.exp(numpy.array([s[4] for s in thesevelsamples]))
                ys= numpy.exp(numpy.array([s[1] for s in thesevelsamples]))
                out[nout]['szhsz_corr']= numpy.corrcoef(xs,ys)[0,1]
                ys= numpy.array([s[2] for s in thesevelsamples])
                out[nout]['p1hsz_corr']= numpy.corrcoef(xs,ys)[0,1]
                ys= numpy.array([s[3] for s in thesevelsamples])
                out[nout]['p2hsz_corr']= numpy.corrcoef(xs,ys)[0,1]
                xs= numpy.array([s[1] for s in thesevelrsamples])
                out[nout]['sr_err']= 0.5*(-numpy.exp(numpy.mean(xs)-numpy.std(xs))+numpy.exp(numpy.mean(xs)+numpy.std(xs)))
            nout+= 1
    #Write output
    fitsio.write(options.outfile,out,clobber=True)

def get_options():
    usage = "usage: %prog [options] <savefiles> <savefile>\n\nsavefiles= (in this order) name of the file with the density fits\nname of the file with density samples\nname of the file with masses\nname of the file with mass samples\nname of the file with vertical velocity fits\nname of the file with vertical velocity samples"
    parser = OptionParser(usage=usage)
    parser.add_option("-o",dest='outfile',default=None,
                      help="Name for output file")
    parser.add_option("--sample",dest='sample',default='g',
                      help="Use 'G' or 'K' dwarf sample")
    parser.add_option("--select",dest='select',default='all',
                      help="Select 'all' or 'program' stars")
    parser.add_option("--dfeh",dest='dfeh',default=0.1,type='float',
                      help="FeH bin size")
    parser.add_option("--dafe",dest='dafe',default=0.05,type='float',
                      help="[a/Fe] bin size")
    parser.add_option("--minndata",dest='minndata',default=100,type='int',
                      help="Minimum number of objects in a bin to perform a fit")
    parser.add_option("--densmodel",dest='densmodel',default='hwr',
                      help="Density Model of fit")
    parser.add_option("--velmodel",dest='velmodel',default='hwr',
                      help="Density Model of fit")
    return parser

if __name__ == '__main__':
    parser= get_options()
    options,args= parser.parse_args()
    collateFits(options,args)


"""
Test the Item class.
"""

import pymongo
from bson.objectid import ObjectId
from tests.base import BaseTest

import unittest
import lib.text
from lib import data
import lib.query

from models.item import Item
from models.db import Db, ItemDb
PK = 'PROPS'
TK = 'TAGS'

class TestItem(BaseTest):

    def setUp(self):
        self.email = 'test@gmail.com'
        self.db = Db()
        self.item_db = ItemDb()

        self.db.items.remove()
        for x in data.gen_cannonical_items():
            self.db.items.insert(x)

        self.item_db.publish({})

    def test_items_exist(self):
        assert (len(self.db.items.find_one({'A': 0, 'B': 1})) >= 1)

    def test_item_initialization(self):
        #no request give empty request
        i = Item(None)
        assert (isinstance(i, Item))
        assert (i.request == {})

        #keys can be called directly through request.
        i = Item({PK: {'A': 1}})
        assert (i.request[PK] == {'A': 1})

    def test_item_rows(self):
        i = Item({PK: {'A': 1}})
        assert (len([x for x in i.rows]) == 2)

        i = Item({TK: ['A']})
        assert (len(list(i.rows)) == 4)

    def test_build_query(self):
        i = Item({})

        query, projection = lib.query.build(props={'A':0})
        assert ({'A':0} == query)
        assert (projection == {'A': 0})

        query, projection = lib.query.build(tags=['A'])
        assert (query == {'_tags': {"$all": ['A']}})
        assert (projection is None)

    def test_apply_function_to_values(self):

        i = Item({})

        chars = 'ext'
        new_chars = 'ZZZ'
        func = lambda x: str.replace(x, chars, new_chars)
        i.apply_function_to_values(func, prop='text')

        rows = list(i.item_db.get_rows({'text':'tZZZ'}))
        assert(len(rows) == 1)

        rows = list(i.item_db.get_rows({'text':'text'}))
        assert(len(rows) == 0)

    def test_replace_value_chars(self):

        i = Item({})
        i.replace_value_chars(chars='ext', new_chars='ZZZ', prop='text')

        rows = list(i.item_db.get_rows({'text':'tZZZ'}))
        assert(len(rows) == 1)

        rows = list(i.item_db.get_rows({'text':'text'}))
        assert(len(rows) == 0)

    def test_child_properties(self):
        i = Item({PK: {'A': 1}})
        child_properties = i.child_properties(i.rows)
        self.assertIsNotNone(child_properties)

    def test_hash(self):
        i = Item({PK: {'A': 1}})
        h = i.hash
        self.assertEqual(h, '59e74de16a7aefddb71de55f136d47b9')

    def test_add_image(self):
        image_url = 'http://www.wroscoe.com/uploads/7/8/1/7/7817903/7578675_orig.jpg'
        i = Item({})
        i.add_image(i.query, image_url)
        self.assertIsNotNone(list(i.rows)[0].get('_image_ids'))

    def test_get_item_by_upload_id(self):
        oid = str(ObjectId())
        item_row = {'A':'1'}
        #self.db.items.insert(item_row)
        self.item_db.insert_row(item_row, self.email, oid, True)
        print(list(self.db.items.find()))
        i = Item({'UPLOAD_ID': oid})
        self.assertEqual(len(list(i.rows)), 1)


# -*- coding: utf-8 -*-

# mui sample app

import sys
import asyncio
import time

from datetime import timezone, timedelta

from threading import Lock
mutex = Lock()

from mui_ui import Display, MuiFont, Text, Image, Widget, Border, AbsApp, Message, DigitalClock
from mui_ui import TextAlignment, MotionEvent, InputEvent, InputEventListener, InputHandler, OnTouchEventListener, AppEventListener, OnUpdateRequestListener
from mui_ui import GestureListener, GestureDetector
from mui_ui import Keyboard, KeyboardListener
from mui_ui import DisplayManager, DisplayEventListener

from app_wifisetting import WiFiSetting

import os
dir = os.path.dirname(os.path.abspath(__file__))

def get_file_path(name):
    return os.path.normpath(os.path.join(dir, name))

class ImageViewerApp(AbsApp, OnUpdateRequestListener, OnTouchEventListener):

    # please add images to this list.
    # when tap display, change to next image of this list.
    #
    # image requirements :
    # - width 200px
    # - height 32px
    # - PNG Image
    # - RGB format
    # - black pixel is turn on LED dot
    IMAGE_LIST = [
        './images/mount_fuji.png',
        './images/kyoto_arashiyama.png',
        './images/moon.png',
    ]

    def __init__(self, appEventListener: AppEventListener, lang='en-US'):
        super().__init__(appEventListener)

        self._lang = lang

        # create Image view
        # this view is fullscreen size
        def createImageView():
            widget = Widget(200, 32)
            self.addView(widget)

            imageView = Image(get_file_path(ImageViewerApp.IMAGE_LIST[self._image_index]))
            imageView.setSize(0, 0, 200, 32)
            imageView.addOnTouchViewListener(self)
            widget.addParts(imageView)
            self.setView(imageView, 'image_view')

        self._image_index = 0
        createImageView()

        self._next = None
        self._prev = None

    def setRelativeApps(self, next: AbsApp, prev: AbsApp):
        self._next = next
        self._prev = prev

    def _changeToNextImage(self):
        self._image_index += 1
        if self._image_index == len(ImageViewerApp.IMAGE_LIST):
            self._image_index = 0

        imageView = self.getView('image_view')
        imageView.setImage(get_file_path(ImageViewerApp.IMAGE_LIST[self._image_index]))
        self.updateRequest(0)

    # ------------------------
    # override AbsApp methods

    def startTask(self):
        # here is called when start this app
        pass

    def stopTask(self):
        pass

    def dispatchFlingEvent(self, e1, e2, x, y):
        if e1.x > e2.x:
            # next
            self.setNextApp(self._next)

        elif e1.x < e2.x:
            # prev
            self.setNextApp(self._prev)

        return True

    def onTurnOffDisplay(self):
        # allow turn off
        # if you do not want to allow auto turn off, please return False
        return True

    # ------------------------
    # OnUpdateRequestListener implementation

    def onUpdateView(self, view):
        self.updateRequest(0)

    # ------------------------
    # OnTouchEventListener implementation

    def onTouch(self, view, e):
        imageView = self.getView('image_view')

        if view == imageView:
            # change to next image
            self._changeToNextImage()

class DummyWeatherApp(AbsApp, OnUpdateRequestListener, OnTouchEventListener):

    def __init__(self, appEventListener: AppEventListener, lang='en-US'):
        super().__init__(appEventListener)

        self._lang = lang

        # create weather forecast UI
        def createWeatherForecastUI():
            widget = Widget(189, 32)
            widget.visible = False
            self.addView(widget)
            self.setView(widget, 'forecast_view')

            dateText = Text()
            dateText.setSize(9, 3, 80, 8)
            widget.addParts(dateText)
            self.setView(dateText, 'dateText')

            wIcon = Image()
            wIcon.setSize(15, 18, 26, 14)
            widget.addParts(wIcon)
            self.setView(wIcon, 'wIcon')

            highTemp = Text()
            highTemp.setSize(85, 3, 35, 8)
            widget.addParts(highTemp)
            self.setView(highTemp, 'hTemp')

            tempIconName = './assets/weather/icon_f.png' if self._lang == 'en-US' else './assets/weather/icon_c.png'
            tempIconPath = os.path.normpath(os.path.join(dir, tempIconName))

            hTempIcon = Image(tempIconPath)
            hTempIcon.setSize(98, 3, 9, 7)
            widget.addParts(hTempIcon)
            self.setView(hTempIcon, 'hTempIcon')

            lowTemp = Text()
            lowTemp.setSize(85, 21, 35, 8)
            widget.addParts(lowTemp)
            self.setView(lowTemp, 'lTemp')

            lTempIcon = Image(tempIconPath)
            lTempIcon.setSize(98, 21, 9, 7)
            widget.addParts(lTempIcon)
            self.setView(lTempIcon, 'lTempIcon')

            pIcon = Image()
            pIcon.setSize(134, 3, 9, 10)
            widget.addParts(pIcon)
            self.setView(pIcon, 'pIcon')

            pText = Text()
            pText.setSize(148, 3, 32, 8)
            widget.addParts(pText)
            self.setView(pText, 'pText')

            percentIconName = './assets/weather/icon_percent.png'
            percentIconPath = os.path.normpath(os.path.join(dir, percentIconName))

            percentIcon = Image(percentIconPath)
            percentIcon.setSize(160, 3, 3, 7)
            widget.addParts(percentIcon)
            self.setView(percentIcon, 'percentIcon')

            widget.visible = False

        # common area
        def createCommonMenu():
            # add home icon
            iconHome = Image(os.path.normpath(os.path.join(dir, './assets/icon_home.png')))
            iconHome.setSize(190, 0, iconHome.width, iconHome.height)
            iconHome.addOnTouchViewListener(self)
            self.addView(iconHome)
            self.setView(iconHome, 'home')

            # add current icon(this icon has no action)
            iconWeather = Image(os.path.normpath(os.path.join(dir, './assets/icon_weather.png')))
            iconWeather.setSize(191, 23, iconWeather.width, iconWeather.height)
            self.addView(iconWeather)

        createWeatherForecastUI()
        createCommonMenu()

        self._next = None
        self._prev = None

    def setRelativeApps(self, next: AbsApp, prev: AbsApp):
        self._next = next
        self._prev = prev

    def _setupDummyData(self):
        """
        set dummy data
        """
        self.getView('dateText').setText('21 July Sun.')
        self.getView('wIcon').setImage(os.path.normpath(os.path.join(dir, './assets/weather/icon_weather_101.png')))
        self.getView('hTemp').setText('28')
        self.getView('lTemp').setText('12')
        self.getView('pIcon').setImage(os.path.normpath(os.path.join(dir, './assets/weather/icon_precip_10.png')))
        self.getView('pText').setText('10')

        self.getView('forecast_view').visible = True
        self.updateRequest(2)

    # ------------------------
    # override AbsApp methods

    def startTask(self):
        self._setupDummyData()

    def stopTask(self):
        self.getView('forecast_view').visible = False

    def dispatchFlingEvent(self, e1, e2, x, y):
        if e1.x > e2.x:
            # next
            self.setNextApp(self._next)

        elif e1.x < e2.x:
            # prev
            self.setNextApp(self._prev)

        return True

    def dispatchLongPressEvent(self, e):
        pass

    def onTurnOffDisplay(self):
        # always allow turn off
        return True

    # ------------------------
    # OnUpdateRequestListener implementation

    def onUpdateView(self, view):
        self.updateRequest(0)

    # ------------------------
    # OnTouchEventListener implementation

    def onTouch(self, view, e):
        iconHome = self.getView('home')

        if view == iconHome:
            # close this application
            self.close()

class DummyThermoApp(AbsApp, OnUpdateRequestListener, OnTouchEventListener):

    def __init__(self, appEventListener: AppEventListener, lang='en-US'):
        super().__init__(appEventListener)

        dummy = Text('dummy thermostat UI')
        dummy.setSize(0, 11, 189, 8)
        self.addView(dummy)

        # common area
        def createCommonMenu():
            # add home icon
            iconHome = Image(os.path.normpath(os.path.join(dir, './assets/icon_home.png')))
            iconHome.setSize(190, 0, iconHome.width, iconHome.height)
            iconHome.addOnTouchViewListener(self)
            self.addView(iconHome)
            self.setView(iconHome, 'home')

            # add current icon(this icon has no action)
            iconWeather = Image(os.path.normpath(os.path.join(dir, './assets/icon_thermo.png')))
            iconWeather.setSize(191, 23, iconWeather.width, iconWeather.height)
            self.addView(iconWeather)

        createCommonMenu()

        self._next = None
        self._prev = None

    def setRelativeApps(self, next: AbsApp, prev: AbsApp):
        self._next = next
        self._prev = prev

    # ------------------------
    # override AbsApp methods

    def startTask(self):
        pass

    def stopTask(self):
        pass

    def dispatchFlingEvent(self, e1, e2, x, y):
        if e1.x > e2.x:
            # next
            self.setNextApp(self._next)

        elif e1.x < e2.x:
            # prev
            self.setNextApp(self._prev)

        return True

    def dispatchLongPressEvent(self, e):
        pass

    def onTurnOffDisplay(self):
        # always allow turn off
        return True

    # ------------------------
    # OnUpdateRequestListener implementation

    def onUpdateView(self, view):
        self.updateRequest(0)

    # ------------------------
    # OnTouchEventListener implementation

    def onTouch(self, view, e):
        iconHome = self.getView('home')

        if view == iconHome:
            # close this application
            self.close()

class HomeApp(AbsApp, OnUpdateRequestListener, OnTouchEventListener):

    def __init__(self, appEventListener: AppEventListener):
        super().__init__(appEventListener)

        # create home UI

        # add clock
        def addClock():
            tz = timezone(timedelta(hours=9)) # this timezone is JST(+9:00). please change to your timezone
            clock = DigitalClock(timezone=tz)
            clock.setPos(173, 0)
            clock.addOnUpdateViewListener(self)
            self.addView(clock)
            self.setView(clock, 'clock')

        # add menu
        def createMenu():
            # create weahter app icon
            iconWeather = Image(get_file_path('./assets/icon_weather.png'))
            iconWeather.addOnTouchViewListener(self)
            self.setView(iconWeather, 'icon_weather')

            # create thermostat app icon
            iconThermo = Image(get_file_path('./assets/icon_thermo.png'))
            iconThermo.addOnTouchViewListener(self)
            self.setView(iconThermo, 'icon_thermo')

            # create image viewer app icon
            iconImage = Image(get_file_path('./assets/icon_pen.png'))
            iconImage.addOnTouchViewListener(self)
            self.setView(iconImage, 'icon_image')

            # create wi-fi setting app icon
            iconWiFi = Image(get_file_path('./assets/icon_wifi_enable.png'))
            iconWiFi.addOnTouchViewListener(self)
            self.setView(iconWiFi, 'icon_wifi')

            # create menu widget
            menu = Widget(
                (iconWeather.width + iconThermo.width + 2 + iconImage.width + 2),
                22)
            menu.setPos(0, 11)
            self.addView(menu)

            # add icons to menu widget
            menu.addParts(iconWeather)

            iconThermo.x = iconWeather.width + 2
            menu.addParts(iconThermo)

            iconImage.x = iconThermo.x + iconThermo.width + 2
            menu.addParts(iconImage)

            iconWiFi.x = iconWeather.width + 2
            iconWiFi.y = 11
            menu.addParts(iconWiFi)

        # create application
        def createApplication():
            weatherApp = DummyWeatherApp(self.appEventListener)
            thermoApp = DummyThermoApp(self.appEventListener)
            imageApp = ImageViewerApp(self.appEventListener)
            wifiApp = WiFiSetting(self.appEventListener, lang='en-US') # if you want to change English, please change to 'en-US'

            weatherApp.setRelativeApps(next=thermoApp, prev=imageApp)
            thermoApp.setRelativeApps(next=imageApp, prev=weatherApp)
            imageApp.setRelativeApps(next=weatherApp, prev=thermoApp)

            self._apps = {}
            self._apps['weather'] = weatherApp
            self._apps['thermo'] = thermoApp
            self._apps['image'] = imageApp
            self._apps['wifi'] = wifiApp

        def addHomeIcon():
            iconHome = Image(os.path.normpath(os.path.join(dir, './assets/icon_home.png')))
            iconHome.setSize(190, 23, iconHome.width, iconHome.height)
            self.addView(iconHome)

        addClock()
        createMenu()
        createApplication()
        addHomeIcon()

    # ------------------------
    # override AbsApp methods

    def startTask(self):
        # start clock update
        self.getView('clock').startTick()

    def stopTask(self):
        # stop clock update
        self.getView('clock').stopTick()

    def dispatchFlingEvent(self, e1, e2, x, y):
        return False

    def dispatchLongPressEvent(self, e):
        pass

    def onTurnOffDisplay(self):
        # always allow turn off
        return True

    # ------------------------
    # OnUpdateRequestListener implementation

    def onUpdateView(self, view):
        self.updateRequest(0)

    # ------------------------
    # OnTouchEventListener implementation

    def onTouch(self, view, e):
        iconWeather = self.getView('icon_weather')
        iconThermo = self.getView('icon_thermo')
        iconImage = self.getView('icon_image')
        iconWiFi = self.getView('icon_wifi')

        if view == iconWeather:
            next = self._apps['weather']

        elif view == iconThermo:
            next = self._apps['thermo']

        elif view == iconImage:
            next = self._apps['image']

        elif view == iconWiFi:
            next = self._apps['wifi']

        if next is not None:
            self.setNextApp(next)

class MuiMain(InputEventListener, GestureListener, AppEventListener, DisplayEventListener):
    """
    Main class
    this class connect to mui's hardware(display and touch panel) and control applications transition.
    """

    def __init__(self):
        # connect to mui touchpanel
        self.input = InputHandler(self)

        # create gesture detector(for swipe)
        self.gesture_detector = GestureDetector(listener=self, longpress_timeout=2)

        # connect to mui display
        self.display = Display()
        # set birghtness level
        self.display.setDuty(100)
        # clear and turn on display
        self.display.clearDisplay()
        self.display.turnOn(0)

        # create display manager(for auto turn off display)
        # after 15 seconds from last user touch to mui, turn off display.
        self.display_manager = DisplayManager(self, time_to_dismiss=15)

        # create base application and set it to current application
        self.app = self._baseApp = HomeApp(appEventListener = self)

    def main_loop(self):
        # start display manager check
        self.display_manager.startDismissTimer()
        # start capture touch event
        self.input.startEventLoop()

    def startTask(self):
        self.app.startTask()

    def updateUI(self, fade=0, turn_on=False, turn_off=False):
        with mutex:
            if (fade > 0) and (turn_on is False):
                # fade out (1 - 4 : 4 is very slow)
                self.display.turnOff(fade)

            if (turn_on is False) and (turn_off is False):
                # set layout data
                self.display.setLayout(self.app.getUI())
                # update Display internal data buffer (do not refesh display until call refreshDisplay())
                self.display.updateLayout()
                # refresh Display
                self.display.refreshDisplay()

            if (fade > 0) and (turn_off is False):
                # fade in
                self.display.turnOn(fade)

    # ------------------------
    # InputEventListener implementation

    def onInputEvent(self, e: MotionEvent):
        if self.display_manager.on is False:
            if e.action == 0:
                self.display_manager.on = True
                self.updateUI(fade=2, turn_on=True)
                self.display_manager.startDismissTimer()
            return

        # pass to gesture detector
        handle = self.gesture_detector.onTouchEvent(e)

        # dispatch touch event to current application
        if handle is False:
            self.app.dispatchTouchEvent(e)

        # reset display turn off timer
        self.display_manager.startDismissTimer()

    # ------------------------
    # AppEventListener implementation

    def requestUpdateDisplay(self, app, fade):
        self.updateUI(fade)

    def setNextApp(self, app):
        self.display_manager.startDismissTimer()

        # stop old application task
        self.app.stopTask()

        # change current application
        self.app = app
        # update UI
        self.updateUI(2)
        # start new application task
        self.app.startTask()

    def onCloseApp(self, app):
        self.display_manager.startDismissTimer()

        # close current application, so return to base application
        self.app = self._baseApp
        self.updateUI(2)
        self.app.startTask()

    def onChangeDuty(self, duty):
        # request brightness change to display class
        self.display.setDuty(duty)

    # ------------------------
    # DisplayEventListener implementation

    def onDismissTime(self) -> bool:
        # check app allow turn off
        return self.app.onTurnOffDisplay()

    def onDismiss(self):
        # turn off display with fade effect
        self.updateUI(fade=3, turn_off=True)

    # ------------------------
    # GestureListener implementation

    def onFling(self, e1: MotionEvent, e2: MotionEvent, x, y):
        # swipe event occured, pass to current application
        return self.app.dispatchFlingEvent(e1, e2, x, y)

    def onLongPress(self, e: MotionEvent):
        # long press event occured, pass to current application
        self.app.dispatchLongPressEvent(e)

if __name__ == "__main__":
    try:
        app = MuiMain()

        # draw UI
        app.updateUI(fade=3)

        # kick appliction task
        app.startTask()

        # start capture touch panel event
        app.main_loop()

    except (KeyboardInterrupt, EOFError):
        pass

    sys.exit(0)


from django.conf.urls import url

from tastypie import fields, http
from tastypie.utils import trailing_slash

from .mixins import DefaultResourceMixin
from .tag import TagResource
from workmate.conf import settings
from workmate.gateways import get_gateway_class
from workmate.models import Contact

class ContactResource(DefaultResourceMixin):
    address = fields.CharField(attribute='address', readonly=True, default='')
    name = fields.CharField(attribute='name', readonly=True)
    tags = fields.ToManyField(TagResource, 'tags', null=True, full=True)

    class Meta(DefaultResourceMixin.Meta):
        include_absolute_url = True
        queryset = Contact.onsite.all().prefetch_related('tags')
        resource_name = 'contact'

    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/call%s$" % (self._meta.resource_name, trailing_slash()),
                self.wrap_view('call'), name="api_call"),
        ]

    def call(self, request, **kwargs):
        self.method_check(request, allowed=['post'])
        self.is_authenticated(request)
        self.throttle_check(request)

        data = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json'))
        number_type = data.get('type')
        allowed_types = ['home_number', 'mobile_number', 'work_number']

        if not number_type or number_type not in allowed_types:
            return self.error_response(
                request,
                {'status': 'error',
                 'message': 'Requires type parameter, allowed values are : %s' % ', '.join(allowed_types)})
        try:
            object = Contact.objects.get(pk=kwargs.get('pk'))
            number_attr = getattr(object, number_type)
            number = number_attr.as_national.replace(' ', '')
            call_gateway = get_gateway_class(settings.WORKMATE_CALL_GATEWAY)()

            success, message = call_gateway.make_call(request.user, number)
            if success:
                return self.create_response(request, {'status': 'success', 'message': message})
            return self.error_response(request, {'status': 'error', 'message': message})

        except Contact.DoesNotExist:
            return self.error_response(request, {}, http.HttpNotFound)

        return self.error_response(request, {'status': 'error', 'message': 'Oops, Something went wrong'})


#!/usr/bin/env python
#coding=utf-8
#打包IPA 和APK 用的

import os
from common import Log

def build_ipa(proj_path,mode,target,jobs,out_path,sign,clean):
    #清理
    if clean:
        command = 'xcodebuild clean -project %s '\
                '-configuration %s '\
                '-target %s '\
                %(proj_path,mode,target)
        Log.debug('清理')
        Log.debug(command)
        os.system(command)
    #编译
    command =   'xcodebuild -project %s '\
                '-configuration %s '\
                '-target %s '\
                '-sdk iphoneos '\
                '-jobs %s '\
                'CONFIGURATION_BUILD_DIR=\"%s\" '\
                'CODE_SIGN_IDENTITY=\"%s\" '\
                %(proj_path,mode,target,jobs,os.path.expanduser(out_path),sign)
    Log.debug('编译')
    Log.debug(command)
    os.system(command)
    #打包
    Log.debug('打包')
    app_path = os.path.expanduser(os.path.join(out_path,target+'.app'))
    ipa_path = os.path.expanduser(os.path.join(out_path,target+'.ipa'))
    command = "xcrun -sdk iphoneos PackageApplication -v \"%s\" -o \"%s\"" % (app_path, ipa_path)
    Log.debug(command)
    os.system(command)


from twitchtools import login, chat, utils
import time

if __name__ == '__main__':
    utils.Printer.level = "DEBUG"

    # with chat.IRC(("irc.twitch.tv", 6667), login.Profile("bomb_mask")) as twitch:
    #     twitch.capibilities("tags")
    #     twitch.capibilities("commands")
    #
    #     user = input("User>")
    #     message = input("Message>")
    #     length = int(input("Length/2>"))
    #
    #     USER = chat.User(chat.Channel("","testing"), user)
    #
    #     if not message[-1] == ' ':
    #         message += ' '
    #
    #     for i in range(1,length*2):
    #         if i < length:
    #             math = i
    #         else:
    #             math = length - (i%length)
    #
    #         time.sleep(.4)
    #
    #
    #         twitch.whisper(USER, message*math)

    user = input("Channel>")
    message = input("Message>")
    length = int(input("Length/2>"))

    if not message[-1] == ' ':
        message += ' '

    twitch_link=("irc.twitch.tv",6667)
    accounts = ["bomb_mask","themaskoftruth","whitetail_atom","bombmask"]
    twitchs = [chat.IRC(twitch_link, login.Profile(account), True) for account in accounts]
    USER = chat.User(chat.Channel("","testing"), user)

    time.sleep(.2)

    for twitch in twitchs:
        twitch.join(user)

    time.sleep(.2)

    print()

    for i in range(1,length*2):
        if i < length:
            math = i
        else:
            math = length - (i%length)

        twitchs[(i-1)%len(twitchs)].channels[user].pm(message*math)
        #twitchs[(i-1)%len(twitchs)].whisper(USER, message*math)

        time.sleep(.2)

        # if (i-1)/len(twitchs) < 1:
        #     print(i, i/len(twitchs), i%len(twitchs))
        # else:
        #     print(i, i/len(twitchs), i%len(twitchs),'a')

    print()
    for i in twitchs:
        i.disconnect()


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def zigzagLevelOrder(self, root):
        '''
        :type: root: TreeNode
        :rtype: List[List[int]]
        '''
        s, tmp, res, flag = [root], [], [], 1
        if root:
            while s:
                for _ in range(len(s)):
                    node = s.pop(0)
                    tmp.append(node.val)
                    if node.left:
                        s.append(node.left)
                    if node.right:
                        s.append(node.right)
                res.append(tmp[::flag])
                tmp = []
                flag *= -1
            return res
        else:
            return res


import cv2  # подключение библеотеки OpenCV
import pytesseract  # подключение библеотеки PyTesseract
import time  # подключение библеотеки Time

Sp_M = 'etyopahkxcbm'  # переменная типа string, содержащая в себе символы номерного знака
Sp_R = '\|/'  # разделительная строка между номером и регионом
Sp_L = 'ETYOPAHKXCBM'  # переменная типа string, содержащая в себе символы номерного знака
Sp_N = '0123456789'  # переменная типа string, содержащая в себе все цифры для номерного знака
past = ''  # инициализация переменной
now = ''  # инициализация переменной

pytesseract.pytesseract.tesseract_cmd = 'C:\\Program Files\\Tesseract-OCR\\tesseract.exe'  # адресс библеотеки PyTesseract на компьютере
face_cascade_db = cv2.CascadeClassifier(cv2.data.haarcascades+"haarcascade_russian_plate_number.xml")  # подлючение доп каскады для распознавания номера

cap = cv2.VideoCapture(1)  # подключение камеры и получение данных с неё для программы

while True:
    success, img = cap.read()  # захват изображения с камеры

    config = r'--oem 3 --psm 6'  # установка параметров распознавания текста на фото

    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    plate = face_cascade_db.detectMultiScale(img_gray, 1.1, 19)  # обнаружение координат автомобильного номера на фото - (локализация)
    for (x, y, w, h) in plate:  # цикл, с использованием полученных координат
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)  # обрисовывание номера на фото
        cropped = img[y:y+h, x:x+w]  # доп фото, содержащее только автомобильный номер
        t = pytesseract.image_to_string(cropped, config=config)  # перевод изображения в текстовую переменную - (сегментация)
        if (len(t)>=8):  # минимальная длина автомобильного номера с учётом региона не менее 8 символов
            if (t != past):  # условие не вывода одного и того же номера
                for i in range(len(t)):  # разбор каждого символа номера отдельно - (классификация)
                    if(i==0 or i==4 or i==5):  # первый, пятый и шестой символ в номера - буквы - (алгоритм формирования номера)
                        if(t[i] in Sp_M):  # на случай, если программа распознаёт символ как строчную букву
                            now += (chr(ord(t[i]) - 32))  # вывод заглавной буквы номера
                        if(t[i] in Sp_L):  # символ соответствует одному из заранее установленного списка
                            now += (t[i])  # вывод заглавной буквы номера
                    else:  # со второго по четвёртый и последние три символа - цифры номерного знака  - (алгоритм формирования номера)
                        if(t[i] in Sp_N):  #  символ соответствует одному из заранее установленного списка
                            now += (t[i])  # вывод цифры номерного знака
                if (len(now)>=8):  # если полученный номер содержит минимальное кол-во символов,
                    print(now)  # то программа его выводит в консоль
                    print('')  # после завершения распознавания номерного знака, перенос на следующую строку
                    now = ''  # сброс переменной для следующего цикла
                past = t  # необходимо для сравнения
    cv2.imshow('ta-da', img)  # вывод первоначального изображения с обрисованым номерным знаком
    time.sleep(0.5)  # таймер с задержкой в одну секунду
    if cv2.waitKey(1) & 0xff == ord('q'):  # условия остановки программы
        break  # команда для остановки работы програмы

cap.release()  # остановка видеозахвата с камеры
cv2.destroyAllWindows()  # остановка демонстрации работы программы


# -*- coding: utf-8 -*-
__author__ = 'stevenkaplan'
import django
django.setup()
from sources.Maharsha.parse import *
import os
from sources.functions import post_text, post_link, post_index, convertDictToArray, post_term
from sefaria.model import *

maharam_line = 0

def Gemara(maharam_line, which_line, daf, results):
    maharam_line += 1
    which_line['gemara'] += 1
    if results['gemara'][which_line['gemara']] == '0':
        missing_ones.append(
            title + " on " + masechet + "." + AddressTalmud.toStr("en", daf) + "." + str(maharam_line))
    else:
        links_to_post.append({
            "refs": [
                results['gemara'][which_line['gemara']],
                title + " on " + masechet + "." + AddressTalmud.toStr("en", daf) + "." + str(
                    maharam_line)
            ],
            "type": "commentary",
            "auto": True,
            "generated_by": title + masechet + " linker",
        })
    return maharam_line, which_line

def getTC(category, daf, masechet):
    if category in ["tosafot", "ran", "rosh"]:
        title = "{} on {}".format(category.title(), masechet)
        return Ref(title + "." + AddressTalmud.toStr("en", daf)).text('he')
    elif category == "gemara":
        return Ref(masechet + " " + AddressTalmud.toStr("en", daf)).text('he')
    elif category == "rashi":
        rashi = Ref("Rashi on " + masechet + "." + AddressTalmud.toStr("en", daf)).text('he')
        if len(rashi.text) == 0:
            print("rashbam by default {} {}".format(masechet, AddressTalmud.toStr("en", daf)))
            return Ref("Rashbam on " + masechet + "." + AddressTalmud.toStr("en", daf)).text('he')
        else:
            return rashi
    elif category == "rashbam":
        print("rashbam {} {}".format(masechet, AddressTalmud.toStr("en", daf)))
        return Ref("Rashbam on " + masechet + "." + AddressTalmud.toStr("en", daf)).text('he')

def parseDH(prev_dh, comment, category, same_dh):
    orig_comment = comment
    if same_dh is None:
        len_chulay = len("כו'")
        chulay = comment.find("כו'") + len_chulay
        if chulay > len_chulay - 1:
            dh, comment = comment[0:chulay], comment[chulay:]
        else:
            dh = comment
            comment = ""

        prev_dh = dh
    addDHComment(prev_dh, comment, category, same_dh)
    return prev_dh

def addDHComment(dh, comment, category, same_dh):
    dh = removeAllTags(dh)
    comment = removeAllTags(comment)
    dh = dh
    comment = comment
    dh1_dict[current_daf].append((category, dh))
    if same_dh:
        post_comment = comment
    else:
        post_comment = dh + comment

    post_comment = post_comment.strip()
    first_word = post_comment.split(" ")[0]
    post_comment = u"<b>{}</b> {}".format(first_word, " ".join(post_comment.split(" ")[1:]))
    comm_dict[current_daf].append(post_comment)
    dh_by_cat[category][current_daf].append(dh)
    if looking_for_perakim:
        dh_by_perek[current_perek].append((category, dh, current_daf))
        comm_by_perek[current_perek].append(post_comment)

def dh_extract_method(str):
    str = str
    str = str.replace('בד"ה', '').replace('וכו', '').replace('שם','')
    for each in [rashi, tosafot, gemara, ran, rashbam, rosh, 'בא"ד']:
        if each in str[0]:
            str = " ".join(str.split(" ")[1:])
            break
    return str

def determineCategory(category, count, comment):
    comment = comment + ':'
    if count == 0 and len(comment) == 0:
        return "", category
    comment = comment.strip()
    word = comment.split(" ")[0]
    if rashi in word:
        category = 'rashi'
    elif tosafot in word:
        category = 'tosafot'
    elif gemara in word or word in mishnah or shom in word:
        category = 'gemara'
    elif ran in word:
        category = 'ran'
    elif rosh in word:
        category = 'rosh'
    elif rashbam in word:
        category = "rashbam"
    elif word in dibbur_hamatchil:
        return "same_dh", category
    return None, category

def convertToOldFormat(arr):
    arr = arr['matches']
    for index, item in enumerate(arr):
        if item is None:
            arr[index] = '0'
        else:
            arr[index] = arr[index].normal()
    return arr

def Commentary(which_line, maharam_line, daf, category, results):
    maharam_line += 1
    which_line[category] += 1
    title = category.title() + " on " + masechet
    base_ref = results[category][which_line[category]]
    comm_ref = "Chokhmat Shlomo on Shevuot " + "."+AddressTalmud.toStr("en", daf)+"."+str(maharam_line)
    if base_ref == '0':
        missing_ones.append(comm_ref)
    else:
        links_to_post.append({
            "refs": [
                         base_ref,
                        comm_ref
                    ],
            "type": "commentary",
            "auto": True,
            "generated_by": title+masechet+" linker"
        })
        gemara_ref = getGemaraRef(base_ref)
        links_to_post.append({
            "refs": [
                comm_ref,
                gemara_ref
            ],
            "type": "commentary",
            "auto": True,
            "generated_by": title+masechet+" linker"
        })
    return which_line, maharam_line

def getGemaraRef(ref):
    ref = Ref(ref)
    assert len(ref.sections) == 3 ^ (not ref.is_segment_level())
    d = ref._core_dict()
    if len(d['sections']) == 3:
        d['sections'] = d['sections'][0:-1]
        d['toSections'] = d['toSections'][0:-1]
        gemara_ref = Ref(_obj=d)
    return gemara_ref.normal().replace("Tosafot on ", "").replace("Rashi on ", "").replace("Rosh on ", "").replace("Ran on ", "")

def postLinks(masechet):
    def base_tokenizer(str):
        str = re.sub(r"\([^\(\)]+\)", u"", str)
        word_list = re.split(r"\s+", str)
        word_list = [w for w in word_list if w]  # remove empty strings
        return word_list

    rosh_results = []
    perek_key = {}
    for perek in sorted(dh_by_perek.keys()):
        tuples = filter(lambda x: x[0] is 'rosh', dh_by_perek[perek])
        if len(tuples) > 0:
            cats, dhs, dappim = zip(*tuples)
            #for each daf and dh pair, that's the key to get the perek
            for daf, dh in zip(list(dappim), list(dhs)):
                perek_key[(daf, dh)] = perek
            base = Ref("Rosh on {} {}".format(masechet, perek)).text('he')
            assert len(base.text) > 0
            these_results = match_ref(base, list(dhs), base_tokenizer, dh_extract_method=dh_extract_method, verbose=False, with_num_abbrevs=False)['matches']
            assert len(tuples) is len(these_results)
            rosh_results.append(these_results)

    results = {}
    comments = {}

    for daf in sorted(dh1_dict.keys()):
        comments[daf] = {}
        results[daf] = {}
        for each_cat in categories:
            if each_cat == 'rosh':
                continue
            comments[daf][each_cat] = dh_by_cat[each_cat][daf]
        for each_type in comments[daf]:
            if each_type == 'rosh':
                continue
            results[daf][each_type] = []
            if len(comments[daf][each_type]) > 0:
                base = getTC(each_type, daf, masechet)
                if len(base.text) == 0:
                    comm_wout_base.write("{} {}: {}\n".format(masechet, daf, each_type))
                    base = getTC(each_type, daf-1, masechet)
                    combined_comments = comments[daf-1][each_type]+comments[daf][each_type]
                    if len(base.text) == 0:
                        print("Problem in {}".format(AddressTalmud.toStr("en", daf)))
                    else:
                        results[daf-1][each_type] = match_ref(base, combined_comments, base_tokenizer, dh_extract_method=dh_extract_method, verbose=False, with_num_abbrevs=False)
                        results[daf-1][each_type] = convertToOldFormat(results[daf-1][each_type])
                    dh1_dict[daf] = [x for x in dh1_dict[daf] if x[0] != each_type]
                else:
                    results[daf][each_type] = match_ref(base, comments[daf][each_type], base_tokenizer, dh_extract_method=dh_extract_method, verbose=False, with_num_abbrevs=False)
                    results[daf][each_type] = convertToOldFormat(results[daf][each_type])

    prev_perek = 0
    for daf in sorted(dh1_dict.keys()):
        maharam_line = 0
        which_line = {"rashi": -1, "tosafot": -1, "rosh": -1, "ran": -1, "gemara": -1, "rashbam": -1}
        for category, dh in dh1_dict[daf]:
            if category == 'gemara':
                Gemara(maharam_line, which_line, daf, results[daf])
            elif category == 'rosh':
                perek = perek_key[(daf, dh)]
                if perek > prev_perek:
                    rosh_line = -1
                prev_perek = perek
                maharam_line = Rosh(maharam_line, perek, daf, dh, rosh_results)
            else:
                which_line, maharam_line = Commentary(which_line, maharam_line, daf, category, results[daf])

    post_link(links_to_post, server=SEFARIA_SERVER)

def Rosh(maharam_line, perek, daf, dh, results):
    maharam_line += 1
    rosh_line += 1
    if results[perek - 1][rosh_line]:
        links_to_post.append({
            "refs": [
                results[perek - 1][rosh_line].normal(),
                title + " on " + masechet + "." + AddressTalmud.toStr("en", daf) + "." + str(
                    maharam_line)
            ],
            "type": "commentary",
            "auto": True,
            "generated_by": title + masechet + " linker",
        })
    return maharam_line

def create_index(tractate, title, heTitle):
    categories = library.get_index(tractate).categories
    root=JaggedArrayNode()
    heb_masechet = library.get_index(tractate).get_title('he')
    root.add_title(title+" on "+tractate.replace("_"," "), "en", primary=True)
    root.add_title(heTitle+u" על "+heb_masechet, "he", primary=True)
    root.key = title+tractate
    root.sectionNames = ["Daf", "Comment"]
    root.depth = 2
    root.addressTypes = ["Talmud", "Integer"]

    root.validate()

    index = {
        "title": title+" on "+tractate.replace("_"," "),
        "categories": ["Talmud", "Bavli", "Commentary", title, categories[-1]],
        "schema": root.serialize(),
        "base_text_titles": [tractate],
        "collective_title": title,
        "dependence": "Commentary",

    }
    post_index(index, server=SEFARIA_SERVER)
    return tractate

heb_numbers = ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "ששי", "שביעי", "שמיני", "תשיעי", "עשירי", "אחד עשר", "שנים עשר", "שלשה עשר", "ארבעה עשר", "חמשה", "ששה"]
comm_dict = {}
dh1_dict = {}
rashi ='רש"י'
rashbam = 'פרשב"ם'
ran = 'ר"ן'
rosh = 'רא"ש'
tosafot = "תוס"
dibbur_hamatchil = ['בד"ה', 'ד"ה', 'בא"ד', """ד'"ה"""]
gemara = "גמ"
shom = "שם"
amud_bet = 'ע"ב'
mishnah = ['במשנה', 'מתני']
current_daf = 2
current_perek = 0
categories = ['rashi', 'tosafot', 'gemara', 'ran', 'rosh', 'rashbam']
dh_by_cat = {cat: {} for cat in categories}
links_to_post = []
category = "gemara"
prev_dh = ""
comm_by_perek = {}
dh_by_perek = {}
rosh_line = 0
looking_for_perakim = False
missing_ones = []
which_line = {}
comm_wout_base = open("comm_wout_base.txt", 'w')

if __name__ == "__main__":
    masechet = "Shevuot"
    title = "Chokhmat Shlomo"
    heTitle = "חכמת שלמה"
    file = "shevuot.tsv"
    create_index(masechet, title, heTitle)
    prev_dh = ""
    with open(file) as f:
        prev_daf = 1
        for n, line in enumerate(f):
            poss_daf, comment = line.split("\t")
            if poss_daf == "":
                current_daf = prev_daf
            else:
                curr_amud = int(poss_daf.find(".") == -1) - 1   # result is -1 for . and 0 for :
                current_daf = 2*getGematria(poss_daf) + curr_amud
                assert current_daf > prev_daf, line
                prev_daf = current_daf
                prev_dh = ""

            if not current_daf in dh1_dict:
                dh1_dict[current_daf] = []
                comm_dict[current_daf] = []
                for each_cat in categories:
                    dh_by_cat[each_cat][current_daf] = []

            comments = comment.strip().split(":")
            for count, comment in enumerate(comments):
                if len(comment.replace(" ", "")) < 3:
                    continue
                if comment[0] == ' ':
                    comment = comment[1:]
                comment += ':'
                same_dh, new_category = determineCategory(category, count, comment)
                if category != new_category:
                    category = new_category
                prev_dh = parseDH(prev_dh, comment, category, same_dh)
    text_to_post = convertDictToArray(comm_dict)
    send_text = {
        "versionTitle": "Vilna Edition",
        "versionSource": "http://primo.nli.org.il/primo_library/libweb/action/dlDisplay.do?vid=NLI&docId=NNL_ALEPH001300957",
        "language": "he",
        "text": text_to_post,
    }
    post_text("{} on {}".format(title, masechet), send_text, "on", server=SEFARIA_SERVER)
    postLinks(masechet)