<commit_before>import auth, datetime, json, logging, os, praw, random, telebot, time, urllib.request
from colorama import init, Fore
from markov import Markov
from twitter import *

init()
dt = datetime.datetime

"""
API and auth keys. Will be located in auth.py.
"""

# Kuma-chan's unique ID.
bot = telebot.TeleBot(auth.Telegram.api_key)

# Kuma-chan's twitter, @KumaKaiNi.
t = Twitter(auth = OAuth(auth.TwitterAuth.access_key, auth.TwitterAuth.access_key_secret, auth.TwitterAuth.consumer_key, auth.TwitterAuth.consumer_key_secret))

# Reddit stuff.
r = praw.Reddit(user_agent='Telegram:KumaKaiNi-Py:v1.0.0 (by @rekyuu_senkan)')

"""
Helper functions and definitions.
"""

# Logging definitions.
CON = {
   'log': ''.join(['[', Fore.YELLOW, 'LOG', Fore.RESET, ']']),
   'err': ''.join(['[', Fore.RED,    'ERR', Fore.RESET, ']']),
   'img': ''.join(['[', Fore.GREEN,  'IMG', Fore.RESET, ']']),
   'msg': ''.join(['[', Fore.GREEN,  'MSG', Fore.RESET, ']']),
   'twt': ''.join(['[', Fore.CYAN,   'TWT', Fore.RESET, ']']),
}

# Logs all words to a file for later use with Markov.
def word_log (m):
   if not os.path.exists('./wordlogs'):
      os.makedirs('./wordlogs')
   try:
      log = open('./wordlogs/' + str(m.chat.id) + '.log', 'a+', encoding='utf8')
   except:
      print(CON['err'], 'Log file does not exist. Creating.')
      log = open('./wordlogs/' + str(m.chat.id) + '.log', 'w', encoding='utf8')
   finally:
      # Ignores messages that start with links or are just links
      if m.text.split(':')[0] not in ['http', 'https']:
         log.write(m.text + '\n')
      log.close()

# Function to populate top posts of a given subreddit
def get_top_posts (name):

   if not os.path.exists('./subreddits'):
      os.makedirs('./subreddits')
   conf = open('./subreddits/' + name + '.json', 'w', encoding='utf8')

   data = {}
   data['time'] = str(dt.now())
   data['posts'] = []

   sub = r.get_subreddit(name)

   print(CON['log'], "Populating list...")
   pid = 0
   for post in sub.get_hot(limit=25):
      url = post.url
      title = post.title
      data['posts'].append({'pid': pid, 'title': title, 'url': url})
      pid += 1
   json.dump(data, conf, ensure_ascii=False)
   print(CON['log'], "List populated!")

   conf.close()

# Function that sends the image
IMAGE_TYPES = ['jpg', 'jpeg', 'gif', 'png']
def send_sub_image (msg, name):
   while True:
      try:
         conf = open('./subreddits/' + name + '.json', encoding='utf8')
         data = json.loads(conf.read())
         conf.close()
         break
      except:
         print(CON['err'], "List has not been created. Creating.")
         get_top_posts(name)

   # Checks freshness of posts.
   if dt.now() - dt.strptime(data['time'], '%Y-%m-%d %H:%M:%S.%f') >= datetime.timedelta(days=1):
      print(CON['log'], "24 hours have past since last update!")
      get_top_posts(name)

   # Chooses a random listing and downloads the image.
   while True:
      try:
         rand = random.randint(0, len(data['posts']) - 1)
         dl = data['posts'][rand]['url']
         filename = dl.split('/')[-1]
         print(CON['log'], "Downloading", filename + "...")

         if filename.split('.')[-1] not in IMAGE_TYPES:
            # If the file is not an image, it will try again.
            print(CON['err'], "Not an image. Deleting entry and trying again.")
            del data['posts'][rand]
            if len(data['posts']) == 0:
               get_top_posts(sub)
         else:
            # Downloads the image.
            urllib.request.urlretrieve(dl, filename)

            # Sends the downloaded image and the title.
            photo = open(filename, 'rb')
            out = str(data['posts'][rand]['title'])
            bot.send_photo(msg.chat.id, photo)
            print(CON['img'], filename)

            bot.send_message(msg.chat.id, out)
            print(CON['msg'], out)

            # Closes the photo and removes it from the system.
            photo.close()
            os.remove(filename)
            del data['posts'][rand]

            conf = open('./subreddits/' + name + '.json', 'w', encoding='utf8')
            json.dump(data, conf, ensure_ascii=False)
            conf.close()
            break
      except:
         print(CON['err'], "Error downloading image. Trying again.")
         del data['posts'][rand]
         if len(data['posts']) == 0:
            get_top_posts(sub)

# Regex function
def to_regex (words, beg='', end=''):
   regex = ''.join(['^(', beg, ')('])
   for word in words:
      regex += '('
      letters = list(word)
      for letter in letters:
         regex = ''.join([regex, '(', letter.upper(), '|', letter.lower(), ')'])
      regex += ')|'
   regex = regex[:-1]
   regex = ''.join([regex, ')(', end, ')$'])
   return regex

# Probability function, ie, 1:100, etc.
def prob (x, y):
   rand = random.randint(1, y)
   if rand <= x:
      return True
   else:
      return False

"""
Command definitions and listeners.
"""

# List off commands.
@bot.message_handler(commands=['help'])
def send_help (m):
   bot.send_message(m.chat.id,
      "First ship of the Kuma-class light cruisers, Kuma, kuma.\n"
      + "Born in Sasebo, kuma. I got some old parts, but I'll try my best, kuma.\n"
      + "\n"
      + "/add x y z - takes your numbers and adds them together.\n"
      + "/coin - flips a coin.\n"
      + "/meme - sends a meme.\n"
      + "/predict - sends a prediction.\n"
      + "/roll x - rolls a number between 1 and x. Also takes 4d6, etc.\n"
      + "/say - repeats what you say.\n"
      + "/ship - posts an image from the top posts of r/warshipporn.\n"
      + "/tank - posts an image from the top posts of r/tankporn.\n"
      + "\n"
      + "Just as a warning, there is a 1% chance that I will tweet whatever bullshit you just said, kuma. https://twitter.com/KumaKaiNi\n"
      + "\n"
      + "Source: https://github.com/rekyuu/telegram-kuma")

# Command to let you know she's alive.
@bot.message_handler(commands=['kuma'])
def send_welcome (m):
   out = "Kuma ~"
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# Repeats what the user just said.
@bot.message_handler(commands=['say'])
def send_say (m):
   try:
      out = m.text.split(' ', 1)[1]
   except:
      out = 'There is nothing to say, kuma.'
   finally:
      bot.send_message(m.chat.id, out)
      print(CON['msg'], out)

# Adds two numbers or makes jokes.
@bot.message_handler(commands=['add'])
def add_num (m):
   msg = m.text.split()
   del msg[0]

   try:
      add = 0
      for n in msg:
         add += int(n)

      if len(msg) == 2 and msg[0] == '1' and msg[1] == '1':
         out = "1 + 1 = 69 get it ?? lol ahahahahaha 69 = sexspoisition 1 = girl + boy ahaha"
      elif len(msg) == 0:
         out = "You didn't submit numbers!"
      else:
         out = "Your sum of numbers is: " + str(add)
   except:
      if m.from_user.username == "Liseda":
         out = "fuck off"
      else:
         out = "Invalid input, sorry!"
   finally:
      bot.send_message(m.chat.id, out)
      print(CON['msg'], out)

# Sends the user a boat!
@bot.message_handler(commands=['ship'])
def send_boat (m):
   send_sub_image (m, 'warshipporn')

# Sends the user a tank!
@bot.message_handler(commands=['tank'])
def send_tonk (m):
   send_sub_image (m, 'tankporn')

# Sends the user a meme!
@bot.message_handler(commands=['meme'])
def send_meme (m):
   send_sub_image (m, 'foodporn')

# Anti-Wayne command
@bot.message_handler(commands=['dank', 'kush', 'pot', 'merrywanna'])
def send_dank (m):
   name = m.from_user.username
   if name is None:
      name = m.from_user.first_name
   out = ''.join(['Shut the fuck up, @', name])
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# Sends the user a prediction.
PREDICTIONS = [
   'It is certain.',
   'It is decidedly so.',
   'Without a doubt.',
   'Yes, definitely.',
   'You may rely on it.',
   'As I see it, yes.',
   'Most likely.',
   'Outlook good.',
   'Yes.',
   'Signs point to yes.',
   'Reply hazy, try again.',
   'Ask again later.',
   'Better not tell you now.',
   'Cannot predict now.',
   'Concentrate and ask again.',
   'Don\'t count on it.',
   'My reply is no.',
   'My sources say no.',
   'Outlook not so good.',
   'Very doubtful.'
]
@bot.message_handler(commands=['predict'])
def send_prediction (m):
   if len(m.text.split()) == 1:
      out = "You didn't ask a question ya dingus"
   else:
      out = PREDICTIONS[random.randint(0, len(PREDICTIONS) - 1)]
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# Flips a coin.
@bot.message_handler(commands=['flip', 'coin'])
def send_coinflip (m):
   coin = random.randint(0,1)
   if coin == 0:
      out = "Heads."
   else:
      out = "Tails."
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# Rolls dice.
@bot.message_handler(commands=['roll'])
def send_diceroll (m):
   try:
      dice = m.text.split()[1]
      mult = dice.split('d')
      if len(m.text.split()) >= 3:
         out = "Please only send one input."
      elif len(mult) == 2:
         if int(mult[0]) <= 1 or int(mult[1]) <= 1:
            out = "Inputs must be 2 or more. Example: 4d6"
         else:
            out = "Rolled"
            for x in range (0, int(mult[0])):
               out = ' '.join([out, str(random.randint(1, int(mult[1]))) + ","])
            out = out[:-1] # Remove [,]
      else:
         if int(dice) <= 1:
            out = "Input must be 2 or more."
         else:
            out = "Rolled a " + str(random.randint(0,int(dice)))
   except:
      out = "Please send only numbers."
   finally:
      bot.send_message(m.chat.id, out)
      print(CON['msg'], out)

# Sends a link to /r/botsrights
@bot.message_handler(commands=['botsrights'])
def send_rights (m):
   out = "http://reddit.com/r/botsrights"
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# Prints available json to the console.
@bot.message_handler(commands=['json'])
def print_json (m):
   print(CON['log'], 'info:', m.__dict__)
   print(CON['log'], 'from_user:', m.from_user.__dict__)
   print(CON['log'], 'chat:', m.chat.__dict__)

# Prints available json to the console.
@bot.message_handler(commands=['test'])
def testing_function (m):
   send_sub_image (m, 'warshipporn')

"""
Regex listeners.
"""

# Returns a greeting if a user starts a sentence with the following regex.
GREETS = ['hi', 'hello', 'yo', 'sup']
GREET_REPLIES = ['sup loser', 'yo', 'ay', 'go away', 'hi', 'wassup']
@bot.message_handler(regexp=to_regex(GREETS,'','()|( ).*'))
def send_hello (m):
   out = GREET_REPLIES[random.randint(0, len(GREET_REPLIES) - 1)]
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# Replies to thank you's.
THANKS = ['thank you kuma', 'thanks kuma', 'ty kuma']
TY_REPLIES = ['np', 'don\'t mention it', 'anytime', 'sure thing', 'ye whateva']
@bot.message_handler(regexp=to_regex(THANKS))
def send_thanks (m):
   out = TY_REPLIES[random.randint(0, len(TY_REPLIES) - 1)]
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# 1% chance to tweet an incoming message, if none of the above were processed.
last_msg = ''
@bot.message_handler(regexp=".")
def all_other_messages (m):
   global last_msg

   # Logs incoming messages to a file
   word_log(m)

   # 1:20 chance of firing a markov chain message
   if prob(1,20) == True:
      file_ = open('./wordlogs/' + str(m.chat.id) + '.log', encoding='utf8')

      # Will file once the log reaches 100 lines or more
      if len(file_.read().splitlines()) >= 100:
         word_count, msg_total = 0
         for line in file_.read().splitlines():
            word_count += int(len(line.split()))
            msg_total += 1
         word_avg = word_count / msg_total

         markov = Markov(file_)
         out = markov.generate_markov_text(word_avg + random.randint(0,5))

         bot.send_message(m.chat.id, out)
         print(CON['msg'], out)
         t.statuses.update(status=out + ' *Kuma Kai Ni')
         print(CON['twt'], out + ' *Kuma Kai Ni')
      file_.close()

   # Really simple and lazy spam protection
   if last_msg != m.text:
      last_msg = m.text
      # 1:100 chance to tweet the last message recieved
      if prob(1,100) == True:
         try:
            name = m.from_user.username
         except:
            name = m.from_user.first_name
         out = m.text + ' *' + name
         t.statuses.update(status=out)
         bot.send_message(m.chat.id, "lmao I'm live tweeting this shit")
         print(CON['twt'], out)
   else:
      last_msg = m.text

"""
Main command listener.
"""

bot.polling(none_stop=True)
print(CON['log'], 'Kuma! Shutsugeki suru, kuma!')
while True:
   time.sleep(100)<commit_msg>fixed twitter names<commit_after>import auth, datetime, json, logging, os, praw, random, telebot, time, urllib.request
from colorama import init, Fore
from markov import Markov
from twitter import *

init()
dt = datetime.datetime

"""
API and auth keys. Will be located in auth.py.
"""

# Kuma-chan's unique ID.
bot = telebot.TeleBot(auth.Telegram.api_key)

# Kuma-chan's twitter, @KumaKaiNi.
t = Twitter(auth = OAuth(auth.TwitterAuth.access_key, auth.TwitterAuth.access_key_secret, auth.TwitterAuth.consumer_key, auth.TwitterAuth.consumer_key_secret))

# Reddit stuff.
r = praw.Reddit(user_agent='Telegram:KumaKaiNi-Py:v1.0.0 (by @rekyuu_senkan)')

"""
Helper functions and definitions.
"""

# Logging definitions.
CON = {
   'log': ''.join(['[', Fore.YELLOW, 'LOG', Fore.RESET, ']']),
   'err': ''.join(['[', Fore.RED,    'ERR', Fore.RESET, ']']),
   'img': ''.join(['[', Fore.GREEN,  'IMG', Fore.RESET, ']']),
   'msg': ''.join(['[', Fore.GREEN,  'MSG', Fore.RESET, ']']),
   'twt': ''.join(['[', Fore.CYAN,   'TWT', Fore.RESET, ']']),
}

# Logs all words to a file for later use with Markov.
def word_log (m):
   if not os.path.exists('./wordlogs'):
      os.makedirs('./wordlogs')
   try:
      log = open('./wordlogs/' + str(m.chat.id) + '.log', 'a+', encoding='utf8')
   except:
      print(CON['err'], 'Log file does not exist. Creating.')
      log = open('./wordlogs/' + str(m.chat.id) + '.log', 'w', encoding='utf8')
   finally:
      # Ignores messages that start with links or are just links
      if m.text.split(':')[0] not in ['http', 'https']:
         log.write(m.text + '\n')
      log.close()

# Function to populate top posts of a given subreddit
def get_top_posts (name):

   if not os.path.exists('./subreddits'):
      os.makedirs('./subreddits')
   conf = open('./subreddits/' + name + '.json', 'w', encoding='utf8')

   data = {}
   data['time'] = str(dt.now())
   data['posts'] = []

   sub = r.get_subreddit(name)

   print(CON['log'], "Populating list...")
   pid = 0
   for post in sub.get_hot(limit=25):
      url = post.url
      title = post.title
      data['posts'].append({'pid': pid, 'title': title, 'url': url})
      pid += 1
   json.dump(data, conf, ensure_ascii=False)
   print(CON['log'], "List populated!")

   conf.close()

# Function that sends the image
IMAGE_TYPES = ['jpg', 'jpeg', 'gif', 'png']
def send_sub_image (msg, name):
   while True:
      try:
         conf = open('./subreddits/' + name + '.json', encoding='utf8')
         data = json.loads(conf.read())
         conf.close()
         break
      except:
         print(CON['err'], "List has not been created. Creating.")
         get_top_posts(name)

   # Checks freshness of posts.
   if dt.now() - dt.strptime(data['time'], '%Y-%m-%d %H:%M:%S.%f') >= datetime.timedelta(days=1):
      print(CON['log'], "24 hours have past since last update!")
      get_top_posts(name)

   # Chooses a random listing and downloads the image.
   while True:
      try:
         rand = random.randint(0, len(data['posts']) - 1)
         dl = data['posts'][rand]['url']
         filename = dl.split('/')[-1]
         print(CON['log'], "Downloading", filename + "...")

         if filename.split('.')[-1] not in IMAGE_TYPES:
            # If the file is not an image, it will try again.
            print(CON['err'], "Not an image. Deleting entry and trying again.")
            del data['posts'][rand]
            if len(data['posts']) == 0:
               get_top_posts(sub)
         else:
            # Downloads the image.
            urllib.request.urlretrieve(dl, filename)

            # Sends the downloaded image and the title.
            photo = open(filename, 'rb')
            out = str(data['posts'][rand]['title'])
            bot.send_photo(msg.chat.id, photo)
            print(CON['img'], filename)

            bot.send_message(msg.chat.id, out)
            print(CON['msg'], out)

            # Closes the photo and removes it from the system.
            photo.close()
            os.remove(filename)
            del data['posts'][rand]

            conf = open('./subreddits/' + name + '.json', 'w', encoding='utf8')
            json.dump(data, conf, ensure_ascii=False)
            conf.close()
            break
      except:
         print(CON['err'], "Error downloading image. Trying again.")
         del data['posts'][rand]
         if len(data['posts']) == 0:
            get_top_posts(sub)

# Regex function
def to_regex (words, beg='', end=''):
   regex = ''.join(['^(', beg, ')('])
   for word in words:
      regex += '('
      letters = list(word)
      for letter in letters:
         regex = ''.join([regex, '(', letter.upper(), '|', letter.lower(), ')'])
      regex += ')|'
   regex = regex[:-1]
   regex = ''.join([regex, ')(', end, ')$'])
   return regex

# Probability function, ie, 1:100, etc.
def prob (x, y):
   rand = random.randint(1, y)
   if rand <= x:
      return True
   else:
      return False

"""
Command definitions and listeners.
"""

# List off commands.
@bot.message_handler(commands=['help'])
def send_help (m):
   bot.send_message(m.chat.id,
      "First ship of the Kuma-class light cruisers, Kuma, kuma.\n"
      + "Born in Sasebo, kuma. I got some old parts, but I'll try my best, kuma.\n"
      + "\n"
      + "/add x y z - takes your numbers and adds them together.\n"
      + "/coin - flips a coin.\n"
      + "/meme - sends a meme.\n"
      + "/predict - sends a prediction.\n"
      + "/roll x - rolls a number between 1 and x. Also takes 4d6, etc.\n"
      + "/say - repeats what you say.\n"
      + "/ship - posts an image from the top posts of r/warshipporn.\n"
      + "/tank - posts an image from the top posts of r/tankporn.\n"
      + "\n"
      + "Just as a warning, there is a 1% chance that I will tweet whatever bullshit you just said, kuma. https://twitter.com/KumaKaiNi\n"
      + "\n"
      + "Source: https://github.com/rekyuu/telegram-kuma")

# Command to let you know she's alive.
@bot.message_handler(commands=['kuma'])
def send_welcome (m):
   out = "Kuma ~"
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# Repeats what the user just said.
@bot.message_handler(commands=['say'])
def send_say (m):
   try:
      out = m.text.split(' ', 1)[1]
   except:
      out = 'There is nothing to say, kuma.'
   finally:
      bot.send_message(m.chat.id, out)
      print(CON['msg'], out)

# Adds two numbers or makes jokes.
@bot.message_handler(commands=['add'])
def add_num (m):
   msg = m.text.split()
   del msg[0]

   try:
      add = 0
      for n in msg:
         add += int(n)

      if len(msg) == 2 and msg[0] == '1' and msg[1] == '1':
         out = "1 + 1 = 69 get it ?? lol ahahahahaha 69 = sexspoisition 1 = girl + boy ahaha"
      elif len(msg) == 0:
         out = "You didn't submit numbers!"
      else:
         out = "Your sum of numbers is: " + str(add)
   except:
      if m.from_user.username == "Liseda":
         out = "fuck off"
      else:
         out = "Invalid input, sorry!"
   finally:
      bot.send_message(m.chat.id, out)
      print(CON['msg'], out)

# Sends the user a boat!
@bot.message_handler(commands=['ship'])
def send_boat (m):
   send_sub_image (m, 'warshipporn')

# Sends the user a tank!
@bot.message_handler(commands=['tank'])
def send_tonk (m):
   send_sub_image (m, 'tankporn')

# Sends the user a meme!
@bot.message_handler(commands=['meme'])
def send_meme (m):
   send_sub_image (m, 'foodporn')

# Anti-Wayne command
@bot.message_handler(commands=['dank', 'kush', 'pot', 'merrywanna'])
def send_dank (m):
   name = m.from_user.username
   if name is None:
      name = m.from_user.first_name
   out = ''.join(['Shut the fuck up, @', name])
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# Sends the user a prediction.
PREDICTIONS = [
   'It is certain.',
   'It is decidedly so.',
   'Without a doubt.',
   'Yes, definitely.',
   'You may rely on it.',
   'As I see it, yes.',
   'Most likely.',
   'Outlook good.',
   'Yes.',
   'Signs point to yes.',
   'Reply hazy, try again.',
   'Ask again later.',
   'Better not tell you now.',
   'Cannot predict now.',
   'Concentrate and ask again.',
   'Don\'t count on it.',
   'My reply is no.',
   'My sources say no.',
   'Outlook not so good.',
   'Very doubtful.'
]
@bot.message_handler(commands=['predict'])
def send_prediction (m):
   if len(m.text.split()) == 1:
      out = "You didn't ask a question ya dingus"
   else:
      out = PREDICTIONS[random.randint(0, len(PREDICTIONS) - 1)]
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# Flips a coin.
@bot.message_handler(commands=['flip', 'coin'])
def send_coinflip (m):
   coin = random.randint(0,1)
   if coin == 0:
      out = "Heads."
   else:
      out = "Tails."
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# Rolls dice.
@bot.message_handler(commands=['roll'])
def send_diceroll (m):
   try:
      dice = m.text.split()[1]
      mult = dice.split('d')
      if len(m.text.split()) >= 3:
         out = "Please only send one input."
      elif len(mult) == 2:
         if int(mult[0]) <= 1 or int(mult[1]) <= 1:
            out = "Inputs must be 2 or more. Example: 4d6"
         else:
            out = "Rolled"
            for x in range (0, int(mult[0])):
               out = ' '.join([out, str(random.randint(1, int(mult[1]))) + ","])
            out = out[:-1] # Remove [,]
      else:
         if int(dice) <= 1:
            out = "Input must be 2 or more."
         else:
            out = "Rolled a " + str(random.randint(0,int(dice)))
   except:
      out = "Please send only numbers."
   finally:
      bot.send_message(m.chat.id, out)
      print(CON['msg'], out)

# Sends a link to /r/botsrights
@bot.message_handler(commands=['botsrights'])
def send_rights (m):
   out = "http://reddit.com/r/botsrights"
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# Prints available json to the console.
@bot.message_handler(commands=['json'])
def print_json (m):
   print(CON['log'], 'info:', m.__dict__)
   print(CON['log'], 'from_user:', m.from_user.__dict__)
   print(CON['log'], 'chat:', m.chat.__dict__)

# Prints available json to the console.
@bot.message_handler(commands=['test'])
def testing_function (m):
   send_sub_image (m, 'warshipporn')

"""
Regex listeners.
"""

# Returns a greeting if a user starts a sentence with the following regex.
GREETS = ['hi', 'hello', 'yo', 'sup']
GREET_REPLIES = ['sup loser', 'yo', 'ay', 'go away', 'hi', 'wassup']
@bot.message_handler(regexp=to_regex(GREETS,'','()|( ).*'))
def send_hello (m):
   out = GREET_REPLIES[random.randint(0, len(GREET_REPLIES) - 1)]
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# Replies to thank you's.
THANKS = ['thank you kuma', 'thanks kuma', 'ty kuma']
TY_REPLIES = ['np', 'don\'t mention it', 'anytime', 'sure thing', 'ye whateva']
@bot.message_handler(regexp=to_regex(THANKS))
def send_thanks (m):
   out = TY_REPLIES[random.randint(0, len(TY_REPLIES) - 1)]
   bot.send_message(m.chat.id, out)
   print(CON['msg'], out)

# 1% chance to tweet an incoming message, if none of the above were processed.
last_msg = ''
@bot.message_handler(regexp=".")
def all_other_messages (m):
   global last_msg

   # Logs incoming messages to a file
   word_log(m)

   # 1:20 chance of firing a markov chain message
   if prob(1,20) == True:
      file_ = open('./wordlogs/' + str(m.chat.id) + '.log', encoding='utf8')

      # Will file once the log reaches 100 lines or more
      if len(file_.read().splitlines()) >= 100:
         word_count, msg_total = 0
         for line in file_.read().splitlines():
            word_count += int(len(line.split()))
            msg_total += 1
         word_avg = word_count / msg_total

         markov = Markov(file_)
         out = markov.generate_markov_text(word_avg + random.randint(0,5))

         bot.send_message(m.chat.id, out)
         print(CON['msg'], out)
         t.statuses.update(status=out + ' *Kuma Kai Ni')
         print(CON['twt'], out + ' *Kuma Kai Ni')
      file_.close()

   # Really simple and lazy spam protection
   if last_msg != m.text:
      last_msg = m.text
      # 1:100 chance to tweet the last message recieved
      if prob(1,100) == True:
         name = m.from_user.username
         if name is None:
            name = m.from_user.first_name
         out = m.text + ' *' + name
         t.statuses.update(status=out)
         bot.send_message(m.chat.id, "lmao I'm live tweeting this shit")
         print(CON['twt'], out)
   else:
      last_msg = m.text

"""
Main command listener.
"""

bot.polling(none_stop=True)
print(CON['log'], 'Kuma! Shutsugeki suru, kuma!')
while True:
   time.sleep(100)<|endoftext|>


<commit_before>from datetime import datetime
import logging
import signal
import socket
import struct
from subprocess import run, check_output, CalledProcessError, TimeoutExpired
from threading import Thread
import time

from coapthon.server.coap import CoAP as CoAPServer
from coapthon.resources.resource import Resource
import msgpack
from persistent_queue import PersistentQueue

from sensors import sht21
from sensors.lcd import LCDWriter
from sensors.dylos import Dylos
from sensors.wireless import WirelessMonitor

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s:%(threadName)s:%(levelname)s:'
                           '%(name)s:%(message)s',
                    handlers=[
                        logging.handlers.TimedRotatingFileHandler(
                            'dylos.log', when='midnight', backupCount=7,
                            delay=True),
                        logging.StreamHandler()])
LOGGER = logging.getLogger(__name__)
RUNNING = True

# pylint: disable=abstract-method
class AirQualityResource(Resource):
    def __init__(self, queue, lcd):
        super().__init__("AirQualityResource")
        self.queue = queue
        self.lcd = lcd

        self.payload = None

    def render_GET(self, request):
        try:
            LOGGER.info("Received GET request with payload: %s",
                         repr(request.payload))
            ack, size = struct.unpack('!HH', request.payload)

            # Delete the amount of data that has been ACK'd
            LOGGER.info("Deleting %s items from the queue", ack)
            self.queue.delete(ack)
            self.queue.flush()

            LOGGER.debug("Updating LCD")
            self.lcd.queue_size = len(self.queue)
            self.lcd.update_queue_time = datetime.now()
            self.lcd.display_data()

            # Get data from queue
            size = min(size, len(self.queue))
            LOGGER.info("Getting %s items from the queue", size)
            data = self.queue.peek(size)

            # Make sure data is always a list
            if isinstance(data, list) and len(data) > 0 and \
               not isinstance(data[0], list):
                data = [data]

            LOGGER.debug("Sending data: %s", data)
            self.payload = msgpack.packb(data)

            return self
        except Exception:
            LOGGER.exception("An error occurred!")

# pylint: disable=abstract-method
class DummyResource(Resource):
    def __init__(self):
        super().__init__("DummyResource")

# Read data from the sensor
def read_data(dylos, temp_sensor, lcd, wifi, queue):
    sequence_number = 0

    # Update LCD on boot
    lcd.queue_size = len(queue)
    lcd.display_data()

    while RUNNING:
        try:
            LOGGER.info("Getting new data from sensors")
            LOGGER.debug("Reading from dylos sensor")
            air_data = dylos.read()
            LOGGER.debug("Reading from temperature sensor")
            temp_data = temp_sensor()
            LOGGER.debug("Reading from wifi sensor")
            wifi_data = wifi.stats()

            now = time.time()
            sequence_number += 1

            # Combine data together
            data = {"sampletime": now,
                    "sequence": sequence_number,
                    **air_data,
                    **temp_data,
                    **wifi_data}

            # Transform the data
            # ['connected', 'humidity', 'invalid_misc', 'large',
            #  'link_quality', 'noise_level', 'rx_invalid_crypt',
            #  'rx_invalid_frag', 'rx_invalid_nwid', 'sampletime', 'sequence',
            # 'signal_level', 'small', 'temperature', 'tx_retires']
            data = [[v for k, v in sorted(data.items())]]

            # Save data for later
            LOGGER.debug("Pushing %s into queue", data)
            queue.push(data)

            ip_address = wifi.ip_address()

            # Display results
            lcd.small = air_data['small']
            lcd.large = air_data['large']
            lcd.update_air_time = datetime.now()
            lcd.queue_size = len(queue)
            lcd.address = ip_address.split('.')[-1]
            lcd.display_data()

        except KeyboardInterrupt:
            break
        except Exception:
            # Keep going no matter of the exception
            # Hopefully it will fix itself
            LOGGER.exception("An exception occurred!")

            if RUNNING:
                LOGGER.debug("Waiting 15 seconds and then trying again")
                time.sleep(15)
                continue

def main():
    # Start LCD screen
    lcd = LCDWriter()

    for i in reversed(range(30)):
        lcd.display("Waiting ({})".format(i))
        time.sleep(1)

    try:
        lcd.display("Updating clock")
        run("ntpdate -b -s -u pool.ntp.org", shell=True, check=True, timeout=120)
        LOGGER.debug("Updated to current time")
    except (TimeoutExpired, CalledProcessError):
        LOGGER.warning("Unable to update time")

    lcd.display("Loading queue")
    LOGGER.info("Loading persistent queue")
    queue = PersistentQueue('dylos.queue',
                            dumps=msgpack.packb,
                            loads=msgpack.unpackb)

    LOGGER.info("Getting host name")
    hostname = socket.gethostname()
    LOGGER.info("Hostname: %s", hostname)

    LOGGER.info("Starting Dylos sensor")
    dylos = Dylos()

    LOGGER.info("Starting temperature sensor")
    temp_sensor = sht21.setup()

    LOGGER.info("Starting wireless monitor")
    wifi = WirelessMonitor()

    # Start reading from sensors
    sensor_thread = Thread(target=read_data,
                           args=(dylos, temp_sensor, lcd, wifi, queue))
    sensor_thread.start()

    # Start server
    LOGGER.info("Starting server")
    server = CoAPServer(("224.0.1.187", 5683), multicast=True)
    server.add_resource('air_quality/', AirQualityResource(queue, lcd))
    server.add_resource('name={}'.format(hostname), DummyResource())
    server.add_resource('type=dylos', DummyResource())

    def stop_running(sig_num, frame):
        global RUNNING

        LOGGER.debug("Shutting down sensors")
        RUNNING = False
        dylos.stop()

        LOGGER.debug("Shutting down server")
        server.close()

    signal.signal(signal.SIGTERM, stop_running)
    signal.signal(signal.SIGINT, stop_running)

    # Keep listening, even if there is an error
    while True:
        try:
            # Block until server.close() is called
            server.listen()
        except Exception as e:
            LOGGER.error("Exception occurred while listening: %s", e)
            if not RUNNING:
                LOGGER.debug("Stopping because running is false")
                break

    sensor_thread.join()
    LOGGER.debug("Quitting...")

if __name__ == '__main__':
    main()
<commit_msg>Update Dylos version<commit_after>from datetime import datetime
import logging
import signal
import socket
import struct
from subprocess import run, check_output, CalledProcessError, TimeoutExpired
from threading import Thread
import time

from coapthon.server.coap import CoAP as CoAPServer
from coapthon.resources.resource import Resource
import msgpack
from persistent_queue import PersistentQueue

from sensors import sht21
from sensors.lcd import LCDWriter
from sensors.dylos import Dylos
from sensors.wireless import WirelessMonitor

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s:%(threadName)s:%(levelname)s:'
                           '%(name)s:%(message)s',
                    handlers=[
                        logging.handlers.TimedRotatingFileHandler(
                            'dylos.log', when='midnight', backupCount=7,
                            delay=True),
                        logging.StreamHandler()])
LOGGER = logging.getLogger(__name__)
RUNNING = True

# pylint: disable=abstract-method
class AirQualityResource(Resource):
    def __init__(self, queue, lcd):
        super().__init__("AirQualityResource")
        self.queue = queue
        self.lcd = lcd

        self.payload = None

    def render_GET(self, request):
        try:
            LOGGER.info("Received GET request with payload: %s",
                         repr(request.payload))
            ack, size = struct.unpack('!HH', request.payload)

            # Delete the amount of data that has been ACK'd
            LOGGER.info("Deleting %s items from the queue", ack)
            self.queue.delete(ack)
            self.queue.flush()

            LOGGER.debug("Updating LCD")
            self.lcd.queue_size = len(self.queue)
            self.lcd.update_queue_time = datetime.now()
            self.lcd.display_data()

            # Get data from queue
            size = min(size, len(self.queue))
            LOGGER.info("Getting %s items from the queue", size)
            data = self.queue.peek(size)

            # Make sure data is always a list
            if isinstance(data, list) and len(data) > 0 and \
               not isinstance(data[0], list):
                data = [data]

            LOGGER.debug("Sending data: %s", data)
            self.payload = msgpack.packb(data)

            return self
        except Exception:
            LOGGER.exception("An error occurred!")

# pylint: disable=abstract-method
class DummyResource(Resource):
    def __init__(self):
        super().__init__("DummyResource")

# Read data from the sensor
def read_data(dylos, temp_sensor, lcd, wifi, queue):
    sequence_number = 0

    # Update LCD on boot
    lcd.queue_size = len(queue)
    lcd.display_data()

    while RUNNING:
        try:
            LOGGER.info("Getting new data from sensors")
            LOGGER.debug("Reading from dylos sensor")
            air_data = dylos.read()
            LOGGER.debug("Reading from temperature sensor")
            temp_data = temp_sensor()
            LOGGER.debug("Reading from wifi sensor")
            wifi_data = wifi.stats()

            now = time.time()
            sequence_number += 1

            # Combine data together
            data = {"sampletime": now,
                    "sequence": sequence_number,
                    **air_data,
                    **temp_data,
                    **wifi_data}

            # Transform the data
            # ['connected', 'humidity', 'invalid_misc', 'large',
            #  'link_quality', 'noise_level', 'rx_invalid_crypt',
            #  'rx_invalid_frag', 'rx_invalid_nwid', 'sampletime', 'sequence',
            # 'signal_level', 'small', 'temperature', 'tx_retires']
            data = [[v for k, v in sorted(data.items())]]

            # Save data for later
            LOGGER.debug("Pushing %s into queue", data)
            queue.push(data)

            ip_address = wifi.ip_address()

            # Display results
            lcd.small = air_data['small']
            lcd.large = air_data['large']
            lcd.update_air_time = datetime.now()
            lcd.queue_size = len(queue)
            lcd.address = ip_address.split('.')[-1]
            lcd.display_data()

        except KeyboardInterrupt:
            break
        except Exception:
            # Keep going no matter of the exception
            # Hopefully it will fix itself
            LOGGER.exception("An exception occurred!")

            if RUNNING:
                LOGGER.debug("Waiting 15 seconds and then trying again")
                time.sleep(15)
                continue

def main():
    # Start LCD screen
    lcd = LCDWriter()

    for i in reversed(range(30)):
        lcd.display("Waiting ({})".format(i))
        time.sleep(1)

    try:
        lcd.display("Updating clock")
        run("ntpdate -b -s -u pool.ntp.org", shell=True, check=True, timeout=120)
        LOGGER.debug("Updated to current time")
    except (TimeoutExpired, CalledProcessError):
        LOGGER.warning("Unable to update time")

    lcd.display("Loading queue")
    LOGGER.info("Loading persistent queue")
    queue = PersistentQueue('dylos.queue',
                            dumps=msgpack.packb,
                            loads=msgpack.unpackb)

    LOGGER.info("Getting host name")
    hostname = socket.gethostname()
    LOGGER.info("Hostname: %s", hostname)

    LOGGER.info("Starting Dylos sensor")
    dylos = Dylos()

    LOGGER.info("Starting temperature sensor")
    temp_sensor = sht21.setup()

    LOGGER.info("Starting wireless monitor")
    wifi = WirelessMonitor()

    # Start reading from sensors
    sensor_thread = Thread(target=read_data,
                           args=(dylos, temp_sensor, lcd, wifi, queue))
    sensor_thread.start()

    # Start server
    LOGGER.info("Starting server")
    server = CoAPServer(("224.0.1.187", 5683), multicast=True)
    server.add_resource('air_quality/', AirQualityResource(queue, lcd))
    server.add_resource('name={}'.format(hostname), DummyResource())
    server.add_resource('type=dylos-2', DummyResource())

    def stop_running(sig_num, frame):
        global RUNNING

        LOGGER.debug("Shutting down sensors")
        RUNNING = False
        dylos.stop()

        LOGGER.debug("Shutting down server")
        server.close()

    signal.signal(signal.SIGTERM, stop_running)
    signal.signal(signal.SIGINT, stop_running)

    # Keep listening, even if there is an error
    while True:
        try:
            # Block until server.close() is called
            server.listen()
        except Exception as e:
            LOGGER.error("Exception occurred while listening: %s", e)
            if not RUNNING:
                LOGGER.debug("Stopping because running is false")
                break

    sensor_thread.join()
    LOGGER.debug("Quitting...")

if __name__ == '__main__':
    main()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import random
import logging
import os
import time
import threading
import urllib2
import wave
import yaml

from flask import Flask, app, request, url_for
from twilio import twiml, TwilioRestException
from twilio.rest import TwilioRestClient
from google.cloud import speech

DIRECTORY_FILE = 'DC_EC_Members.yaml'
DISTRICTS_FILE = 'DC_Districts.yaml'

TWILIO_ACCOUNT_SID = os.environ['TWILIO_ACCOUNT_SID']
TWILIO_AUTH_TOKEN = os.environ['TWILIO_AUTH_TOKEN']

COUNTRY_PREFIX = os.environ.get('RC_COUNTRY_PREFIX', '+852')
DEBUG_DIAL_NUMBER = os.environ.get('RC_DEBUG_DIAL_NUMBER')

app = Flask(__name__)
random.seed()

name_dir = None
district_dir = None
district_alias_dir = None
speech_context = []

def _load_directory():
    global name_dir, district_dir, district_alias_dir
    with open(DIRECTORY_FILE, 'r') as f:
        name_dir = yaml.load(f)
        district_dir = dict()
        district_alias_dir = dict()
        for name, attr in name_dir.iteritems():
            speech_context.append(name)
            district = attr['district']
            if district in district_dir:
                district_dir[district].append(name)
            else:
                speech_context.append(district)
                district_dir[district] = [name]
        app.logger.error("evt=load_directory loaded=%d", len(name_dir))
    with open(DISTRICTS_FILE, 'r') as f:
        districts = yaml.load(f)
        for district, attr in districts.iteritems():
            for alt in attr['alt']:
                speech_context.append(alt)
                district_alias_dir[alt] = district

def _recognize(recording_url):
    content = None
    wav = None

    try:
        for i in range(4):
            try:
                content = urllib2.urlopen(recording_url)
            except HTTPError as e:
                app.logger.warn("even=fetch_recording_error sid=%s recording_url=%s err=%s", request.form['CallSid'], recording_url, e)
                time.sleep(0.5)

        wav = wave.open(content, 'r')
        encoding = 'LINEAR16'
        sample_rate = wav.getframerate()
        frames = wav.readframes(wav.getnframes())

        client = speech.Client()
        sample = client.sample(encoding=encoding, sample_rate=sample_rate, content=frames)
        results = sample.sync_recognize(max_alternatives=1, language_code='zh-HK', speech_context=speech_context)
        app.logger.info("even=recognize_success sid=%s recording_url=%s transcript=%s confidence=%s", request.form['CallSid'], recording_url, results[0].transcript, results[0].confidence)

        return results[0].transcript
    except Exception as e:
        app.logger.info("evt=recognize_fail sid=%s recording_url=%s err=%s", request.form['CallSid'], recording_url, e)
        raise
    finally:
        # Clean up
        t = threading.Thread(target=_delete_recording, args=(recording_url,))
        t.start()

        if content != None:
            content.close()
        if wav != None:
            wav.close()

def _delete_recording(recording_url):
    sid = recording_url[recording_url.rindex('/') + 1:]
    client = TwilioRestClient(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
    try:
        client.recordings.delete(sid)
        app.logger.info("evt=delete_recording_success sid=%s", sid)
    except TwilioRestException as e:
        app.logger.warn("evt=delete_recording_fail sid=%s", sid)

def _play(r, url):
    r.play(url)

def _say(r, message):
    r.say(message, voice='alice', language='zh-HK')

def _lookup_name(text):
    return filter(lambda key: key in text, name_dir)

def _lookup_district(text):
    return filter(lambda key: key in text, district_dir) +\
        [value for key, value in district_alias_dir.items() if key in text]

@app.route('/', methods=['POST', 'GET'])
def hello():
    r = twiml.Response()
    _say(r, u'你好！呢度係前線科技人員嘅，真 We Connect 熱線。請問喺十八區入面，你喺屬於邊一區？另外你亦可以講出區議員嘅名字')
    r.record(action=url_for('accept'), maxLength=6, playBeep=True, timeout=2)
    r.redirect(url_for('retry'))
    app.logger.info("evt=hello sid=%s from=%s", request.form['CallSid'], request.form['From'])

    return str(r), 200, {'Content-Type': 'text/xml'}

@app.route('/retry', methods=['POST', 'GET'])
def retry():
    r = twiml.Response()
    _say(r, u'請試多次，請讀出你嘅地區或者區議員名稱')
    r.record(action=url_for('accept'), maxLength=6, playBeep=True, timeout=2)
    r.hangup()

    app.logger.info("evt=retry sid=%s", request.form['CallSid'])

    return str(r), 200, {'Content-Type': 'text/xml'}

@app.route('/accept', methods=['POST', 'GET'])
def accept():
    recording_url = request.form['RecordingUrl']
    r = twiml.Response()
    _say(r, u'等等')
    r.redirect(url_for('recognize', RecordingUrl=recording_url))

    app.logger.info("evt=accept sid=%s", request.form['CallSid'])

    return str(r), 200, {'Content-Type': 'text/xml'}

@app.route('/recognize', methods=['POST', 'GET'])
def recognize():
    if 'RecordingUrl' in request.args:
        recording_url = request.args['RecordingUrl']
    else:
        recording_url = request.form['RecordingUrl']

    r = twiml.Response()
    try:
        text = _recognize(recording_url)
        name_matches = _lookup_name(text)
        district_matches = _lookup_district(text)
        name = None
        if u'老母' in text:
            _say(r, u'講還講唔好講粗口')
        if len(name_matches) > 0:
            name = name_matches[0]
            app.logger.info("evt=recognize_name sid=%s name=%s", request.form['CallSid'], name)
            _say(r, u'而家我會幫你打比')
        elif len(district_matches) > 0:
            district = district_matches[0]
            name = random.choice(district_dir[district])
            app.logger.info("evt=recognize_district sid=%s district=%s name=%s", request.form['CallSid'], district, name)
            _say(r, u'而家我會幫你打比')
            _say(r, district)
            _say(r, u'其中一位屬於特首選委既區議員')

        if name is not None:
            attr = name_dir[name]
            desc = attr.get('desc', name)
            tel = attr.get('tel')

            _say(r, desc)
            _say(r, u'咁你就可以盡情同佢 connect 番夠本啦，記住唔好收線啊！')

            if tel is not None and type(tel) is list and len(tel) > 0:
                if DEBUG_DIAL_NUMBER is None:
                    tel = tel[0]
                else:
                    tel = DEBUG_DIAL_NUMBER

                _say(r, u'佢既電話係：{}'.format(''.join([' ' + d for d in tel])))
                r.dial(COUNTRY_PREFIX + tel)
            else:
                _say(r, u'找不到電話號碼')

            r.hangup()
        else:
            _say(r, u'我搵唔到呢個名')
            r.redirect(url_for('retry'))
    except ValueError:
        _say(r, u'我聽唔到你講乜野')
        r.redirect(url_for('retry'))

    return str(r), 200, {'Content-Type': 'text/xml'}

@app.errorhandler(500)
def server_error(e):
    # Log the error and stacktrace.
    app.logger.exception('evt=error err=%s', e)
    r = twiml.Response()
    _say(r, u'唔好意思，系統發生咗啲故障，請遲啲再打過黎啦')
    r.hangup()
    return str(r), 200, {'Content-Type': 'text/xml'}

_load_directory()

if __name__ == '__main__':
    # This is used when running locally. Gunicorn is used to run the
    # application on Google App Engine. See entrypoint in app.yaml.
    app.run(host='127.0.0.1', port=8080, debug=True)<commit_msg>Improve logging of directory stat<commit_after># -*- coding: utf-8 -*-
import random
import logging
import os
import time
import threading
import urllib2
import wave
import yaml

from flask import Flask, app, request, url_for
from twilio import twiml, TwilioRestException
from twilio.rest import TwilioRestClient
from google.cloud import speech

DIRECTORY_FILE = 'DC_EC_Members.yaml'
DISTRICTS_FILE = 'DC_Districts.yaml'

TWILIO_ACCOUNT_SID = os.environ['TWILIO_ACCOUNT_SID']
TWILIO_AUTH_TOKEN = os.environ['TWILIO_AUTH_TOKEN']

COUNTRY_PREFIX = os.environ.get('RC_COUNTRY_PREFIX', '+852')
DEBUG_DIAL_NUMBER = os.environ.get('RC_DEBUG_DIAL_NUMBER')

app = Flask(__name__)
random.seed()

name_dir = None
district_dir = None
district_alias_dir = None
speech_context = []

def _load_directory():
    global name_dir, district_dir, district_alias_dir
    with open(DIRECTORY_FILE, 'r') as f:
        name_dir = yaml.load(f)
        district_dir = dict()
        district_alias_dir = dict()
        for name, attr in name_dir.iteritems():
            speech_context.append(name)
            district = attr['district']
            if district in district_dir:
                district_dir[district].append(name)
            else:
                speech_context.append(district)
                district_dir[district] = [name]
    with open(DISTRICTS_FILE, 'r') as f:
        districts = yaml.load(f)
        for district, attr in districts.iteritems():
            for alt in attr['alt']:
                speech_context.append(alt)
                district_alias_dir[alt] = district
    app.logger.error("evt=load_directory names=%d districts=%d district_aliases=%d", len(name_dir), len(district_dir), len(district_alias_dir))

def _recognize(recording_url):
    content = None
    wav = None

    try:
        for i in range(4):
            try:
                content = urllib2.urlopen(recording_url)
            except HTTPError as e:
                app.logger.warn("even=fetch_recording_error sid=%s recording_url=%s err=%s", request.form['CallSid'], recording_url, e)
                time.sleep(0.5)

        wav = wave.open(content, 'r')
        encoding = 'LINEAR16'
        sample_rate = wav.getframerate()
        frames = wav.readframes(wav.getnframes())

        client = speech.Client()
        sample = client.sample(encoding=encoding, sample_rate=sample_rate, content=frames)
        results = sample.sync_recognize(max_alternatives=1, language_code='zh-HK', speech_context=speech_context)
        app.logger.info("even=recognize_success sid=%s recording_url=%s transcript=%s confidence=%s", request.form['CallSid'], recording_url, results[0].transcript, results[0].confidence)

        return results[0].transcript
    except Exception as e:
        app.logger.info("evt=recognize_fail sid=%s recording_url=%s err=%s", request.form['CallSid'], recording_url, e)
        raise
    finally:
        # Clean up
        t = threading.Thread(target=_delete_recording, args=(recording_url,))
        t.start()

        if content != None:
            content.close()
        if wav != None:
            wav.close()

def _delete_recording(recording_url):
    sid = recording_url[recording_url.rindex('/') + 1:]
    client = TwilioRestClient(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
    try:
        client.recordings.delete(sid)
        app.logger.info("evt=delete_recording_success sid=%s", sid)
    except TwilioRestException as e:
        app.logger.warn("evt=delete_recording_fail sid=%s", sid)

def _play(r, url):
    r.play(url)

def _say(r, message):
    r.say(message, voice='alice', language='zh-HK')

def _lookup_name(text):
    return filter(lambda key: key in text, name_dir)

def _lookup_district(text):
    return filter(lambda key: key in text, district_dir) +\
        [value for key, value in district_alias_dir.items() if key in text]

@app.route('/', methods=['POST', 'GET'])
def hello():
    r = twiml.Response()
    _say(r, u'你好！呢度係前線科技人員嘅，真 We Connect 熱線。請問喺十八區入面，你喺屬於邊一區？另外你亦可以講出區議員嘅名字')
    r.record(action=url_for('accept'), maxLength=6, playBeep=True, timeout=2)
    r.redirect(url_for('retry'))
    app.logger.info("evt=hello sid=%s from=%s", request.form['CallSid'], request.form['From'])

    return str(r), 200, {'Content-Type': 'text/xml'}

@app.route('/retry', methods=['POST', 'GET'])
def retry():
    r = twiml.Response()
    _say(r, u'請試多次，請讀出你嘅地區或者區議員名稱')
    r.record(action=url_for('accept'), maxLength=6, playBeep=True, timeout=2)
    r.hangup()

    app.logger.info("evt=retry sid=%s", request.form['CallSid'])

    return str(r), 200, {'Content-Type': 'text/xml'}

@app.route('/accept', methods=['POST', 'GET'])
def accept():
    recording_url = request.form['RecordingUrl']
    r = twiml.Response()
    _say(r, u'等等')
    r.redirect(url_for('recognize', RecordingUrl=recording_url))

    app.logger.info("evt=accept sid=%s", request.form['CallSid'])

    return str(r), 200, {'Content-Type': 'text/xml'}

@app.route('/recognize', methods=['POST', 'GET'])
def recognize():
    if 'RecordingUrl' in request.args:
        recording_url = request.args['RecordingUrl']
    else:
        recording_url = request.form['RecordingUrl']

    r = twiml.Response()
    try:
        text = _recognize(recording_url)
        name_matches = _lookup_name(text)
        district_matches = _lookup_district(text)
        name = None
        if u'老母' in text:
            _say(r, u'講還講唔好講粗口')
        if len(name_matches) > 0:
            name = name_matches[0]
            app.logger.info("evt=recognize_name sid=%s name=%s", request.form['CallSid'], name)
            _say(r, u'而家我會幫你打比')
        elif len(district_matches) > 0:
            district = district_matches[0]
            name = random.choice(district_dir[district])
            app.logger.info("evt=recognize_district sid=%s district=%s name=%s", request.form['CallSid'], district, name)
            _say(r, u'而家我會幫你打比')
            _say(r, district)
            _say(r, u'其中一位屬於特首選委既區議員')

        if name is not None:
            attr = name_dir[name]
            desc = attr.get('desc', name)
            tel = attr.get('tel')

            _say(r, desc)
            _say(r, u'咁你就可以盡情同佢 connect 番夠本啦，記住唔好收線啊！')

            if tel is not None and type(tel) is list and len(tel) > 0:
                if DEBUG_DIAL_NUMBER is None:
                    tel = tel[0]
                else:
                    tel = DEBUG_DIAL_NUMBER

                _say(r, u'佢既電話係：{}'.format(''.join([' ' + d for d in tel])))
                r.dial(COUNTRY_PREFIX + tel)
            else:
                _say(r, u'找不到電話號碼')

            r.hangup()
        else:
            _say(r, u'我搵唔到呢個名')
            r.redirect(url_for('retry'))
    except ValueError:
        _say(r, u'我聽唔到你講乜野')
        r.redirect(url_for('retry'))

    return str(r), 200, {'Content-Type': 'text/xml'}

@app.errorhandler(500)
def server_error(e):
    # Log the error and stacktrace.
    app.logger.exception('evt=error err=%s', e)
    r = twiml.Response()
    _say(r, u'唔好意思，系統發生咗啲故障，請遲啲再打過黎啦')
    r.hangup()
    return str(r), 200, {'Content-Type': 'text/xml'}

_load_directory()

if __name__ == '__main__':
    # This is used when running locally. Gunicorn is used to run the
    # application on Google App Engine. See entrypoint in app.yaml.
    app.run(host='127.0.0.1', port=8080, debug=True)<|endoftext|>


<commit_before>import sys, re, json

try:
	deck_file = open(sys.argv[1], 'r')
except IndexError:
	print "No file passed"
	sys.exit(0)

jsonData = open("./res/AllCards.json")
cardData = json.load(jsonData)

costArray = [0 for i in range(8)]

lines = deck_file.readlines()
for cards in lines:
	info = re.split('(\d+)', cards.strip())
	num = int(info[1])
	name = info[2]
	if name[0] == ' ':
		name = name[1:]
	try:
		card_cost = int(cardData[name]["cmc"])
		if card_cost > 7:
			card_cost = 7
		costArray[card_cost] += num
	except KeyError:
		#contnues if the card has no cost
		if not cardData[name]["type"].startswith("Basic Land"):
			costArray[0] += num
		continue
for i in range(0, len(costArray)):
	if i == 7:
		print str(i) + "+: " + str(costArray[i])
	else:
		print str(i) + ": " + str(costArray[i])
<commit_msg>added sample hand output<commit_after>import sys, re, json, random

try:
	deck_file = open(sys.argv[1], 'r')
except IndexError:
	print "No file passed"
	sys.exit(0)

jsonData = open("./res/AllCards.json")
cardData = json.load(jsonData)

costArray = [0 for i in range(8)]
totalCards = 0
cardList = []

lines = deck_file.readlines()
for cards in lines:
	info = re.split('(\d+)', cards.strip())
	num = int(info[1])
	totalCards += num
	name = info[2]

	if name[0] == ' ':
		name = name[1:]
	try:
		card_cost = int(cardData[name]["cmc"])
		if card_cost > 7:
			card_cost = 7
		costArray[card_cost] += num
	except KeyError:
		#contnues if the card has no cost
		if not cardData[name]["type"].startswith("Basic Land"):
			costArray[0] += num
	for i in range(0, num):
		cardList.append(name)
for i in range(0, len(costArray)):
	if i == 7:
		print str(i) + "+: " + str(costArray[i])
	else:
		print str(i) + ": " + str(costArray[i])

print "Sample hand:"
for i in range(0, 6):
	print cardList[random.randint(0, totalCards-1)]
<|endoftext|>


<commit_before>from flask import Flask, request, Response
from feedgen.feed import FeedGenerator
import requests
import json
import re

app = Flask(__name__)

def osf_url(urls, service):
    r = re.compile('preprints/{0}/'.format(service.lower()), re.IGNORECASE)
    for url in urls:
        if 'osf' in url:
            return r.sub('', url)
    return ''

def build_feed(url, service):
    fg = FeedGenerator()
    fg.id('http://osf.io/preprints/{0}'.format(service.lower()))
    fg.title('{0} Preprints'.format(service))
    fg.author({'name': service})
    fg.link(href=url, rel='self')
    fg.link(href='https://osf.io/preprints/{0}'.format(service.lower()), rel='alternate')
    fg.subtitle('Preprints submitted to {0} at https://osf.io/preprints/{1}'.format(service, service.lower()))

    headers = {'Content-Type': 'application/json'}

    response = requests.post(
        'https://share.osf.io/api/v2/search/creativeworks/_search',
        headers=headers,

        data=json.dumps({
            "query": {
                "bool": {
                    "must": {
                        "query_string": {
                            "query": "*"
                        }
                    },
                    "filter": [{
                        "term": {
                            "sources": service
                        }
                    }]
                }
            },
            "from": 0,
            "size": 50,
            "sort": {
                "date_updated": "desc"
            }
        })
    )

    for entry in response.json()['hits']['hits']:
        fe = fg.add_entry()
        fe.title(entry['_source']['title'])
        fe.description(entry['_source']['description'])
        urls = entry['_source']['identifiers']
        link_url = osf_url(urls, service)
        fe.link(href=link_url)
        fe.id(link_url)

    return fg

@app.route("/")
def index():
    return "Feeds"

@app.route("/<service>.rss")
def socarxiv_rss(service=None):
    if service=='socarxiv':
        service = 'SocArXiv'
    fg = build_feed(request.url, service)
    response = Response(fg.rss_str(pretty=True))
    response.headers['Content-Type'] = 'application/rss+xml'
    return response

if __name__ == "__main__":
    app.run()<commit_msg>Generalize the normalization of service names<commit_after>from flask import Flask, request, Response
from feedgen.feed import FeedGenerator
import requests
import json
import re

app = Flask(__name__)

services = {
    'socarxiv': 'SocArXiv',
    'engrxiv': 'engrXiv'
}

def osf_url(urls, service):
    r = re.compile('preprints/{0}/'.format(service.lower()), re.IGNORECASE)
    for url in urls:
        if 'osf' in url:
            return r.sub('', url)
    return ''

def build_feed(url, service):
    fg = FeedGenerator()
    fg.id('http://osf.io/preprints/{0}'.format(service.lower()))
    fg.title('{0} Preprints'.format(service))
    fg.author({'name': service})
    fg.link(href=url, rel='self')
    fg.link(href='https://osf.io/preprints/{0}'.format(service.lower()), rel='alternate')
    fg.subtitle('Preprints submitted to {0} at https://osf.io/preprints/{1}'.format(service, service.lower()))

    headers = {'Content-Type': 'application/json'}

    response = requests.post(
        'https://share.osf.io/api/v2/search/creativeworks/_search',
        headers=headers,

        data=json.dumps({
            "query": {
                "bool": {
                    "must": {
                        "query_string": {
                            "query": "*"
                        }
                    },
                    "filter": [{
                        "term": {
                            "sources": service
                        }
                    }]
                }
            },
            "from": 0,
            "size": 50,
            "sort": {
                "date_updated": "desc"
            }
        })
    )

    for entry in response.json()['hits']['hits']:
        fe = fg.add_entry()
        fe.title(entry['_source']['title'])
        fe.description(entry['_source']['description'])
        urls = entry['_source']['identifiers']
        link_url = osf_url(urls, service)
        fe.link(href=link_url)
        fe.id(link_url)

    return fg

@app.route("/")
def index():
    return "Feeds"

@app.route("/<service>.rss")
def rss(service=None):
    lowercase_service = service.lower()
    if lowercase_service in services:
        service = services[lowercase_service]

    fg = build_feed(request.url, service)
    response = Response(fg.rss_str(pretty=True))
    response.headers['Content-Type'] = 'application/rss+xml'
    return response

if __name__ == "__main__":
    app.run()<|endoftext|>


<commit_before>import sys
#import Tkinter as tk
from Tkinter import *

UNIQUE_TEAMS = 6

# Globals for graph data
winHeight = 0
winWidth = 0
################
# Graph object #
################
class Graph:
# Initialize the graph instance
    def __init__(self):
        self.baseX = 0
        self.baseY = 0
        self.height = winHeight
        self.width = winWidth

        self.graphNumber = 0
        self.xTicks = 6 # Matches
        self.yTicks = 5 # Scores
    def __init__(self, graphCount=1, matchCount=6, initalGraph=0):
        if (graphCount > 4 or graphCount < 1):
            print "Fatal error, bad graph count"
            sys.exit(10)

        if graphCount/2 == 0:
            self.height = winHeight
            self.baseY = 0
        else:
            self.height = winHeight/2
            self.baseY = winHeight/2

        if graphCount%2 == 1:
            self.width = winWidth
            self.baseX = 0
        else:
            self.width = winWidth/2
            self.baseX = winWidth/2
        self.graphNumber = initalGraph # Which graph to display
        self.xTicks = matchCount # Matches
        self.yTicks = masterGraphData[initialGraph]['tickCount'] # Scores
        self.graphID = graphID # Used to tell the graph where it appears on the screen
# Draw the graph to the screen

    def draw(self,canvas):
        # Draw a bounding box around the entire graph instance
        canvas.create_rectangle(self.baseX, self.baseY, self.baseX+self.width, self.baseY+self.height)

#########################################
# State of graphs for saving/workspaces #
#########################################
class State:
    def __init__(self):
        self.graphCount = 1
        self.teams = [0]*UNIQUE_TEAMS
        self.graphs = [0]*self.graphCount
    def getGraphCount(self):
        return self.graphCount
    def getTeams(self):
        return self.teams
    def getGraphs(self):
        return self.graphs
    def addGraph(self):
        if (self.graphCount < 4):
            self.graphCount += 1
            self.graphs.append(0)
    def removeGraph(self, index=-1):
        if (index == -1):
            index = self.graphCount - 1
        if (index >= 0 and index < 4):
            print "Popping"
            self.graphCount -= 1
            self.graphs.pop(index)

######################
# Configuration file #
######################
def loadConfigFile():
    try:
        configFile = open("config.txt",'r')
        readed = configFile.read().split("\n")[:-1]
        configFile.close()

        matchCount = eval(readed[0])
        readed = readed[1:]
        # Load all of the graph data
        for i in range(len(readed)):
            tempSplit = readed[i].split("\t")

            tempD = {}
            tempD['id']            = int(tempSplit[0]) # Numerical id of graph, used in Graph as graphNumber
            tempD['name']          =     tempSplit[1]  # Name of graph, displayed in dropdown
            tempD['tickCount']     = int(tempSplit[2]) # Count of ticks on the y-axis
            tempD['solidCol']      = int(tempSplit[3]) # Column in the CSV file of the line that will be solid
            tempD['dashCol']       = int(tempSplit[4]) # Column in the CSV file of the line that will be dashed

            masterGraphData.append(tempD)

    except:
        print "Error: Invalid config file"
        sys.exit(1)

######################
# Load the team data #
######################
def loadMatchData():
    try:
        matchFile = open("matches.csv",'r')
        readed = matchFile.read().split("\n")[1:-1]
        print "len: ",len(readed)
        matchFile.close()

        # Sort the data from the teams by team/match number for easier graphing
        tempR = readed.split(",")
        while len(tempR) != 0:
            minIndex = 0
            minTeam = 0
            minMatch = -100
            for i in range(len(tempR)):
                tS = tempR[i].split(",")
                # Check if the team number is the smallest thus far
                if tS[0] < minTeam:
                    minIndex = i
                    minTeam = tS[0]
                    minMatch = tS[1]
                elif tS[0] == minTeam and tS[1] < minMatch:
                    minIndex = i
                    minMatch = tS[1]
            matchData.append(tempR.pop(minIndex))
    except:
        print "Error: Invalid match file"
        sys.exit(2)

def drawGraph(canvas, state):
    # Draw the bounding boxes
    canvas.create_rectangle(0, 0, largeGraphDimensions[0], largeGraphDimensions[1], fill='black', outline='white')
    if state.graphCount > 1:
        canvas.create_rectangle(0, 0, smallGraphDimensions[0], largeGraphDimensions[1], outline='white')
    if state.graphCount > 2:
        canvas.create_rectangle(0, smallGraphDimensions[1], largeGraphDimensions[0], largeGraphDimensions[1], outline='white')

    # Draw each of the graphs
    if state.graphCount == 1:
        currentGraph = state.graphs[0]

        canvas.create_line(125,75,125,windowDimensions[1]-100, fill='white')
        canvas.create_line(125,windowDimensions[1]-100,largeGraphDimensions[0]-100,windowDimensions[1]-100, fill='white')
        # Horizontal ticks
        h_dist = (largeGraphDimensions[0]-225)/matchCount
        for i in range(matchCount):
            canvas.create_line(125+h_dist*(i+1),largeGraphDimensions[1]-100,125+h_dist*(i+1),largeGraphDimensions[1]-90, fill='white')
        # Vertical ticks
        v_dist = (largeGraphDimensions[1]-175)/(masterGraphData[currentGraph]['tickCount']-1)
        for i in range(masterGraphData[currentGraph]['tickCount']):
            canvas.create_line(115,75+v_dist*i,125,75+v_dist*i, fill='white')

        # TODO Add the lines for the different teams
    elif state.graphCount == 2:
        for j in range(state.graphCount):
            currentGraph = state.graphs[j]

            canvas.create_line(j*smallGraphDimensions[0]+50,75,j*smallGraphDimensions[0]+50,windowDimensions[1]-100, fill='white')
            canvas.create_line(j*smallGraphDimensions[0]+50,windowDimensions[1]-100,(j+1)*smallGraphDimensions[0]-50,windowDimensions[1]-100, fill='white')
            # Horizontal ticks
            h_dist = (smallGraphDimensions[0]-100)/matchCount
            for i in range(matchCount):
                canvas.create_line(j*smallGraphDimensions[0]+50+h_dist*(i+1),windowDimensions[1]-100,j*smallGraphDimensions[0]+50+h_dist*(i+1),windowDimensions[1]-90, fill='white')
            # Vertical ticks
            v_dist = (largeGraphDimensions[1]-175)/(masterGraphData[currentGraph]['tickCount']-1)
            print largeGraphDimensions[1]-175
            for i in range(masterGraphData[currentGraph]['tickCount']):
                canvas.create_line(j*smallGraphDimensions[0]+40,v_dist*i+75,j*smallGraphDimensions[0]+50,v_dist*i+75, fill='white')
    else:
        for j in range(2):
            for k in range(2):
                currentGraph = state.graphs[j+k*2]

                canvas.create_line(j*smallGraphDimensions[0]+50,k*smallGraphDimensions[1]+50,j*smallGraphDimensions[0]+50,(k+1)*smallGraphDimensions[1]-75, fill='white')
                canvas.create_line(j*smallGraphDimensions[0]+50,(k+1)*smallGraphDimensions[1]-75,(j+1)*smallGraphDimensions[0]-50,(k+1)*smallGraphDimensions[1]-75, fill='white')

    # Testing solid vs dashed
    canvas.create_line(100,200,150,200, fill='red',     dash=(4,4), width=4)
    canvas.create_line(100,210,150,210, fill='red',                 width=4)
    canvas.create_line(100,250,150,250, fill='green',   dash=(4,4), width=4)
    canvas.create_line(100,260,150,260, fill='green',               width=4)
    canvas.create_line(100,300,150,300, fill='blue',    dash=(4,4), width=4)
    canvas.create_line(100,310,150,310, fill='blue',                width=4)
    canvas.create_line(100,350,150,350, fill='yellow',  dash=(4,4), width=4)
    canvas.create_line(100,360,150,360, fill='yellow',              width=4)
    canvas.create_line(100,400,150,400, fill='orange',  dash=(4,4), width=4)
    canvas.create_line(100,410,150,410, fill='orange',              width=4)
    canvas.create_line(100,450,150,450, fill='magenta', dash=(4,4), width=4)
    canvas.create_line(100,460,150,460, fill='magenta',             width=4)

def drawComments(canvas, section):
    pass

def key(event):
    if event.char == event.keysym:
        print 'Normal key %s' % event.char
    if event.char == 'w':
        print "Increasing..."
        states[currentState].addGraph()
        drawGraph(canvas,states[currentState])
    elif event.char =='s':
        print "Decreasing..."
        states[currentState].removeGraph()
        drawGraph(canvas,states[currentState])

matchData = []
masterGraphData = []
matchCount = 6
states = [State()]*9
currentState = 0

windowDimensions = (1024,576)
commentsDimensions = (224,windowDimensions[1]/6)
largeGraphDimensions = (800,windowDimensions[1])
smallGraphDimensions = (400,windowDimensions[1]/2)
root = Tk()
root.geometry("%dx%d" % windowDimensions)
root.title("Hazy Scout")
canvas = Canvas(root, width=windowDimensions[0], height=windowDimensions[1])
canvas.pack()

loadConfigFile()

states[currentState].addGraph()
states[currentState].graphs[1]=1
states[currentState].addGraph()
states[currentState].addGraph()
drawGraph(canvas,states[currentState])

#text = Text(root)
#text.insert(INSERT,"Testing things! Lots and lots of letters....a eu8fagoc u7a,f.g u78aeod uba7fcgu dthjomqeufgcdhtao emugcaoht epm.,tha pmacoth umeoauthym.,9ugth nmeu.pugchte nom.,89geh otmugoh tem.pguoeh utrmcue8arc meuoigreh tmuearogeh emuorch utcmuorc tcm.rcoe m")
#text.pack()

root.bind_all('<Key>',key)
root.mainloop()

sys.exit(0)

var = tk.StringVar(root)
var.set('red')

choices = ['red', 'green', 'blue', 'yellow', 'white', 'magenta']
option = tk.OptionMenu(root, var, *choices)
option.pack(side='left', padx=10, pady=10)

button = tk.Button(root, text='check value selected', command=select)
button.pack(side='left', padx=20, pady=10)

root.mainloop()
<commit_msg>Finished adding tics<commit_after>import sys
#import Tkinter as tk
from Tkinter import *

UNIQUE_TEAMS = 6

# Globals for graph data
winHeight = 0
winWidth = 0
################
# Graph object #
################
class Graph:
# Initialize the graph instance
    def __init__(self):
        self.baseX = 0
        self.baseY = 0
        self.height = winHeight
        self.width = winWidth

        self.graphNumber = 0
        self.xTicks = 6 # Matches
        self.yTicks = 5 # Scores
    def __init__(self, graphCount=1, matchCount=6, initalGraph=0):
        if (graphCount > 4 or graphCount < 1):
            print "Fatal error, bad graph count"
            sys.exit(10)

        if graphCount/2 == 0:
            self.height = winHeight
            self.baseY = 0
        else:
            self.height = winHeight/2
            self.baseY = winHeight/2

        if graphCount%2 == 1:
            self.width = winWidth
            self.baseX = 0
        else:
            self.width = winWidth/2
            self.baseX = winWidth/2
        self.graphNumber = initalGraph # Which graph to display
        self.xTicks = matchCount # Matches
        self.yTicks = masterGraphData[initialGraph]['tickCount'] # Scores
        self.graphID = graphID # Used to tell the graph where it appears on the screen
# Draw the graph to the screen

    def draw(self,canvas):
        # Draw a bounding box around the entire graph instance
        canvas.create_rectangle(self.baseX, self.baseY, self.baseX+self.width, self.baseY+self.height)

#########################################
# State of graphs for saving/workspaces #
#########################################
class State:
    def __init__(self):
        self.graphCount = 1
        self.teams = [0]*UNIQUE_TEAMS
        self.graphs = [0]*self.graphCount
    def getGraphCount(self):
        return self.graphCount
    def getTeams(self):
        return self.teams
    def getGraphs(self):
        return self.graphs
    def addGraph(self):
        if (self.graphCount < 4):
            self.graphCount += 1
            self.graphs.append(0)
    def removeGraph(self, index=-1):
        if (index == -1):
            index = self.graphCount - 1
        if (index > 0 and index < 4):
            print "Popping"
            self.graphCount -= 1
            self.graphs.pop(index)

######################
# Configuration file #
######################
def loadConfigFile():
    try:
        configFile = open("config.txt",'r')
        readed = configFile.read().split("\n")[:-1]
        configFile.close()

        matchCount = eval(readed[0])
        readed = readed[1:]
        # Load all of the graph data
        for i in range(len(readed)):
            tempSplit = readed[i].split("\t")

            tempD = {}
            tempD['id']            = int(tempSplit[0]) # Numerical id of graph, used in Graph as graphNumber
            tempD['name']          =     tempSplit[1]  # Name of graph, displayed in dropdown
            tempD['tickCount']     = int(tempSplit[2]) # Count of ticks on the y-axis
            tempD['solidCol']      = int(tempSplit[3]) # Column in the CSV file of the line that will be solid
            tempD['dashCol']       = int(tempSplit[4]) # Column in the CSV file of the line that will be dashed

            masterGraphData.append(tempD)

    except:
        print "Error: Invalid config file"
        sys.exit(1)

######################
# Load the team data #
######################
def loadMatchData():
    try:
        matchFile = open("matches.csv",'r')
        readed = matchFile.read().split("\n")[1:-1]
        print "len: ",len(readed)
        matchFile.close()

        # Sort the data from the teams by team/match number for easier graphing
        tempR = readed.split(",")
        while len(tempR) != 0:
            minIndex = 0
            minTeam = 0
            minMatch = -100
            for i in range(len(tempR)):
                tS = tempR[i].split(",")
                # Check if the team number is the smallest thus far
                if tS[0] < minTeam:
                    minIndex = i
                    minTeam = tS[0]
                    minMatch = tS[1]
                elif tS[0] == minTeam and tS[1] < minMatch:
                    minIndex = i
                    minMatch = tS[1]
            matchData.append(tempR.pop(minIndex))
    except:
        print "Error: Invalid match file"
        sys.exit(2)

def drawGraph(canvas, state):
    # Draw the bounding boxes
    canvas.create_rectangle(0, 0, largeGraphDimensions[0], largeGraphDimensions[1], fill='black', outline='white')
    if state.graphCount > 1:
        canvas.create_rectangle(0, 0, smallGraphDimensions[0], largeGraphDimensions[1], outline='white')
    if state.graphCount > 2:
        canvas.create_rectangle(0, smallGraphDimensions[1], largeGraphDimensions[0], largeGraphDimensions[1], outline='white')

    # Draw each of the graphs
    if state.graphCount == 1:
        currentGraph = state.graphs[0]

        canvas.create_line(125,75,125,windowDimensions[1]-100, fill='white')
        canvas.create_line(125,windowDimensions[1]-100,largeGraphDimensions[0]-100,windowDimensions[1]-100, fill='white')
        # Horizontal ticks
        h_dist = (largeGraphDimensions[0]-225)/matchCount
        for i in range(matchCount):
            canvas.create_line(125+h_dist*(i+1),largeGraphDimensions[1]-100,125+h_dist*(i+1),largeGraphDimensions[1]-90, fill='white')
        # Vertical ticks
        v_dist = (largeGraphDimensions[1]-175)/(masterGraphData[currentGraph]['tickCount']-1)
        for i in range(masterGraphData[currentGraph]['tickCount']):
            canvas.create_line(115,75+v_dist*i,125,75+v_dist*i, fill='white')

        # TODO Add the lines for the different teams
    elif state.graphCount == 2:
        for j in range(state.graphCount):
            currentGraph = state.graphs[j]

            canvas.create_line(j*smallGraphDimensions[0]+50,75,j*smallGraphDimensions[0]+50,windowDimensions[1]-100, fill='white')
            canvas.create_line(j*smallGraphDimensions[0]+50,windowDimensions[1]-100,(j+1)*smallGraphDimensions[0]-50,windowDimensions[1]-100, fill='white')
            # Horizontal ticks
            h_dist = (smallGraphDimensions[0]-100)/matchCount
            for i in range(matchCount):
                canvas.create_line(j*smallGraphDimensions[0]+50+h_dist*(i+1),windowDimensions[1]-100,j*smallGraphDimensions[0]+50+h_dist*(i+1),windowDimensions[1]-90, fill='white')
            # Vertical ticks
            v_dist = (largeGraphDimensions[1]-175)/(masterGraphData[currentGraph]['tickCount']-1)
            print largeGraphDimensions[1]-175
            for i in range(masterGraphData[currentGraph]['tickCount']):
                canvas.create_line(j*smallGraphDimensions[0]+40,v_dist*i+75,j*smallGraphDimensions[0]+50,v_dist*i+75, fill='white')
    else:
        for j in range(2):
            for k in range(2):
                currentGraph = state.graphs[j+k*2]

                canvas.create_line(j*smallGraphDimensions[0]+50,k*smallGraphDimensions[1]+50,j*smallGraphDimensions[0]+50,(k+1)*smallGraphDimensions[1]-75, fill='white')
                canvas.create_line(j*smallGraphDimensions[0]+50,(k+1)*smallGraphDimensions[1]-75,(j+1)*smallGraphDimensions[0]-50,(k+1)*smallGraphDimensions[1]-75, fill='white')
                # Horizontal ticks
                h_dist = (smallGraphDimensions[0]-100)/matchCount
                for i in range(matchCount):
                    canvas.create_line(j*smallGraphDimensions[0]+50+h_dist*(i+1),(k+1)*smallGraphDimensions[1]-65,j*smallGraphDimensions[0]+50+h_dist*(i+1),(k+1)*smallGraphDimensions[1]-75, fill='white')
                # Vertical ticks
                v_dist = (smallGraphDimensions[1]-125)/(masterGraphData[currentGraph]['tickCount']-1)
                for i in range(masterGraphData[currentGraph]['tickCount']):
                    canvas.create_line(j*smallGraphDimensions[0]+50,k*smallGraphDimensions[1]+v_dist*i+50,j*smallGraphDimensions[0]+40,k*smallGraphDimensions[1]+v_dist*i+50, fill='white')

    # Testing solid vs dashed
    canvas.create_line(100,200,150,200, fill='red',     dash=(4,4), width=4)
    canvas.create_line(100,210,150,210, fill='red',                 width=4)
    canvas.create_line(100,250,150,250, fill='green',   dash=(4,4), width=4)
    canvas.create_line(100,260,150,260, fill='green',               width=4)
    canvas.create_line(100,300,150,300, fill='blue',    dash=(4,4), width=4)
    canvas.create_line(100,310,150,310, fill='blue',                width=4)
    canvas.create_line(100,350,150,350, fill='yellow',  dash=(4,4), width=4)
    canvas.create_line(100,360,150,360, fill='yellow',              width=4)
    canvas.create_line(100,400,150,400, fill='orange',  dash=(4,4), width=4)
    canvas.create_line(100,410,150,410, fill='orange',              width=4)
    canvas.create_line(100,450,150,450, fill='magenta', dash=(4,4), width=4)
    canvas.create_line(100,460,150,460, fill='magenta',             width=4)

def drawComments(canvas, section):
    pass

def key(event):
    if event.char == event.keysym:
        print 'Normal key %s' % event.char
    if event.char == 'w':
        print "Increasing..."
        states[currentState].addGraph()
        drawGraph(canvas,states[currentState])
    elif event.char =='s':
        print "Decreasing..."
        states[currentState].removeGraph()
        drawGraph(canvas,states[currentState])

matchData = []
masterGraphData = []
matchCount = 6
states = [State()]*9
currentState = 0

windowDimensions = (1024,576)
commentsDimensions = (224,windowDimensions[1]/6)
largeGraphDimensions = (800,windowDimensions[1])
smallGraphDimensions = (400,windowDimensions[1]/2)
root = Tk()
root.geometry("%dx%d" % windowDimensions)
root.title("Hazy Scout")
canvas = Canvas(root, width=windowDimensions[0], height=windowDimensions[1])
canvas.pack()

loadConfigFile()

states[currentState].addGraph()
states[currentState].graphs[1]=1
states[currentState].addGraph()
states[currentState].addGraph()
drawGraph(canvas,states[currentState])

#text = Text(root)
#text.insert(INSERT,"Testing things! Lots and lots of letters....a eu8fagoc u7a,f.g u78aeod uba7fcgu dthjomqeufgcdhtao emugcaoht epm.,tha pmacoth umeoauthym.,9ugth nmeu.pugchte nom.,89geh otmugoh tem.pguoeh utrmcue8arc meuoigreh tmuearogeh emuorch utcmuorc tcm.rcoe m")
#text.pack()

root.bind_all('<Key>',key)
root.mainloop()

sys.exit(0)

var = tk.StringVar(root)
var.set('red')

choices = ['red', 'green', 'blue', 'yellow', 'white', 'magenta']
option = tk.OptionMenu(root, var, *choices)
option.pack(side='left', padx=10, pady=10)

button = tk.Button(root, text='check value selected', command=select)
button.pack(side='left', padx=20, pady=10)

root.mainloop()
<|endoftext|>


<commit_before>import fcntl
import json
import random
import re
import socket
import struct
import urllib
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from SocketServer import ThreadingMixIn
from cv2 import imshow, namedWindow, setWindowProperty
from platform import machine
from threading import Thread

import cv2
import numpy as np

from btns import desk, Button

STAGE = 0
LANCAM = list()
WindowName = 'Term'
FULLSCREEN = True
__version__ = 0.3
RUN = True

with open('settings.json') as json_data:
	settings = json.load(json_data)

def geturl(url):
	print(url)
	try:
		url = urllib.urlopen(url)
	except Exception as e:
		print(e)
		return e
	ret = url.getcode()
	print('Ret: ' + str(ret))
	url.close()
	return ret

class CamHandler(BaseHTTPRequestHandler):
	streams = None

	def log_message(self, format, *args):
		if len(args) > 0:
			if args[0] == 'GET /0 HTTP/1.1':
				return
			else:
				print(args[0])

	def do_GET(self):
		path = self.path.split('/')[1:]
		data = path[-1]
		name = data
		args = dict()
		end = str()
		server = self.client_address[0]

		if '?' in data:
			name, args = data.split('?')
			args = args.split('&')
			ar = dict()
			for i in range(len(args)):
				r = args[i].split('=')
				if len(r) == 2:
					ar.update({r[0]: r[1]})
				else:
					ar.update({r[0]: str()})
			args = ar
		if '.' in name:
			name, end = name.split('.')

		if name == 'execute_1':
			game.setServer(server)
			param_1 = int(args.get('param_1', ''))
			game.start(param_1)
			self.send_response(200)
			self.send_header('Content-type', 'application/json')
			self.end_headers()
			self.wfile.write('{success: 1}')

		if end == 'btn':
			self.send_response(200)
			game.netClick(desk.get(name))

		if name == '0' and end == '':
			game.setServer(server)
			self.send_response(200)
			self.send_header('Content-type', 'application/json')
			self.end_headers()
			self.wfile.write('{state_int_1: %i, state_int_2: %i}' % (game.stage, game.round))

		if end == 'mjpg':
			self.send_response(200)
			self.send_header('Content-type', 'multipart/x-mixed-replace; boundary=--jpgboundary')
			self.end_headers()
			while RUN:
				try:
					num = int(name)
					img = self.streams[num].read()
					if img is not None:
						img = cv2.imencode(".png", img)[1].tostring()
					else:
						continue

					self.wfile.write('--jpgboundary\r\n')
					self.send_header('Content-type', 'image/jpeg')
					self.send_header('Content-length', str(len(img)))
					self.end_headers()
					self.wfile.write(img)
				except KeyboardInterrupt:
					break
			return

		if end == 'html' and len(path) == 1 and name.isdigit():
			self.send_response(200)
			self.send_header('Content-type', 'text/html')
			self.end_headers()
			self.wfile.write('')
			self.wfile.write('' % int(name))
			self.wfile.write('')

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
	"""Handle requests in a separate thread."""

class VideoStream:
	frame = None
	grabbed = None
	stream = None
	stopped = True
	paused = False
	src = None

	net = None

	def __init__(self, src=0):
		if type(src) == int or not src.startswith('http:'):
			self.src = src
			print('Creating camera %s' % src)
			self.stream = cv2.VideoCapture(src)
			self.stream.set(3, 320)
			self.stream.set(4, 240)
			try:
				#self.grabbed, self.frame = self.stream.read()
				self.grabbed = self.stream.grab()
			except Exception as e:
				print('Camera %s error: %s' % (self.src, e))
			self.stopped = False
		else:
			pattern = r"^http:\/\/(?P<ip>[0-9.]+):(?P<port>[0-9]+)\/(?P<fn>.+)\.(?P<ft>.+)$"
			self.net = re.search(pattern, src).groupdict()
			self.src = str(src)
			self.stopped = False
			self.paused = True
		self.th = Thread(target=self.update, args=()).start()

	def update(self):
		if type(self.src) == str:
			stream = None
			while stream is None:
				try:
					stream = urllib.urlopen(self.src)
				except Exception as e:
					print(self.src + ': ' + str(e))
			data = bytes()
			while RUN:
				if self.stopped:
					return
				if self.paused:
					continue

				data += stream.read(1)

				b = data.find(b'\r\n\r\n')

				if b == -1:
					continue

				a = data.find(b'--')

				if a != -1 and b != -1:
					head = data[a:b].split('\r\n')
					for i in head:
						if 'length' in i:
							l = int(i[i.find(': ') + 2:])

					jpg = bytes()
					data = bytes()
					while len(jpg) < l:
						jpg += stream.read(l - len(jpg))

					self.frame = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)

		else:
			while RUN:
				if self.stopped:
					return
				if self.paused:
					continue
				try:
					self.grabbed = self.stream.grab()
					self.frame = self.stream.retrieve()
				except Exception as e:
					print('Camera %s error: %s' % (self.src, e))

	def read(self):
		self.pause()
		img = self.frame
		self.start()
		return img

	def pause(self):
		self.paused = True
		return self

	def start(self):
		self.paused = False
		return self

	def stop(self):
		self.stopped = True
		return self

	def __del__(self):
		self.stop()
		self.stream.release()

def getImg(c):
	for i in c:
		d = i.read()
		yield d

def comp(*img):
	img = list(img)

	for i in range(len(img)):
		if None in img:
			img.remove(None)

	if len(img) == 0:
		vis = np.zeros((1, 1), np.uint8)
		frame = cv2.resize(vis, tuple(settings['size']))
		return frame

	h = [i.shape[0] for i in img]
	w = [i.shape[1] for i in img]

	sz = (max(h), sum(w), 3)

	vis = np.zeros(sz, np.uint8)
	for i in range(len(img)):
		vis[:h[i], sum(w[:i]):sum(w[:(i + 1)])] = img[i]

	frame = cv2.resize(vis, tuple(settings['size']))
	return frame

class Game:
	stage = 0
	round = 0
	btns = list()
	server = '127.0.0.1'

	def __init__(self):
		self.reset()
		Button.callback = self.clicked

	def setServer(self, s):
		if self.server != s:
			self.server = s
			print('New server: ' + str(s))

	def start(self, num):
		self.getRandBtns()
		self.round = 0
		self.stage = num

	def reset(self):
		self.stage = 0
		self.round = 0
		self.getRandBtns()

	def getRandBtns(self):
		desk.leds(False)
		for i in desk.L:
			i.clicked = False
		for i in desk.R:
			i.clicked = False

		self.btns = list([random.choice(desk.L), random.choice(desk.R)])
		for i in self.btns:
			i.led(True)

	def endStage(self):
		geturl('http://%s:3000/events/0/event_1?param_1=%i' % (self.server, self.stage))
		self.round = 0
		self.stage = 0

	def nextRound(self):
		if self.round >= 3:
			self.endStage()
		else:
			self.round += 1
			self.getRandBtns()
			print('next round: ' + str(self.round))

	def resetRound(self):
		print('reset round')
		self.round = 0
		self.getRandBtns()

	def netClick(self, btn):
		print('NET ' + btn.pos + str(btn.num))
		if btn not in self.btns:
			self.round = 0
			self.getRandBtns()
		else:
			btn.led(False)
			self.btns.remove(btn)
			if len(self.btns) == 0:
				self.nextRound()

	def clicked(self, btn):
		print('click: ' + str(btn.pos) + str(btn.num))

		if self.stage == 0:
			return

		elif self.stage in [1, 2]:
			if btn not in self.btns:
				self.resetRound()
			else:
				btn.led(False)
				if self.btns[0].clicked and self.btns[1].clicked:
					self.nextRound()
		elif self.stage == 3:
			a = list(LANCAM)

			if btn.pos == 'L':
				net = a[0].net
			elif btn.pos == 'R':
				net = a[1].net

			url = 'http://' + str(net['ip']) + ':' + str(net['port']) + '/' + str(btn) + '.btn'
			geturl(url)

def createFrame():
	frames = list()

	if game.stage == 1:
		frames = getImg(cam)
	elif game.stage == 2:
		a = cam[::-1]
		frames = getImg(a)
	elif game.stage == 3:
		for i in LANCAM:
			if i.paused:
				i.start()
		frames = getImg(LANCAM)

	frame = comp(*frames)
	return frame

def window(*cam):
	global STAGE
	global RUN

	while RUN:
		frame = createFrame()

		if frame is not None:
			imshow(WindowName, frame)

		key = cv2.waitKey(1)

		if key & 0xFF == 27:
			RUN = False
			break

		if key & 0xFF == 32:
			STAGE = (STAGE + 1) % 3

	for i in cam:
		i.stop()
	cv2.destroyAllWindows()
	exit(-1)

def serve():
	global server
	CamHandler.streams = cam
	server = ThreadedHTTPServer(('', settings['port']), CamHandler)
	print("Server started")
	server.serve_forever()

def get_ip_address(ifname):
	s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

	try:
		addr = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', ifname[:15]))[20:24])
	except:
		addr = None
	return addr

cam = list()
game = Game()
server = None

if __name__ == '__main__':
	ip = get_ip_address('eth0' if machine() == 'armv7l' else 'wlp3s0')
	WindowName = str(ip)
	other = settings.get(ip, [])
	print('twoHands: %s' % __version__)
	print('OpenCV: %s' % cv2.__version__)
	print('My addr: %s' % ip)
	print('Other: %s' % other)
	cam = list([VideoStream(0).start(), VideoStream(1).start()])
	print('Cam created')

	if FULLSCREEN:
		namedWindow(WindowName, cv2.WND_PROP_FULLSCREEN)
		if cv2.__version__.startswith('2.'):
			setWindowProperty(WindowName, cv2.WND_PROP_FULLSCREEN, cv2.cv.CV_WINDOW_FULLSCREEN)
		if cv2.__version__.startswith('3.'):
			setWindowProperty(WindowName, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

	th = Thread(target=window, args=(cam))
	th.start()
	th1 = Thread(target=serve, args=())
	th1.start()

	LANCAM = list()
	for i in other:
		url = 'http://' + str(i[0]) + ':' + str(settings['port']) + '/' + str(i[1]) + '.mjpg'
		d = VideoStream(url)
		print('NetCam created: ' + url)
		LANCAM.append(d)

	while (RUN):
		pass
	print('Exit')
	server.shutdown()
	th1.join(1)
	th.join(1)
<commit_msg>Wtf? Oo<commit_after>import fcntl
import json
import random
import re
import socket
import struct
import urllib
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from SocketServer import ThreadingMixIn
from cv2 import imshow, namedWindow, setWindowProperty
from platform import machine
from threading import Thread

import cv2
import numpy as np

from btns import desk, Button

STAGE = 0
LANCAM = list()
WindowName = 'Term'
FULLSCREEN = True
__version__ = 0.3
RUN = True

with open('settings.json') as json_data:
	settings = json.load(json_data)

def geturl(url):
	print(url)
	try:
		url = urllib.urlopen(url)
	except Exception as e:
		print(e)
		return e
	ret = url.getcode()
	print('Ret: ' + str(ret))
	url.close()
	return ret

class CamHandler(BaseHTTPRequestHandler):
	streams = None

	def log_message(self, format, *args):
		if len(args) > 0:
			if args[0] == 'GET /0 HTTP/1.1':
				return
			else:
				print(args[0])

	def do_GET(self):
		path = self.path.split('/')[1:]
		data = path[-1]
		name = data
		args = dict()
		end = str()
		server = self.client_address[0]

		if '?' in data:
			name, args = data.split('?')
			args = args.split('&')
			ar = dict()
			for i in range(len(args)):
				r = args[i].split('=')
				if len(r) == 2:
					ar.update({r[0]: r[1]})
				else:
					ar.update({r[0]: str()})
			args = ar
		if '.' in name:
			name, end = name.split('.')

		if name == 'execute_1':
			game.setServer(server)
			param_1 = int(args.get('param_1', ''))
			game.start(param_1)
			self.send_response(200)
			self.send_header('Content-type', 'application/json')
			self.end_headers()
			self.wfile.write('{success: 1}')

		if end == 'btn':
			self.send_response(200)
			game.netClick(desk.get(name))

		if name == '0' and end == '':
			game.setServer(server)
			self.send_response(200)
			self.send_header('Content-type', 'application/json')
			self.end_headers()
			self.wfile.write('{state_int_1: %i, state_int_2: %i}' % (game.stage, game.round))

		if end == 'mjpg':
			self.send_response(200)
			self.send_header('Content-type', 'multipart/x-mixed-replace; boundary=--jpgboundary')
			self.end_headers()
			while RUN:
				try:
					num = int(name)
					img = self.streams[num].read()
					if img is not None:
						img = cv2.imencode(".png", img)[1].tostring()
					else:
						continue

					self.wfile.write('--jpgboundary\r\n')
					self.send_header('Content-type', 'image/jpeg')
					self.send_header('Content-length', str(len(img)))
					self.end_headers()
					self.wfile.write(img)
				except KeyboardInterrupt:
					break
			return

		if end == 'html' and len(path) == 1 and name.isdigit():
			self.send_response(200)
			self.send_header('Content-type', 'text/html')
			self.end_headers()
			self.wfile.write('')
			self.wfile.write('' % int(name))
			self.wfile.write('')

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
	"""Handle requests in a separate thread."""

class VideoStream:
	frame = None
	grabbed = None
	stream = None
	stopped = True
	paused = False
	src = None

	net = None

	def __init__(self, src=0):
		if type(src) == int or not src.startswith('http:'):
			self.src = src
			print('Creating camera %s' % src)
			self.stream = cv2.VideoCapture(src)
			self.stream.set(3, 320)
			self.stream.set(4, 240)
			try:
				#self.grabbed, self.frame = self.stream.read()
				self.grabbed = self.stream.grab()
			except Exception as e:
				print('Camera %s error: %s' % (self.src, e))
			self.stopped = False
		else:
			pattern = r"^http:\/\/(?P<ip>[0-9.]+):(?P<port>[0-9]+)\/(?P<fn>.+)\.(?P<ft>.+)$"
			self.net = re.search(pattern, src).groupdict()
			self.src = str(src)
			self.stopped = False
			self.paused = True
		self.th = Thread(target=self.update, args=()).start()

	def update(self):
		if type(self.src) == str:
			stream = None
			while stream is None:
				try:
					stream = urllib.urlopen(self.src)
				except Exception as e:
					print(self.src + ': ' + str(e))
			data = bytes()
			while RUN:
				if self.stopped:
					return
				if self.paused:
					continue

				data += stream.read(1)

				b = data.find(b'\r\n\r\n')

				if b == -1:
					continue

				a = data.find(b'--')

				if a != -1 and b != -1:
					head = data[a:b].split('\r\n')
					for i in head:
						if 'length' in i:
							l = int(i[i.find(': ') + 2:])

					jpg = bytes()
					data = bytes()
					while len(jpg) < l:
						jpg += stream.read(l - len(jpg))

					self.frame = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)

		else:
			while RUN:
				if self.stopped:
					return
				if self.paused:
					continue
				try:
					self.grabbed = self.stream.grab()
					self.frame = self.stream.retrieve()
				except Exception as e:
					print('Camera %s error: %s' % (self.src, e))

	def read(self):
		self.pause()
		img = self.frame
		self.start()
		return img

	def pause(self):
		self.paused = True
		return self

	def start(self):
		self.paused = False
		return self

	def stop(self):
		self.stopped = True
		return self

	def __del__(self):
		self.stop()
		self.stream.release()

def getImg(c):
	for i in c:
		d = i.read()
		yield d

def comp(*img):
	img = list(img)

	for i in range(len(img)):
		if None in img:
			img.remove(None)

	if len(img) == 0:
		vis = np.zeros((1, 1), np.uint8)
		frame = cv2.resize(vis, tuple(settings['size']))
		return frame

	h = [i.shape[0] for i in img]
	w = [i.shape[1] for i in img]

	sz = (max(h), sum(w), 3)

	vis = np.zeros(sz, np.uint8)
	for i in range(len(img)):
		vis[:h[i], sum(w[:i]):sum(w[:(i + 1)])] = img[i]

	frame = cv2.resize(vis, tuple(settings['size']))
	return frame

class Game:
	stage = 0
	round = 0
	btns = list()
	server = '127.0.0.1'

	def __init__(self):
		self.reset()
		Button.callback = self.clicked

	def setServer(self, s):
		if self.server != s:
			self.server = s
			print('New server: ' + str(s))

	def start(self, num):
		self.getRandBtns()
		self.round = 0
		self.stage = num

	def reset(self):
		self.stage = 0
		self.round = 0
		self.getRandBtns()

	def getRandBtns(self):
		desk.leds(False)
		for i in desk.L:
			i.clicked = False
		for i in desk.R:
			i.clicked = False

		self.btns = list([random.choice(desk.L), random.choice(desk.R)])
		for i in self.btns:
			i.led(True)

	def endStage(self):
		geturl('http://%s:3000/events/0/event_1?param_1=%i' % (self.server, self.stage))
		self.round = 0
		self.stage = 0

	def nextRound(self):
		if self.round >= 3:
			self.endStage()
		else:
			self.round += 1
			self.getRandBtns()
			print('next round: ' + str(self.round))

	def resetRound(self):
		print('reset round')
		self.round = 0
		self.getRandBtns()

	def netClick(self, btn):
		print('NET ' + btn.pos + str(btn.num))
		if btn not in self.btns:
			self.round = 0
			self.getRandBtns()
		else:
			btn.led(False)
			self.btns.remove(btn)
			if len(self.btns) == 0:
				self.nextRound()

	def clicked(self, btn):
		print('click: ' + str(btn.pos) + str(btn.num))

		if self.stage == 0:
			return

		elif self.stage in [1, 2, 3]:
			if btn not in self.btns:
				self.resetRound()
			else:
				btn.led(False)
				if self.btns[0].clicked and self.btns[1].clicked:
					self.nextRound()
		elif self.stage == 9:
			a = list(LANCAM)

			if btn.pos == 'L':
				net = a[0].net
			elif btn.pos == 'R':
				net = a[1].net

			url = 'http://' + str(net['ip']) + ':' + str(net['port']) + '/' + str(btn) + '.btn'
			geturl(url)

def createFrame():
	frames = list()

	if game.stage == 1:
		frames = getImg(cam)
	elif game.stage == 2:
		a = cam[::-1]
		frames = getImg(a)
	elif game.stage == 3:
		for i in LANCAM:
			if i.paused:
				i.start()
		frames = getImg(LANCAM)

	frame = comp(*frames)
	return frame

def window(*cam):
	global STAGE
	global RUN

	while RUN:
		frame = createFrame()

		if frame is not None:
			imshow(WindowName, frame)

		key = cv2.waitKey(1)

		if key & 0xFF == 27:
			RUN = False
			break

		if key & 0xFF == 32:
			STAGE = (STAGE + 1) % 3

	for i in cam:
		i.stop()
	cv2.destroyAllWindows()
	exit(-1)

def serve():
	global server
	CamHandler.streams = cam
	server = ThreadedHTTPServer(('', settings['port']), CamHandler)
	print("Server started")
	server.serve_forever()

def get_ip_address(ifname):
	s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

	try:
		addr = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', ifname[:15]))[20:24])
	except:
		addr = None
	return addr

cam = list()
game = Game()
server = None

if __name__ == '__main__':
	ip = get_ip_address('eth0' if machine() == 'armv7l' else 'wlp3s0')
	WindowName = str(ip)
	other = settings.get(ip, [])
	print('twoHands: %s' % __version__)
	print('OpenCV: %s' % cv2.__version__)
	print('My addr: %s' % ip)
	print('Other: %s' % other)
	cam = list([VideoStream(0).start(), VideoStream(1).start()])
	print('Cam created')

	if FULLSCREEN:
		namedWindow(WindowName, cv2.WND_PROP_FULLSCREEN)
		if cv2.__version__.startswith('2.'):
			setWindowProperty(WindowName, cv2.WND_PROP_FULLSCREEN, cv2.cv.CV_WINDOW_FULLSCREEN)
		if cv2.__version__.startswith('3.'):
			setWindowProperty(WindowName, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

	th = Thread(target=window, args=(cam))
	th.start()
	th1 = Thread(target=serve, args=())
	th1.start()

	LANCAM = list()
	for i in other:
		url = 'http://' + str(i[0]) + ':' + str(settings['port']) + '/' + str(i[1]) + '.mjpg'
		d = VideoStream(url)
		print('NetCam created: ' + url)
		LANCAM.append(d)

	while (RUN):
		pass
	print('Exit')
	server.shutdown()
	th1.join(1)
	th.join(1)
<|endoftext|>