import webapp2
import os
import jinja2
import logging

from google.appengine.ext import ndb
from google.appengine.api import users
from models import SchedifyUser, Connect, Event, Attendance

the_jinja_env = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
    extensions=['jinja2.ext.autoescape'],
    autoescape=True)

class LandingHandler(webapp2.RequestHandler):
  def get(self):
    user = users.get_current_user()
    # If the user is logged in...
    if user:
      signout_link_html = 'sign out' % (
          users.create_logout_url('/'))
      email_address = user.nickname()
      schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()
      # If the user is registered...
      if schedify_user:
        # Enter home page here:
        # Enter the page that the user sees after they have signed in
        # Greet them with their personal information

        # Home Handler
        user = users.get_current_user()
        email_address = user.nickname()
        email_list = email_address.split('@')
        email_start = email_list[0]

        signout_link = users.create_logout_url('/')

        home_data = {
            "emailStart": email_start,
            "sign_out": signout_link,
            "first_name": schedify_user.first_name,
            "last_name":schedify_user.last_name,
            "friend_list": schedify_user.friends
        }
        home_template = the_jinja_env.get_template('templates/home.html')
        self.response.write(home_template.render(home_data))

        #  Coding to know
        # self.response.write('''
        #     ENTER HOME PAGE TEMPLATE HERE!
Welcome %s %s (%s)!
 %s
''' % (
        #       schedify_user.first_name,
        #       schedify_user.last_name,
        #       email_address,
        #       signout_link_html))
      # If the user isn't registered...
      else:
        # Offer a registration form for a first-time visitor:
        sign_up_template = the_jinja_env.get_template('templates/sign-up.html')
        signout_link = users.create_logout_url('/')
        sign_up_data = {
            "sign_out": signout_link
        }
        self.response.write(sign_up_template.render(sign_up_data))
    else:
      # If the user isn't logged in...
      landing_template = the_jinja_env.get_template('templates/landing.html')
      login_url = users.create_login_url('/')
      landing_data = {
        "login": login_url,
      }
      # Prompt the user to sign in.
      self.response.write(landing_template.render(landing_data))

  def post(self):
    # Enter home page here:
    # Enter the page that the user sees after they have signed in
    user = users.get_current_user()
    username = self.request.get('user_name')
    firstname = self.request.get('first_name')
    lastname = self.request.get('last_name')

    schedify_user = SchedifyUser(
        first_name = firstname,
        last_name = lastname,
        username = username,
        friends = [],
        bio = None,
        email=user.nickname())
        #email=self.request.get('email')) because i want to parse their email to get their cal
    schedify_user.put()
    welcome_template = the_jinja_env.get_template('templates/welcome.html')
    welcome_data = {
        "first_name": firstname,
        "last_name": lastname
    }
    self.response.write(welcome_template.render(welcome_data))
class ScheduleHandler(webapp2.RequestHandler):
    def get(self):
        welcome_template = the_jinja_env.get_template('templates/schedule.html')
        user = users.get_current_user()
        email_address = user.nickname()
        email_list = email_address.split('@')
        email_start = email_list[0]
        schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()

        welcome_data = {
            "emailStart": email_start,
            "friend_list": schedify_user.friends,
            "friendIndex":0,
            "friendEmailStart": None
        }
        self.response.write(welcome_template.render(welcome_data))
    def post(self):
        welcome_template = the_jinja_env.get_template('templates/schedule.html')
        welcome_data = {
            "first_name": firstname,
            "last_name": lastname
        }
        self.response.write(welcome_template.render())

class EventFeedHandler(webapp2.RequestHandler):
    def get(self):

        # if somebody deleted an event...
        delete_response = self.request.get('delete_event')
        if delete_response == "Delete event":
            event_id = self.request.get('event_id')
            event_key = ndb.Key("Event", int(event_id))
            event_info = event_key.get()
            event_info.key.delete()

        user = users.get_current_user()
        email_address = user.nickname()
        schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()

        # attending variables
        attendance_value = "none"
        response = self.request.get('event-type')

        user = users.get_current_user()
        email_address = user.nickname()
        schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()

        event_ownership = self.request.get('attendance')

        friends_key_list = schedify_user.friends
        users_key = [schedify_user.key]
        users_key.extend(friends_key_list)

        event_list = []
        for user_key in users_key:
            events = Event.query(Event.owner == user_key).fetch()
            event_list.extend(events)

        event_template = the_jinja_env.get_template('templates/event-feed.html')

        # creates a list is user is attending or not
        user_attending_status = []
        for event in event_list:
            user_status = "neither"
            atendees_key_list = event.attending
            absentee_key_list = event.not_attending
            logging.log(logging.INFO, "atendee: " + str(atendees_key_list))
            logging.log(logging.INFO, "absentee: " + str(absentee_key_list))

            for atendee_key in atendees_key_list:
                if atendee_key == schedify_user.key:
                    user_status = "yes"
                    break

            for absentee_key in absentee_key_list:
                if absentee_key == schedify_user.key:
                    user_status = "no"
                    break

            user_attending_status.append(user_status)

        logging.log(logging.INFO, user_attending_status)

        if response == "Attending":
            event_searched.add_attending(schedify_user.key)
            attendance_value == "yes"
        elif response == "Will not attend":
            event_searched.add_not_attending(schedify_user.key)
            attendance_value == "no"
        elif response == "Will no longer attend":
            event_searched.add_not_attending(schedify_user.key)
            event_searched.remove_attending(schedify_user.key)
            attendance_value == "no"
        elif response == "Will be attending":
            event_searched.add_attending(schedify_user.key)
            event_searched.remove_not_attending(schedify_user.key)
            attendance_value == "yes"

        event_data = {
            "event_info": event_list,
            "answer": attendance_value,
            "user_key": schedify_user.key,
            "attending_list": user_attending_status

        }
        self.response.write(event_template.render(event_data))

    def post(self):
        #  user info
        user = users.get_current_user()
        email_address = user.nickname()
        schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()

        event_ownership = self.request.get('event-type')

        # event info
        attendance_value = "none"
        response = self.request.get('attendance')

        if event_ownership == "self":
            event_list = Event.query(Event.owner == schedify_user.key).fetch()
        elif event_ownership == "friends":
            friends_key_list = schedify_user.friends
            event_list = []
            for friend_key in friends_key_list:
                events = Event.query(Event.owner == friend_key).fetch()
                event_list.extend(events)
        else:
            friends_key_list = schedify_user.friends
            users_key = [schedify_user.key]
            users_key.extend(friends_key_list)

            event_list = []
            for user_key in users_key:
                events = Event.query(Event.owner == user_key).fetch()
                event_list.extend(events)

        # checks to see which button was pressed
        if response == "Attending":
            #  event information
            event_searched_id = self.request.get('event_searchid')
            event_key = ndb.Key("Event", int(event_searched_id))
            event_searched = event_key.get()

            event_searched.add_attending(schedify_user.key)
        elif response == "Will not attend":
            #  event information
            event_searched_id = self.request.get('event_searchid')
            event_key = ndb.Key("Event", int(event_searched_id))
            event_searched = event_key.get()

            event_searched.add_not_attending(schedify_user.key)
        elif response == "Will no longer attend":
            #  event information
            event_searched_id = self.request.get('event_searchid')
            event_key = ndb.Key("Event", int(event_searched_id))
            event_searched = event_key.get()

            event_searched.add_not_attending(schedify_user.key)
            event_searched.remove_attending(schedify_user.key)
        elif response == "Will be attending":
            #  event information
            event_searched_id = self.request.get('event_searchid')
            event_key = ndb.Key("Event", int(event_searched_id))
            event_searched = event_key.get()

            event_searched.add_attending(schedify_user.key)
            event_searched.remove_not_attending(schedify_user.key)

        # creates a list is user is attending or not
        user_attending_status = []
        for event in event_list:
            user_status = "neither"
            atendees_key_list = event.attending
            absentee_key_list = event.not_attending
            logging.log(logging.INFO, "atendee: " + str(atendees_key_list))
            logging.log(logging.INFO, "absentee: " + str(absentee_key_list))

            for atendee_key in atendees_key_list:
                if atendee_key == schedify_user.key:
                    user_status = "yes"
                    break

            for absentee_key in absentee_key_list:
                if absentee_key == schedify_user.key:
                    user_status = "no"
                    break

            user_attending_status.append(user_status)

        event_template = the_jinja_env.get_template('templates/event-feed.html')

        event_data = {
            "event_info": event_list,
            "answer": attendance_value,
            "user_key": schedify_user.key,
            "attending_list": user_attending_status
        }
        self.response.write(event_template.render(event_data))

class EventHandler(webapp2.RequestHandler):
    def post(self):
        event_template = the_jinja_env.get_template('templates/event.html')

        event_searched_id = self.request.get('event_searchid')
        # logging.log(Level.INFO, "event_searchid = " + event_searched_id)
        event_key = ndb.Key("Event", int(event_searched_id))
        event_searched = event_key.get()
        owner_instance = event_searched.owner.get()

        user = users.get_current_user()
        email_address = user.nickname()
        schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()

        event_data = {
            "event_instancekey": event_key,
            "event_title": event_searched.title,
            "user_instance": schedify_user,
            "owner_instance": owner_instance,
            "event_description": event_searched.summary,
            "attendingkey_list": event_searched.attending,
            "abesntkey_list": event_searched.not_attending,
        }

        self.response.write(event_template.render(event_data))

class NewEventHandler(webapp2.RequestHandler):
    def get(self):
        user = users.get_current_user()
        if user:
          email_address = user.nickname()
          schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()
          if schedify_user:
            newevent_template = the_jinja_env.get_template('templates/newevent.html')
            self.response.write(newevent_template.render())
            return
        self.error(403)
        return
    def post(self):
        # create new event?
        # look at the sign in if statement
        # grab the email adress through google users api then search
        #   for schedify through that email address
        newevent_template = the_jinja_env.get_template('templates/newevent.html')

        user = users.get_current_user()
        email_address = user.nickname()
        schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()

        schedify_event = Event(
            owner = schedify_user.key,
            title = self.request.get('event_title'),
            summary = self.request.get('event_summary'),
            exclusives = [],
            attending = [],
            not_attending = []
        )

        schedify_event.put()
        # Add later when you add the home page html and link it to this page
        #       You need to make sure you can call a user that is loged in
        #
        # schedify_attendance = Attendance (
        #      user =
        #      event = schedify_event,
        # )
        self.response.write(newevent_template.render())

class EventSettingHandler(webapp2.RequestHandler):
    def get(self):
        event_id = self.request.get('event_id')
        event_key = ndb.Key("Event", int(event_id))
        event_info = event_key.get()

        event_setting_template = the_jinja_env.get_template('templates/event-setting.html')
        event_setting_data = {
            "event": event_info,
        }
        self.response.write(event_setting_template.render(event_setting_data))
    def post(self):
        event_id = self.request.get('event_id')
        event_key = ndb.Key("Event", int(event_id))
        event_info = event_key.get()

        new_event_title = self.request.get('new_title')
        new_event_summary = self.request.get('new_summary')

        event_info.update_event(new_event_title,new_event_summary)

        event_setting_template = the_jinja_env.get_template('templates/event-setting.html')
        event_setting_data = {
            "event": event_info,
        }
        self.response.write(event_setting_template.render(event_setting_data))

class ConnectionsHandler(webapp2.RequestHandler):
    def get(self):
        user = users.get_current_user()
        email_address = user.nickname()
        schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()
        connections_template = the_jinja_env.get_template('templates/connections.html')
        search_username = self.request.get('username_search')
        searches = SchedifyUser.query().filter(SchedifyUser.username == search_username).fetch()

        connections_data = {
            "friend_list": schedify_user.friends,
            "requestkey_list": schedify_user.requests,
            "search_list": searches
        }
        self.response.write(connections_template.render(connections_data))

    # this shows the list of users who match that username
    def post(self):
        user = users.get_current_user()
        email_address = user.nickname()
        schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()
        connections_template = the_jinja_env.get_template('templates/connections.html')
        resolve_request = self.request.get('request_answer')
        if resolve_request == "Accept":
            requester_id = self.request.get('request_userid')
            requester_key = ndb.Key("SchedifyUser", int(requester_id))
            requester = requester_key.get()

            schedify_user.add_friend(requester_key)
            schedify_user.remove_request(requester_key)
            requester.add_friend(schedify_user.key)
        elif resolve_request == "Decline":
            requester_id = self.request.get('request_userid')
            requester_key = ndb.Key("SchedifyUser", int(requester_id))
            schedify_user.remove_request(requester_key)
        connections_data = {
            "friend_list": schedify_user.friends,
            "requestkey_list": schedify_user.requests
        }
        self.response.write(connections_template.render(connections_data))

class ProfileHandler(webapp2.RequestHandler):
    # your profile
    def get(self):
        profile_template = the_jinja_env.get_template('templates/profile.html')
        user = users.get_current_user()
        email_address = user.nickname()
        schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()

        logout_url = users.create_logout_url('/')

        profile_data = {
            "user_instance": schedify_user,
            "account": "self",
            "sign_out": logout_url
        }
        self.response.write(profile_template.render(profile_data))

    # user profile lookup
    def post(self):
        profile_template = the_jinja_env.get_template('templates/profile.html')
        user = users.get_current_user()
        email_address = user.nickname()
        schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()

        # there should only be one username per account
        username_id = self.request.get('username_searchid')
        username_key = ndb.Key("SchedifyUser", int(username_id))
        user_search = username_key.get()

        # checks to see if user is passing in their own Account
        if user_search == schedify_user:
            account_status = "self"
            friend_status = None
            request_status = None
            user_key = None
        else:
            account_status = "other"
            friend_status = self.request.get('friend_status')
            request_status = False

            # if button to add/remove friend was cliked launch this code
            if (friend_status == "add friend"):
                request_status = True
                user_search.add_request(schedify_user.key)
            elif (friend_status == "remove friend"):
                schedify_user.remove_friend(user_search.key)
                user_search.remove_friend(schedify_user.key)
                request_status = False
            elif (friend_status == "request"):
                user_search.remove_request(schedify_user.key)
                request_status = False

            # checks if profile is part of friends group
            friend_status = False

            for friend_key in schedify_user.friends:
                if friend_key == user_search.key:
                    friend_status = True

            # check if you requested a connections
            for request_key in user_search.requests:
                if request_key == schedify_user.key:
                    request_status = True

        profile_data = {
            "user_instance": user_search,
            "friend_status": friend_status,
            "request_status": request_status,
            "account": account_status,
            "search_id": username_id,
        }
        self.response.write(profile_template.render(profile_data))

class SettingHandler(webapp2.RequestHandler):
    def get(self):
        user_id = self.request.get('user_id')
        user_key = ndb.Key("SchedifyUser", int(user_id))
        user_profile = user_key.get()

        profile_template = the_jinja_env.get_template('templates/setting.html')
        setting_data = {
            "user": user_profile,
        }
        self.response.write(profile_template.render(setting_data))
    def post(self):
        user_id = self.request.get('user_id')
        user_key = ndb.Key("SchedifyUser", int(user_id))
        user_profile = user_key.get()

        new_user = self.request.get('new_username')
        new_first = self.request.get('new_first_name')
        new_last = self.request.get('new_last_name')
        new_bio = self.request.get('new_bio')

        user_profile.update_profile(new_user,new_first,new_last,new_bio)

        profile_template = the_jinja_env.get_template('templates/setting.html')
        setting_data = {
            "user": user_profile,
        }
        self.response.write(profile_template.render(setting_data))

class DeleteHandler(webapp2.RequestHandler):
    def get(self):
        user = users.get_current_user()
        email_address = user.nickname()
        schedify_user = SchedifyUser.query().filter(SchedifyUser.email == email_address).get()

        delete_response = self.request.get('delete_user')
        if delete_response == "Delete user":
            schedify_user.key.delete()

        delete_data = {
            "user": schedify_user,
        }

        logout_template = the_jinja_env.get_template('templates/log-out.html')
        self.response.write(logout_template.render(delete_data))

app = webapp2.WSGIApplication([
    ('/', LandingHandler),
    # schedule page should be connected to home page
    ('/schedule', ScheduleHandler),
    ('/event-feed', EventFeedHandler),
    ('/new_event', NewEventHandler),
    ('/event', EventHandler),
    ('/event_setting', EventSettingHandler),
    ('/connections', ConnectionsHandler),
    ('/setting', SettingHandler),
    ('/profile', ProfileHandler),
    ('/delete', DeleteHandler),

], debug=True)


'''
To do list:
    *Find font that will better fit the app.
    *Make code revision and optimization.

Possible additional features:
    *Online leaderboard with player nicknames and hiscores
    *Translation to other languages.
'''

#!/usr/bin/python3
# Random numbers generator module
import random

#Custom module for loading data needed from files
import dataloader as dt

from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivymd.uix.snackbar import Snackbar
from kivymd.uix.dialog import MDDialog

# Dictionary with master data about countries
c_dict = {}
#List for performing operations on countries data
countries_list = []

# Assigning data to appropriate variables
countries_list = dt.data_from_csv(c_dict, countries_list)

# This method makes device keyboard appear below main screen
Window.softinput_mode = 'pan'
#Resolution which simulates mobile phone
#Window.size = (405,900)

# ScreenManager and Screen classes
class SManager(ScreenManager):
    pass

class TemplateScreen(Screen):
    pass

class MainMenu(TemplateScreen):
    pass

class Capitals(TemplateScreen):
    pass

class Flags(TemplateScreen):
    pass

class Continents(TemplateScreen):
    pass

class HiScores(TemplateScreen):
    pass

# Main application class
class CountriesQuiz(MDApp):
    def build(self):
        self.theme_cls.primary_palette = "Indigo"
        # Setting up first values of screen variables
        self.score = 0
        self.country_name = ''
        self.correct_answers = 0
        self.answer_streak = 0
        # Default backgrund RGBA value. Used in kv file
        self.bg_color = (78/255, 99/255, 194/255, 1)
        # Loading .kv file
        self.uix = Builder.load_file('uix.kv')
        return self.uix

    '''Method used in all modes for determining country used in current
       question.
    '''
    def pick_country(self):

        self.country_name = ""
        #If there are no more countries from the list, assign all of them
        #to the list.
        if len(countries_list) == 0:
            self.reload_countries_list()
        #Proceed if there are still countries to choose from
        if len(countries_list) > 0:
            self.country_name = random.choice(countries_list)
            print(f"Chosen country: {self.country_name}")
            print(f"No of countries still in dictionary {len(countries_list)}\n")

        return self.country_name

    '''Method used to assign chosen country to question label in capitals
       and continents quiz modes.
    '''
    def assign_country_to_label(self, mode_number):
        self.country_name = self.pick_country()
        if mode_number == 0:
            self.text_to_display = "What is the capital of {}?".format(
                self.country_name)
            self.root.get_screen(
                'CapitalsScreen').ids.capitals_toolbar.question = self.text_to_display

        if mode_number == 2:
            self.text_to_display = "In which continent lies {}?".format(
                self.country_name)
            self.root.get_screen(
                'ContinentsScreen').ids.continents_toolbar.question = self.text_to_display

        return self.country_name

    #Reloads modified list of countries to original state
    def reload_countries_list(self):
        print("There are no more countries to guess. Loading the list anew.")
        countries_list.clear()
        for i in c_dict.keys():
            countries_list.append(i)
        print(f"List length after reloading: {len(countries_list)}\n")
        return countries_list

    # Method for checking answer in capitals quiz mode
    def check_answer(self):
        if self.root.get_screen('CapitalsScreen').ids.answer.text == c_dict[self.country_name]['capital']:
            print('Well done')
            #Remove country from current list of countries
            countries_list.remove(self.country_name)
            # Add +1 to correct answers, correct answers streak, points and
            # clear answer field
            self.add_points(0)
            self.add_canswer()
            self.add_streak(True)
            self.clear_answer_field()
            #Prompt displayed after correct answer
            self.root.get_screen('CapitalsScreen').ids.answer_popup.text = "[color=#f7faf8]Congratulations, correct answer.[/color]"
            self.root.get_screen('CapitalsScreen').ids.answer_popup.opacity = 1
            self.root.get_screen('CapitalsScreen').ids.answer_popup.md_bg_color = [55/256,209/255,21/255,1]

        else:
            print('Wrong answer')
            # Zero correct answer streak
            self.add_streak(False)
            self.clear_answer_field()
            #Prompt displayed after wrong answer
            self.root.get_screen('CapitalsScreen').ids.answer_popup.text = f"[color=#f7faf8]Wrong answer. The capital of {self.country_name} is {c_dict[self.country_name]['capital']}.[/color]"
            self.root.get_screen('CapitalsScreen').ids.answer_popup.opacity = 1
            self.root.get_screen('CapitalsScreen').ids.answer_popup.md_bg_color = [219/256,20/255,20/255,1]

    '''Multi-mode method adding points to user score.The indexing [7:] is
       present because in each mode score indicator string starts with
       'Score: ', so with 7th index begins current numeric value.Tried to
       do it as one segment for all modes, but replacing kivy widget id with a
       variable breaks this function. (To be investigated)
    '''
    def add_points(self, mode_number):
        points_to_add = 10
        streak_modifier = 10
        # Capitals
        if mode_number == 0:
            #Calculates score multiplier based on current streak
            points_to_add += (streak_modifier * int(self.root.get_screen
                ('CapitalsScreen').ids.capitals_toolbar.streak[15:]))
            self.score = int(self.root.get_screen(
                'CapitalsScreen').ids.capitals_toolbar.score[7:]) + points_to_add
            score_text = 'Score: {}'.format(self.score)
            self.root.get_screen(
                'CapitalsScreen').ids.capitals_toolbar.score = score_text
        # Flags
        if mode_number == 1:
            #Calculates score multiplier based on current streak
            points_to_add += (streak_modifier * int(self.root.get_screen(
                'FlagsScreen').ids.flag_toolbar.streak[15:]))
            self.score = int(self.root.get_screen(
                'FlagsScreen').ids.flag_toolbar.score[7:]) + points_to_add
            score_text = 'Score: {}'.format(self.score)
            self.root.get_screen(
                'FlagsScreen').ids.flag_toolbar.score = score_text
        # Continents
        if mode_number == 2:
            #Calculates score multiplier based on current streak
            points_to_add += (streak_modifier * int(self.root.get_screen(
                'ContinentsScreen').ids.continents_toolbar.streak[16:]))
            self.score = int(self.root.get_screen(
                'ContinentsScreen').ids.continents_toolbar.score[7:]) + points_to_add
            score_text = 'Score: {}'.format(self.score)
            self.root.get_screen(
                'ContinentsScreen').ids.continents_toolbar.score = score_text

    # Used only in capiatals quiz mode
    def clear_answer_field(self):
        self.root.get_screen('CapitalsScreen').ids.answer.text = ''

    def disable_answer_popup(self):
        self.root.get_screen('CapitalsScreen').ids.answer_popup.opacity = 0

    '''Used only in capitals quiz mode. Increments number of correct user
       answers and displays them in appropriate kivy widget. The indexing
       is based on the same principle as in add_points method, but here
       score preceding text is: 'Correct answers: '
    '''
    def add_canswer(self):
        self.correct_answers = int(self.root.get_screen(
            'CapitalsScreen').ids.capitals_toolbar.correct_answers[17:]) + 1
        current_canswers = self.root.get_screen(
            'CapitalsScreen').ids.capitals_toolbar.correct_answers[:17] + str(self.correct_answers)
        self.root.get_screen(
            'CapitalsScreen').ids.capitals_toolbar.correct_answers = current_canswers

    '''Used only in capitals quiz mode. Increases correct answers streak or
       resets it if the answer is incorrect. The indexing
       is based on the same principle as in add_points method, but here
       score preceding text is: 'Current streak: '
    '''
    def add_streak(self, correct_or_wrong):
        if (correct_or_wrong):
            self.answer_streak = int(self.root.get_screen(
                'CapitalsScreen').ids.capitals_toolbar.streak[15:]) + 1
            current_answer_streak = self.root.get_screen(
                'CapitalsScreen').ids.capitals_toolbar.streak[:16] + str(self.answer_streak)
            self.root.get_screen(
                'CapitalsScreen').ids.capitals_toolbar.streak = current_answer_streak
        else:
            self.root.get_screen(
                'CapitalsScreen').ids.capitals_toolbar.streak = 'Current streak: 0'

    '''Used only in capitals quiz mode. Creates file name base on question text.
       Then the file name is used to display a flag of an asked country.
    '''
    def assign_flag(self):
        compatible_name = self.country_name.lower().replace(' ','-')
        flag_file_name = 'data/flags/' + compatible_name + '_flag-jpg-xs.jpg'
        print(flag_file_name)
        self.root.get_screen('CapitalsScreen').ids.question_flag.source = flag_file_name

    # Used only in flags quiz mode.
    def pick_flag(self):
        self.flag_name = self.pick_country()
        self.flag_chosen = self.flag_name
        self.text_to_display = "What is the flag of {}?".format(
            self.flag_name)
        self.root.get_screen(
            'FlagsScreen').ids.flag_toolbar.question = self.text_to_display
        # Array holding all items displaying flags in this mode
        self.flag_position = [self.root.get_screen(
            'FlagsScreen').ids.country0, self.root.get_screen(
            'FlagsScreen').ids.country1, self.root.get_screen(
            'FlagsScreen').ids.country2,
            self.root.get_screen(
            'FlagsScreen').ids.country3]
        #Check how many countries are available and randomize appropriate
        #number of countries.
        countries_in_the_list = len(countries_list)
        print(f"Total number of countries in the list {countries_in_the_list}")
        countries_to_randomize = 0
        if countries_in_the_list > 3:
            countries_to_randomize = 3
        elif countries_in_the_list == 3:
            countries_to_randomize = 2
            self.root.get_screen(
            'FlagsScreen').ids.country3.opacity = 0
        elif countries_in_the_list == 2:
            countries_to_randomize = 1
            self.root.get_screen(
            'FlagsScreen').ids.country2.opacity = 0
        elif countries_in_the_list == 1:
            countries_to_randomize = 0
            self.root.get_screen(
            'FlagsScreen').ids.country1.opacity = 0
        #Make all flags visible again after reloading countries list
        if countries_in_the_list == len(c_dict.keys()):
            self.root.get_screen(
            'FlagsScreen').ids.country1.opacity = 1
            self.root.get_screen(
            'FlagsScreen').ids.country2.opacity = 1
            self.root.get_screen(
            'FlagsScreen').ids.country3.opacity = 1
        # Randomly pick a place where flag with correct answer will be placed
        correct_flag_place = random.randrange(0, countries_to_randomize+1)
        #List storing chosen countries
        chosen_countries = []
        chosen_countries.append(self.flag_name)
        # Assigning flag images to appropriate kivy widget
        for i in range(0, countries_to_randomize+1):
            # Correct answer flag
            if i == correct_flag_place:
                cf_path = 'data/flags/{}_flag-jpg-xs.jpg'.format(
                    self.flag_name.lower().replace(' ', '-'))
                self.flag_position[i].source = cf_path
            # Other flags
            else:
                '''Choose random flag for other widgets. However, currently
                   flags may overlap as they are no removed from
                   the list after being used.
                '''
                random_flag = self.pick_country()
                while random_flag in chosen_countries:
                    random_flag = self.pick_country()
                chosen_countries.append(random_flag)
                cf_path = 'data/flags/{}_flag-jpg-xs.jpg'.format(
                    random_flag.lower().replace(' ', '-'))
                self.flag_position[i].source = cf_path

        print(f'Countries on the list: {chosen_countries}')
        #clear the list before ending the method
        chosen_countries.clear()
        #Make bottom bar button disabled
        self.root.get_screen('FlagsScreen').ids.flags_bottom_bar.disabled = True
        #Make tiles with flags clickable again
        self.root.get_screen('FlagsScreen').ids.country0.disabled = False
        self.root.get_screen('FlagsScreen').ids.country1.disabled = False
        self.root.get_screen('FlagsScreen').ids.country2.disabled = False
        self.root.get_screen('FlagsScreen').ids.country3.disabled = False
        #Switch tiles color to default one
        self.root.get_screen('FlagsScreen').ids.country0.md_bg_color = (159/256,189/256,237/256,1)
        self.root.get_screen('FlagsScreen').ids.country1.md_bg_color = (159/256,189/256,237/256,1)
        self.root.get_screen('FlagsScreen').ids.country2.md_bg_color = (159/256,189/256,237/256,1)
        self.root.get_screen('FlagsScreen').ids.country3.md_bg_color = (159/256,189/256,237/256,1)
        return self.flag_chosen

    '''Used only in flags quiz mode. Indice ranges are explained in
       description of add_canswer and add_streak methods.'''
    def check_flag(self, image_number):
        #Make bottom bar button enabled
        self.root.get_screen('FlagsScreen').ids.flags_bottom_bar.disabled = False
        #Make tiles with flags not clickable
        self.root.get_screen('FlagsScreen').ids.country0.disabled = True
        self.root.get_screen('FlagsScreen').ids.country1.disabled = True
        self.root.get_screen('FlagsScreen').ids.country2.disabled = True
        self.root.get_screen('FlagsScreen').ids.country3.disabled = True

        flag_clicked = self.jpg_file_name_to_country_name(image_number)

        if flag_clicked == self.flag_chosen.lower():
            print('good answer')
            print(f"removing {self.flag_chosen} from the list")
            countries_list.remove(self.flag_chosen)
            self.add_points(1)
            add_ca = int(self.root.get_screen(
                'FlagsScreen').ids.flag_toolbar.correct_answers[17:]) + 1
            self.root.get_screen('FlagsScreen').ids.flag_toolbar.correct_answers = self.root.get_screen(
                'FlagsScreen').ids.flag_toolbar.correct_answers[:17] + str(add_ca)

            add_streak = int(self.root.get_screen(
                'FlagsScreen').ids.flag_toolbar.streak[15:]) + 1
            self.root.get_screen('FlagsScreen').ids.flag_toolbar.streak = self.root.get_screen(
                'FlagsScreen').ids.flag_toolbar.streak[:15] + str(add_streak)

            if image_number == 0:
                self.root.get_screen('FlagsScreen').ids.country0.md_bg_color = (0,1,0,1)
            if image_number == 1:
                self.root.get_screen('FlagsScreen').ids.country1.md_bg_color = (0,1,0,1)
            if image_number == 2:
                self.root.get_screen('FlagsScreen').ids.country2.md_bg_color = (0,1,0,1)
            if image_number == 3:
                self.root.get_screen('FlagsScreen').ids.country3.md_bg_color = (0,1,0,1)
            self.root.get_screen('FlagsScreen').ids.flags_forward.opacity = 1
            print(add_ca)
        else:
            #Change corect's answer background to green
            if self.jpg_file_name_to_country_name(0) == self.flag_chosen.lower():
                self.root.get_screen('FlagsScreen').ids.country0.md_bg_color = (0,1,0,1)
            if self.jpg_file_name_to_country_name(1) == self.flag_chosen.lower():
                self.root.get_screen('FlagsScreen').ids.country1.md_bg_color = (0,1,0,1)
            if self.jpg_file_name_to_country_name(2) == self.flag_chosen.lower():
                self.root.get_screen('FlagsScreen').ids.country2.md_bg_color = (0,1,0,1)
            if self.jpg_file_name_to_country_name(3) == self.flag_chosen.lower():
                self.root.get_screen('FlagsScreen').ids.country3.md_bg_color = (0,1,0,1)
            #Change tile background color to red, depending on which was selected
            if image_number == 0:
                self.root.get_screen('FlagsScreen').ids.country0.md_bg_color = (1,0,0,1)
            if image_number == 1:
                self.root.get_screen('FlagsScreen').ids.country1.md_bg_color = (1,0,0,1)
            if image_number == 2:
                self.root.get_screen('FlagsScreen').ids.country2.md_bg_color = (1,0,0,1)
            if image_number == 3:
                self.root.get_screen('FlagsScreen').ids.country3.md_bg_color = (1,0,0,1)
            #Make forward button visible
            self.root.get_screen('FlagsScreen').ids.flags_forward.opacity = 1
            print('wrong answer')
            self.root.get_screen('FlagsScreen').ids.flag_toolbar.streak = self.root.get_screen(
                'FlagsScreen').ids.flag_toolbar.streak[:15] + '0'

    '''Used only in flags quiz mode. Makes bottom bar invisible'''
    def disable_flags_bottom_bar(self):
        self.root.get_screen('FlagsScreen').ids.flags_forward.opacity = 0

    '''Used only in flags quiz mode. Converts currently displayed flags
       file paths to country names
    '''
    def jpg_file_name_to_country_name(self, image_number):
        images_array = [self.root.get_screen(
            'FlagsScreen').ids.country0.source, self.root.get_screen(
            'FlagsScreen').ids.country1.source, self.root.get_screen(
            'FlagsScreen').ids.country2.source, self.root.get_screen(
            'FlagsScreen').ids.country3.source]
        clicked_flag_country_name = images_array[image_number]
        clicked_flag_country_name = clicked_flag_country_name.split('/')
        # Currently: 0 - data, 1 - flags, 2 - flag file name
        clicked_flag_country_name = clicked_flag_country_name[2]
        # Another split used to remove the rest of the file name from country name
        clicked_flag_country_name = clicked_flag_country_name.split('_')
        '''File names have hyphen if a country name consists of 2 or more
           parts. So it needs to be replaced with a space.
        '''
        clicked_flag_country_name = clicked_flag_country_name[0].replace(
            '-', ' ')
        print(clicked_flag_country_name)

        return clicked_flag_country_name

    '''Used only in continents quiz. Index range of current_country is
       [24:-1] becasue first 24 characters in the text of quiestion widget
       are: 'On which continent lies ', and the rest of the text contains
       country name.
    '''
    def check_continent(self, image_number):
        #Make continents bottom bar enabled and visible
        self.root.get_screen('ContinentsScreen').ids.continents_bottom_bar.disabled = False
        self.root.get_screen('ContinentsScreen').ids.continents_forward.opacity = 1
        #Disable continents tiles
        self.root.get_screen('ContinentsScreen').ids.africa.disabled = True
        self.root.get_screen('ContinentsScreen').ids.asia.disabled = True
        self.root.get_screen('ContinentsScreen').ids.europe.disabled = True
        self.root.get_screen('ContinentsScreen').ids.na.disabled = True
        self.root.get_screen('ContinentsScreen').ids.oceania.disabled = True
        self.root.get_screen('ContinentsScreen').ids.sa.disabled = True

        current_country = self.root.get_screen(
            'ContinentsScreen').ids.continents_toolbar.question
        current_country = current_country[24:-1]

        if image_number == 0:
            clicked_continent = self.root.get_screen(
                'ContinentsScreen').ids.africa.source
        if image_number == 1:
            clicked_continent = self.root.get_screen(
                'ContinentsScreen').ids.asia.source
        if image_number == 2:
            clicked_continent = self.root.get_screen(
                'ContinentsScreen').ids.europe.source
        if image_number == 3:
            clicked_continent = self.root.get_screen(
                'ContinentsScreen').ids.na.source
        if image_number == 4:
            clicked_continent = self.root.get_screen(
                'ContinentsScreen').ids.oceania.source
        if image_number == 5:
            clicked_continent = self.root.get_screen(
                'ContinentsScreen').ids.sa.source
        '''Index is based continent image path currently
           'data/continents/continent.jpg'. Fitst 16 are for the path and -4 for
           file extension
        '''
        clicked_continent = clicked_continent[16:-4]

        if c_dict[current_country]['continent'] == clicked_continent:
            #Make user selected continent tile bakcground green
            if image_number == 0:
                self.root.get_screen('ContinentsScreen').ids.africa.md_bg_color = (0,1,0,1)
            if image_number == 1:
                self.root.get_screen('ContinentsScreen').ids.asia.md_bg_color = (0,1,0,1)
            if image_number == 2:
                self.root.get_screen('ContinentsScreen').ids.europe.md_bg_color = (0,1,0,1)
            if image_number == 3:
                self.root.get_screen('ContinentsScreen').ids.na.md_bg_color = (0,1,0,1)
            if image_number == 4:
                self.root.get_screen('ContinentsScreen').ids.oceania.md_bg_color = (0,1,0,1)
            if image_number == 5:
                self.root.get_screen('ContinentsScreen').ids.sa.md_bg_color = (0,1,0,1)
            # Adding points in continents screen
            self.add_points(2)
            '''
            Adding +1 to correct answers in continents screen. [17:] is the text with space
            the rest is current score number.
            '''
            correct_answers = int(self.root.get_screen(
                'ContinentsScreen').ids.continents_toolbar.correct_answers[17:]) + 1
            self.root.get_screen('ContinentsScreen').ids.continents_toolbar.correct_answers = self.root.get_screen(
                'ContinentsScreen').ids.continents_toolbar.correct_answers[:17] + str(correct_answers)
            #Remove country from current list of countries
            countries_list.remove(self.country_name)
            '''
            Adding +1 to current streak in continents screen. [16:] is the text with space
            the rest is current score number
            '''
            current_streak = int(self.root.get_screen(
                'ContinentsScreen').ids.continents_toolbar.streak[16:]) + 1
            self.root.get_screen('ContinentsScreen').ids.continents_toolbar.streak = self.root.get_screen(
                'ContinentsScreen').ids.continents_toolbar.streak[:16] + str(current_streak)
            print('correct')
        else:
            #Make selected continent tile red
            if image_number == 0:
                self.root.get_screen('ContinentsScreen').ids.africa.md_bg_color = (1,0,0,1)
            if image_number == 1:
                self.root.get_screen('ContinentsScreen').ids.asia.md_bg_color = (1,0,0,1)
            if image_number == 2:
                self.root.get_screen('ContinentsScreen').ids.europe.md_bg_color = (1,0,0,1)
            if image_number == 3:
                self.root.get_screen('ContinentsScreen').ids.na.md_bg_color = (1,0,0,1)
            if image_number == 4:
                self.root.get_screen('ContinentsScreen').ids.oceania.md_bg_color = (1,0,0,1)
            if image_number == 5:
                self.root.get_screen('ContinentsScreen').ids.sa.md_bg_color = (1,0,0,1)
            #Set appropriate continent as green
            if c_dict[current_country]['continent'] == 'Africa':
               self.root.get_screen('ContinentsScreen').ids.africa.md_bg_color = (0,1,0,1)
            if c_dict[current_country]['continent'] == 'Asia':
               self.root.get_screen('ContinentsScreen').ids.asia.md_bg_color = (0,1,0,1)
            if c_dict[current_country]['continent'] == 'Europe':
               self.root.get_screen('ContinentsScreen').ids.europe.md_bg_color = (0,1,0,1)
            if c_dict[current_country]['continent'] == 'North America':
               self.root.get_screen('ContinentsScreen').ids.na.md_bg_color = (0,1,0,1)
            if c_dict[current_country]['continent'] == 'Oceania':
               self.root.get_screen('ContinentsScreen').ids.oceania.md_bg_color = (0,1,0,1)
            if c_dict[current_country]['continent'] == 'South America':
               self.root.get_screen('ContinentsScreen').ids.sa.md_bg_color = (0,1,0,1)
            #Reset current correct answer streak
            self.root.get_screen(
                'ContinentsScreen').ids.continents_toolbar.streak = 'Current streak: 0'
            print('false')

    def continents_postanswer(self):
        #Make continents bottom bar disabled and invisible
        self.root.get_screen('ContinentsScreen').ids.continents_bottom_bar.disabled = True
        self.root.get_screen('ContinentsScreen').ids.continents_forward.opacity = 0
        #Enable continents tiles
        self.root.get_screen('ContinentsScreen').ids.africa.disabled = False
        self.root.get_screen('ContinentsScreen').ids.asia.disabled = False
        self.root.get_screen('ContinentsScreen').ids.europe.disabled = False
        self.root.get_screen('ContinentsScreen').ids.na.disabled = False
        self.root.get_screen('ContinentsScreen').ids.oceania.disabled = False
        self.root.get_screen('ContinentsScreen').ids.sa.disabled = False
        #Revert tiles background to default color
        self.root.get_screen('ContinentsScreen').ids.africa.md_bg_color = (159/256,189/256,237/256,1)
        self.root.get_screen('ContinentsScreen').ids.asia.md_bg_color = (159/256,189/256,237/256,1)
        self.root.get_screen('ContinentsScreen').ids.europe.md_bg_color = (159/256,189/256,237/256,1)
        self.root.get_screen('ContinentsScreen').ids.na.md_bg_color = (159/256,189/256,237/256,1)
        self.root.get_screen('ContinentsScreen').ids.oceania.md_bg_color = (159/256,189/256,237/256,1)
        self.root.get_screen('ContinentsScreen').ids.sa.md_bg_color = (159/256,189/256,237/256,1)

    def check_if_hiscore(self,mode,user_score):
        #Load hiscores from the csv file
        current_scores = dt.get_scores()
        #Store new hiscore position on the list
        positon = 0
        #Check if the current user score is higher than
        #any score in hiscores file.
        for hiscore in range(0,len(current_scores[mode])):
            if int(user_score) > int(current_scores[mode][hiscore]):
                position = hiscore+1
                #Add score in current place
                current_scores[mode].insert(hiscore,user_score)
                #Remove last element from the list of hiscores for
                #this mode.
                current_scores[mode].pop()
                #Stop searching.
                output_str = 'capitals,flags,continents\n'
                #Save new score to file
                for current_score in range(0,10):
                    output_str = output_str + str(current_scores['capitals'][current_score]) + ',' + str(current_scores['flags'][current_score]) + ',' + str(current_scores['continents'][current_score]) + '\n'
                with open('data/hiscores.csv','w') as data_to_write:
                    data_to_write.write(output_str)
                #Assign different position ending depending on which position the new
                # hiscore will be assigned.
                score_endings = ['st','nd','rd','th']
                ending = ''
                if position == 1:
                    ending = score_endings[0]
                elif position == 2:
                    ending = score_endings[1]
                elif position == 3:
                    ending = score_endings[2]
                else:
                    ending = score_endings[3]

                inform_about_new_hiscore = MDDialog(
                    text = f"Congratulations [color=#13D152]{user_score} pts[/color] is a [color=#13D152]new high score[/color]\n and [color=#13D152]{position}{ending}[/color] best score in {mode.capitalize()} mode",
                    radius=[20,20,20,20],
                    #md_bg_color = (19/255,209/255,82/255,1)
                )
                inform_about_new_hiscore.open()
                #break from the loop
                break

    def fill_hiscores(self):
        #Load hiscores from the csv file
        current_scores = dt.get_scores()
        #Fill hiscores in capitals hiscores table
        self.root.get_screen('HSScreen').ids.ca_pos1.text = current_scores['capitals'][0]
        self.root.get_screen('HSScreen').ids.ca_pos2.text = current_scores['capitals'][1]
        self.root.get_screen('HSScreen').ids.ca_pos3.text = current_scores['capitals'][2]
        self.root.get_screen('HSScreen').ids.ca_pos4.text = current_scores['capitals'][3]
        self.root.get_screen('HSScreen').ids.ca_pos5.text = current_scores['capitals'][4]
        self.root.get_screen('HSScreen').ids.ca_pos6.text = current_scores['capitals'][5]
        self.root.get_screen('HSScreen').ids.ca_pos7.text = current_scores['capitals'][6]
        self.root.get_screen('HSScreen').ids.ca_pos8.text = current_scores['capitals'][7]
        self.root.get_screen('HSScreen').ids.ca_pos9.text = current_scores['capitals'][8]
        self.root.get_screen('HSScreen').ids.ca_pos10.text = current_scores['capitals'][9]
        #Fill hiscores in flags hiscores table
        self.root.get_screen('HSScreen').ids.f_pos1.text = current_scores['flags'][0]
        self.root.get_screen('HSScreen').ids.f_pos2.text = current_scores['flags'][1]
        self.root.get_screen('HSScreen').ids.f_pos3.text = current_scores['flags'][2]
        self.root.get_screen('HSScreen').ids.f_pos4.text = current_scores['flags'][3]
        self.root.get_screen('HSScreen').ids.f_pos5.text = current_scores['flags'][4]
        self.root.get_screen('HSScreen').ids.f_pos6.text = current_scores['flags'][5]
        self.root.get_screen('HSScreen').ids.f_pos7.text = current_scores['flags'][6]
        self.root.get_screen('HSScreen').ids.f_pos8.text = current_scores['flags'][7]
        self.root.get_screen('HSScreen').ids.f_pos9.text = current_scores['flags'][8]
        self.root.get_screen('HSScreen').ids.f_pos10.text = current_scores['flags'][9]
        #Fill hiscores in continents table
        self.root.get_screen('HSScreen').ids.co_pos1.text = current_scores['continents'][0]
        self.root.get_screen('HSScreen').ids.co_pos2.text = current_scores['continents'][1]
        self.root.get_screen('HSScreen').ids.co_pos3.text = current_scores['continents'][2]
        self.root.get_screen('HSScreen').ids.co_pos4.text = current_scores['continents'][3]
        self.root.get_screen('HSScreen').ids.co_pos5.text = current_scores['continents'][4]
        self.root.get_screen('HSScreen').ids.co_pos6.text = current_scores['continents'][5]
        self.root.get_screen('HSScreen').ids.co_pos7.text = current_scores['continents'][6]
        self.root.get_screen('HSScreen').ids.co_pos8.text = current_scores['continents'][7]
        self.root.get_screen('HSScreen').ids.co_pos9.text = current_scores['continents'][8]
        self.root.get_screen('HSScreen').ids.co_pos10.text = current_scores['continents'][9]

    def testing(self):
        print("testing")

# Running the app
CountriesQuiz().run()


"""
Will search through the database for all of the interval nodes that have been added to the database that are not apart
of a relative time line or universal timeline.
"""
import isodate
import datetime
import logging
from sleekxmpp.plugins.base import base_plugin
from rhobot.components.storage import StoragePayload
from rhobot.components.storage.enums import UpdateFlags
from rhobot.components.storage.namespace import NEO4J
from rhobot.components.storage.events import STORAGE_FOUND
from rhobot.namespace import TIMELINE
from rdflib.namespace import DCTERMS

logger = logging.getLogger(__name__)

class Maintainer(base_plugin):
    name = 'timeline_maintainer'
    description = 'Search database for unassociated intervals and associate them with the correct timeline.'
    dependencies = {'rho_bot_scheduler', 'rho_bot_storage_client', 'rho_bot_get_or_create',
                    'rho_bot_representation_manager', 'rho_bot_rdf_publish'}

    # Query that is used to find unassociated intervals.
    query = """
    MATCH (node:`%s`)
    WHERE NOT (node)-[:`%s`]->(:`%s`)
    RETURN node
    LIMIT 1
    """ % (TIMELINE.Interval, TIMELINE.timeline, TIMELINE.RelativeTimeLine)

    # Delays
    _work_to_do_delay = 1.0
    _no_work_delay = 600.0

    def plugin_init(self):
        """
        Subscribe to joining the channel event to see if there are missing associations.
        :return:
        """
        self.xmpp.add_event_handler(STORAGE_FOUND, self._storage_found)
        self.query = ' '.join(self.query.split())

    def post_init(self):
        """
        Finish configuring this plugin.
        :return:
        """
        super(Maintainer, self).post_init()
        self._storage_client = self.xmpp['rho_bot_storage_client']
        self._scheduler = self.xmpp['rho_bot_scheduler']
        self._get_or_create = self.xmpp['rho_bot_get_or_create']
        self._representation_manager = self.xmpp['rho_bot_representation_manager']
        self._rdf_publish = self.xmpp['rho_bot_rdf_publish']

    def _storage_found(self, *args):
        """
        Can now kick off the commands to be able to start finding the intervals.
        :return:
        """
        self.xmpp.del_event_handler(STORAGE_FOUND, self._storage_found)
        self._scheduler.schedule_task(self._start_process, delay=self._work_to_do_delay)

    def _start_process(self):
        """
        Kick off the processes to find the intervals and add them to the chain.
        :return:
        """
        promise = self._scheduler.defer(lambda: dict())
        promise = promise.then(self._find_work_node)
        promise = promise.then(self._get_interval_properties)
        promise = promise.then(self._get_timelines)
        promise = promise.then(self._update_interval)

        promise.then(self._scheduler.generate_promise_handler(self._reschedule, self._work_to_do_delay),
                     self._scheduler.generate_promise_handler(self._reschedule, self._no_work_delay))

    def handle_interval_modification(self, node_uri):
        """
        Handle work done to add/update the interval to the
        :param node_uri:
        :return:
        """
        try:
            promise = self._scheduler.defer(lambda: dict(node_uri=node_uri))
            promise = promise.then(self._get_interval_properties)
            promise = promise.then(self._get_timelines)
            promise = promise.then(self._update_interval)

            return promise
        except Exception as e:
            logger.error('Exception: ', e)

    def _find_work_node(self, session):
        """
        Find a node to work over.
        :param session:
        :return:
        """
        def _handle_cypher_result(_result):
            """
            Handle the results from the cypher result.  If there as no result found then reject the promise, otherwise
            update the session with the uri of the node, and
            :param _result:
            :return:
            """
            if not _result.results:
                raise Exception('No results to work')

            node_uri = _result.results[0].about

            session['node_uri'] = node_uri

            return session

        payload = StoragePayload()
        payload.add_property(key=NEO4J.cypher, value=self.query)
        promise = self._storage_client.execute_cypher(payload).then(_handle_cypher_result)

        return promise

    def _get_interval_properties(self, session):
        """
        Fetch the properties of the the node stored in the session.
        :param session:
        :return:
        """
        def _handle_get_results(_result):
            if not _result.about:
                # This is a weird case, and should never happen
                raise Exception('Node does not exist')

            session['node'] = _result
            return session

        payload = StoragePayload()
        payload.about = session['node_uri']
        promise = self._storage_client.get_node(payload).then(_handle_get_results)

        return promise

    def _get_timelines(self, session):
        """
        Create a promise list that will fetch all of the timelines that the interval should be connected to.
        :param session:
        :return:
        """
        start_date_string = session['node'].properties.get(str(TIMELINE.start), None)
        end_date_string = session['node'].properties.get(str(TIMELINE.end), None)

        start_date_time = isodate.parse_datetime(start_date_string[0])
        start_date = datetime.datetime(start_date_time.year, start_date_time.month, start_date_time.day,
                                       tzinfo=start_date_time.tzinfo)

        if end_date_string:
            end_date_time = isodate.parse_datetime(end_date_string[0])
            end_date = datetime.datetime(end_date_time.year, end_date_time.month, end_date_time.day,
                                         tzinfo=start_date_time.tzinfo)
        else:
            end_date = start_date

        promises = []

        date_difference = end_date - start_date

        for day in range(0, date_difference.days+1):
            delta = datetime.timedelta(days=day)
            timeline_date = start_date + delta

            promise = self._find_or_create_relative_map_for_date(timeline_date)

            promises.append(promise)

        promise = self._scheduler.create_promise_list(*promises).then(
            self._scheduler.generate_promise_handler(self._store_found_timelines, session))

        return promise

    def _store_found_timelines(self, result, session):
        session['timelines'] = result
        return session

    def _find_or_create_relative_map_for_date(self, date):
        """
        Find or create a relative timeline scale that connects to an origin map with the correct date value.
        :param date: date object
        :return:
        """
        def _handle_find_node(_result):
            if not _result.about:
                raise Exception('Result not found')

            return _result

        origin = isodate.isodatetime.datetime_isoformat(date)

        search_payload = StoragePayload()
        search_payload.add_type(TIMELINE.OriginMap)
        search_payload.add_property(TIMELINE.origin, origin)

        promise = self._get_or_create(search_payload)
        promise = promise.then(_handle_find_node)
        promise = promise.then(self._get_range_timeline)

        return promise

    def _get_range_timeline(self, timeline_map):
        """
        Get or create the range timeline for the origin map that was previously found.
        :param timeline_map: the timeline map.
        :return:
        """
        time_lines = timeline_map.references.get(str(TIMELINE.rangeTimeLine), None)
        if time_lines:
            return time_lines[0]

        def _handle_create_and_update_session(_result):
            timeline = _result.results[0].about

            update_payload = StoragePayload()
            update_payload.about = timeline_map.about
            update_payload.add_reference(TIMELINE.rangeTimeLine, timeline)

            # Publish the create event
            self._rdf_publish.publish_all_results(_result, created=True)

            _promise = self._storage_client.update_node(update_payload)
            _promise = _promise.then(self._scheduler.generate_promise_handler(self._rdf_publish.publish_all_results,
                                                                              created=False))
            _promise = _promise.then(lambda s: timeline)

            return _promise

        # otherwise it needs to be created and then return.
        create_payload = StoragePayload()
        create_payload.add_type(TIMELINE.RelativeTimeLine)
        create_payload.add_reference(DCTERMS.creator, self._representation_manager.representation_uri)

        promise = self._storage_client.create_node(create_payload).then(_handle_create_and_update_session)

        return promise

    def _update_interval(self, session):
        """

        Now that the timeline stuff has been found, update the interval as well.
        :param session:
        :return:
        """
        def return_session(result):
            self._rdf_publish.publish_all_results(result, created=False)
            return session

        update_payload = StoragePayload()
        update_payload.about = session['node'].about
        update_payload.add_reference(TIMELINE.timeline, session['timelines'])

        update_payload.add_flag(UpdateFlags.REPLACE_DEFINED, True)

        return self._storage_client.update_node(update_payload).then(return_session)

    def _reschedule(self, session, delay):
        """
        Reschedule the task.
        :param session:
        :param delay:
        :return:
        """
        self._scheduler.schedule_task(self._start_process, delay=delay)

timeline_maintainer = Maintainer


from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.index),
    url(r'^wall$', views.wall),
    url(r'^register$', views.register),
    url(r'^post_message$', views.post_message),
    url(r'^post_comment$', views.post_comment),
    url(r'^delete/comment/(?P<comment_id>\d+)/$', views.delete_comment),
    url(r'^delete/message/(?P<message_id>\d+)/$', views.delete_message),
    url(r'^logoff$', views.logoff),
    url(r'^login$', views.login),
]


from django.urls import path

from contatos.views import ContatoCreate, ContatoDelete, ContatoList, ContatoUpdate

app_name = 'contatos'

urlpatterns = [
    path('', ContatoList.as_view(), name='list'),
    path('criar/', ContatoCreate.as_view(), name='create'),
    path('<uuid:contato_id>/atualizar/', ContatoUpdate.as_view(), name='update'),
    path('<uuid:contato_id>/deletar/', ContatoDelete.as_view(), name='delete')
]


from django.urls import path
from .views import subscribe, CategoryListView, PostsList, PostDetail, PostCreate, PostUpdate, PostDelete, Search, upgrade_me

urlpatterns = [
   path('', PostsList.as_view()),
   path('<int:pk>/', PostDetail.as_view()),
   path('search/', Search.as_view(), name='search'),
   path('news/create/', PostCreate.as_view(), name='post_create'),
   path('news/<int:pk>/update/', PostUpdate.as_view(), name='post_update'),
   path('news/<int:pk>/delete/', PostDelete.as_view(), name='post_delete'),
   path('articles/create/', PostCreate.as_view(), name='post_create'),
   path('articles/<int:pk>/update/', PostUpdate.as_view(), name='post_update'),
   path('articles/<int:pk>/delete/', PostDelete.as_view(), name='post_delete'),
   path('upgrade/', upgrade_me, name='upgrade'),
   path('categories/<int:pk>/', CategoryListView.as_view(), name='category_list'),
   path('categories/<int:pk>/subscribe', subscribe, name='subscribe'),
]


#!/usr/bin/env python3

from __future__ import print_function
from os import path

import docopt
import sys

__author__ = "lteasnail"

CLI_ARGS = """
USAGE:
alignment_summerise.py [options]

OPTIONS:
 -t STRING        String to count

counts the number of each base pair
"""

def base_counter(stringy):
    base_count = {}
    for base in stringy:
        base_count[base] = base_count.get(base, 0) + 1
    return base_count['A'], base_count['C'], base_count['G'], base_count['T']

# If I am being run as a script...
if __name__ == '__main__':
    opts = docopt.docopt(CLI_ARGS)
    string_file = opts['-t']
    string_filey = open(string_file, 'r')
    stringy = string_filey.read()
    c1, c2, c3, c4 = base_counter(stringy)
    print('{} {} {} {}'.format(c1, c2, c3, c4), file=sys.stderr)


import subprocess
import os
import re
import hashlib
from urllib.request import Request, urlopen
from base64 import b64encode

REGEX = re.compile(r".*[/\\](.*?)-([^/\\]*)_(.*?)[/\\]bin[/\\](.*?)\.dll")

class IDAHelper(object):
    """ Helper class that provides an easy-to-use interface to IDA Pro. """

    def __init__(self, dll, pdb, idaq, idaq64, artifactoryPath, auth):
        """ Initializes an instance of this class.

            :param dll: the path of the dll to be analyzed with IDA Pro
            :param pdb: the path of the PDB file that should be applied
            :param idaq: the full path to idaq.exe
            :param idaq64: the full path to idaq64.exe
            :param artifactortPath: the URL base path for the artifactory
            :param auth: HTTP basic auth tokens for the artifactory
        """
        super(IDAHelper, self).__init__()
        self._dll = (os.getcwd() + "/" + dll).replace("\\", "/")
        self._pdb = (os.getcwd() + "/" + pdb).replace("\\", "/")
        self._idaq = idaq if "x64" not in dll else idaq64
        self._idb = (self._dll.replace(".dll", ".idb") if "x64" not in self._dll
                     else self._dll.replace(".dll", ".i64"))
        self._cwd = os.getcwd() + "/" + "/".join(dll.split("/")[:-1])
        self._cwd = self._cwd.replace("\\", "/")
        self._artifactoryPath = artifactoryPath
        self._auth = auth

    def makeidb(self):
        """ Runs IDA Pro with command line flags to output an IDB file. """
        args = [self._idaq,
                # overwrite existing
                "-c",
                # batch mode (create IDB and ASM file automatically and exit)
                "-B",
                # autonomous mode (no dialog boxes etc; remove on IDA crash)
                "-A",
                # pass arguments to our script
                "-Obindifflib:{}".format(self._pdb),
                # tell IDA to execute the bindifflib_exporter script
                "-S\"{}/bindifflib_exporter.py\"".format(os.getcwd()),
                # pack database
                "-P+",
                self._dll]
        # run IDA
        subprocess.run(args, cwd=self._cwd)

    def storeresult(self):
        """ Stores the IDB, DLL, and PDB file in the artifactory. """

        # well, storing into void is not that useful
        if self._artifactoryPath is None:
            return

        m = REGEX.search(self._dll)
        if m:
            # extract some information from the path where the DLL is
            name = m.group(1)
            version = m.group(2)
            compiler = m.group(3)
            filename = m.group(4)

            # send each file separately
            names = [self._dll, self._pdb, self._idb]
            for file in names:
                # construct the PUT header, e.g. MD5 and SHA-1 hashes
                # of the file and, most importantly, setup HTTP basic auth
                headers = {
                    "Content-Type": "application/octet-stream",
                    "X-Checksum-md5": hashlib.md5(
                        open(file, "rb").read()).hexdigest(),
                    "X-Checksum-sha1": hashlib.sha1(
                        open(file, "rb").read()).hexdigest(),
                    "Authorization": "Basic {}".format(
                        b64encode(
                            ":".join(self._auth).encode()).decode("ascii")),
                }

                # construct the urllib request
                r = Request(self._artifactoryPath +
                            "bin/{name}/{version}/{compiler}/{fname}".format(
                                name=name, version=version, compiler=compiler,
                                fname=file.replace("\\", "/").split("/")[-1]),
                            headers=headers, data=open(file, "rb").read(),
                            method="PUT")

                # send the request and upload the file
                urlopen(r)

    @property
    def dll(self):
        return self._dll


import os
import numpy as np
from torch.utils.data import DataLoader, Dataset
from PIL import Image
import config

class ImageDS(Dataset):
    def __init__(self, root):
        super().__init__()
        self.data = []
        self.root = root
        self.class_names = os.listdir(root)

        for idx, name in enumerate(self.class_names):
            files = os.listdir(os.path.join(root, name))
            self.data += list(zip(files, [idx]*len(files)))

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        img_file, label = self.data[idx]
        root_and_dir = os.path.join(self.root, self.class_names[label])
        image = np.array(Image.open(os.path.join(root_and_dir, img_file)))
        image = config.both_transforms(image=image)["image"]
        high_res = config.highres_transform(image=image)["image"]
        low_res = config.lowres_transform(image=image)["image"]
        return low_res, high_res

def test():
    dataset = ImageDS(root="Data/")
    loader = DataLoader(dataset, batch_size=1)
    for low_res, high_res in loader:
        print(low_res.shape)
        print(high_res.shape)


from typing import Optional, Tuple, Union
import numpy
from . import (Grid2DFloat32, Grid2DFloat64, Grid3DFloat32, Grid3DFloat32,
               Grid3DFloat64, TemporalGrid3DFloat64, TemporalGrid3DFloat32)

class FirstGuess:
    Zero: 'FirstGuess'
    ZonalAverage: 'FirstGuess'

class ValueType:
    Undefined: 'Undefined'
    Defined: 'Defined'
    All: 'All'

def loess_float64(
        grid: Union[Grid2DFloat64, Grid3DFloat64, TemporalGrid3DFloat64],
        nx: int = 3,
        ny: int = 3,
        processing_mode: Optional[str] = None,
        num_threads: int = 0) -> numpy.ndarray[numpy.float64]:
    ...

def loess_float32(
        grid: Union[Grid2DFloat32, Grid3DFloat32, TemporalGrid3DFloat32],
        nx: int = 3,
        ny: int = 3,
        processing_mode: Optional[str] = None,
        num_threads: int = 0) -> numpy.ndarray[numpy.float64]:
    ...

def gauss_seidel_float64(grid: numpy.ndarray[numpy.float64],
                         first_guess: FirstGuess = FirstGuess.ZonalAverage,
                         is_circle: bool = True,
                         max_iterations: int = 2000,
                         epsilon: float = 0.0001,
                         relaxation: float = 1.0,
                         num_thread: int = 0) -> Tuple[int, float]:
    ...

def gauss_seidel_float32(grid: numpy.ndarray[numpy.float32],
                         first_guess: FirstGuess = FirstGuess.ZonalAverage,
                         is_circle: bool = True,
                         max_iterations: int = 2000,
                         epsilon: float = 0.0001,
                         relaxation: float = 1.0,
                         num_thread: int = 0) -> Tuple[int, float]:
    ...


from collections import defaultdict
from typing import List

class Solution:
    def __init__(self):
        self.total = 0

    def traversal(self, id, manager_to_subordinates, informTime, cur_time):
        # 记录当前节点传给下一个节点的时间
        cur_time += informTime[id]
        # 遇到叶子节点开始更新最大值，统计最大总时间
        if id not in manager_to_subordinates:
            self.total = max(self.total, cur_time)
            return
        # 对每个孩子节点递归
        for child in manager_to_subordinates[id]:
            self.traversal(child, manager_to_subordinates, informTime, cur_time)

        return

    def numOfMinutes(self, n: int, headID: int, manager: List[int], informTime: List[int]) -> int:
        """
        Time O(n)
        Space O(n)
        先构建manager到employee ID的dictionary，表示树的关系。从头到尾开始dfs遍历整个树，找到最大的路径和及最终的结果。
        """
        # 构建字典表示的树
        manager_to_subordinates = defaultdict(list)
        for index, value in enumerate(manager):
            manager_to_subordinates[value].append(index)

        self.traversal(headID, manager_to_subordinates, informTime, 0)

        return self.total

n = 11
headID = 4
manager = [5, 9, 6, 10, -1, 8, 9, 1, 9, 3, 4]
informTime = [0, 213, 0, 253, 686, 170, 975, 0, 261, 309, 337]
s = Solution()
print(s.numOfMinutes(n=n, headID=headID, manager=manager, informTime=informTime))


#!/usr/bin/python3

import argparse
import os
import tempfile
from io import SEEK_CUR

AR_FILE_NAME_SIZE = 16
AR_SIZE_OFFSET = 32
AR_SIZE_SIZE = 10
AR_FILE_START_OFFSET = 2

class CaseInsensitiveDict():
    def __init__(self):
        self._d = dict()

    def __contains__(self, k):
        return k.lower() in self._d

    def __len__(self):
        return len(self._d)

    def __iter__(self):
        return iter(self._d)

    def __getitem__(self, k):
        return self._d[k.lower()]

    def __setitem__(self, k, v):
        self._d[k.lower()] = v

    def get(self, k, default=None):
        if k.lower() in self._d:
            return self._d[k.lower()]
        else:
            return default

def is_file_system_case_sensitive():
    with tempfile.NamedTemporaryFile(prefix='TmP') as tmp_file:
        return(not os.path.exists(tmp_file.name.lower()))

def extract_archive(archive_path, destination_path):

    archive = open(archive_path, 'rb')

    global_header = archive.read(8)
    if global_header != str.encode('!<arch>\n'):
        print('Oops!, ' + archive_path + ' seems not to be an archive file!')
        exit(1)

    if is_file_system_case_sensitive():
        processed_files = dict()
    else:
        processed_files = CaseInsensitiveDict()

    count = 0
    while True:
        count = count+1
        ar_file_name_bytes = archive.read(AR_FILE_NAME_SIZE)
        if len(ar_file_name_bytes) == 0:
            break
        ar_file_name_raw = ar_file_name_bytes.rstrip(b' ').decode()
        archive.seek(AR_SIZE_OFFSET, SEEK_CUR)
        ar_file_size = int(archive.read(AR_SIZE_SIZE).rstrip(b' ').decode())
        if ar_file_name_raw.startswith('#1/'):
            file_name_size = int(ar_file_name_raw.replace('#1/', ''))
            ar_file_size = ar_file_size - file_name_size
            archive.seek(AR_FILE_START_OFFSET, SEEK_CUR)
            ar_file_name = archive.read(file_name_size).rstrip(b'\x00').decode()
        else:
            ar_file_name = ar_file_name_raw.decode()
            archive.seek(AR_FILE_START_OFFSET, SEEK_CUR)

        if ar_file_name in processed_files:
            filename, ext = os.path.splitext(ar_file_name)
            new_file_name = str(processed_files[ar_file_name] + 1) + '-' + filename + ext
            processed_files[ar_file_name] = processed_files[ar_file_name] + 1
        else:
            new_file_name = ar_file_name

        processed_files[ar_file_name] = processed_files.get(ar_file_name, 1)

        with open(os.path.join(destination_path, new_file_name), 'wb') as out:
            out.write(archive.read(ar_file_size))

        if archive.tell() % 2 == 1:
            archive.read(1)

    archive.close()

parser = argparse.ArgumentParser(description='Extract archive files.')
parser.add_argument('--archive', type=str, help='Path to the archive to extract')
parser.add_argument('--destination', type=str, help='Path to the destination')
args = parser.parse_args()

extract_archive(args.archive, args.destination)


import os
import numpy as np
import pandas as pd
from PIL import Image

import torch
from torch import nn
from torch.utils.data import Dataset, DataLoader
from torchvision import datasets
from torchvision import datasets, transforms

device = 'cuda' if torch.cuda.is_available() else 'cpu'

class MyDataSet(Dataset):
    def __init__(self,
                 annotation_file,
                 img_dir,
                 transform=None,
                 target_transform=None):
        self.label = pd.read_csv(os.path.join(img_dir, annotation_file),
                                 header=None).to_numpy()
        n_label = len(self.label)
        self.img_fn = ['{:05}.png'.format(i) for i in range(n_label)]
        self.img_dir = img_dir
        self.transform = transform
        self.target_transform = target_transform

    def __len__(self):
        return len(self.label)

    def __getitem__(self, idx):
        img_path = os.path.join(self.img_dir, self.img_fn[idx])
        image = Image.open(img_path)
        label = self.label[idx, :]
        if self.transform:
            image = self.transform(image)
        if self.target_transform:
            label = self.target_transform(label)
        return image, label

def crop125(image):
    return transforms.functional.crop(image, 0, 0, 50, 140)

preprocess = transforms.Compose([
    transforms.ToTensor(),
    transforms.Grayscale(),
    transforms.Lambda(crop125)
])

class MyNetwork(nn.Module):
    def __init__(self):
        super(MyNetwork, self).__init__()
        self.net = nn.Sequential(
            nn.Conv2d(1, 32, (3, 3), padding='same'),
            nn.ReLU(),
            nn.Conv2d(32, 32, (3, 3)),
            nn.ReLU(),
            nn.BatchNorm2d(32),
            nn.MaxPool2d((2, 2)),
            nn.Dropout2d(),
            nn.Conv2d(32, 64, (3, 3), padding='same'),
            nn.ReLU(),
            nn.Conv2d(64, 64, (3, 3)),
            nn.ReLU(),
            nn.BatchNorm2d(64),
            nn.MaxPool2d((2, 2)),
            nn.Dropout2d(),
            nn.Conv2d(64, 128, (3, 3), padding='same'),
            nn.ReLU(),
            nn.Conv2d(128, 128, (3, 3)),
            nn.ReLU(),
            nn.BatchNorm2d(128),
            nn.MaxPool2d((2, 2)),
            nn.Dropout2d(),
            nn.Conv2d(128, 256, (3, 3)),
            nn.ReLU(),
            nn.BatchNorm2d(256),
            nn.MaxPool2d((2, 2)),
            nn.Flatten(),
            nn.Dropout2d(),
        )
        self.Linear = [nn.Linear(1536, 10) for i in range(6)]

    def forward(self, x):
        out = self.net(x)
        multiout = [l(out) for l in self.Linear]
        return multiout

train_data = MyDataSet('train.csv', 'train', preprocess)
test_data = MyDataSet('test.csv', 'test', preprocess)

train_dataloader = DataLoader(train_data, batch_size=64, shuffle=True)
test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True)

model = MyNetwork()
optimizer = torch.optim.Adam(model.parameters())
loss_fn = nn.CrossEntropyLoss()

# start train
def train(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    for batch, (X, y) in enumerate(dataloader):
        pred = model(X)
        loss = 0
        for i in range(6):
            loss += loss_fn(pred[i], y[:, i])

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if batch % 100 == 0:
            loss, current = loss.item(), batch * len(X)
            print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")

def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    test_loss, correct = 0, 0
    with torch.no_grad():
        for X, y in dataloader:
            pred = model(X)
            for i in range(6):
                test_loss += loss_fn(pred[i], y[:, i]).item()
                correct += (pred[i].argmax(1) == y[:, i]).type(
                    torch.float).sum().item()
    test_loss /= num_batches
    correct /= size * 6
    print(
        f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n"
    )

epochs = 5
for t in range(epochs):
    print(f"Epoch {t+1}\n------------------------------")
    train(train_dataloader, model, loss_fn, optimizer)
    test(test_dataloader, model, loss_fn)

# save model
torch.save(model, 'model.pth')


#Classe d'affichage du tableau

from PyQt5.QtWidgets import QGroupBox, QGridLayout

import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas

class Plot_class(QGroupBox) :
    def __init__(self) :
        super().__init__()

        self.setTitle("Simulation des algues : ")

        layout = QGridLayout()
        self.setLayout(layout)

        self.fig = plt.figure()                     #création du graph
        self.canvas = FigureCanvas(self.fig)
        layout.addWidget(self.canvas,0,0)


# -*- coding = utf-8 -*-
# @Time : 2022/10/2 10:15
# @Author : Juyi
# @File : 4.绘制矩形.py
# @Software : PyCharm
import cv2 as cv

img = cv.imread("face1.png")
# 坐标
x, y, w, h = 100, 100, 100, 100
# 绘制矩形
cv.rectangle(img, (x, y), (x + w, y + h), color=(0, 0, 255), thickness=1)
# 绘制圆形
cv.circle(img, center=(x + w, y + h), radius=100, color=(255, 0, 0), thickness=2)

# 显示
cv.imshow("re_img", img)
# 等待(检测到q后退出)
while True:
    if ord('q') == cv.waitKey(0):
        break
# 释放内存
cv.destroyAllWindows()

人脸识别/4.绘制矩形.py


import cv2
from numpy import source

source = cv2.VideoCapture("night.mp4")

while True:
    ret, img = source.read()
    if not ret:
        print("can't read video")
        break

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    cv2.imshow("nightGray", gray)

    wk = cv2.waitKey(10)
    if wk == ord("q"):
        break

cv2.destroyAllWindows()
source.release()


from pyramid.httpexceptions import HTTPFound

from pyramid.security import (
    remember,
    forget,
)

from pyramid.renderers import get_renderer

# from ... import security

from ...lib import common
from ..lib import user_f, security, site_settings_f

login_redirect_url = "core.login"

def forbidden(request):
    if not hasattr(request, "user") or request.user.id == 2:
        path = request.path

        if path == "/logout":
            path = ""

        return HTTPFound(location = "{}?redirect={}".format(
            request.route_url(login_redirect_url),
            common.encode(redirect=path)
        ))

    layout = common.render("blank")

    return dict(
        title = "503: No access permission",
        layout = layout
    )

def login(request):
    request.do_not_log = True
    layout = common.render("blank")

    redirect = request.params.get("redirect", "")
    if redirect != "":
        try:
            redirect = common.decode(redirect)[1]['redirect']
        except Exception:
            redirect = "/"

    else:
        redirect = "/"

    # If no redirect or default redirect, we want to look at maybe sending them back where
    # they came from
    if redirect == "/":
        login_url = request.route_url('core.login')
        referrer = request.url
        if referrer == login_url:
            # never use the login form itself as came_from
            referrer = request.route_url('/')
        came_from = request.params.get('came_from', referrer)
        redirect = came_from

    message  = None
    partial  = None
    username = ''

    if 'username' in request.params:
        user_id, result = security.login(request)

        if user_id == "failure":
            message = "danger", result

        elif result in ("complete", None):
            # They're in? Best do stuff then!
            return security.successful_login(request, user_id, redirect)

            # user_f.update_session_ip(user_id, session_ip=request.remote_addr)
            # headers = remember(request, user_id, max_age = 60*60*24*7*9999)
            # return HTTPFound(location = came_from, headers = headers)
        else:
            # They have partials, we better do something about that
            return HTTPFound(location=request.route_url('core.login') + "?h=" + result)

    if 'h' in request.params:
        partial = security.perform_partial(request)
        if isinstance(partial, HTTPFound):
            return partial

        if 'message' in partial:
            message = partial['message']

    return dict(
        title     = "Login",
        redirect  = redirect,
        message   = message,
        login     = username,
        # url       = request.route_url('core.login'),
        layout    = layout,
        partial   = partial,

        allow_registration = site_settings_f.get_setting("runway.users.allow_registration", False) == "True",
    )

def logout(request):
    headers = forget(request)
    return HTTPFound(location = request.route_url('core.login'), headers = headers)

def external_auth(request):
    layout = common.render("blank")

    message = ""

    return dict(
        title   = "External login",
        layout  = layout,
        message = message,
    )


#!/usr/bin/env python3
from collections import defaultdict

class Day1:
  def __init__(self):
    with open('day1/in.txt') as f:
      content = f.readlines()
    self.list = [int(x.strip()) for x in content]

  def part1(self):
    print('Day 1 pt1 : %d ' % sum(self.list))

  def part2(self):
    dd = defaultdict(int)
    running_sum = 0
    found = False
    while not found:
      for i in self.list:
        running_sum += i
        dd[running_sum] = dd[running_sum] + 1
        if dd[running_sum] > 1:
          found = True
          print('Day 2 tp 2: %d' %  running_sum)
          break


from app.forms.delete_user_form import DeleteUserForm
from app.api.auth_routes import validation_errors_to_error_messages
from app.forms.edit_user_form import EditUserForm
from app.api.aws import public_file_upload
from flask import Blueprint, jsonify, request
from flask_login import login_required
from app.models import User, db

from app.models.user import user_connections

user_routes = Blueprint('users', __name__)

@user_routes.route('/')
@login_required
def users():
    users = User.query.all()
    return {'users': [user.to_dict() for user in users]}

@user_routes.route('/<int:id>')
# @login_required
def user(id):
    user = User.query.get(id)
    return user.to_dict()

@user_routes.route('/<string:username>')
def user_by_name(username):
    user =  User.query.filter( User.username == username).first()

    return user.to_dict()

@user_routes.route('/<int:id>/edit', methods = ['PUT'])
def edit_user(id):

    form = EditUserForm()
    form['csrf_token'].data = request.cookies['csrf_token']

    if form.validate_on_submit():
        user = User.query.get(id)
        isImage = request.form['isImage']
        print('is image', isImage)
        profile_picture_url = user.profile_picture_url if len(isImage) > 0 else 'https://heartstringawsbuckect.s3.amazonaws.com/heartstring-default-profile-picture.jpg'

        print('i am here')
        try:
            print(request.files['image'], 'look at nothing')
            uploaded_file = request.files['image']
            profile_picture_url = public_file_upload    (uploaded_file, 'heartstringawsbuckect')
        except KeyError:
            pass

        user.display_name = form.data['display_name'] if form.data['display_name'] else user.display_name

        user.profile_picture_url = profile_picture_url

        db.session.add(user)

        db.session.commit()

        return user.to_dict()

    return {'errors': validation_errors_to_error_messages(form.errors)}, 401

@user_routes.route('/<int:id>/delete', methods = ['DELETE'])
def delete_user(id):
    form = DeleteUserForm()
    form['csrf_token'].data = request.cookies['csrf_token']

    if form.validate_on_submit():
        user = User.query.get(id)

        for connection in user.connections:
            user.sever_connection(connection.id)

        db.session.delete(user)
        db.session.commit()
        return {'deleted': True}

    return {'errors': validation_errors_to_error_messages(form.errors)}, 401