#batman is the best
from collections import deque
import pygame, ezpztext
import time
import random
import threading
import traceback
import pygame
import os
import sys
from pygame import *
from pygame.locals import *

from Movement import Movement
from Hole import Hole
from Timer import Timer
import ParserThread
import util

pygame.init()

level = 0
numOfLevels = 10
rebelScore = 0

white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0, 255, 0)
yellow = (255, 255, 0)
grey = (96, 125, 139)
orange = (255, 87, 34)

# default colour for text editor font
txtfont_default = white
txtfont_focus = green

# Global settings
control_mode = 'TYPE' # 'KEYPRESS' or 'TYPE'
time_limit = 20 # Time limit that affects Time Bar and Duration countdown

# Use a timer
timer = Timer()

# Use the Movement class to keep track of movements
movement = Movement(1)

# Game state
game_state = 'idle'
parsing = False

#textbox
txtbx = ezpztext.Textbox(lines=14, default_color=txtfont_default,
            focus_color=txtfont_focus, maxlength=28, y=60, x=840)

for i in range(len(txtbx.txtbx)):
    txtbx.txtbx[i].prompt = "{:>2}: ".format(i + 1)

# Use ParserThread to create a separate thread for parsing user code
parser_thread = ParserThread.Thread()

map_width = 800
map_height = 600
status_bar = 40
display_width = map_width +400
display_height = map_height + status_bar

lead_x = 750
lead_y = 540
lead_direction = 'down'
blueprintCollected = False
blueprintExist = False

BlueprintThickness = 30
block_size = 10
FPS = 30
gameDisplay = pygame.display.set_mode((display_width,display_height))
##gameDisplay = pygame.display.set_mode((display_width,display_height),FULLSCREEN)
pygame.display.set_caption('Star Wars: A programming education game')

wallpaper_img = util.load_image('wallpaper/Wallpaper.png')
text_editor_img = util.load_image('pictures/right panel/Text editor.png')
maps = ['pictures/Map/warm_up.png',
           'pictures/Map/Map_0.png','pictures/Map/Map_4.png','pictures/Map/Balcony_map.png',
           'pictures/Map/Map_1.png','pictures/Map/SU.png','pictures/Map/Map_3.png',
           'pictures/Map/Map_5.png','pictures/Map/docking_bay.png','pictures/Map/Last_level_map_space.png']

map_img = [util.load_image(m) for m in maps]

lukeUpStationary = util.load_image('pictures/lukeMove/Luke_up_stationary.png')
lukeUpWalk1 = util.load_image('pictures/lukeMove/Luke_up_walk_1.png')
lukeUpWalk2 = util.load_image('pictures/lukeMove/Luke_up_walk_2.png')
lukeDownStationary = util.load_image('pictures/lukeMove/Luke_down_stationary.png')
lukeDownWalk1 = util.load_image('pictures/lukeMove/Luke_down_walk_1.png')
lukeDownWalk2 = util.load_image('pictures/lukeMove/Luke_down_walk_2.png')
lukeRightStationary = util.load_image('pictures/lukeMove/Luke_right_stationary.png')
lukeRightWalk = util.load_image('pictures/lukeMove/Luke_right_walk_1.png')
lukeLeftStationary = util.load_image('pictures/lukeMove/Luke_left_stationary.png')
lukeLeftWalk = util.load_image('pictures/lukeMove/Luke_left_walk_1.png')

reyUpStationary = util.load_image('pictures/reyMove/Rey_up_stationary.png')
reyUpWalk1 = util.load_image('pictures/reyMove/Rey_up_walk_1.png')
reyUpWalk2 = util.load_image('pictures/reyMove/Rey_up_walk_2.png')
reyDownStationary = util.load_image('pictures/reyMove/Rey_down_stationary.png')
reyDownWalk1 = util.load_image('pictures/reyMove/Rey_down_walk_1.png')
reyDownWalk2 = util.load_image('pictures/reyMove/Rey_down_walk_2.png')
reyRightStationary = util.load_image('pictures/reyMove/Rey_right_stationary.png')
reyRightWalk1 = util.load_image('pictures/reyMove/Rey_right_walk_1.png')
reyRightWalk2 = util.load_image('pictures/reyMove/Rey_right_walk_2.png')
reyLeftStationary = util.load_image('pictures/reyMove/Rey_left_walk_1.png')
reyLeftWalk1 = util.load_image('pictures/reyMove/Rey_left_walk_1.png')
reyLeftWalk2 = util.load_image('pictures/reyMove/Rey_left_walk_2.png')

finnUpStationary = util.load_image('pictures/finnMove/Finn_up_stationary.png')
finnUpWalk1 = util.load_image('pictures/finnMove/Finn_up_walk_1.png')
finnUpWalk2 = util.load_image('pictures/finnMove/Finn_up_walk_2.png')
finnDownStationary = util.load_image('pictures/finnMove/Finn_down_stationary.png')
finnDownWalk1 = util.load_image('pictures/finnMove/Finn_down_walk_1.png')
finnDownWalk2 = util.load_image('pictures/finnMove/Finn_down_walk_2.png')
finnRightStationary = util.load_image('pictures/finnMove/Finn_right_stationary.png')
finnRightWalk1 = util.load_image('pictures/finnMove/Finn_right_walk_1.png')
finnRightWalk2 = util.load_image('pictures/finnMove/Finn_right_walk_2.png')
finnLeftStationary = util.load_image('pictures/finnMove/Finn_left_stationary.png')
finnLeftWalk1 = util.load_image('pictures/finnMove/Finn_left_walk_1.png')
finnLeftWalk2 = util.load_image('pictures/finnMove/Finn_left_walk_2.png')

renUpStationary = util.load_image('pictures/renMove/Ren_up.png')
renDownStationary = util.load_image('pictures/renMove/Ren_down.png')
renRightStationary = util.load_image('pictures/renMove/Ren_right.png')
renLeftStationary = util.load_image('pictures/renMove/Ren_left.png')

darthUpStationary = util.load_image('pictures/darthMove/Darth_up.png')
darthDownStationary = util.load_image('pictures/darthMove/Darth_down.png')
darthRightStationary = util.load_image('pictures/darthMove/Darth_right.png')
darthLeftStationary = util.load_image('pictures/darthMove/Darth_left.png')

stormtUpStationary = util.load_image('pictures/stormtMove/StormT_up.png')
stormtDownStationary = util.load_image('pictures/stormtMove/StormT_down.png')
stormtRightStationary = util.load_image('pictures/stormtMove/StormT_right.png')
stormtLeftStationary = util.load_image('pictures/stormtMove/StormT_left.png')

mFalconStationary = util.load_image('pictures/milleniumFalcon/mFalcon_stationary.png')
mFalconThrusterSmall = util.load_image('pictures/milleniumFalcon/mFalcon_thruster_small.png')
mFalconThrusterBig = util.load_image('pictures/milleniumFalcon/mFalcon_thruster_big.png')

reyMoveUp = [reyUpWalk1, reyUpWalk2, reyUpStationary]
reyMoveDown = [reyDownWalk1, reyDownWalk2, reyDownStationary]
reyMoveRight = [reyRightWalk1, reyRightWalk2, reyRightStationary]
reyMoveLeft = [reyLeftWalk1, reyLeftWalk2, reyLeftStationary]

lukeMoveUp = [lukeUpWalk1, lukeUpWalk2, lukeUpStationary]
lukeMoveDown = [lukeDownWalk1, lukeDownWalk2, lukeDownStationary]
lukeMoveRight = [lukeRightStationary, lukeRightWalk, lukeRightStationary]
lukeMoveLeft = [lukeLeftStationary, lukeLeftWalk, lukeLeftStationary]

finnMoveUp = [finnUpWalk1, finnUpWalk2, finnUpStationary]
finnMoveDown = [finnDownWalk1, finnDownWalk2, finnDownStationary]
finnMoveRight = [finnRightWalk1, finnRightWalk2, finnRightStationary]
finnMoveLeft = [finnLeftWalk1, finnLeftWalk2, finnLeftStationary]

renMoveUp = [renUpStationary, renUpStationary, renUpStationary]
renMoveDown = [renDownStationary, renDownStationary, renDownStationary]
renMoveRight = [renRightStationary, renRightStationary, renRightStationary]
renMoveLeft = [renLeftStationary, renLeftStationary, renLeftStationary]

darthMoveUp = [darthUpStationary, darthUpStationary, darthUpStationary]
darthMoveDown = [darthDownStationary, darthDownStationary, darthDownStationary]
darthMoveRight = [darthRightStationary, darthRightStationary, darthRightStationary]
darthMoveLeft = [darthLeftStationary, darthLeftStationary, darthLeftStationary]

stormtMoveUp = [stormtUpStationary, stormtUpStationary, stormtUpStationary]
stormtMoveDown = [stormtDownStationary, stormtDownStationary, stormtDownStationary]
stormtMoveRight = [stormtRightStationary, stormtRightStationary, stormtRightStationary]
stormtMoveLeft = [stormtLeftStationary, stormtLeftStationary, stormtLeftStationary]

mFalconFireUp = [mFalconStationary, mFalconThrusterSmall, mFalconStationary, mFalconThrusterSmall,
                 mFalconThrusterBig, mFalconStationary, mFalconThrusterSmall, mFalconThrusterBig,
                 mFalconThrusterBig, mFalconStationary, mFalconThrusterSmall, mFalconThrusterBig,
                 mFalconThrusterSmall, mFalconThrusterBig, mFalconThrusterBig, mFalconThrusterBig]
blueprint_img = util.load_image('pictures/Blueprint.png')

# holes
holes = []

trooper_LOS = pygame.Rect(420, 210, 30, 30)

# for run button
btnimg = util.load_image('pictures/runbtn.png')
eraseimg = util.load_image('pictures/erasebtn.png')
runbtn_rect = pygame.Rect(1075, 590, *btnimg.get_rect().size)
erasebtn_rect = pygame.Rect(830, 15, *eraseimg.get_rect().size)

clock = pygame.time.Clock()

smallfont = pygame.font.Font('diehund.ttf', 30)
medfont = pygame.font.Font('diehund.ttf', 40)
largefont = pygame.font.Font('diehund.ttf', 80)

#sound fxps
#---BGM
bgm1 = "sounds/bgm1-throneroom.ogg"
bgm1loop = "sounds/bgm1-throneroomloop.ogg"
bgm2 = "sounds/bgm2-intothetrap.ogg"
bgm2loop = "sounds/bgm2-intothetraploop.ogg"
bgm3 = "sounds/bgm3-countdooku.ogg"
bgm3loop = "sounds/bgm3-countdookuloop.ogg"
bgm4 = "sounds/bgm4-duelofthefates.ogg"
bgm4loop = "sounds/bgm4-duelofthefatesloop.ogg"

falcon = pygame.mixer.Sound("sounds/powerupandblast.ogg")
trooper = pygame.mixer.Sound("sounds/stormtrooper1.ogg")
fall = pygame.mixer.Sound("sounds/fall1.ogg")
bangwall = pygame.mixer.Sound("sounds/bangwall1.ogg")    #done
collectblueprint= pygame.mixer.Sound("sounds/collectblueprint1.ogg")
jump1 = pygame.mixer.Sound("sounds/jump1.ogg")
startGame = pygame.mixer.Sound("sounds/start.ogg")
wallbang = pygame.mixer.Sound("sounds/bang1.ogg")
dvlist = ["sounds/darth vader - die1.wav","sounds/darth vader - i have you now.wav","sounds/darth vaer - breath.wav","sounds/darth vader - thisistheend.wav"]

BEGIN_LOOP = pygame.USEREVENT + 1

def loadLevel(level):
    position=[[360,570],[180,180],[0,450],[30,270],[750,420],[360,30],[420,30],[60,330],[30,270],[30,270]]
    levelXList = [[510,0,0,810],[0,180,360,180,360,600,360,450,420],[0,120,270,420,690,540,390,240,0],
                  [0,0,0,30,780,780],[0,30,780,0,420,180,510,180,300,420,510,30,180,510,630],[0,0,60,390],
             [0,0,270,330,360,450,450,450,450,450,750],
             [0,0,360,600,240,480,720,0,0],[0,0,0,30],[0,0,0,30]]
    levelYList = [[360,0,180,180],[0,0,120,450,390,0,240,0,-30],[0,0,0,0,0,150,270,390,510],[0,30,300,570,30,300],
                  [0,570,0,0,0,480,480,30,30,60,60,210,180,180,210],
                  [0,90,270,0],
                  [0,90,120,120,240,0,120,270,420,540,60],
                  [0,180,180,180,270,270,240,390,300],[0,60,300,570],[0,60,300,570]]
    widthlist = [[300,810,270,30],[180,240,60,630,450,210,240,150,30],
                 [120,150,150,150,120,150,150,150,240],[600,30,30,780,30,30],
                 [30,780,30,390,780,120,120,120,90,90,120,150,120,120,180],
                 [360,60,300,420],
                 [420,240,60,90,60,360,270,180,270,360,60],
                 [810,180,60,60,60,60,90,810,60],[810,30,30,780],[810,30,30,780]]
    heightlist=[[240,180,420,240],[600,120,60,150,60,390,90,180,30],
                [420,300,180,60,600,450,330,210,90],[60,240,270,30,240,270],
                [600,30,570,60,60,90,90,120,90,60,90,120,210,210,120],
                [90,510,330,600],
                [90,390,360,90,360,90,90,90,90,60,480],
                [180,120,120,120,120,120,150,210,90],[60,210,300,30]
                ,[60,210,300,30]]
    win_width = [30,30,120,30,30,30,210,30,30,60]
    win_height = [240,30,30,30,30,30,30,60,510,120]
    win_xyCoordinates = [[780,180],[420,0],[570,0],[780,270],[390,0],[360,570],
                         [240,570],[780,180],[780,60],[510,240]]
    holeCoords = [[],[[570,180],[570,210]],[],[[390,0],[390,30],[390,60],[390,90],[390,120],[390,150],[390,180],[390,210],[390,240],[390,270]
                                               ,[390,300],[390,330],[390,360],[390,390],[390,420],[390,450],[390,480],[390,510],[390,540],[390,570]]
                  ,[],[[360,150],[360,300],[360,420]],[[240,180],[240,360]],[],[[180,210],[180,240],[210,450],[210,480],[210,510],[360,270],[360,270],[360,270],[360,300],[360,330],[570,150],
                                [570,180],[570,210],[510,390],[510,420]],[]]

    vader_face = [1,0,0,2,2,0,0,1,1,3] # 0-Down, 1-Left, 2- Up, 3-Right
    blueprint_xy = [[],[],[],[],[120,150],[],[240,240],[],[],[]]
    return [position[level][0],position[level][1],levelXList[level],levelYList[level],widthlist[level],heightlist[level],win_width[level],win_height[level],\
            win_xyCoordinates[level][0],win_xyCoordinates[level][1],holeCoords[level], vader_face[level],blueprint_xy[level]]

def done_moving():
    if movement.get_next_move() == 'stationary':
        return True
    return False

class Player:

    def __init__(self):
        self.moveUp = lambda steps = 1: self.move('move_up', steps)
        self.moveDown = lambda steps = 1: self.move('move_down', steps)
        self.moveLeft = lambda steps = 1: self.move('move_left', steps)
        self.moveRight = lambda steps = 1: self.move('move_right', steps)

        self.jumpUp = lambda steps = 1: self.move('jump_up', steps)
        self.jumpDown = lambda steps = 1: self.move('jump_down', steps)
        self.jumpLeft = lambda steps = 1: self.move('jump_left', steps)
        self.jumpRight = lambda steps = 1: self.move('jump_right', steps)

    def move(self, direction, steps):
        global game_state
        game_state = direction

        while True:
            if game_state == 'gameover':
                game_state = 'idle' # reset game_state
            if game_state == 'idle':
                steps -= 1
                if steps <= 0: break
                game_state = direction

    def holeInFront(self):
        for hole in holes:
            player_rect = pygame.Rect(lead_x, lead_y, 30, 30)
            collide_direction = hole.collides(player_rect)
##            print player_rect
##            print 'psuedo_holes', collide_direction
##            print 'lead_direction', lead_direction
##            # if lead_direction == collide_direction: return True
            if lead_direction == collide_direction:
                return True
        return False

this_is_impossible_to_be_screwed_up = Player()

def parser_func(code):
    global game_state
    try:
        exec(code)
##    except SystemExit:
##        print "exit from loop."
    except:
        traceback.print_exc()
        game_state = 'error'
    finally:
        parsing = False

def display_error():
    global game_state, rebelScore
    rebelScore -= 2
    paused = True
    message_to_screen("CODE ERROR", red,
                      y_displace=-50, size = "large")
    message_to_screen("Press C to play again", orange,
                      50, size = "medium")
    message_to_screen("or Q to quit", orange,
                      100, size = "medium")
    pygame.display.update()
    while paused:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_c:
                    paused = False
                elif event.key == pygame.K_q:
                    pygame.quit()
                    quit()

        clock.tick(5)

    game_state = 'idle'
    gameLoop()

def barrier(xlocation,ylocation, barrier_width, barrier_height):
    pygame.draw.rect(gameDisplay,black, [xlocation, ylocation, barrier_width, barrier_height])

def pause():
    paused = True
    message_to_screen("Paused", black, -100, size = "large")
    message_to_screen("Press c to continue", black, 25, size = "small")
    pygame.display.update()
    while paused:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_c:
                    paused = False
                elif event.key == pygame.K_q:
                    pygame.quit()
                    quit()

        clock.tick(5)

def helpInstructions(level):
    csmallfont = pygame.font.Font('diehund.ttf', 15)
    csmallfont.set_italic(True);

    xsmallfont = pygame.font.Font('diehund.ttf', 15)
    xsmallfont.set_underline(True)
    xsmallfont.set_bold(True)
    gameDisplay.blit(xsmallfont.render("Level "+str(level + 1), True, white),\
                         [835, 375])
    xsmallfont.set_underline(False)
    xsmallfont.set_bold(False)

    # 9 Lines max
    helpMessage = {0 : ["Commands to move your player", # Learn move
                        "c      self.moveUp()",
                        "c      self.moveRight()",
                        "",
                        "You can put in parameters, eg",
                        "to move right 4 steps",
                        "c      self.moveRight(4)"],
                   1 : ["Commands to move your player", # Learn move
                        "c      self.moveUp()",
                        "c      self.moveRight()",
                        "c      self.moveDown()",
                        "c      self.moveLeft()",
                        "",
                        "Python is indentation and case ",
                        "sensitive!",
                        "It could be the source of your bugs"],
                   2 : ["Loops can ease your pain of coding", # Learn basic loop
                        "lines of the same thing.",
                        "c",
                        "c      while True :",
                        "c          self.moveRight()",
                        "c          self.moveLeft()",
                        "c",
                        "'self' represents the object you are",
                        "controlling, in this case, the player."],
                   3 : ["Here are some useful actions to use", # Learn condition check
                        "for jumping across holes.",
                        "",
                        "c        self.jumpRight()",
                        "c        self.jumpLeft()",
                        "c        self.jumpUp()",
                        "c        self.jumpDown()",],
                   4 : ["The Death Star Blueprint earns you ",
                        "30 points!",
                        "Programming is about efficiency.",
                        "If you didn't realize, points have", # Example conditions 1
                        "been awarded based on how many",
                        "line is your code and how much",
                        "time is left upon reaching the ",
                        "objective.",
                        "",
                        ""],
                   5 : ["Avoid getting detected by infrared",
                        "sensors! They're like holes!",
                        "You can use jump to avoid them. ", # Example conditions 2
                        "",
                        "a condition check.",
                        "c      while True:",
                        "c          if self.holeInFront():",
                        "c              <do stuff>",
                        "c          <do stuff>"],
                   6 : ["Avoid getting detected by Storm", # Test!
                        "Troopers. Jumping isn't going to",
                        "help you.",
                        "Hint:",
                        "      If you like a challenge,",
                        "      collect the blueprint.",
                        "      Otherwise, take the right path.",
                        "",
                        ""],
                   7 : ["Let's see how fast you can get",
                        "this over and done with.",
                        "Hint:",
                        "  You will need 4 moves in a ",
                        "  loop."],
                   8 : ["You are close to completion. The ",
                        "Millenium Falcon is at the next ",
                        "docking bay!",
                        "",
                        "c    while <condition>:",
                        "c        if <condition>:",
                        "c            <do stuff>",
                        "c        else:",
                        "c            <do stuff>"],
                   9 : ["Hop onto the Millenium Falcon and",
                        "escape!",
                        "Holes will randomly appear on the",
                        "map, so try putting if-else ",
                        "statement in a loop!"]}
    for lineNumber in range(len(helpMessage[level])):
        isCode = False
        if len(helpMessage[level][lineNumber]) > 0:
            if helpMessage[level][lineNumber][0] == 'c':
                helpMessage[level][lineNumber] = helpMessage[level][lineNumber][1:];
                isCode = True;

        if isCode:
            gameDisplay.blit(csmallfont.render(helpMessage[level][lineNumber], True, grey),\
                             [835, 395+lineNumber*xsmallfont.get_linesize()])
        else:
            gameDisplay.blit(xsmallfont.render(helpMessage[level][lineNumber], True, white),\
                             [835, 395+lineNumber*xsmallfont.get_linesize()])

def status(score,set_time,elapse_time):
    text = smallfont.render("Score:          " + str(score), True, black)
    gameDisplay.blit(text,[55,map_height])

    if(elapse_time>set_time):
        elapse_time=set_time
    pygame.draw.rect(gameDisplay,red, [map_width/2, map_height+2, map_width*(set_time-elapse_time)/(2*set_time), status_bar])
    pygame.draw.line(gameDisplay,black,(map_width/2-2,map_height),(map_width/2-2,display_height), 4)
    text2 = smallfont.render("Time left", True, black)
    gameDisplay.blit(text2,[3*map_width/4-15,map_height])

def randBlueprintGen():
    randBlueprintX = 120
    randBlueprintY = 150
    return randBlueprintX, randBlueprintY

#----Sounds method for choosing which bgm to load-----------#
def loadBGM(level):
    loadList = []

    if level == 1 or level == 2 or level == 0:
        loadList = [bgm1,bgm1loop]

    elif level == 3 or level == 4:
        loadList = [bgm2,bgm2loop]

    elif level == 5 or level == 6 or level == 7:
        loadList = [bgm3, bgm3loop]

    elif level == 8 or level == 9:
        loadList = [bgm4, bgm4loop]

    return loadList

def game_intro():
    global characterMove
    pygame.mixer.music.load("sounds/intro - star wars main theme.ogg")
    pygame.mixer.music.play(0)
    intro = True

    while intro:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_i:
                    characterMove = [renMoveUp, renMoveDown, renMoveRight, renMoveLeft]
                    intro=False
                if event.key == pygame.K_s:
                    characterMove = [stormtMoveUp, stormtMoveDown, stormtMoveRight, stormtMoveLeft]
                    intro=False
                if event.key == pygame.K_t:
                    characterMove = [lukeMoveUp, lukeMoveDown, lukeMoveRight, lukeMoveLeft]
                    intro=False
                if event.key == pygame.K_d:
                    characterMove = [darthMoveUp, darthMoveDown, darthMoveRight, darthMoveLeft]
                    intro=False
                if event.key == pygame.K_m:
                    startGame.play()
                    characterMove = [finnMoveUp, finnMoveDown, finnMoveRight, finnMoveLeft]
                    intro=False
                if event.key == pygame.K_f:
                    startGame.play()
                    characterMove = [reyMoveUp, reyMoveDown, reyMoveRight, reyMoveLeft]
                    intro=False
                if event.key == pygame.K_q:
                    pygame.quit()
                    quit()

        gameDisplay.fill(white)
        wp = wallpaper_img
        wp = pygame.transform.scale(wp,(display_width,display_height))
        gameDisplay.blit(wp, (0,0))
        pygame.display.update()
        clock.tick(5)

def rebel_move(direction, playerX, playerY, xChange, yChange, rebelScore, time_limit, seconds, xlocation, ylocation, barrier_width,barrier_height,randBlueprintX, randBlueprintY):

    global game_map
    image = None
    for img in characterMove[direction]:

        playerX += xChange
        playerY += yChange

        gameDisplay.fill(white)
        gameDisplay.blit(game_map, (0,0))
        gameDisplay.blit(text_editor, (map_width,0))
        pygame.draw.line(gameDisplay,black,(map_width,display_height),(map_width,0), 2)#draw boundary for user to type code
        pygame.draw.line(gameDisplay,black,(0,map_height),(map_width,map_height), 2)#draw boundary for status bar
        status(rebelScore, time_limit,seconds)
        #if level one
        game_map=map_img[level]
        if (blueprintCollected == False) and blueprintExist:
            gameDisplay.blit(blueprint_img, (randBlueprintX, randBlueprintY))

        gameDisplay.blit(btnimg, runbtn_rect)
        gameDisplay.blit(eraseimg, erasebtn_rect)
        draw_holes()
        gameDisplay.blit(img, (playerX, playerY))
        if level == 9:
            gameDisplay.blit(mFalconStationary, (510, 225))

        image = img

        txtbx.draw(gameDisplay)
        helpInstructions(level)
        pygame.display.update()
        clock.tick(10)

    return playerX, playerY, image

def rebel_jump(direction, playerX, playerY, xChange, yChange, rebelScore, time_limit, seconds, xlocation, ylocation, barrier_width,barrier_height,randBlueprintX, randBlueprintY):

    global game_map
    image = None

    img = characterMove[direction][-1] # get stationary img

    for j in range(6):

        # hardcoding storm trooper line of sight
        player_rect = pygame.Rect(playerX, playerY, 30, 30)
        if player_rect.colliderect(trooper_LOS) and level == 6:
            break

        playerX += xChange

        if direction == 2 or direction == 3:
            if j < 3:
                playerY -= abs(xChange)
            else:
                playerY += abs(xChange)
        elif direction == 0:
            if j < 4:
                playerY -= int(1.7*abs(yChange))
            else:
                playerY += int(0.4*abs(yChange))
        elif direction == 1:
            if j < 2:
                playerY -= int(0.4*abs(yChange))
            else:
                playerY += int(1.7*abs(yChange))

        gameDisplay.fill(white)
        gameDisplay.blit(game_map, (0,0))
        gameDisplay.blit(text_editor, (map_width,0))
        pygame.draw.line(gameDisplay,black,(map_width,display_height),(map_width,0), 2)#draw boundary for user to type code
        pygame.draw.line(gameDisplay,black,(0,map_height),(map_width,map_height), 2)#draw boundary for status bar
        status(rebelScore, time_limit,seconds)
        #if level one
        game_map=map_img[level]

        if (blueprintCollected == False) and blueprintExist:
            #barrier(xlocation, randomHeight, barrier_width)
            gameDisplay.blit(blueprint_img, (randBlueprintX, randBlueprintY))

        #for checking hole position
##            for hole in holes:
##                hole.draw()
        gameDisplay.blit(btnimg, runbtn_rect)
        gameDisplay.blit(eraseimg, erasebtn_rect)
        draw_holes()
        gameDisplay.blit(img, (playerX, playerY))
        if level == 9:
            gameDisplay.blit(mFalconStationary, (510, 225))

        image = img

        txtbx.draw(gameDisplay)
        helpInstructions(level)
        pygame.display.update()
        clock.tick(15)

    return playerX, playerY, image

def mfalcon_fly(rebelScore, time_limit, seconds, randBlueprintX, randBlueprintY):

    global game_map
    falcon.play()
    mFalconX = 510
    mFalconY = 225

    for i in range(len(mFalconFireUp) + 100):

        if i > 15:
            index = 15
            mFalconX += 5
        else:
            index = i

        for j in range(2):
            gameDisplay.fill(white)
            gameDisplay.blit(game_map, (0,0))
            draw_holes()
            gameDisplay.blit(mFalconFireUp[index], (mFalconX, mFalconY))
            gameDisplay.blit(text_editor, (map_width,0))
            pygame.draw.line(gameDisplay,black,(map_width,display_height),(map_width,0), 2)#draw boundary for user to type code
            pygame.draw.line(gameDisplay,black,(0,map_height),(map_width,map_height), 2)#draw boundary for status bar
            status(rebelScore, time_limit,seconds)
            helpInstructions(level)
            #if level one
            game_map=map_img[level]

            if (not blueprintCollected) and blueprintExist:
                gameDisplay.blit(blueprint_img, (randBlueprintX, randBlueprintY))
            gameDisplay.blit(btnimg, runbtn_rect)
            gameDisplay.blit(eraseimg, erasebtn_rect)

            txtbx.draw(gameDisplay)
            helpInstructions(level)
            pygame.display.update()

            if index != 15:
                clock.tick(10)

def place_random_holes():
    del holes[:]
    if level == 9:
        possible_locs = range(3, 20, 2)
    else:
        possible_locs = range(3, 25, 2)
    vertical_locs = random.randint(6, 12)
    for i in range (8): # number of columns of holes
        x = random.randrange(3, 16, 2)
        y = random.randrange(6, 12)
        make_hole_columns(x * 30, y * 30, random.choice((2, 3)))

def make_hole_columns(x, y, height):
    for i in range(height):
        holes.append(Hole(gameDisplay, (x, y + (i * 30))))

def draw_holes():
    if level == numOfLevels - 1: # only draw holes for last level
        for hole in holes:
            hole.draw()

def crashed_into_wall(lead_x, lead_y, xlist, ylist, widthlist, heightlist):
    player_rect = pygame.Rect(lead_x, lead_y, 30, 30)
    for i in range(len(xlist)):
        wall = pygame.Rect(xlist[i], ylist[i], widthlist[i], heightlist[i])
        if wall.colliderect(player_rect): return True
    return False

def linecount_to_score(n):
    return txtbx.lines - n

def text_objects(text,color,size):
    if size == "small":
        textSurface = smallfont.render(text, True, color)
    elif size == "medium":
        textSurface = medfont.render(text, True, color)
    elif size == "large":
        textSurface = largefont.render(text, True, color)
    return textSurface, textSurface.get_rect()

def message_to_screen(msg,color, y_displace = 0, size = "small"):
    textSurf, textRect = text_objects(msg, color, size)
    textRect.center = (map_width / 2), (map_height / 2) + y_displace
    gameDisplay.blit(textSurf, textRect)

def gameLoop():
    global parsing, game_state, text_editor, elemNumber, level,txtbx, game_map, blueprintCollected, characterMove,numOfLevels, rebelScore
    global lead_x, lead_y, lead_direction,holes,blueprintExist, time_limit
    gameWon = False
    gameExit = False
    gameOver = False
    leftCollision = False
    rightCollision = False
    topCollision = False
    bottomCollision = False
    player = characterMove[1][2]
    [lead_x,lead_y,xlist,ylist,widthlist,heightlist,win_width,win_height,win_xlocation,win_ylocation,holeCoords,vadarOrientation,blueprint] = loadLevel(level)

    lead_x_change = 0
    lead_y_change = 0
    randBlueprintX = 0
    randBlueprintY = 0
    blueprintExist = False
    if(len(blueprint)>0):
        blueprintCollected = False
        blueprintExist = True
        randBlueprintX = blueprint[0]
        randBlueprintY = blueprint[1]

    step_count = 0
    pause_duration = 0
    code_lines = 0
    movement.reset()

    timerStart=False
    seconds=0
    del holes[:]
    for i in range(len(holeCoords)):
        holes.append(Hole(gameDisplay, (holeCoords[i][0], holeCoords[i][1])))
    # use get_ticks to time
    #timer.reset()

    barrier_width = 30
    barrier_height = 30
    xlocation = (map_width/2)+ random.randint(-0.2*map_width, 0.2*map_width)
    ylocation = random.randrange(map_height*0.1,map_height*0.6)

    #----------LOAD BGM-----------#
    beginloop = False
    bgmlist = loadBGM(level)
    pygame.mixer.music.stop() # make sure theres no music playing.
    pygame.mixer.music.load(bgmlist[0])
    pygame.mixer.music.play(0)
    pygame.mixer.music.set_endevent(BEGIN_LOOP)

    while not gameExit:

        #Check if bgm has finish playing

        event = pygame.mixer.music.get_endevent()
        pygame.mixer.music.queue(bgmlist[1])

        if gameWon == True:
            rebelScore += linecount_to_score(code_lines)+int(time_limit-seconds)
            pygame.draw.rect(gameDisplay, white, [240, map_height+4, 90, 31])
            status(rebelScore, time_limit,seconds)
            #-----sounds
            pygame.mixer.music.stop()
            pygame.mixer.music.load("sounds/victorybgm.ogg")
            pygame.mixer.music.play(-1)
            #-----sounds
            if level == 9:
                message_to_screen("Congratulations!", green,
                                  y_displace=-150, size = "large")
                message_to_screen("Your Score is " + str(rebelScore), green,
                                  y_displace=-50, size = "medium")
                message_to_screen("Please notify your friendly TA", orange,
                                  50, size = "small")
                message_to_screen("to collect your prize", orange,
                                  100, size = "small")
            else:
                message_to_screen("Level cleared!", green,
                                  y_displace=-50, size = "large")
                message_to_screen("Press C to proceed", orange,
                                  50, size = "small")
                message_to_screen("or Q to quit", orange,
                                  100, size = "small")

            level = (level+1)%numOfLevels
            txtbx.clear()

            pygame.display.update()

        elif gameOver == True:
            rebelScore -= 2
            pygame.mixer.music.stop()
            pygame.mixer.music.load("sounds/lose - imperial march.ogg")
            pygame.mixer.music.play(-1)
            #-----sounds
            message_to_screen("GAME OVER", red,
                              y_displace=-50, size = "large")
            message_to_screen("Press C to play again", orange,
                              50, size = "medium")
            message_to_screen("or Q to quit", orange,
                              100, size = "medium")
            #----- displays
            if vadarOrientation == 0:
                gameDisplay.blit(darthDownStationary, (win_xlocation, win_ylocation))
            elif vadarOrientation == 2:
                gameDisplay.blit(darthUpStationary, (win_xlocation, win_ylocation))
            elif vadarOrientation == 1:
                gameDisplay.blit(darthLeftStationary, (win_xlocation, win_ylocation))
            else:
                gameDisplay.blit(darthRightStationary, (win_xlocation, win_ylocation))
            pygame.display.update()

        while gameOver == True or gameWon == True:
            game_state = 'gameover'
            parser_thread.stop()
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    gameWon = False
                    gameOver = False
                    gameExit = True
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        gameWon = False
                        gameExit = True
                        gameOver = False
                    if event.key == pygame.K_c:
                        game_state = 'idle'
                        gameWon= False
                        pygame.mixer.music.stop()
                        gameLoop()

    ############## timer ##########################
        if timerStart:
            timer.update()
            seconds = timer.get_time() #calculate how many seconds
            if (time_limit - seconds)<=0:
                randnumb = random.randint(0,len(dvlist)-1)
                #-----sounds
                pygame.mixer.Sound(dvlist[randnumb]).play()
                #-----sounds
                gameOver=True
            #print (seconds) #print how many seconds

###################### WIN GAME CONDITIONS: Lands on the exit grid ###########################
        win_rect = pygame.Rect(win_xlocation, win_ylocation, win_width, win_height)
        player_rect = pygame.Rect(lead_x, lead_y, 30, 30)
        if win_rect.colliderect(player_rect):
            gameWon = True
            if level == 9:
                mfalcon_fly(rebelScore, time_limit, seconds, randBlueprintX, randBlueprintY)

###################### END GAME CONDITIONS: Out of bound detection, Timelimit ###########################
        if lead_x > map_width - block_size or lead_x < 0 or lead_y > map_height - block_size \
            or lead_y<0:
            gameOver = True

        if game_state == 'error':
            display_error()

####################### UPDATES PLAYER LOCATION ################################
        # lead_x += lead_x_change
        # lead_y += lead_y_change

####################### displaying it on screen ################################
        gameDisplay.fill(white)
        game_map=map_img[level]
        text_editor=text_editor_img
        gameDisplay.blit(game_map, (0,0))
        gameDisplay.blit(text_editor, (map_width,0))
        pygame.draw.line(gameDisplay,black,(map_width,display_height),(map_width,0), 2) #draw boundary for user to type code
        pygame.draw.line(gameDisplay,black,(0,map_height),(map_width,map_height), 2) #draw boundary for status bar
        if not gameWon:
            gameDisplay.blit(player, (lead_x, lead_y))
        status(rebelScore, time_limit,seconds)
        helpInstructions(level)

        if level == numOfLevels - 1:
            draw_holes()
        if level == 9 and not gameWon:
            gameDisplay.blit(mFalconStationary, (510, 225))

####################### barrier collision detection #############################

        for i in range(0,len(xlist)):
            ylocation = ylist[i]
            xlocation = xlist[i]
            barrier_height = heightlist[i]
            barrier_width = widthlist[i]
            #for debugging:
            #pygame.draw.rect(gameDisplay,red,[xlocation,ylocation,barrier_width,barrier_height])
            if ylocation + barrier_height > lead_y and lead_y + block_size > ylocation:
                if lead_x - (block_size/2) < xlocation + barrier_width and lead_x > xlocation + barrier_width/2:
                    leftCollision = True
                if lead_x + (4*block_size) > xlocation and lead_x < xlocation + barrier_width/2:
                    rightCollision = True
            elif xlocation + barrier_width > lead_x and lead_x + block_size > xlocation:
                if lead_y - (block_size/2) < ylocation + barrier_height and lead_y > ylocation + barrier_height/2:
                    topCollision = True
                if lead_y + (4*block_size) > ylocation and lead_y < ylocation + barrier_height/2:
                    bottomCollision = True

######################## when blueprint have been collected ###########################
        if (blueprintCollected == False) and blueprintExist:
            gameDisplay.blit(blueprint_img, (randBlueprintX, randBlueprintY))
            if lead_x >= randBlueprintX and lead_x <= randBlueprintX + BlueprintThickness or lead_x + block_size >= randBlueprintX and \
               lead_x + block_size <= randBlueprintX + BlueprintThickness:

                if lead_y >= randBlueprintY and lead_y <= randBlueprintY + BlueprintThickness:
                    rebelScore+=30
                    collectblueprint.play()
                    blueprintCollected = True

                elif lead_y + block_size >= randBlueprintY and lead_y + block_size <= randBlueprintY + BlueprintThickness:
                    rebelScore+=30
                    collectblueprint.play()
                    blueprintCollected = True

        clock.tick(30)
            ##for checking holes in map
##        for hole in holes:
##            hole.draw()

    ######################### Player controls - Keypress or Typed text #########################

        events = pygame.event.get()

        # to quit game
        for event in events:
            if event.type == pygame.QUIT:
                gameExit = True

        # Use the Movement class to keep track of moves.
        if control_mode == 'TYPE':
            next_move = movement.get_next_move()
            # print "next_move", next_move
            # print "left collision", leftCollision
            # print "right collision", rightCollision
            # print "top collision", topCollision
            # print "btm collision", bottomCollision

            # 0: up, 1: down, 2: right, 3: left
            if next_move == 'stationary':
                lead_x_change = 0
                lead_y_change = 0
            elif next_move == 'move_up':
                if topCollision:
                    bangwall.play()
                    lead_x, lead_y, player = rebel_move(0, lead_x, lead_y, 0, 0, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)
                    # topCollision = False
                else:
                    lead_x, lead_y, player = rebel_move(0, lead_x, lead_y, 0, -10, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)

            elif next_move == 'move_down':
                if bottomCollision:
                    bangwall.play()
                    lead_x, lead_y, player = rebel_move(1, lead_x, lead_y, 0, 0, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)
                    # bottomCollision = False
                else:
                    lead_x, lead_y, player = rebel_move(1, lead_x, lead_y, 0, 10, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)

            elif next_move == 'move_left':
                if leftCollision:
                    bangwall.play()
                    lead_x, lead_y, player = rebel_move(3, lead_x, lead_y, 0, 0, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)
                    # leftCollision = False
                else:
                    lead_x, lead_y, player = rebel_move(3, lead_x, lead_y, -10, 0, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)

            elif next_move == 'move_right':

                if rightCollision:
                    bangwall.play()
                    lead_x, lead_y, player = rebel_move(2, lead_x, lead_y, 0, 0, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)
                    # rightCollision = False
                else:
                    lead_x, lead_y, player = rebel_move(2, lead_x, lead_y, 10, 0, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)

            elif next_move == 'jump_up':
                jump1.play()
                if topCollision:
                    bangwall.play()
                    lead_x, lead_y, player = rebel_jump(0, lead_x, lead_y, 0, 0, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)
                    # topCollision = False
                else:
                    lead_x, lead_y, player = rebel_jump(0, lead_x, lead_y, 0, -10, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)

            elif next_move == 'jump_down':
                jump1.play()
                if bottomCollision:
                    bangwall.play()
                    lead_x, lead_y, player = rebel_jump(1, lead_x, lead_y, 0, 0, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)
                    # bottomCollision = False
                else:
                    lead_x, lead_y, player = rebel_jump(1, lead_x, lead_y, 0, 10, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)

            elif next_move == 'jump_left':
                jump1.play()
                if leftCollision:
                    bangwall.play()
                    lead_x, lead_y, player = rebel_jump(3, lead_x, lead_y, 0, 0, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)
                    # leftCollision = False
                else:
                    lead_x, lead_y, player = rebel_jump(3, lead_x, lead_y, -10, 0, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)

            elif next_move == 'jump_right':
                jump1.play()
                if rightCollision:
                    bangwall.play()
                    lead_x, lead_y, player = rebel_jump(2, lead_x, lead_y, 0, 0, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)
                    # rightCollision = False
                else:
                    lead_x, lead_y, player = rebel_jump(2, lead_x, lead_y, 10, 0, rebelScore, time_limit, seconds, xlocation, ylocation,
                                                    barrier_width, barrier_height, randBlueprintX, randBlueprintY)

            # reset all collision state after moving (although right now it resets even when not moving)
            topCollision = False
            bottomCollision = False
            leftCollision = False
            rightCollision = False

        if crashed_into_wall(lead_x, lead_y, xlist, ylist, widthlist, heightlist):
            bangwall.play()
            gameOver = True

        # hardcoding storm trooper line of sight
        player_rect = pygame.Rect(lead_x, lead_y, 30, 30)
        if level == 6 and player_rect.colliderect(trooper_LOS):
            trooper.play()
            gameOver = True

        # check if player is on a hole
        for hole in holes:
            player_rect = pygame.Rect(lead_x, lead_y, 30, 30)
            collide_direction = hole.collides(player_rect)
            if collide_direction == 'exact':
                fall.play()
                gameOver = True

        if parsing:
            movement_state = game_state[:4]
            direction = game_state[5:]
            if movement_state == 'jump' or movement_state == 'move':
                movement.add_move(game_state)
                lead_direction = direction
                game_state = 'moving'
            elif game_state == 'moving' and done_moving():
                game_state = 'idle'

        # run code button
        gameDisplay.blit(btnimg, runbtn_rect)
        gameDisplay.blit(eraseimg, erasebtn_rect)
        for event in events:
            if event.type == pygame.MOUSEBUTTONUP:
                # print pygame.mouse.get_pos()
                if erasebtn_rect.collidepoint(pygame.mouse.get_pos()):
                    txtbx.clear()
                if runbtn_rect.collidepoint(pygame.mouse.get_pos()):
                    if timerStart==False:
                        timer.set_ticks_func(pygame.time.get_ticks)
                        timer.reset()
                        timerStart=True

                    if level == numOfLevels - 1:
                        place_random_holes()

                    parsing = True

                    code = txtbx.get_text()
                    code = code.replace('self', 'this_is_impossible_to_be_screwed_up')
                    code_lines += txtbx.get_linecount()
                    parser_thread.start(parser_func, code)

        txtbx.update(events)
        txtbx.draw(gameDisplay)
        pygame.display.update()

    parser_thread.stop()
    pygame.quit()
    quit()

game_intro()
gameLoop()


from utils import prepare_data, load_data, create_data, save_training_data, train
from dataset import ChatbotDataset

from neural import NeuralNetwork

import numpy as np

import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader, TensorDataset

tags = []
words = []
pattern_tag_list = []
words_to_ignore = ['?', '.', '!']

inputs = []
targets = []

# Loading data from json
intents = load_data('Data/intents.json')

# Preparing data by tokenizing and stemming
prepare_data = prepare_data(
    intents, tags, words, pattern_tag_list, words_to_ignore)
words, tags = prepare_data

# Creating data for training
create_data = create_data(inputs, targets, pattern_tag_list, tags, words)
inputs, targets = create_data

# Training data
dataset = ChatbotDataset(inputs, targets)
train_loader = DataLoader(dataset=dataset,
                          batch_size=8,
                          shuffle=True)

input_size = len(inputs[0])
hidden_size = len(tags)
output_size = len(tags)
model = NeuralNetwork(input_size,hidden_size,output_size)

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

# Training phase
train(100, optimizer, criterion, model, train_loader)

# Save data
save_training_data(model.state_dict(), words, tags, input_size, hidden_size, output_size)


from poseModel.Node import Node
from poseModel.Person import Person
from poseModel.Pose import Pose
from utils.Comparator import Comparator

file = open("/data/data.txt", 'r')
output = []
output = open("/data/output.txt", 'w')
person = []
comparator = Comparator()

def existPerson(pose):
    if len(person) == 0:
        return False
    else:
        for p in person:
            if comparator.isPoseBelongsPerson(pose, p):
                return p
        return False

for line in file:
    line.replace("\n", "")
    numbers = line.split(" ")
    for i in range(1, len(numbers), 54):
        pose = Pose()
        count = 0
        for j in range(i, i + 54, 3):
            if j + 2 > len(numbers)-1:
                break
            print(count, numbers[j], numbers[j+1], numbers[j+2])
            pose.addNode(Node(count, float(numbers[j]), float(numbers[j+1]), float(numbers[j+2])))
            count += 1
        if pose.getAveConfidence() >= 0.4:
            if existPerson(pose) != False:
                existPerson(pose).addPose(pose)
            else:
                newPerson = Person()
                newPerson.addPose(pose)
                person.append(newPerson)
for i in range(len(person)):
    output.write(str(i) + "\n")
    person[i].outputPerson(output)
file.close()
output.close()


import sys
import os
import time
import argparse

#### Config ####
import configparser

#### Database ####
import sqlite3

#### Reticulum ####
# Install: pip3 install rns
# Source: https://markqvist.github.io
import RNS
import RNS.vendor.umsgpack as msgpack

##############################################################################################################
# Globals

#### Global Variables - Configuration ####
NAME = "RNS Announce Directory"
DESCRIPTION = "Database for the collection of received announcements"
VERSION = "0.0.1 (2023-01-12)"
COPYRIGHT = "(c) 2023 Sebastian Obele  /  obele.eu"
PATH = os.path.expanduser("~") + "/." + os.path.splitext(os.path.basename(__file__))[0]
PATH_RNS = None

#### Global Variables - System (Not changeable) ####
CONFIG = None
DB = None
RNS_CONNECTION = None
RNS_ANNOUNCE_HANDLER = None

##############################################################################################################
# AnnounceHandler Class

class AnnounceHandler:
    def __init__(self, aspect_filter=None, callback=None, dest_type=None, hidden=False, hop_min=0, hop_max=0, hop_interfaces=[], recall_app_data=None, dest_deny=[]):
        self.aspect_filter = aspect_filter
        self.callback = callback
        self.dest_type = dest_type
        self.hidden = hidden
        self.hop_min = hop_min
        self.hop_max = hop_max
        self.hop_interfaces = hop_interfaces
        self.recall_app_data = recall_app_data
        self.dest_deny = dest_deny

    def received_announce(self, destination_hash, announced_identity, app_data):
        if app_data == None:
            if self.hidden:
                app_data = b''
            else:
                return

        if len(app_data) == 0:
            if self.hidden:
                app_data = b''
            else:
                return

        dest_type = self.dest_type

        if self.recall_app_data and self.recall_app_data != "":
            try:
                identity = RNS.Identity.recall(destination_hash)
                if identity != None:
                    app_data = RNS.Identity.recall_app_data(RNS.Destination.hash_from_name_and_identity(self.recall_app_data, identity))
                    if app_data != None and len(app_data) > 0:
                        pass
                    else:
                        app_data = b''
                else:
                    app_data = b''
            except:
                pass
        else:
            try:
                app_data_dict = msgpack.unpackb(app_data)
                if isinstance(app_data_dict, dict):
                    if "c" in app_data_dict:
                        app_data = app_data_dict["c"]
                    if "f" in app_data_dict and "type" in app_data_dict["f"]:
                        dest_type = app_data_dict["f"]["type"]
            except:
                pass

        try:
            app_data = app_data.decode("utf-8")
            hop_count = RNS.Transport.hops_to(destination_hash)
            hop_interface = RNS_CONNECTION.get_next_hop_if_name(destination_hash)

            if self.hop_min > 0 and hop_count < self.hop_min:
                return

            if self.hop_max > 0 and hop_count < self.hop_max:
                return

            if len(self.hop_interfaces) > 0 and hop_interface not in self.hop_interfaces:
                return

            if len(self.dest_deny) > 0 and destination_hash in self.dest_deny:
                return

            log("RNS - Received '"+self.aspect_filter+"' announce for "+RNS.prettyhexrep(destination_hash)+" "+str(hop_count)+" hops away with data: "+app_data, LOG_DEBUG)

            self.callback(
                dest=destination_hash,
                app_data=app_data,
                dest_type=dest_type,
                hop_count=hop_count,
                hop_interface=hop_interface,
                hop_dest=None
            )

        except Exception as e:
            log("RNS - Error while processing received announce: "+str(e), LOG_ERROR)

##############################################################################################################
# Database

def db_connect():
    global DB

    if DB == None:
        DB = sqlite3.connect(PATH+"/database.db", isolation_level=None, check_same_thread=False)

    return DB

def db_commit():
    global DB

    if DB != None:
        try:
            DB.commit()
        except:
            pass

def db_init(init=True):
    db = db_connect()
    dbc = db.cursor()

    if init:
        dbc.execute("DROP TABLE IF EXISTS announce")
    dbc.execute("CREATE TABLE IF NOT EXISTS announce (dest BLOB PRIMARY KEY, ts INTEGER DEFAULT 0, data TEXT DEFAULT '', type INTEGER DEFAULT 0, hop_count INTEGER DEFAULT 0, hop_interface TEXT DEFAULT '', hop_dest BLOB)")

    db_commit()

def db_migrate():
    db_init(False)

    db = db_connect()
    dbc = db.cursor()

    db_commit()

    db_init(False)

def db_indices():
    pass

def db_load():
    if not os.path.isfile(PATH+"/database.db"):
        db_init()
    else:
        db_migrate()
        db_indices()

def db_announce_add(dest, app_data, dest_type=0x01, hop_count=0, hop_interface="", hop_dest=None):
    db = db_connect()
    dbc = db.cursor()

    if app_data == "":
        query = "SELECT dest FROM announce WHERE dest = ?"
        dbc.execute(query, (dest,))
        result = dbc.fetchall()
        if len(result) > 0:
            query = "UPDATE announce SET ts = ?, type = ?, hop_count = ?, hop_interface = ?, hop_dest = ? WHERE dest = ?"
            dbc.execute(query, (time.time(), dest_type, hop_count, hop_interface, hop_dest, dest))
        else:
            query = "INSERT OR REPLACE INTO announce (dest, ts, data, type, hop_count, hop_interface, hop_dest) values (?, ?, ?, ?, ?, ?, ?)"
            dbc.execute(query, (dest, time.time(), app_data, dest_type, hop_count, hop_interface, hop_dest))
    else:
        query = "INSERT OR REPLACE INTO announce (dest, ts, data, type, hop_count, hop_interface, hop_dest) values (?, ?, ?, ?, ?, ?, ?)"
        dbc.execute(query, (dest, time.time(), app_data, dest_type, hop_count, hop_interface, hop_dest))

    db_commit()

##############################################################################################################
# Config

#### Config - Get #####
def config_get(config, section, key, default="", lng_key=""):
    if not config or section == "" or key == "": return default
    if not config.has_section(section): return default
    if config.has_option(section, key+lng_key):
        return config[section][key+lng_key]
    elif config.has_option(section, key):
        return config[section][key]
    return default

def config_getint(config, section, key, default=0, lng_key=""):
    if not config or section == "" or key == "": return default
    if not config.has_section(section): return default
    if config.has_option(section, key+lng_key):
        return config.getint(section, key+lng_key)
    elif config.has_option(section, key):
        return config.getint(section, key)
    return default

def config_getboolean(config, section, key, default=False, lng_key=""):
    if not config or section == "" or key == "": return default
    if not config.has_section(section): return default
    if config.has_option(section, key+lng_key):
        return config[section].getboolean(key+lng_key)
    elif config.has_option(section, key):
        return config[section].getboolean(key)
    return default

def config_getsection(config, section, default="", lng_key=""):
    if not config or section == "": return default
    if not config.has_section(section): return default
    if config.has_section(section+lng_key):
        return key+lng_key
    elif config.has_section(section):
        return key
    return default

def config_getoption(config, section, key, default=False, lng_key=""):
    if not config or section == "" or key == "": return default
    if not config.has_section(section): return default
    if config.has_option(section, key+lng_key):
        return key+lng_key
    elif config.has_option(section, key):
        return key
    return default

#### Config - Read #####
def config_read(file=None, file_override=None):
    global CONFIG

    if file is None:
        return False
    else:
        CONFIG = configparser.ConfigParser(allow_no_value=True, inline_comment_prefixes="#")
        CONFIG.sections()
        if os.path.isfile(file):
            try:
                if file_override is None:
                    CONFIG.read(file, encoding='utf-8')
                elif os.path.isfile(file_override):
                    CONFIG.read([file, file_override], encoding='utf-8')
                else:
                    CONFIG.read(file, encoding='utf-8')
            except Exception as e:
                return False
        else:
            if not config_default(file=file, file_override=file_override):
                return False
    return True

#### Config - Save #####
def config_save(file=None):
    global CONFIG

    if file is None:
        return False
    else:
        if os.path.isfile(file):
            try:
                with open(file,"w") as file:
                    CONFIG.write(file)
            except Exception as e:
                return False
        else:
            return False
    return True

#### Config - Default #####
def config_default(file=None, file_override=None):
    global CONFIG

    if file is None:
        return False
    elif DEFAULT_CONFIG != "":
        if file_override and DEFAULT_CONFIG_OVERRIDE != "":
            if not os.path.isdir(os.path.dirname(file_override)):
                try:
                    os.makedirs(os.path.dirname(file_override))
                except Exception:
                    return False
            if not os.path.exists(file_override):
                try:
                    config_file = open(file_override, "w")
                    config_file.write(DEFAULT_CONFIG_OVERRIDE)
                    config_file.close()
                except:
                    return False

        if not os.path.isdir(os.path.dirname(file)):
            try:
                os.makedirs(os.path.dirname(file))
            except Exception:
                return False
        try:
            config_file = open(file, "w")
            config_file.write(DEFAULT_CONFIG)
            config_file.close()
            if not config_read(file=file, file_override=file_override):
                return False
        except:
            return False
    else:
        return False

    if not CONFIG.has_section("main"): CONFIG.add_section("main")
    CONFIG["main"]["default_config"] = "True"
    return True

##############################################################################################################
# CMDs

def cmd(path=None):
    global PATH

    if path is not None:
        if path.endswith("/"):
            path = path[:-1]
        PATH = path

    try:
        import readline
    except ImportError:
        pass

    print("---- Database interface ----")
    print("")

    print("File: "+PATH+"/database.db")
    print("")

    db = db_connect()

    while True:
        try:
            print("> ")
            cmd = input()
            if cmd.strip() == "":
                continue
            readline.add_history(cmd)
            if cmd.lower() == "exit" or cmd.lower() == "quit":
                exit()

        except KeyboardInterrupt:
            exit()

        except EOFError:
            exit()

        if cmd.lower() == "clear":
            print("\033c", end="")
        else:
            try:
                dbc = db.cursor()
                dbc.execute(cmd)
                result = dbc.fetchall()
                print("Rows: "+str(len(result)))
                print("Data:")
                for row in result:
                    print(row)
                    print("")
                db_commit()
            except Exception as e:
                print("Error: "+str(e))

def cmd_status(path=None):
    global PATH

    if path is not None:
        if path.endswith("/"):
            path = path[:-1]
        PATH = path

    print("---- Database status ----")
    print("")

    print("File: "+PATH+"/database.db")
    print("Size: "+cmd_size_str(os.path.getsize(PATH+"/database.db")))

    db = db_connect()
    dbc = db.cursor()

    query = "SELECT name FROM sqlite_master WHERE type = 'table'"
    dbc.execute(query)
    result = dbc.fetchall()
    if len(result) < 1:
        print("Error: Empty result")
    else:
        query = ""
        for entry in result:
            query += "SELECT '"+entry[0]+"', count(*) FROM "+entry[0]+" UNION "
        query = query.removesuffix(' UNION ')
        dbc.execute(query)
        result = dbc.fetchall()
        if len(result) < 1:
            print("Error: Empty result")
        else:
            print("")
            print("Tables:")
            for entry in result:
                print(entry[0]+": "+str(entry[1]))

def cmd_size_str(num, suffix='B'):
    if num == None:
        return "0"+suffix
    units = ['','K','M','G','T','P','E','Z']
    last_unit = 'Y'
    if suffix == 'b':
        num *= 8
        units = ['','K','M','G','T','P','E','Z']
        last_unit = 'Y'
    for unit in units:
        if abs(num) < 1000.0:
            if unit == "":
                return "%.0f%s%s" % (num, unit, suffix)
            else:
                return "%.2f%s%s" % (num, unit, suffix)
        num /= 1000.0
    return "%.2f%s%s" % (num, last_unit, suffix)

##############################################################################################################
# Log

LOG_FORCE    = -1
LOG_CRITICAL = 0
LOG_ERROR    = 1
LOG_WARNING  = 2
LOG_NOTICE   = 3
LOG_INFO     = 4
LOG_VERBOSE  = 5
LOG_DEBUG    = 6
LOG_EXTREME  = 7

LOG_LEVEL         = LOG_NOTICE
LOG_LEVEL_SERVICE = LOG_NOTICE
LOG_TIMEFMT       = "%Y-%m-%d %H:%M:%S"
LOG_MAXSIZE       = 5*1024*1024
LOG_PREFIX        = ""
LOG_SUFFIX        = ""
LOG_FILE          = ""

def log(text, level=3, file=None):
    if not LOG_LEVEL:
        return

    if LOG_LEVEL >= level:
        name = "Unknown"
        if (level == LOG_FORCE):
            name = ""
        if (level == LOG_CRITICAL):
            name = "Critical"
        if (level == LOG_ERROR):
            name = "Error"
        if (level == LOG_WARNING):
            name = "Warning"
        if (level == LOG_NOTICE):
            name = "Notice"
        if (level == LOG_INFO):
            name = "Info"
        if (level == LOG_VERBOSE):
            name = "Verbose"
        if (level == LOG_DEBUG):
            name = "Debug"
        if (level == LOG_EXTREME):
            name = "Extra"

        if not isinstance(text, str):
            text = str(text)

        text = "[" + time.strftime(LOG_TIMEFMT, time.localtime(time.time())) +"] [" + name + "] " + LOG_PREFIX + text + LOG_SUFFIX

        if file == None and LOG_FILE != "":
            file = LOG_FILE

        if file == None:
            print(text)
        else:
            try:
                file_handle = open(file, "a")
                file_handle.write(text + "\n")
                file_handle.close()

                if os.path.getsize(file) > LOG_MAXSIZE:
                    file_prev = file + ".1"
                    if os.path.isfile(file_prev):
                        os.unlink(file_prev)
                    os.rename(file, file_prev)
            except:
                return

##############################################################################################################
# System

#### Panic #####
def panic():
    sys.exit(255)

#### Exit #####
def exit():
    sys.exit(0)

##############################################################################################################
# Setup/Start

#### Setup #####
def setup(path=None, path_rns=None, path_log=None, loglevel=None, service=False):
    global PATH
    global PATH_RNS
    global LOG_LEVEL
    global LOG_FILE
    global RNS_CONNECTION
    global RNS_ANNOUNCE_HANDLER

    if path is not None:
        if path.endswith("/"):
            path = path[:-1]
        PATH = path

    if path_rns is not None:
        if path_rns.endswith("/"):
            path_rns = path_rns[:-1]
        PATH_RNS = path_rns

    if loglevel is not None:
        LOG_LEVEL = loglevel
        rns_loglevel = loglevel
    else:
        rns_loglevel = None

    if service:
        LOG_LEVEL = LOG_LEVEL_SERVICE
        if path_log is not None:
            if path_log.endswith("/"):
                path_log = path_log[:-1]
            LOG_FILE = path_log
        else:
            LOG_FILE = PATH
        LOG_FILE = LOG_FILE + "/" + NAME + ".log"
        rns_loglevel = None

    if not config_read(PATH + "/config.cfg", PATH + "/config.cfg.owr"):
        print("Config - Error reading config file " + PATH + "/config.cfg")
        panic()

    if CONFIG["main"].getboolean("default_config"):
        print("Exit!")
        print("First start with the default config!")
        print("You should probably edit the config file \"" + PATH + "/config.cfg\" to suit your needs and use-case!")
        print("You should make all your changes at the user configuration file \"" + PATH + "/config.cfg.owr\" to override the default configuration file!")
        print("Then restart this program again!")
        exit()

    if not CONFIG["main"].getboolean("enabled"):
        print("Disabled in config file. Exit!")
        exit()

    RNS_CONNECTION = RNS.Reticulum(configdir=PATH_RNS, loglevel=rns_loglevel)

    log("...............................................................................", LOG_INFO)
    log("        Name: " + NAME, LOG_INFO)
    log("Program File: " + __file__, LOG_INFO)
    log(" Config File: " + PATH + "/config.cfg", LOG_INFO)
    log("     DB File: " + PATH + "/database.db", LOG_INFO)
    log("     Version: " + VERSION, LOG_INFO)
    log("   Copyright: " + COPYRIGHT, LOG_INFO)
    log("...............................................................................", LOG_INFO)

    log("DB - Loading ...", LOG_DEBUG)

    db_load()

    log("DB - Loaded ...", LOG_DEBUG)

    log("RNS - Connecting ...", LOG_DEBUG)

    RNS_ANNOUNCE_HANDLER = {}

    dest_deny = []
    if CONFIG.has_section("deny"):
        for (key, val) in CONFIG.items("deny"):
            try:
                if len(val) == ((RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2)+2:
                    val = val[1:-1]
                if len(val) != ((RNS.Reticulum.TRUNCATED_HASHLENGTH//8)*2):
                    continue
                val = bytes.fromhex(val)
                dest_deny.append(val)
            except:
                pass

    for section in CONFIG.sections():
        try:
            if section == "main" or section == "deny":
                continue
            if not config_getboolean(CONFIG, section, "enabled"):
                continue

            dest_type = int(config_get(CONFIG, section, "type"), 16)
            hidden = config_getboolean(CONFIG, section, "hidden")
            hop_min = config_getint(CONFIG, section, "hop_min")
            hop_max = config_getint(CONFIG, section, "hop_max")
            hop_interfaces = config_get(CONFIG, section, "hop_interfaces").strip()
            if hop_interfaces.strip() != "":
                hop_interfaces = hop_interfaces.strip().split(",")
            else:
                hop_interfaces = []
            recall_app_data = config_get(CONFIG, section, "recall_app_data")

            RNS_ANNOUNCE_HANDLER[section] = AnnounceHandler(section, db_announce_add, dest_type, hidden, hop_min, hop_max, hop_interfaces, recall_app_data, dest_deny)
            RNS.Transport.register_announce_handler(RNS_ANNOUNCE_HANDLER[section])

            log("RNS - Added announce handler for '"+section+"'", LOG_DEBUG)
        except Exception as e:
            log("RNS - Error while adding announce handler: "+str(e), LOG_ERROR)

    log("RNS - Connected with "+str(len(RNS_ANNOUNCE_HANDLER))+" announce handlers", LOG_DEBUG)

    while True:
        time.sleep(1)

#### Start ####
def main():
    try:
        description = NAME + " - " + DESCRIPTION
        parser = argparse.ArgumentParser(description=description)

        parser.add_argument("-p", "--path", action="store", type=str, default=None, help="Path to alternative config directory")
        parser.add_argument("-pr", "--path_rns", action="store", type=str, default=None, help="Path to alternative Reticulum config directory")
        parser.add_argument("-pl", "--path_log", action="store", type=str, default=None, help="Path to alternative log directory")
        parser.add_argument("-l", "--loglevel", action="store", type=int, default=LOG_LEVEL)
        parser.add_argument("-s", "--service", action="store_true", default=False, help="Running as a service and should log to file")
        parser.add_argument("--exampleconfig", action="store_true", default=False, help="Print verbose configuration example to stdout and exit")
        parser.add_argument("--exampleconfigoverride", action="store_true", default=False, help="Print verbose configuration example to stdout and exit")

        parser.add_argument("--cmd", action="store_true", default=False, help="Database command interface (Execute any sql database command)")
        parser.add_argument("--cmd_status", action="store_true", default=False, help="Database status interface (Shows the current status)")

        params = parser.parse_args()

        if params.exampleconfig:
            print("Config File: " + PATH + "/config.cfg")
            print("Content:")
            print(DEFAULT_CONFIG)
            exit()

        if params.exampleconfigoverride:
            print("Config Override File: " + PATH + "/config.cfg.owr")
            print("Content:")
            print(DEFAULT_CONFIG_OVERRIDE)
            exit()

        if params.cmd:
            cmd(path=params.path)
            exit()

        if params.cmd_status:
            cmd_status(path=params.path)
            exit()

        setup(path=params.path, path_rns=params.path_rns, path_log=params.path_log, loglevel=params.loglevel, service=params.service)

    except KeyboardInterrupt:
        print("Terminated by CTRL-C")
        exit()

##############################################################################################################
# Files

#### Default configuration override file ####
DEFAULT_CONFIG_OVERRIDE = '''# This is the user configuration file to override the default configuration file.
# All settings made here have precedence.
# This file can be used to clearly summarize all settings that deviate from the default.
# This also has the advantage that all changed settings can be kept when updating the program.

#### All announce aspects and settings ####

[lxmf.delivery]
enabled = True
type = 0x01
hidden = False
hop_min = 0 #0=any
hop_max = 0 #0=any
hop_interfaces = #Comma separated list

[lxmf.propagation]
enabled = True
type = 0xAD
hidden = False
hop_min = 0 #0=any
hop_max = 0 #0=any
hop_interfaces = #Comma separated list
recall_app_data = nomadnetwork.node

[nomadnetwork.node]
enabled = True
type = 0xAC
hidden = False
hop_min = 0 #0=any
hop_max = 0 #0=any
hop_interfaces = #Comma separated list

[nomadnetwork.shop]
enabled = True
type = 0xB0
hidden = False
hop_min = 0 #0=any
hop_max = 0 #0=any
hop_interfaces = #Comma separated list
'''

#### Default configuration file ####
DEFAULT_CONFIG = '''# This is the default config file.
# You should probably edit it to suit your needs and use-case.

#### Main program settings ####
[main]

# Enable/Disable this functionality.
enabled = True

#### Deny certain addresses/destinations ####
[deny]
#2858b7a096899116cd529559cc679ffe
'''

##############################################################################################################
# Init

if __name__ == "__main__":
    main()


import time
from dataclasses import dataclass
from typing import Any, Callable, Dict, List, Optional, Tuple, Union

import numpy as np
import torch
from torch import nn
from torch.utils.data import DataLoader, Dataset
from tqdm import tqdm

from modelscope.metainfo import Trainers
from modelscope.models.base import Model, TorchModel
from modelscope.models.nlp import BertForTextRanking
from modelscope.msdatasets.ms_dataset import MsDataset
from modelscope.preprocessors.base import Preprocessor
from modelscope.trainers.builder import TRAINERS
from modelscope.trainers.nlp_trainer import NlpEpochBasedTrainer
from modelscope.utils.constant import DEFAULT_MODEL_REVISION
from modelscope.utils.logger import get_logger

logger = get_logger()

@dataclass
class GroupCollator():
    """
    Wrapper that does conversion from List[Tuple[encode_qry, encode_psg]] to
    List[qry], List[psg] and pass batch separately to the actual collator.
    Abstract out data detail for the model.
    """

    def get_gis(self, gis, inps):
        gis_input_ids, gis_token_type_ids, gis_rel_type_ids = ([], [], [])
        gis_absolute_position_ids, gis_relative_position_ids = ([], [])
        gis_prov_ids, gis_city_ids, gis_dist_ids = ([], [], [])
        china_version = False
        for doc in inps:
            if len(doc) == 0:
                continue
            if len(doc[0]) == 6:
                for geom_id, geom_type, rel_type, absolute_position, relative_position, lxly in doc:
                    gis_input_ids.append(geom_id)
                    gis_token_type_ids.append(geom_type)
                    gis_rel_type_ids.append(rel_type)
                    gis_absolute_position_ids.append(absolute_position)
                    gis_relative_position_ids.append(relative_position)
            elif len(doc[0]) == 9:
                china_version = True
                for geom_id, geom_type, rel_type, absolute_position, relative_position, \
                        prov_id, city_id, dist_id, lxly in doc:
                    gis_input_ids.append(geom_id)
                    gis_token_type_ids.append(geom_type)
                    gis_rel_type_ids.append(rel_type)
                    gis_absolute_position_ids.append(absolute_position)
                    gis_relative_position_ids.append(relative_position)
                    gis_prov_ids.append(prov_id)
                    gis_city_ids.append(city_id)
                    gis_dist_ids.append(dist_id)

        gis.update(gis_input_ids, gis_token_type_ids, gis_rel_type_ids,
                   gis_absolute_position_ids, gis_relative_position_ids,
                   gis_prov_ids, gis_city_ids, gis_dist_ids, china_version)
        return gis

    def __call__(self, features: List[Dict[str, Any]]) -> Dict[str, Any]:
        if isinstance(features[0], list):
            features = sum(features, [])
        keys = features[0].keys()
        batch = {k: list() for k in keys}
        for ele in features:
            for k, v in ele.items():
                batch[k].append(v)
        merged_batch = {}
        gis_list = []
        gis_tp = []
        for k in batch:
            if 'sentence1_gis' == k:
                gis = batch['gis1'][0]
                gis = self.get_gis(gis, batch['sentence1_gis'])
                if gis.prov_ids is not None:
                    gis_list.append({
                        'input_ids': gis.input_ids,
                        'attention_mask': gis.attention_mask,
                        'token_type_ids': gis.token_type_ids,
                        'rel_type_ids': gis.rel_type_ids,
                        'absolute_position_ids': gis.absolute_position_ids,
                        'relative_position_ids': gis.relative_position_ids,
                        'prov_ids': gis.prov_ids,
                        'city_ids': gis.city_ids,
                        'dist_ids': gis.dist_ids
                    })
                else:
                    gis_list.append({
                        'input_ids':
                        gis.input_ids,
                        'attention_mask':
                        gis.attention_mask,
                        'token_type_ids':
                        gis.token_type_ids,
                        'rel_type_ids':
                        gis.rel_type_ids,
                        'absolute_position_ids':
                        gis.absolute_position_ids,
                        'relative_position_ids':
                        gis.relative_position_ids
                    })
                gis_tp.append(torch.LongTensor([1]).to(gis.input_ids.device))
            elif 'sentence2_gis' == k:
                gis = batch['gis2'][0]
                gis = self.get_gis(gis, batch['sentence2_gis'])
                if gis.prov_ids is not None:
                    gis_list.append({
                        'input_ids': gis.input_ids,
                        'attention_mask': gis.attention_mask,
                        'token_type_ids': gis.token_type_ids,
                        'rel_type_ids': gis.rel_type_ids,
                        'absolute_position_ids': gis.absolute_position_ids,
                        'relative_position_ids': gis.relative_position_ids,
                        'prov_ids': gis.prov_ids,
                        'city_ids': gis.city_ids,
                        'dist_ids': gis.dist_ids
                    })
                else:
                    gis_list.append({
                        'input_ids':
                        gis.input_ids,
                        'attention_mask':
                        gis.attention_mask,
                        'token_type_ids':
                        gis.token_type_ids,
                        'rel_type_ids':
                        gis.rel_type_ids,
                        'absolute_position_ids':
                        gis.absolute_position_ids,
                        'relative_position_ids':
                        gis.relative_position_ids
                    })
                gis_tp.append(torch.LongTensor([0]).to(gis.input_ids.device))
            elif 'qid' in k or 'labels' in k:
                merged_batch[k] = torch.cat(batch[k], dim=0)
            elif not k.startswith('gis'):
                k_t = [it.t() for it in batch[k]]
                pad = torch.nn.utils.rnn.pad_sequence(k_t)
                if len(pad.size()) <= 2:
                    merged_batch[k] = pad.t()
                else:
                    l, b1, b2 = pad.size()
                    merged_batch[k] = pad.view(l, b1 * b2).t()
        if len(gis_list) > 0:
            merged_batch['gis_list'] = gis_list
        if len(gis_tp) > 0:
            merged_batch['gis_tp'] = gis_tp
        return merged_batch

@TRAINERS.register_module(module_name=Trainers.mgeo_ranking_trainer)
class MGeoRankingTrainer(NlpEpochBasedTrainer):

    def __init__(
            self,
            model: Optional[Union[TorchModel, nn.Module, str]] = None,
            cfg_file: Optional[str] = None,
            cfg_modify_fn: Optional[Callable] = None,
            arg_parse_fn: Optional[Callable] = None,
            data_collator: Optional[Callable] = None,
            train_dataset: Optional[Union[MsDataset, Dataset]] = None,
            eval_dataset: Optional[Union[MsDataset, Dataset]] = None,
            preprocessor: Optional[Preprocessor] = None,
            optimizers: Tuple[torch.optim.Optimizer,
                              torch.optim.lr_scheduler._LRScheduler] = (None,
                                                                        None),
            model_revision: Optional[str] = DEFAULT_MODEL_REVISION,
            **kwargs):

        if data_collator is None:
            data_collator = GroupCollator()

        super().__init__(
            model=model,
            cfg_file=cfg_file,
            cfg_modify_fn=cfg_modify_fn,
            arg_parse_fn=arg_parse_fn,
            data_collator=data_collator,
            preprocessor=preprocessor,
            optimizers=optimizers,
            train_dataset=train_dataset,
            eval_dataset=eval_dataset,
            model_revision=model_revision,
            **kwargs)

    def compute_mrr(self, result, k=10):
        mrr = 0
        for res in result.values():
            sorted_res = sorted(res, key=lambda x: x[0], reverse=True)
            ar = 0
            for index, ele in enumerate(sorted_res[:k]):
                if str(ele[1]) == '1':
                    ar = 1.0 / (index + 1)
                    break
            mrr += ar
        return mrr / len(result)

    def compute_ndcg(self, result, k=10):
        ndcg = 0
        from sklearn import ndcg_score
        for res in result.values():
            sorted_res = sorted(res, key=lambda x: [0], reverse=True)
            labels = np.array([[ele[1] for ele in sorted_res]])
            scores = np.array([[ele[0] for ele in sorted_res]])
            ndcg += float(ndcg_score(labels, scores, k=k))
        ndcg = ndcg / len(result)
        return ndcg

    def to_device(self, val, device):
        if isinstance(val, torch.Tensor):
            return val.to(device)
        elif isinstance(val, list):
            return [self.to_device(item, device) for item in val]
        elif isinstance(val, dict):
            new_val = {}
            for key in val:
                new_val[key] = self.to_device(val[key], device)
            return new_val
        print('can not convert to device')
        raise Exception('can not convert to device')

    def evaluate(self,
                 checkpoint_path: Optional[str] = None,
                 *args,
                 **kwargs) -> Dict[str, float]:
        """evaluate a dataset

        evaluate a dataset via a specific model from the `checkpoint_path` path,
        if the `checkpoint_path` does not exist, read from the config file.

        Args:
            checkpoint_path (Optional[str], optional): the model path. Defaults
            to None.

        Returns:
            Dict[str, float]: the results about the evaluation Example:
            {"accuracy": 0.5091743119266054, "f1": 0.673780487804878}
        """
        # get the raw online dataset
        self.eval_dataloader = self._build_dataloader_with_dataset(
            self.eval_dataset,
            **self.cfg.evaluation.get('dataloader', {}),
            collate_fn=self.eval_data_collator)
        # generate a standard dataloader
        # generate a model
        if checkpoint_path is not None:
            model = BertForTextRanking.from_pretrained(checkpoint_path)
        else:
            model = self.model

        # copy from easynlp (start)
        model.eval()
        total_samples = 0

        logits_list = list()
        label_list = list()
        qid_list = list()

        total_spent_time = 0.0
        device = 'cuda:0' if torch.cuda.is_available() else 'cpu'
        model.to(device)
        for _step, batch in enumerate(tqdm(self.eval_dataloader)):
            try:
                batch = self.to_device(batch, device)
            except RuntimeError:
                batch = {key: val for key, val in batch.items()}

            infer_start_time = time.time()
            with torch.no_grad():
                label_ids = batch.pop('labels').detach().cpu().numpy()
                qids = batch.pop('qid').detach().cpu().numpy()
                outputs = model(**batch)
            infer_end_time = time.time()
            total_spent_time += infer_end_time - infer_start_time
            total_samples += self.eval_dataloader.batch_size

            def sigmoid(logits):
                return np.exp(logits) / (1 + np.exp(logits))

            logits = outputs['logits'].squeeze(-1).detach().cpu().numpy()
            logits = sigmoid(logits).tolist()

            label_list.extend(label_ids)
            logits_list.extend(logits)
            qid_list.extend(qids)

        logger.info('Inference time = {:.2f}s, [{:.4f} ms / sample] '.format(
            total_spent_time, total_spent_time * 1000 / total_samples))

        rank_result = {}
        for qid, score, label in zip(qid_list, logits_list, label_list):
            if qid not in rank_result:
                rank_result[qid] = []
            rank_result[qid].append((score, label))

        for qid in rank_result:
            rank_result[qid] = sorted(rank_result[qid], key=lambda x: x[0])

        eval_outputs = list()
        for metric in self.metrics:
            if metric.startswith('mrr'):
                k = metric.split('@')[-1]
                k = int(k)
                mrr = self.compute_mrr(rank_result, k=k)
                logger.info('{}: {}'.format(metric, mrr))
                eval_outputs.append((metric, mrr))
            elif metric.startswith('ndcg'):
                k = metric.split('@')[-1]
                k = int(k)
                ndcg = self.compute_ndcg(rank_result, k=k)
                logger.info('{}: {}'.format(metric, ndcg))
                eval_outputs.append(('ndcg', ndcg))
            else:
                raise NotImplementedError('Metric %s not implemented' % metric)

        return dict(eval_outputs)


from sklearn.datasets import load_wine
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

# Load the wine dataset
wine = load_wine()
X, y = wine.data, wine.target

# Preprocess the data by standardizing it
scalar = StandardScaler()
X = scalar.fit_transform(X)

# Split the data into training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=1)

kernels = ['linear', 'poly', 'rbf', 'sigmoid']
c = 0.1

max_accuracy = 0.0
best_kernel = ''
best_c = 0.0

for kernel in kernels:
    for i in range(10):
        # Fit SVM model
        svm = SVC(kernel=kernel, C=c, random_state=1)
        svm.fit(X_train, y_train)

        # Check the accuracy of the model
        accuracy = accuracy_score(y_test, svm.predict(X_test))
        if accuracy > max_accuracy:
            max_accuracy = accuracy
            best_kernel = kernel
            best_c = c

        c += 0.1

print(f"The best kernel is {best_kernel} with a C value of {best_c:.1f} and an accuracy of {100*max_accuracy:.2f}%")


#Daily Temperatures
'''
Given an array of integers temperatures represents the daily temperatures, return an array answer such that answer[i] is the number of days you have to wait
after the ith day to get a warmer temperature. If there is no future day for which this is possible, keep answer[i] == 0 instead.

    Example:
    Input: temperatures = [73,74,75,71,69,72,76,73]
    Output: [1,1,4,2,1,1,0,0]
'''

from collections import deque
class Solution:
    def dailyTemperatures(self,temperatures):
        res,s=[0]*len(temperatures),deque()
        for i,x in enumerate(temperatures):
            while s and x>temperatures[s[-1]]:
                res[s[-1]]=i-s[-1]
                s.pop()
            s.append(i)
        return res


from django import forms
from django.forms import ModelForm

from .models import TodoModel

class TodoForm(ModelForm):
    class Meta:
        model = TodoModel
        fields = '__all__'
        widgets = {
          'description': forms.Textarea(attrs={'rows':4, 'cols':15}),
        }


#!/usr/bin/env python3

import functools
import operator
import sys

def parse_ans(ans_file):
#    answer_content = '''s SATISFIABLE
#v 1 2 -3 4 0'''

    answer_content = ans_file.read()

    answer_content = answer_content.splitlines()[1]
    answer_content = answer_content.split()[1:-1]

    answer_size = len(answer_content)
    answer = { abs(int(value)): int(value) > 0 for value in answer_content }

    return answer, answer_size

def parse_problem(problem_file):
#     problem_content = '''c xd
# p cnf 3 4
# 1 -2 0
# 1 3 0
# 2 -3 0
# -1 0'''

    problem_content = problem_file.read()

    problem = []
    problem_lines = problem_content.splitlines()
    for line in problem_lines:
        if line[0] == 'c':
            continue
        elif line[0] == 'p':
            metadata = line.split()
            assert metadata[1] == 'cnf', 'not cnf'
            problem_clause = metadata[2]
            problem_literal = metadata[3]
        else:
            clause = line.split()
            assert clause[-1] == '0', 'no 0 end'
            clause.pop()
            clause = { abs(int(value)): int(value) > 0 for value in clause }
            problem.append(clause)

    return problem

def check_answer(problem, answer):
    for idx, clause in enumerate(problem, 0):
        # print(clause)
        sat = [ not(clause[k] ^ answer[k]) for k in clause ]

        # print(sat)
        is_sat = functools.reduce(operator.or_, sat)

        if not is_sat:
            print('false at clause {}: '.format(idx))
            print_clause(clause)
            return False

    return True

def print_clause(clause):
    for k, v in clause.items():
        if v:
            print(k, end=' ')
        else:
            print('-', k, sep='', end=' ')
    print('0')

def main():
    if len(sys.argv) != 3:
        print('invalid number of arguments')
        print('./{} <problem> <answer>')
        sys.exit(1)

    problem_file = open(sys.argv[1], 'r')
    answer_file = open(sys.argv[2], 'r')

    problem = parse_problem(problem_file)
    answer, answer_size = parse_ans(answer_file)

    # print("[p]", problem)
    # print("[a]", answer)

    ret = check_answer(problem, answer)
    if ret:
        print('SAT')

main()


import datetime as dt

from rest_framework import serializers
from .models import Event, Price

class PriceSrializer(serializers.ModelSerializer):
    class Meta:
        model = Price
        fields = ['currency', 'price_type', 'max_price', 'min_price']

class EventSerializer(serializers.ModelSerializer):
    prices = PriceSrializer(many=True, read_only=True)
    class Meta:
        model = Event
        fields = ['id', 'name', 'description', 'url', 'start_date', 'end_date', 'promoter_name', 'prices' ]

    def __validate_datetimes(self, data, event):
        start_date = data.get('start_date') or event.start_date
        end_date = data.get('end_date') or event.end_date

        if start_date and end_date and start_date > end_date:
            raise serializers.ValidationError("Finish must occur after start")

    @staticmethod
    def validate_prices(data):
        event = Event.objects.get(id=data.get('id'))
        for price in data.get('prices', []):
            price = PriceSrializer().validate(price)
            min_price = price.get('min_price')
            max_price = price.get('max_price')
            price_type = price.get('price_type')
            try:
                price_obj = Price.objects.get(event=event, price_type=price_type)
                min_price = min_price or price_obj.min_price
                max_price = max_price or price_obj.max_price
            except Price.DoesNotExist:
                pass

            if min_price and float(min_price) < 0:
                raise serializers.ValidationError("Price should be positive decimal number!")
            if max_price and float(max_price) < 0:
                raise serializers.ValidationError("Price should be positive decimal number!")

            if min_price and max_price and float(min_price) > float(max_price):
                raise serializers.ValidationError("Min Price should not be greater than max price!")

    def validate(self, data):
        data = super().validate(data)
        event = Event.objects.get(id=data.get('id'))
        self.__validate_datetimes(data, event)
        return data


from setuptools import setup, find_packages

with open('README.rst', 'r') as f:
    readme = f.read()

setup(
    name='eclipseChallenge',
    version='0.1.0',
    description='Direction Controller',
    long_description=readme,
    author='Sajj Farahani',
    author_email='sajjfarahni@outlook.com',
    packages=find_packages('src'),
    package_dir={'':'src'},
    install_requires=[],
    entry_points={
        'console_scripts': [
            'directioncontroller=directioncontroller.sender:main'
        ]
    }

)


# Mwangi Stephen, Mutuku Moses, Mokaya Sharon
import codecs
import json
import numpy as np

class NeuralNetwork:
    """
        Neural Network Class
        A single layer network (one hidden layer)
        Takes no. of input nodes, number of hidden nodes, number of output nodes and the learning rate during initialization
    """
    def __init__(self, n_inputs, n_hidden, n_outputs, learning_rate):
        self.n_inputs = n_inputs
        self.n_hidden = n_hidden
        self.n_outputs = n_outputs
        self.learning_rate = learning_rate
        # initialize weights using random normally distributed values
        self.weights_ih = np.random.normal(0.0, pow(self.n_hidden, -0.5), (self.n_hidden, self.n_inputs))
        self.weights_ho = np.random.normal(0.0, pow(self.n_outputs, -0.5), (self.n_outputs, self.n_hidden))

    @staticmethod
    def sigmoid(X):
        # sigmoid activation function
        return 1 / (1 + np.exp(-X))

    @staticmethod
    def load_from_file(filepath):
        # static method to load a saved neural network model from a file
        model = json.loads(codecs.open(filepath).read())
        n_inputs, n_hidden, n_outputs, learning_rate = model[0]
        nn = NeuralNetwork(n_inputs, n_hidden, n_outputs, learning_rate)
        nn.weights_ih = np.array(model[1])
        nn.weights_ho = np.array(model[2])
        return nn

    def accuracy(self, data_, labels_):
        # function to calculate the accuracy of the neural network given certain inputs and labels
        err = 0
        total = len(data_)
        for i_ in range(total):
            item_ = data_[i_]
            pred = np.argmax(self.predict(item_))
            if pred != np.argmax(labels_[i_]):
                err += 1
        return 1 - err / total

    def write_to_file(self, filepath):
        # function to save the neural network model to a file in json format
        config = [self.n_inputs, self.n_hidden, self.n_outputs, self.learning_rate]
        model = [config, self.weights_ih.tolist(), self.weights_ho.tolist()]
        json.dump(model, codecs.open(filepath, 'w', encoding='utf-8'), separators=(',', ':'), sort_keys=False, indent=1)

    def predict(self, input_list, returnLayerOutputs=False):
        # function to feed forward the inputs and return a classification at the end
        inputs = np.array(input_list, ndmin=2).T
        hidden_inputs = np.dot(self.weights_ih, inputs)
        hidden_outputs = self.sigmoid(hidden_inputs)
        final_inputs = np.dot(self.weights_ho, hidden_outputs)
        final_outputs = self.sigmoid(final_inputs)

        if returnLayerOutputs:
            return [final_outputs, hidden_outputs, inputs]
        else:
            return final_outputs.ravel()

    def train(self, input_list, target_list):
        # function to train the network by adjusting the connection weights using gradient descent (backpropagation algorithm)
        targets = np.array(target_list, ndmin=2).T
        final_outputs, hidden_outputs, inputs = self.predict(input_list, True)
        output_errors = targets - final_outputs
        hidden_errors = np.dot(self.weights_ho.T, output_errors)
        self.weights_ho += self.learning_rate * np.dot((output_errors * final_outputs * (1.0 - final_outputs)), np.transpose(hidden_outputs))
        self.weights_ih += self.learning_rate * np.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), np.transpose(inputs))