import asyncio
import json
import os
import time
import settings

import discord
from discord.ext import commands
import datetime

import requests
from bs4 import BeautifulSoup

from calendar_manager import CalendarManager
from file_manager import FileManager

print('ok')

cm = CalendarManager('calendars')

TOKEN = settings.TOKEN

client = discord.Client()

bot = commands.Bot(command_prefix='$', case_insensitive=True)

stop = False

green_circle = '\U0001F7E2'
orange_circle = '\U0001F7E0'

tasks = {}

days = {'monday': 0, 'tuesday': 1, 'wednesday': 2, 'thursday': 3, 'friday': 4, 'saturday': 5, 'sunday': 6}

@bot.event
async def on_ready():
    start()

def start():
    files = os.listdir(os.path.join(os.getcwd(), 'schedules'))
    for file in files:
        guild = file.split('.')[0]
        cm.get_calendar(guild)
        tasks[guild] = asyncio.get_event_loop().create_task(schedule_manager(guild))

@bot.command()
async def stop(ctx):
    if ctx.guild in tasks:
        try:
            tasks[ctx.guild].cancel()
        except asyncio.CancelledError:
            await ctx.send(f'The scheduler has been stopped.')

async def schedule_manager(guild):
    schedule = FileManager.get_schedule(guild)
    channels = FileManager.get_channels(guild)
    active_lecture = None
    orange_lecture = None
    print('started')
    while True:
        print(f'check {guild}')
        now = datetime.datetime.now()
        nl = await next_lecture(guild)
        if nl:
            if nl['end_time'] > now.time():
                sleep_time = await seconds_diff(nl['start_time'], now.time())
            else:
                sleep_time = 3600
        else:
            sleep_time = 3600
        if active_lecture:
            sleep_time = await seconds_diff(active_lecture['end_time'], now.time())
            if active_lecture['end_time'] < now.time():
                channel = bot.get_channel(channels[active_lecture['id']])
                await channel.edit(name=active_lecture['og_name'])
                print(f"The {active_lecture['og_name']} has ended.")
                active_lecture = None
        for lecture in schedule[now.weekday()]:
            channel = None
            if lecture['start_time'] <= now.time() <= lecture['end_time'] and not active_lecture:
                print(lecture['id'])
                if lecture['id'] in channels:
                    channel = bot.get_channel(channels[lecture['id']])
                print(channel)
                if channel:
                    if orange_lecture and orange_lecture['id'] == lecture['id']:
                        if green_circle not in channel.name:
                            new_name = green_circle + '' + orange_lecture['og_name']
                            await channel.edit(name=new_name)
                            active_lecture = orange_lecture
                            orange_lecture = None
                    else:
                        print(f"active lecture: {lecture['id']}")
                        active_lecture = lecture
                        if green_circle not in channel.name:
                            active_lecture['og_name'] = channel.name
                            new_name = green_circle + '' + channel.name
                            await channel.edit(name=new_name)
                        else:
                            active_lecture = lecture
                            active_lecture['og_name'] = channel.name[1:]
                sleep_time = await seconds_diff(active_lecture['end_time'], now.time())
            if (now + datetime.timedelta(minutes=15)).time() >= lecture['start_time'] >= now.time():
                if not orange_lecture:
                    if lecture['id'] in channels:
                        channel = bot.get_channel(channels[lecture['id']])
                    if channel:
                        print(f"next lecture: {lecture['id']}")
                        orange_lecture = lecture
                        if orange_circle not in channel.name:
                            orange_lecture['og_name'] = channel.name
                            new_name = orange_circle + '' + channel.name
                            await channel.edit(name=new_name)
        if sleep_time < 60:
            sleep_time = 60
        if sleep_time > 3600:
            sleep_time = 3600
        print(sleep_time)
        await asyncio.sleep(sleep_time)

@bot.command()
async def now(ctx):
    print('now')
    schedule = FileManager.get_schedule(ctx.guild)
    now = datetime.datetime.now()
    for lecture in schedule[now.weekday()]:
        if lecture['start_time'] <= now.time() <= lecture['end_time']:
            await ctx.send(f"The current lecture is {lecture['id']}.")
            return
    await ctx.send(
        'No Lecture right now have fun! (you probably have to do some assignment)'
    )

@bot.command()
async def next(ctx):
    print('next')
    nl = await next_lecture(ctx.guild)
    if not nl:
        ctx.send('No lecture scheduled.')
    ctx.send(f"The next lecture is {nl['id']} at {nl['start_time']}")

async def next_lecture(guild):
    schedule = FileManager.get_schedule(guild)
    now = datetime.datetime.now()
    next_lecture = None
    for lecture in schedule[now.weekday()]:
        if lecture['start_time'] <= now.time():
            if lecture == schedule[now.weekday()][-1]:
                next_day = now.weekday()
                while True:
                    if next_day == 6:
                        next_day = 0
                    else:
                        next_day += 1
                    if len(schedule[next_day]) > 0:
                        next_lecture = schedule[next_day][0]
                        break
            else:
                lecture = schedule[now.weekday()][schedule[now.weekday()].index(lecture) + 1]
                if lecture['start_time'] <= now.time():
                    continue
                next_lecture = lecture
        else:
            return lecture
    return next_lecture

async def seconds_diff(a, b):
    return a.second - b.second + (a.minute - b.minute) * 60 + (a.hour - b.hour) * 3600

@bot.command()
async def menu(ctx, day: str = None, campus: str = None):
    print('menu')
    now = datetime.datetime.now()
    today = now.weekday()
    usi = False
    if campus and campus.lower() == 'usi':
        usi = True

    if today > 5:
        today = 5
    if day:
        if day.lower() in list(days.keys()):
            day = days[day.lower()]
            if day < 5:
                if today > day:
                    day = 5 - today + day
                elif today < day:
                    day = day - today
                else:
                    day = 0
            else:
                await ctx.send("Saturday and Sunday the canteen is closed.")
                return
        elif day.lower() == 'usi':
            usi = True
            day = 0
        elif day.lower() == 'supsi':
            usi = False
            day = 0
        else:
            await ctx.send("Invalid day. (come on it's simple english)")
            return
    menu = get_menu(day, usi)
    await ctx.send(menu)

def get_menu(day=None, usi=False):
    if not day:
        day = 0
    if 0 <= day < 5:
        if usi:
            URL = 'https://polo-universitario-lugano.sv-restaurant.ch/en/menu/campus-ovest/'
        else:
            URL = 'https://polo-universitario-lugano.sv-restaurant.ch/en/menu/campus-est/'
        page = requests.get(URL)

        text = ''
        soup = BeautifulSoup(page.content, "html.parser")
        menus = soup.find_all("div", class_='menu-plan-grid')
        items = menus[day].find_all("div", class_='menu-item')
        for item in items:
            title = item.find_all("span", class_='menuline')[0]
            desc = item.find_all("h2", class_='menu-title')[0]
            tab = 1
            if len(title.text) < 6:
                tab = 2
            text += f"{title.text}: " + "\t" * tab + f"{desc.text}\n"
        return text
    return f'Day not valid {day}'

@bot.command()
async def homework(ctx):
    text = ''
    channels = FileManager.get_channels(ctx.guild.name)
    if ctx.channel.id in list(channels.values()):
        channel = list(channels.keys())[list(channels.values()).index(ctx.channel.id)]
    else:
        channel = None
    hws = cm.get_homework(ctx.guild.name, channel)
    if hws:
        for hw in hws:
            text += f"__{hw['channel'].capitalize()}__: **{hw['title']}** ({hw['end_time'].strftime('%d-%m-%y %H:%M')})\n"
        await ctx.send(text[:-1])
    else:
        await ctx.send("There is no homework. :partying_face:")

bot.run(TOKEN)


from selenium.webdriver.support.wait import WebDriverWait
from AppiumFramework.base.BasePage import BasePage
import AppiumFramework.utilities.CustomLogger as CL

"""
This page contains locators and methods related to Contact Us Form
such as enter text, click on submit buttons and validate entered text
"""

class EnterSomeValuePage(BasePage):

    _enterSomeValueField = '//android.widget.EditText[@resource-id="com.code2lead.kwad:id/Et1"]'
    _submitBtn = '//android.widget.Button[@resource-id="com.code2lead.kwad:id/Btn1"]'

    def __init__(self, driver):
        super().__init__(driver)
        self.driver = driver
        self.wait = WebDriverWait(self.driver, 15, poll_frequency=.5)

    def validateContactUsFormLandingPage(self):
        assert True == self.isDisplayed(self._enterSomeValueField)
        CL.allureLogs("Contact Us Form Page Reached Successfully")
        self.takeScreenshot(ssSection="EnterSomeValueLandingPage")

    def enterSomeValueText(self, textToEnter):
        self.sendKeys(textToEnter, self._enterSomeValueField)
        self.log(f"{textToEnter}, entered correclty on field", True)
        # CL.allureLogs(f"{textToEnter} entered Successfully on enter some value field")
        self.takeScreenshot(ssSection="EnterSomeValueData")

    def clickSubmitBtn(self):
        self.clickElement(self._submitBtn)
        CL.allureLogs("Submit button clicked successfully on entersome value section")

    def validateSubmittedText(self, textToVAlidate):
        assert True == self.isDisplayed(textToVAlidate, "text")
        self.log(f"{textToVAlidate} has been submitted correctly", True)
        CL.allureLogs(f"{textToVAlidate} has been submitted correctly")


# coding=utf-8
import os
import json
import logging
import subprocess

from ajenti.api import *
from ajenti.plugins.main.api import SectionPlugin
from ajenti.ui import on
from ajenti.ui.binder import Binder

from templates import config_templates

config_dirs = {
    'main': '/etc/fail2ban/',
    'jails': '/etc/fail2ban/jail.d/',
    'actions': '/etc/fail2ban/action.d/',
    'filters': '/etc/fail2ban/filter.d/',
    'extra': '/etc/fail2ban/fail2ban.d/'
}

config_file_types = ('.conf', '.local')

# fail2ban:
#     configurations=
#             [
#                 f2b_configs:
#                     name=
#                     path=
#                     confillist=
#                         f2b_list:
#                             path=
#                             type=
#                             __list__=
#                                     f2b_config:
#                                         name=
#                                         configfile=
#                                         config=
#
#             ]

class f2b_Config(object):
    def __init__(self, name, path):
        self.name = name
        self.path = path
        self.configfile = os.path.join(path, name)
        self.config = ''

    def __repr__(self):
        return json.dumps({'name': self.name, 'configfile': self.configfile, 'config': self.config})

    def save(self):
        self.configfile = os.path.join(self.path, self.name)
        try:
            open(self.configfile, 'w').write(self.config)
            return self
        except IOError as e:
            logging.error(e.message)

    def update(self):
        self.configfile = os.path.join(self.path, self.name)
        self.config = ''.join((open(self.configfile).readlines()))
        return self

class f2b_Configs(object):
    def __init__(self, name, path):
        self.name = name
        self.path = path
        self.configlist = f2b_list(path=path, type=name)
        self.configlist.path = self.path

    def update(self):
        for filename in os.listdir(self.path):
            try:
                cf = os.path.join(self.path, filename)
                if os.path.isfile(cf) and (os.path.splitext(filename)[-1] in config_file_types):
                    self.configlist.append(f2b_Config(filename, self.path).update())
            except IOError as e:
                logging.error('Error reading file {0} in {1}.'.format(filename, self.path))
        self.configlist.sort(key=lambda k: k.name)
        return self

class f2b_list(list):
    def __init__(self, path='', type=''):
        self.path = path
        self.type = type

@plugin
class fail2ban(SectionPlugin):
    def init(self):
        self.title = 'fail2ban'
        self.icon = 'shield'
        self.category = _('Software')
        self.f2b_v = subprocess.check_output(['fail2ban-client', '--version']).splitlines()[0]
        self.append(self.ui.inflate('fail2ban:main'))
        self.binder = Binder(self, self)
        self.update_status = True

        def on_config_update(o, c, config, u):
            if config.__old_name != config.name:
                if os.path.exists(os.path.join(c.path, config.name)):
                    self.context.notify('error', _(
                        'File with name {0} already exists in {1}.').format(config.name, c.path))
                    self.update_status = False
                    config.name = config.__old_name
                    return
                logging.debug('renamed config file %s to %s' % (config.__old_name, config.name))
                os.unlink(config.configfile)
            config.save()
            self.update_status = True

        def on_config_bind(o, c, config, u):
            config.__old_name = config.name

        def new_config(c):
            new_fn = 'untitled{0}.conf'
            s_fn = new_fn.format('')
            filename = os.path.join(c.path, s_fn)
            i = 1
            while os.path.exists(filename):
                s_fn = new_fn.format('_' + str(i))
                filename = os.path.join(c.path, s_fn)
                i += 1
            try:
                logging.debug('add config %s' % filename)
                conf = f2b_Config(s_fn, c.path)
                conf.config = config_templates[c.type]
                return conf.save()
            except IOError as e:
                print('Error writing file {0} in {1}'.format(filename, c.path))

        def delete_config(config, c):
            filename = config.configfile
            logging.debug('removed config %s' % config.configfile)
            c.remove(config)
            os.unlink(filename)

        self.find('configlist').post_item_update = on_config_update
        self.find('configlist').post_item_bind = on_config_bind
        self.find('configlist').new_item = new_config
        self.find('configlist').delete_item = delete_config

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.configurations = [
            f2b_Configs(k, d).update()
            for k, d in config_dirs.iteritems()
            if os.path.isdir(d)
        ]
        self.binder.setup(self).populate()

    @on('save-button', 'click')
    def save(self):
        self.binder.update()
        if self.update_status:
            self.context.notify('info', _('Saved'))
        self.update_status = True
        self.binder.setup(self).populate()

    @on('check-regex', 'click')
    def check_regex(self):
        self.find('check-status').text = ''
        log_fname = self.find('log-filename').value
        filter_fname = self.find('filter-filename').value
        log_as_text = self.find('log-file').value
        filter_as_text = self.find('filter-file').value
        if not (log_fname or log_as_text) or not (filter_fname or filter_as_text):
            logging.debug('Filter checker. Some parameters are empty.')
            self.context.notify('error', _('Some parameters are empty.'))
            return

        with open(filter_fname + '.tmp', 'w') as rt:
            rt.write(self.find('filter-file').value)
            rt_name = rt.name
            rt.close()

        p = subprocess.Popen(['fail2ban-regex', '--full-traceback', log_fname, rt_name], stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT)
        out, err = p.communicate()
        self.find('check-status').text = out

        os.unlink(rt_name)

    @on('open-filter-button', 'click')
    def open_filter(self):
        self.find('openfilterdialog').show()

    @on('openfilterdialog', 'button')
    def on_open_filter_dialog(self, button):
        self.find('openfilterdialog').visible = False

    @on('openfilterdialog', 'select')
    def on_filter_file_select(self, path=None):
        if not path:
            return
        self.find('openfilterdialog').visible = False
        self.find('filter-filename').value = path
        self.find('filter-file').value = ''.join(open(path).readlines())

    @on('open-log-button', 'click')
    def open_log(self):
        self.find('openlogdialog').show()

    @on('openlogdialog', 'button')
    def on_open_log_dialog(self, button):
        self.find('openlogdialog').visible = False

    @on('openlogdialog', 'select')
    def on_log_file_select(self, path=None):
        if not path:
            return
        self.find('openlogdialog').visible = False
        self.find('log-filename').value = path
        self.find('log-file').value = ''.join(open(path).readlines())

    @on('save-filter-button', 'click')
    def save_filter(self):
        try:
            open(self.find('filter-filename').value, 'w').write(self.find('filter-file').value)
        except IOError as e:
            self.context.notify('error', _('Could not save config file. %s') % str(e))
            logging.error(e.message)


""" Scraping from JSM """
import csv
from bs4 import BeautifulSoup #pylint: disable=E0401
import requests #pylint: disable=E0401

source = requests.get('https://jsmliving.com/search-available-units', timeout=10).text

soup = BeautifulSoup(source, 'lxml')
AVAIL_UNITS = 0

with open('JSM_scraped_info.csv', 'w', encoding='utf8') as csv_file:
    csv_writer = csv.writer(csv_file)
    csv_writer.writerow(['Address', 'Rent', 'Bedrooms', 'Bathrooms'])

    for article in soup.find_all('article'):
        rent = article.find('div', class_ = "unit__card-rent").text
        if "No Units Available" in rent:
            break
        rent2 = rent.split(':')

        AVAIL_UNITS += 1
        # print(avail_units)
        # address = article.find('div',
        # class_= "field field--name-field-building field--type-entity-reference
        # field--label-hidden field--item").a.text
        address = article.h4.a.text
        # print(address)

        print(rent2[1].strip())

        bed = article.find('div', class_ = 'unit__card-bedrooms').p.text
        # print(bed)

        bath = article.find('div', class_ = 'unit__card-bathrooms').p.text
        # print(bath)
        # print("--------")
        csv_writer.writerow([address, rent2[1].strip(), bed, bath])


import signal
import argparse
import _thread
import azure_download
import ftp_download
from queue import Queue

import time
import os

def get_args():
	parser = argparse.ArgumentParser()
	parser.description = argparse.ArgumentParser(description='span args command:')
	parser.add_argument("--storage_name", type=str, help="my storagename")
	parser.add_argument("--storage_key", type=str, help="my storagekey")
	parser.add_argument("--span_path", type=str, help="span file path")
	parser.add_argument("--base", type=str, help="is download base data",choices=['yes','no'])
	parser.add_argument("--ephemeris", type=str, help="is download ephemeris data",choices=['yes','no'])
	return parser.parse_args()

def set_cmd_para():
    args = get_args()

    para_dict = {"storage_name": "","storage_key": "","span_path": "","base": "","ephemeris":""}
    if args.storage_name == None:
        print ("please input your storage name")
        storage_name = input()
    else:
        storage_name = args.storage_name
    para_dict["storage_name"] = storage_name
    if args.storage_key == None:
        print ("please input your storage key")
        storage_key = input()
    else:
        storage_key = args.storage_key
    para_dict["storage_key"] = storage_key
    if args.span_path == None:
        print ("please input your span path")
        span_path = input()
    else:
        span_path = args.span_path
    para_dict["span_path"] = span_path

    if args.base == None:
        print ("is download base data? yes or no")
        base_download = input()
    else:
        base_download = args.base
    para_dict["base"] = base_download

    if args.ephemeris == None:
        print ("is download ephemeris data? yes or no")
        ephemeris_download = input()
    else:
        ephemeris_download = args.ephemeris
    para_dict["ephemeris"] = ephemeris_download
    return para_dict

def kill_app(signal_int,call_back):
    print ('exit app')
    os.kill(os.getpid(),signal.SIGINT)

if __name__ == '__main__':
	signal.signal(signal.SIGINT,kill_app)
	para_dict = set_cmd_para()
	print (para_dict)
	base_run_queue = Queue(maxsize=1000)
	ephemeris_run_queue = Queue(maxsize=1000)

	if para_dict["ephemeris"] == 'yes':
		_thread.start_new_thread(ftp_download.ephemeris_download,("ephemeris_thread",para_dict["span_path"],ephemeris_run_queue))
	if para_dict["base"] == 'yes':
		_thread.start_new_thread(azure_download.base_download,("base_thread",para_dict["span_path"],para_dict["storage_name"],para_dict["storage_key"],base_run_queue))

	base_queue_mes = ''
	ephemeris_queue_mes = ''
	base_run_flag = False
	ephemeris_run_flag = False
	if para_dict["ephemeris"] == 'no':
		ephemeris_run_flag = True
	if para_dict["base"] == 'no':
		base_run_flag = True
	while True:
		try:
			base_queue_mes = base_run_queue.get_nowait()
		except:
			pass
		try:
			ephemeris_queue_mes = ephemeris_run_queue.get_nowait()
		except:
			pass
		if(ephemeris_queue_mes == 'ftp_end'):
			ephemeris_run_flag = True
			print(ephemeris_queue_mes)
		if(base_queue_mes == 'azure_end'):
			base_run_flag = True
			print(base_queue_mes)
		if(ephemeris_run_flag == True) and (base_run_flag == True):
			print("exit")
			exit()
		time.sleep(5)


import datetime, yaml
isUpdating = False
async def update(self,):
    global isUpdating
    if isUpdating: return

    isUpdating = True
    try:
        await updateSchedules(self,)
        await updateData(self,)
        if len(self.Data['PlayerData']) == 0: return
        for pid in self.Data['PlayerData'].keys():
            await updatePlayer(self, pid)

        await updatePlayerMenu(self,)
    except Exception as e:
        raise e
    isUpdating = False

async def updateSchedules(self,):
    channelName = 'schedule-info'
    maxToDisplay = 25
    ignoreScheduleList = ['Start Of Turn', 'Start Of Day']
    paramMap = {
        'Time': "(HH:MM:SS)"
    }
    msgs = {}
    toSend = []
    for sched in self.Data['Schedules']:
        if sched in ignoreScheduleList: continue
        try:
            diff = self.Data['Schedules'][sched]['nextTime'] - self.getFromDict(self.Data['Schedules'][sched]['parameter'])
            if diff < diff * 0: diff = diff * 0
            if isinstance(diff, datetime.timedelta):
                diff = str(diff + self.minute - datetime.timedelta(seconds=diff.seconds % 60)).replace(':00 ',' ')
            if self.Data['Schedules'][sched]['parameter'] in paramMap:
                msgs[sched]  = f"**{sched}** will occur in {diff} {paramMap[self.Data['Schedules'][sched]['parameter']]} \n"
            else:
                msgs[sched]  = f"**{sched}** will occur in {diff} {self.Data['Schedules'][sched]['parameter']} \n"

        except Exception as e:
            nt = self.Data['Schedules'][sched]['nextTime']
            ct = self.getFromDict(self.Data['Schedules'][sched]['parameter'])
            if isinstance(nt, datetime.datetime): nt = nt - datetime.timedelta(seconds=nt.second)
            if isinstance(ct, datetime.datetime): ct = ct - datetime.timedelta(seconds=ct.second)
            msgs[sched]  = f"**{sched}** is waiting for **{self.Data['Schedules'][sched]['parameter']}** \n"
            msgs[sched] += f"   To become: {nt} \n"
            msgs[sched] += f"   It is now: {ct} "

        msgs[sched] = msgs[sched].replace('-05:51','').replace('-06:00','').replace('-05:00','').replace('+05:00','')

    for k in sorted(msgs.keys()): toSend.append(msgs[k].strip())

    # Create Channel
    channel = self.Refs['channels'].get(channelName)
    if channel is None:
        overwrites = {
            self.Refs['roles'][self.playerRole]: self.discord.PermissionOverwrite(read_messages=True),
            self.server.default_role: self.discord.PermissionOverwrite(read_messages=False),
            self.Refs['roles']['Bot']: self.discord.PermissionOverwrite(read_messages=True),
        }
        channel = await self.server.create_text_channel("schedule-info", overwrites=overwrites, category= self.Refs['category']['Game-Data'])
        self.Refs['channels'][channelName] = channel
        print('      Added Channel:', channelName)

    msgs = self.Data.get('Schedule-Channel-MSGS')
    if msgs is None: msgs = []
    if len(msgs) != maxToDisplay:
        print('   |   Purging Schedule-Channel-MSGS', len(msgs) , len(toSend))
        self.Data['Schedule-Channel-MSGS'] = []
        await channel.purge()
        for i in range(maxToDisplay):
            msg = await channel.send(".")
            self.Data['Schedule-Channel-MSGS'].append([msg.id, ""])

    msgs = self.Data.get('Schedule-Channel-MSGS')
    for i in range(1,len(toSend)+1):
        mid, old_txt = msgs[-i]
        if old_txt != toSend[i-1]:
            try: msg = await channel.fetch_message(mid)
            except:
                self.Data['Schedule-Channel-MSGS'] = []
                await updateSchedules(self)
                return
            await msg.edit(content = toSend[i-1])
            self.Data['Schedule-Channel-MSGS'][-i] = [mid, toSend[i-1]]

    for i in range(len(toSend)+1, maxToDisplay+1):
        mid, old_txt = msgs[-i]
        if old_txt != ".":
            try: msg = await channel.fetch_message(mid)
            except:
                self.Data['Schedule-Channel-MSGS'] = []
                await updateSchedules(self)
                return
            #print('   |   Editing Schedule List')
            await msg.edit(content = ".")
            self.Data['Schedule-Channel-MSGS'][-i] = [mid, "."]

async def updatePlayer(self,pid):
    channel = None
    channelName = self.Data['PlayerData'][pid].get('Info-Channel')
    if channelName is None or self.Refs['channels'].get(channelName) is None:
        channelName = f"{self.Data['PlayerData'][pid]['Name'].lower()}-game-data".replace('#','-').replace(' ','-').replace('$','s')

        if self.Refs['channels'].get(channelName) is None:
            overwrites = {
                self.Refs['roles'][self.moderatorRole]: self.discord.PermissionOverwrite(read_messages=True),
                self.Refs['roles']['Bot']: self.discord.PermissionOverwrite(read_messages=True),
                self.server.default_role: self.discord.PermissionOverwrite(read_messages=False),
                self.Refs['players'][pid]: self.discord.PermissionOverwrite(read_messages=True),
            }
            channel = await self.server.create_text_channel(channelName, overwrites=overwrites, category= self.Refs['category']['Game-Data'])
            self.Refs['channels'][channel.name] = channel
            self.Data['PlayerData'][pid]['Info-Channel'] = channel.name

            print('   |   Added Channel:', channel.name)
        else:
            channelName = f"{self.Data['PlayerData'][pid]['Name'].lower()}-game-data".replace('#','-').replace(' ','-').replace('$','s')
            self.Data['PlayerData'][pid]['Info-Channel'] = channelName
    channel = self.Refs['channels'].get(channelName)

    maxToDisplay = 25
    ignoreKeys = ['Proposal', 'Info-Channel', 'InactiveWarned', 'query', 'Query', 'Rock Paper Scissor Guess']
    paramMap = {
        'Time': "(HH:MM:SS)",
        'EmojiHold' : 'Emoji Hold',
        'EmpathyCounter': 'Correct Mood Guesses',
        'Inactive':'Reason For Inactivity',
        'MoodGuess': 'Mood Guess',
        'Offers': "Amount of Tokens Offered In Market",
        'Challanged' : 'Has Challenged This Week'

    }
    msgs = {}
    toSend = []
    for k in self.Data['PlayerData'][pid].keys():
        if k in ignoreKeys: continue
        val = self.Data['PlayerData'][pid][k]

        if isinstance(val, dict):  val = '```'+yaml.dump(self.Data['PlayerData'][pid][k])+'```'
        if isinstance(val, datetime.datetime): val = val - datetime.timedelta(seconds=val.second)

        name = str(k)
        if name in paramMap: name = paramMap[name]
        msgs[k]  = f"**{name}**:   {val}"

        msgs[k] = msgs[k].replace('-05:51','').replace('-05:00','').replace('-06:00','').replace('+05:00','')
        if len(msgs[k]) > 1000:
            msgs[k] = msgs[k][:1000]
    for k in sorted(msgs.keys()): toSend.append(msgs[k].strip())

    msgs = self.Data.get(f'{channelName}-MSGS')
    if msgs is None: msgs = []
    if len(msgs) != maxToDisplay:
        print(f'   |   Purging {channelName}-MSGS',  len(msgs))
        self.Data[f'{channelName}-MSGS'] = []
        await channel.purge()
        for i in range(maxToDisplay):
            msg = await channel.send(".")
            self.Data[f'{channelName}-MSGS'].append([msg.id, ""])

    msgs = self.Data.get(f'{channelName}-MSGS')
    for i in range(1,len(toSend)+1):
        mid, old_txt = msgs[-i]
        if old_txt != toSend[i-1]:
            try: msg = await channel.fetch_message(mid)
            except:
                self.Data[f'{channelName}-MSGS'] = []
                await updatePlayer(self, pid)
                return
            #print(f'   |   Editing {channelName}')
            await msg.edit(content = toSend[i-1])
            self.Data[f'{channelName}-MSGS'][-i] = [mid, toSend[i-1]]

    for i in range(len(toSend)+1, maxToDisplay+1):
        mid, old_txt = msgs[-i]
        if old_txt != ".":
            try: msg = await channel.fetch_message(mid)
            except:
                self.Data[f'{channelName}-MSGS'] = []
                await updatePlayer(self, pid)
                return
            #print(f'   |   Editing {channelName}')
            await msg.edit(content = ".")
            self.Data[f'{channelName}-MSGS'][-i] = [mid, "."]

async def updateData(self):
    channelName = 'game-info'
    if self.Refs['channels'].get(channelName) is None:
        overwrites = {
            self.Refs['roles'][self.moderatorRole]: self.discord.PermissionOverwrite(read_messages=True),
            self.Refs['roles']['Bot']: self.discord.PermissionOverwrite(read_messages=True),
            self.server.default_role: self.discord.PermissionOverwrite(read_messages=True)
        }
        channel = await self.server.create_text_channel(channelName, overwrites=overwrites, category= self.Refs['category']['Game-Data'])
        self.Refs['channels'][channelName] = channel
        print('   |   Added Channel:', channel.name)
    channel = self.Refs['channels'].get(channelName)

    maxToDisplay = 35
    ignoreKeys = ['PlayerData','Schedules','Queue','Queue-MSGS','RuleList',
                  'Schedule-Channel-MSGS','Suber-Votes-1','Suber-Votes-2',
                  'Suber-Votes-3','Suber-Votes-4','Suber-Votes-5','Subers',
                  'Suber-MSG','Votes','Mood','Array','lastAlive','NextTurnStartTime',
                  'CurrTurnStartTime','channels', 'admin','server','Emoji Recipes',
                  'Turn -3 RPS Winners','Turn -2 RPS Winners','Turn -1 RPS Winners', 'Tubby',
                  'Haymaker','VotingEnabled','Votes-1','Votes-2','Votes-3','Votes-4','Votes-5','Wizard', 'Canvas']
    paramMap = {
        'TurnTime': 'Elasped Turn Time (sec)'
    }

    msgs = {}
    toSend = []
    for k in self.Data.keys():
        if k in ignoreKeys: continue
        if 'MSG' in k: continue
        val = self.Data[k]

        if isinstance(val, dict):  val = '```'+yaml.dump(self.Data[k])+'```'
        if isinstance(val, datetime.datetime): val = val - datetime.timedelta(seconds=val.second)

        name = str(k)
        if name in paramMap: name = paramMap[name]
        msgs[k]  = f"**{name}**:   {val}"

        for pid in self.Data['PlayerData'].keys():
            msgs[k] = msgs[k].replace(str(pid), self.Data['PlayerData'][pid]['Name']).replace('-05:51','').replace('-06:00','').replace('-05:00','').replace('+05:00','')
        if len(msgs[k]) > 1000:
            msgs[k] = msgs[k][:1000]
    for k in sorted(msgs.keys()): toSend.append(msgs[k].strip())

    msgs = self.Data.get(f'{channelName}-MSGS')
    if msgs is None: msgs = []
    if len(msgs) != maxToDisplay:
        print(f'   |   Purging {channelName}-MSGS',  len(msgs))
        self.Data[f'{channelName}-MSGS'] = []
        await channel.purge()
        for i in range(maxToDisplay):
            msg = await channel.send(".")
            self.Data[f'{channelName}-MSGS'].append([msg.id, ""])

    msgs = self.Data.get(f'{channelName}-MSGS')
    for i in range(1,len(toSend)+1):
        mid, old_txt = msgs[-i]
        if old_txt != toSend[i-1]:
            try: msg = await channel.fetch_message(mid)
            except:
                self.Data[f'{channelName}-MSGS'] = []
                await updatePlayer(self, pid)
                return
            await msg.edit(content = toSend[i-1])
            self.Data[f'{channelName}-MSGS'][-i] = [mid, toSend[i-1]]

    for i in range(len(toSend)+1, maxToDisplay+1):
        mid, old_txt = msgs[-i]
        if old_txt != ".":
            try: msg = await channel.fetch_message(mid)
            except:
                self.Data[f'{channelName}-MSGS'] = []
                await updatePlayer(self, pid)
                return
            await msg.edit(content = ".")
            self.Data[f'{channelName}-MSGS'][-i] = [mid, "."]

async def updatePlayerMenu(self):
    channelName = 'player-menu'

    # Create Channel
    channel = self.Refs['channels'].get(channelName)
    if channel is None:
        overwrites = {
            self.Refs['roles'][self.playerRole]: self.discord.PermissionOverwrite(read_messages=True),
            self.Refs['roles']['Bot']: self.discord.PermissionOverwrite(read_messages=True),
        }
        channel = await self.server.create_text_channel(channelName, overwrites=overwrites, category= self.Refs['category']['Game-Data'])
        self.Refs['channels'][channelName] = channel
        print('      Added Channel:', channelName)

    sortedP = list(sorted( dict(self.Data['PlayerData']).keys()))

    # If Structure not right size, regenerate to keep uniform spacing.
    if self.Data.get('PlayerMenu-MSGS') is None or len(self.Data['PlayerMenu-MSGS']) != len(sortedP):
        await self.Refs['channels'][channelName].purge()
        self.Data['PlayerMenu-MSGS'] = []
        for pid in sortedP:
            channelid = self.Refs['channels'].get( self.Data['PlayerData'][pid]['Info-Channel'] ).id
            msg = await self.Refs['channels'][channelName].send(f"<#{channelid}>")
            self.Data['PlayerMenu-MSGS'].append(msg.id)
            for r in ['👁', '💤']: await msg.add_reaction(r)

async def on_reaction(self,payload):
    if payload['Channel'] == 'player-menu' and payload['mode'] == 'add':
        await payload['message'].remove_reaction(payload['emoji'] , payload['user'])

        channelid = int(payload['Content'].replace('<#','').replace('>',''))
        channel = await self.server.fetch_channel(channelid)

        if payload['emoji'] == '👁':
            await channel.set_permissions(payload['user'], read_messages=True, send_messages=False)

        if payload['emoji'] == '💤':
            await channel.set_permissions(payload['user'], read_messages=False, send_messages=False)


import networkx as nx
import matplotlib.pyplot as plt
from art import text2art

print("========================================================================")
print(text2art("Grafo Boys", font="small"))
print("                                    2023 Grafoboys™. All rights reserved")
print("========================================================================")

# Pergunta se o grafo é direcionado
is_dirigido = input("O grafo é direcionado? (s/n): ").lower() == 's'

# Pergunta se o grafo é valorado
is_valorado = input("O grafo é valorado? (s/n): ").lower() == 's'

# Cria o grafo correspondente ao tipo
if is_dirigido:
    grafo = nx.DiGraph()
else:
    grafo = nx.Graph()

# Solicita a entrada de vértices
print("\nDigite os vertices do grafo: ")
while(True):
    v = input()
    if not v:
        break
    grafo.add_node(v)

# Solicita a entrada de arestas
print("\nDigite as arestas do grafo(x y peso): ")
while(True):
    a = input()
    if not a:
        break

    a1, a2, *peso = a.split()
    peso = float(peso[0]) if peso else 1.0

    if is_valorado:
        grafo.add_edge(a1, a2, weight=peso)
    else:
        grafo.add_edge(a1, a2)

# Imprime o grafo
pos = nx.spring_layout(grafo)
labels = nx.get_edge_attributes(grafo, 'weight')
nx.draw_networkx_nodes(grafo, pos, node_color='r', node_size=500)
nx.draw_networkx_edges(grafo, pos, edge_color='b', arrows=True)
nx.draw_networkx_labels(grafo, pos, font_size=20, font_family='sans-serif')
nx.draw_networkx_edge_labels(grafo, pos, edge_labels=labels, font_size=16)
plt.axis('off')
plt.show()

# Imprime ordem e tamanho do grafo
print("Ordem do grafo:", grafo.order())
print("Tamanho do grafo:", grafo.size())

# Imprime os vértices adjacentes a cada vértice
for v in grafo.nodes():
    print("Vértices adjacentes a", v, ":", list(grafo.neighbors(v)))

# Solicita a entrada de um vértice para imprimir o grau
print("\nDigite um vertice: ")
while(True):
    v = input()
    if not v:
        break
    print("Grau do vértice ", v,": ", grafo.degree(v))
    print("Lista de vértices adjacentes a", v, ": ")
    if is_dirigido:
        print("Entrada:", list(grafo.predecessors(v)))
        print("Saída:", list(grafo.successors(v)))
    else:
        print(list(grafo.neighbors(v)))
    print("\nDigite um vertice: ")

# Solicita a entrada de um par de vértices para imprimir se eles são adjacentes, menor caminho e custo do menor caminho
while(True):
    print("\nDigite um par vertices(x y): ")
    print("(Ou digite 'finalizar' para ver o raio e diâmetro):")

    v = input()
    if v.lower() == "finalizar":
        break

    v1, v2 = v.split()

    # Verifica se são adjacentes
    if grafo.has_edge(v1, v2):
        print("O vértice", v1, "é adjacente ao vértice", v2)
    else:
        print("O vértice", v1, "não é adjacente ao vértice", v2)
    if not is_dirigido:
        if nx.has_path(grafo, v1, v2):
            menor_caminho = nx.shortest_path(grafo, source=v1, target=v2, weight='weight') if is_valorado else nx.shortest_path(grafo, source=v1, target=v2)
            print("Menor caminho entre os vértices: ", str(menor_caminho))

            custo_menor_caminho = nx.shortest_path_length(grafo, source=v1, target=v2, weight='weight')
            print("Peso do menor caminho entre os vértices: ", custo_menor_caminho)
        else:
            print("Não  há caminho entre os vértices!")
    else:
        if nx.has_path(grafo.reverse(), v2, v1):
            menor_caminho = nx.shortest_path(grafo, source=v1, target=v2, weight='weight') if is_valorado else nx.shortest_path(grafo, source=v1, target=v2)
            print("Menor caminho entre os vértices: ", menor_caminho)

            custo_menor_caminho = nx.shortest_path_length(grafo, source=v1, target=v2, weight='weight')
            print("Peso do menor caminho entre os vértices: ", custo_menor_caminho)
        else:
            print("Não  há caminho entre os vértices!")

    # Calcula o menor caminho e o custo do menor caminho (caso o grafo seja valorado)

# Calcula e imprime o raio e o diâmetro do grafo
try:
    raio = nx.radius(grafo)
except nx.NetworkXError:
    print ("O grafo tem raio infinito!")

try:
    diametro = nx.diameter(grafo)
except nx.NetworkXError:
        print ("O grafo tem diâmetro infinito!")


from utils.node import Model, Node
from utils.io import Input, InputType

class SaveModel(Node):

    def function(self, data:Input, folder, prefix):

        if data.type != InputType.MODEL:
            raise TypeError(f"Input needs to be a model coming from a model node but got '{data.type.name.lower()}'")

        model:Model
        model, just_loaded = data.get()

        if not just_loaded:
            model.save(folder, prefix)
            self.done()
        else:
            self.clear_status()


from nextcord.ext import commands
import json

class serverevents(commands.Cog):
  def _init_(self, bot):
    self.bot = bot

  @commands.Cog.listener()
  async def on_guild_join(self, guild):
    with open('db/servers.json', 'r') as f:
      servers = json.load(f)

    servers[guild.id]= {}
    servers[guild.id]['name']= guild.name
    servers[guild.id]['prefix'] = "$"

    with open('db/servers.json', 'w') as f:
      json.dump(servers,f)

  @commands.Cog.listener()
  async def on_guild_remove(self, guild):
    with open('db/servers.json', 'r') as f:
      servers = json.load(f)

    try:
      servers.pop(str(guild.id))
    except:
      print("lmao")

    with open('db/servers.json', 'w') as f:
      json.dump(servers,f)

def setup(bot):
  bot.add_cog(serverevents(bot))


'''
Clase: Menu principal de Ventas
Autor: Martha Soto Luna
Matricula: 181803008
Fecha creación: 25/10/2022
Última fecha de modificación: 27/10/2022
Docente: Rebeca Rodríguez Huesca
Materia: Ingeniería de requisitos
Proyecto: Veterinaria
Versión: 2.0
'''

from ast import Delete
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from EliminarProducto import ventanaEliminar
from SalesMain import Ui_MenuVentas
from AgregarVenta import OtraVenta
from ConsultarVenta import ventanaConsultar

class ventanaPrincipalVent(QMainWindow):
    def __init__(self):
        super(ventanaPrincipalVent, self).__init__()
        self.ui = Ui_MenuVentas()
        self.ui.setupUi(self)

        self.ui.pushButton_Back.clicked.connect(self.salir)

        self.ui.pushButton_AddVenta.clicked.connect(self.VentanaAgregarV)
        self.ad = OtraVenta()

        self.ui.pushButton_consultVenta.clicked.connect(self.consultar)
        self.brows = ventanaConsultar()

    #Funciones para que los botones muestren las interfaces de VENTAS

    def VentanaAgregarV(self):
        self.ad.show()

    def consultar(self):
        self.brows.show()

    def salir(self):
        self.hide()

if __name__ == '__main__':
    app = QApplication([])
    main = ventanaPrincipalVent()
    main.show()
    sys.exit(app.exec())


from pyramid.traversal import find_interface

from substanced.util import get_dotted_name
from substanced.objectmap import find_objectmap

from substanced.catalog.indexes import AllowedIndex
from substanced.catalog import Catalog

import logging

_marker = object()

logger = logging.getLogger('evolution')

def evolve(root, registry):
    logger.info(
        'Running substanced evolve step 9: reindex all allowed indices '
        'due to change in discriminator principal repr'
        )

    site = root

    objectmap = find_objectmap(site)

    index_oids = objectmap.get_extent(get_dotted_name(AllowedIndex))

    for oid in index_oids:
        index = objectmap.object_for(oid)
        catalog = find_interface(index, Catalog)
        catalog.reindex(indexes=(index.__name__,))


#!/usr/bin/python

import sys
import timeit as tm
import subprocess as subpc
import numpy as np
import matplotlib.pyplot as plt

if __name__ != "__main__" or len(sys.argv) != 3:
    print("USAGE: ", sys.argv[0], " BINDIR FILENAME")

bindir = sys.argv[1]
filename = sys.argv[2]

def bench(name, grid, steps):
    start = tm.default_timer()
    subpc.run([bindir + "/" + name, str(grid), str(steps)])
    end = tm.default_timer()
    return end - start

ncells = 2 ** 29;
# grids = np.array([
#     16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256
#     ], dtype=np.uint)

grids = np.array([16, 32, 64, 80, 96, 112, 128, 144, 160], dtype=np.uint)

# static_cfg = [
#         ("linear", 0), ("linear", 1), ("linear", 2), ("linear", 3),
#         ("linear", 4), ("vector", 0), ("vector", 1), ("vector", 2),
#         ("zcube2", 0), ("zcube2", 1), ("zcube2", 2), ("zcube2", 3)
#         ]

static_cfg = [("vector", 0), ("vector", 2), ("zcube2", 0), ("zcube2", 3), ("linear", 0), ("linear", 4)]
# static_cfg = [("linear", 4), ("vector", 2), ("zcube2", 3)]
# static_cfg = [("vector", 2),]

fig, ax = plt.subplots()
ax.set_title("time benchmark, " + str(ncells) + " cells")

for (tile, rank) in static_cfg:
    name = tile + "_" + str(rank)
    times = np.array(
            [bench(name, grid, ncells / (grid ** 3)) for grid in grids])
    ax.plot(grids, times, label=name)

ax.set_xlabel("grid, nodes")
ax.set_ylabel("time, sec")
ax.set_ylim([0, None])

ax.legend()
plt.savefig(filename)


#In the 5 by 5 matrix below, the minimal path sum from the top left to the bottom right, by only moving to the right and down, is indicated in red and is equal to 2427.
#
#
#131    673    234    103    18
#201    96    342    965    150
#630    803    746    422    111
#537    699    497    121    956
#805    732    524    37    331
#
#
#Find the minimal path sum, in matrix.txt (right click and 'Save Link/Target As...'), a 31K text file containing a 80 by 80 matrix, from the top left to the bottom right by only moving right and down.

import logging
from util import parse_matrix

def main(args):
    matrix = parse_matrix("data/p081_matrix.txt")
    n = len(matrix)

    for i in range(n):
        for j in range(n):
            if (i == 0 and j == 0): continue
            if (i == 0):
                matrix[i][j] += matrix[i][j-1]
                continue
            if (j == 0):
                matrix[i][j] += matrix[i-1][j]
                continue
            if (matrix[i-1][j] < matrix[i][j-1]):
                matrix[i][j] += matrix[i-1][j]
            else:
                matrix[i][j] += matrix[i][j-1]

    logging.info("answer: {}".format(matrix[n-1][n-1]))


import numpy as np
import cv2

'''
Modifica la cantidad de fps y tamano del video.
Seteado ahora en dividir a 1/3 los fps
'''

video = '../data/videos/large1.mp4'
out = 'large1-10fps.mp4'
x,y,h,w = 0,0,720,1280

# Open the video
cap = cv2.VideoCapture(video)

# Initialize frame counter
cnt = 0

# Some characteristics from the original video
w_frame, h_frame = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps, frames = cap.get(cv2.CAP_PROP_FPS), cap.get(cv2.CAP_PROP_FRAME_COUNT)

# Here you can define your croping values
# x,y,h,w = 350,200,720,1280
# output
fourcc = cv2.VideoWriter_fourcc(*'MP4V')
#out = cv2.VideoWriter('720x1280-x350-y200_originalfps.mp4', fourcc, fps, (w, h))
out = cv2.VideoWriter(out, fourcc, fps/3, (w, h))

frames_mid_eliminate=0

# Now we start
while(cap.isOpened()):
    ret, frame = cap.read()
    cnt += 1 # Counting frames

    # Avoid problems when video finish
    if ret==True:
        if frames_mid_eliminate != 0:
            frames_mid_eliminate+=1
            if frames_mid_eliminate == 3:
                frames_mid_eliminate=0
            continue

        frames_mid_eliminate+=1
        # Croping the frame
        crop_frame = frame[y:y+h, x:x+w]

        # Percentage

        # Saving from the desired frames
        #if 15 <= cnt <= 90:
        #    out.write(crop_frame)

        # I see the answer now. Here you save all the video
        out.write(crop_frame)

        # Just to see the video in real time
        cv2.imshow('frame',frame)
        cv2.imshow('croped',crop_frame)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break

cap.release()
out.release()
cv2.destroyAllWindows()


from odoo import api, fields, models
from odoo.exceptions import UserError
import logging
_logger = logging.getLogger(__name__)

class MrpProduction(models.Model):
    _inherit = 'mrp.production'

    flsp_qty_backflushed = fields.Float(string="Qty Backflushed")

    def open_produce_product(self):
        self.ensure_one()
        self.action_assign()
        res = super(MrpProduction, self).open_produce_product()
        #if self.product_id.tracking in ['none', 'lot']:
            # needs the total quantity
        raw_moves = self.env['stock.move'].search([('raw_material_production_id', '=', self.id)])
        for move in raw_moves:
            if move.flsp_backflush:
                qtt_to_wip = move.product_uom_qty - move.reserved_availability
                if qtt_to_wip > 0:
                    self.create_wip_qty(move.product_id, qtt_to_wip)
                    self.action_assign()
#        else:
#            # needs only qty to produce 1
            #            raw_moves = self.env['stock.move'].search([('raw_material_production_id', '=', self.id)])
            #for move in raw_moves:
                    #                if move.flsp_backflush:
                    #qtt_to_wip = move.product_uom_qty - move.reserved_availability
                    #if qtt_to_wip > 0:
                        #                        self.create_wip_qty(move.product_id, 1)
                        #self.action_assign()
        return res

    def button_mark_done(self):
        self.ensure_one()
        self.action_assign()
        backflush_qty = self.product_qty - self.flsp_qty_backflushed
        self.new_backflush_flsp(backflush_qty)
        self.flsp_qty_backflushed = self.product_qty
        res = super(MrpProduction, self).button_mark_done()
        return res

    def post_inventory(self):
        self.ensure_one()
        self.action_assign()
        self.backflush_partials_flsp()
        res = super(MrpProduction, self).post_inventory()
        return res

    def backflush_partials_flsp(self):

        stock_move_done = self.env['stock.move'].search(
        ['&', '&', '&', ('product_id', '=', self.product_id.id),
                        ('production_id', '=', self.id),
                        ('is_done', '=', True),
                        ('scrapped', '=', False)])
        total_backflushable = 0
        for move in stock_move_done:
            total_backflushable += move.product_qty

        if self.flsp_qty_backflushed:
            total_to_backflush = total_backflushable - self.flsp_qty_backflushed
        else:
            total_to_backflush = total_backflushable

        self.new_backflush_flsp(total_to_backflush)
        if self.flsp_qty_backflushed:
            self.flsp_qty_backflushed += total_to_backflush
        else:
            self.flsp_qty_backflushed = total_to_backflush

    def new_backflush_flsp(self, backflush_qty=0):

        wip_location = self.env['stock.location'].search([('complete_name', '=', 'WH/PA/WIP')])
        stock_virtual_location = self.env['stock.location'].search([('complete_name', '=', 'Virtual Locations/My Company: Inventory adjustment')])
        virtual_production_location = self.env['stock.location'].search([('complete_name', '=', 'Virtual Locations/My Company: Production')])
        stock_picking_type = self.env['stock.picking.type'].search([('sequence_code', '=', 'INT')])
        pa_location = self.env['stock.location'].search([('complete_name', '=', 'WH/PA')]).parent_path
        pa_wip_locations = self.env['stock.location'].search([('parent_path', 'like', pa_location+'%')]).ids
        if not stock_picking_type:
            raise UserError('Picking type Internal is missing')
        if not stock_virtual_location:
            raise UserError('Stock Virtual Location is missing')
        if not virtual_production_location:
            raise UserError('Stock Virtual Production is missing')
        if not wip_location:
            raise UserError('WIP Stock Location is missing')
        if not pa_location:
            raise UserError('WIP Stock Location is missing')
        if not pa_wip_locations:
            raise UserError('WIP Stock Location is missing')

        ## Check if backflush is already done
        if backflush_qty <= 0:
            backflush_qty = self.product_qty - self.flsp_qty_backflushed
        if backflush_qty <= 0:
            return

        ## Verifing quantities of components in PA/WIP if available move the quantity needed on MO to virtual production:
        bom_components = self._get_flattened_totals(self.bom_id, backflush_qty)
        stock_picking = False
        for prod in bom_components:
            if bom_components[prod]['level'] == 1:
                continue
            if prod.type in ['service', 'consu']:
                continue
            if bom_components[prod]['total'] <= 0:
                continue

            if not stock_picking:
                create_val = {
                    'origin': self.name + ' FLSP-Backflush',
                    'picking_type_id': stock_picking_type.id,
                    'location_id': wip_location.id,
                    'location_dest_id': virtual_production_location.id,
                    'state': 'assigned',
                }
                stock_picking = self.env['stock.picking'].create(create_val)
            tracking = False
            wip_lot = {}
            if prod.tracking != 'none':
                tracking = prod.tracking
                ## Need to check if the quantity is available in WIP, if it is not do not transfer.
                stock_wip = self.env['stock.quant'].search(['&', ('product_id', '=', prod.id), ('location_id', 'in', pa_wip_locations)])
                qty_needed = bom_components[prod]['total']
                pa_wip_qty = 0
                for stock_lin in stock_wip:
                    pa_wip_qty += stock_lin.quantity
                qty_needed = bom_components[prod]['total']
                if qty_needed > pa_wip_qty:
                    qtt = qty_needed - pa_wip_qty
                    self.create_wip_qty(prod, qtt)
                    stock_wip = self.env['stock.quant'].search(['&', ('product_id', '=', prod.id), ('location_id', 'in', pa_wip_locations)])

                for lot in stock_wip:
                    if lot.quantity > 0:
                        if lot.quantity - qty_needed >= 0:
                            wip_lot[lot.lot_id] = {'qty': qty_needed, 'location': lot.location_id}
                            qty_needed = 0
                            break
                        else:
                            wip_lot[lot.lot_id] = {'qty': lot.quantity, 'location': lot.location_id}
                            qty_needed -= lot.quantity
                # In case we don't have the total quantity available will create a lot 999999_000000
                if qty_needed > 0:
                    if prod.tracking == 'lot':
                        new_lot = self.create_lot(prod, 1)
                        if new_lot:
                            wip_lot[new_lot[0]] = {'qty': qty_needed, 'location': wip_location}
                    else:
                        new_lot = self.create_lot(prod, int(qty_needed))
                        for lot in new_lot:
                            wip_lot[lot] = {'qty': 1, 'location': wip_location}
            else:
                qty_needed = bom_components[prod]['total']
                pa_wip_qty = 0
                stock_wip = self.env['stock.quant'].search(['&', ('product_id', '=', prod.id), ('location_id', 'in', pa_wip_locations)])
                for stock_lin in stock_wip:
                    pa_wip_qty += stock_lin.quantity
                qty_needed = bom_components[prod]['total']

                if qty_needed > pa_wip_qty:
                    qtt = qty_needed - pa_wip_qty
                    self.create_wip_qty(prod, qtt)
                    stock_wip = self.env['stock.quant'].search(['&', ('product_id', '=', prod.id), ('location_id', 'in', pa_wip_locations)])

            stock_move = self.env['stock.move'].create({
                'name': prod.name,
                'product_id': prod.id,
                'product_uom': prod.uom_id.id,
                'product_uom_qty': bom_components[prod]['total'],
                'picking_id': stock_picking.id,
                'location_id': wip_location.id,
                'location_dest_id': virtual_production_location.id
            })
            if tracking:
                for lot in wip_lot:
                    move_line = self.env['stock.move.line'].create({
                        'product_id': prod.id,
                        'product_uom_id': prod.uom_id.id,
                        'qty_done': wip_lot[lot]['qty'],
                        'lot_id': lot.id,
                        'picking_id': stock_picking.id,
                        'move_id': stock_move.id,
                        'location_id': wip_lot[lot]['location'].id,
                        'location_dest_id': virtual_production_location.id,
                        'state': 'assigned',
                        'done_move': True,
                    })
            else:
                move_line = self.env['stock.move.line'].create({
                    'product_id': prod.id,
                    'product_uom_id': prod.uom_id.id,
                    'qty_done': bom_components[prod]['total'],
                    #'lot_id': line.lot_id.id,
                    'picking_id': stock_picking.id,
                    'move_id': stock_move.id,
                    'location_id': wip_location.id,
                    'location_dest_id': virtual_production_location.id,
                    'state': 'assigned',
                    'done_move': True,
                })
        if stock_picking:
            stock_picking.button_validate()

    def _get_flattened_totals(self, bom, factor=1, totals=None, level=None):
        """Calculate the **unitary** product requirements of flattened BOM.
        *Unit* means that the requirements are computed for one unit of the
        default UoM of the product.
        :returns: dict: keys are components and values are aggregated quantity
        in the product default UoM.
        """
        if level is None:
            level = 1
        if totals is None:
            totals = {}
        factor /= bom.product_uom_id._compute_quantity(
            bom.product_qty, bom.product_tmpl_id.uom_id, round=False
        )
        for line in bom.bom_line_ids:
            # check if the product is consumable and backflushed, skip breaking it down in backflush if it is
            if line.product_id and line.product_id.type == 'consu' and line.product_id.flsp_backflush:
                continue

            sub_bom = bom._bom_find(product=line.product_id)
            if sub_bom:
                if not line.product_tmpl_id.flsp_backflush:
                    if totals.get(line.product_id):
                        totals[line.product_id]['total'] += (
                            factor
                            * line.product_uom_id._compute_quantity(
                                line.product_qty, line.product_id.uom_id, round=False
                            )
                        )
                    else:
                        totals[line.product_id] = {'total':(
                            factor
                            * line.product_uom_id._compute_quantity(
                                line.product_qty, line.product_id.uom_id, round=False
                            )
                        ), 'level': level, 'bom': sub_bom.code}
                    continue
                else:
                    new_factor = factor * line.product_uom_id._compute_quantity(
                        line.product_qty, line.product_id.uom_id, round=False
                    )

                level += 1
                self._get_flattened_totals(sub_bom, new_factor, totals, level)
                level -= 1
            else:
                if totals.get(line.product_id):
                    totals[line.product_id]['total'] += (
                        factor
                        * line.product_uom_id._compute_quantity(
                            line.product_qty, line.product_id.uom_id, round=False
                        )
                    )
                else:
                    totals[line.product_id] = {'total':(
                        factor
                        * line.product_uom_id._compute_quantity(
                            line.product_qty, line.product_id.uom_id, round=False
                        )
                    ), 'level': level, 'bom': ''}
        return totals

    def create_lot(self, prod, qty):
        ret = []
        company_id = self.env.company.id
        self._cr.execute("select max(name) as code from stock_production_lot where name like '999999%' ")
        retvalue = self._cr.fetchall()
        returned_registre = retvalue[0]
        latest_lot = returned_registre[0]
        if latest_lot:
            next_lot = ('00000'+str(int(latest_lot[-5:])+1))[-5:]
        else:
            next_lot = '00001'
        for x in range(0,qty):
            lot = self.env['stock.production.lot'].create({
                'name': '999999_'+next_lot,
                'product_id': prod.id,
                'ref': 'Backflush Adjust',
                'company_id': company_id,
            })
            next_lot = ('00000' + str(int(next_lot[1:6]) + 1))[-5:]
            ret.append(lot)
        return ret

    def create_wip_qty(self, prod, qty):
        wip_location = self.env['stock.location'].search([('complete_name', '=', 'WH/PA/WIP')])
        stock_virtual_location = self.env['stock.location'].search([('complete_name', '=', 'Virtual Locations/My Company: Inventory adjustment')])
        stock_picking_type = self.env['stock.picking.type'].search([('sequence_code', '=', 'INT')])
        if qty <= 0:
            return
        prod.flsp_bf_check = True
        if prod.tracking == 'none':
            create_val = {
                 'origin': self.name + ' FLSP-BF-ADJUST',
                 'picking_type_id': stock_picking_type.id,
                 'location_id': stock_virtual_location.id,
                 'location_dest_id': wip_location.id,
                 'state': 'assigned',}
            stock_picking = self.env['stock.picking'].create(create_val)
            stock_move = self.env['stock.move'].create({
                     'name': prod.name,
                     'product_id': prod.id,
                     'product_uom': prod.uom_id.id,
                     'product_uom_qty': qty,
                     'picking_id': stock_picking.id,
                     'location_id': stock_virtual_location.id,
                     'location_dest_id': wip_location.id,
                     'state': 'assigned',
                 })
            move_line = self.env['stock.move.line'].create({
                     'product_id': prod.id,
                     'product_uom_id': prod.uom_id.id,
                     'qty_done': qty,
                     'picking_id': stock_picking.id,
                     'move_id' : stock_move.id,
                     'location_id': stock_virtual_location.id,
                     'location_dest_id': wip_location.id,
                     'state': 'assigned',
                     'done_move': True,
                 })
            stock_picking.button_validate()
        elif prod.tracking == 'lot':
            new_lot = self.create_lot(prod, 1)
            create_val = {
                 'origin': self.name + ' FLSP-BF-ADJUST',
                 'picking_type_id': stock_picking_type.id,
                 'location_id': stock_virtual_location.id,
                 'location_dest_id': wip_location.id,
                 'state': 'assigned',}
            stock_picking = self.env['stock.picking'].create(create_val)
            stock_move = self.env['stock.move'].create({
                     'name': prod.name,
                     'product_id': prod.id,
                     'product_uom': prod.uom_id.id,
                     'product_uom_qty': qty,
                     'picking_id': stock_picking.id,
                     'location_id': stock_virtual_location.id,
                     'location_dest_id': wip_location.id,
                     'state': 'assigned',
                 })
            move_line = self.env['stock.move.line'].create({
                     'product_id': prod.id,
                     'product_uom_id': prod.uom_id.id,
                     'qty_done': qty,
                     'picking_id': stock_picking.id,
                     'move_id' : stock_move.id,
                     'lot_id': new_lot[0].id,
                     'location_id': stock_virtual_location.id,
                     'location_dest_id': wip_location.id,
                     'state': 'assigned',
                     'done_move': True,
                 })
            stock_picking.button_validate()
        else:
            new_lot = self.create_lot(prod, int(qty))
            create_val = {
                 'origin': self.name + ' FLSP-BF-ADJUST',
                 'picking_type_id': stock_picking_type.id,
                 'location_id': stock_virtual_location.id,
                 'location_dest_id': wip_location.id,
                 'state': 'assigned',}
            stock_picking = self.env['stock.picking'].create(create_val)
            stock_move = self.env['stock.move'].create({
                     'name': prod.name,
                     'product_id': prod.id,
                     'product_uom': prod.uom_id.id,
                     'product_uom_qty': qty,
                     'picking_id': stock_picking.id,
                     'location_id': stock_virtual_location.id,
                     'location_dest_id': wip_location.id,
                     'state': 'assigned',
                 })
            for lot in new_lot:
                move_line = self.env['stock.move.line'].create({
                         'product_id': prod.id,
                         'product_uom_id': prod.uom_id.id,
                         'qty_done': 1,
                         'picking_id': stock_picking.id,
                         'move_id': stock_move.id,
                         'lot_id': lot.id,
                         'location_id': stock_virtual_location.id,
                         'location_dest_id': wip_location.id,
                         'state': 'assigned',
                         'done_move': True,
                     })
            stock_picking.button_validate()


import streamlit as st
from st_clickable_images import clickable_images
import pandas as pd
from pytube import YouTube
import os
import requests
from time import sleep

upload_endpoint = "https://api.assemblyai.com/v2/upload"
transcript_endpoint = "https://api.assemblyai.com/v2/transcript"

headers = {
    "authorization": st.secrets["auth_key"],
    "content-type": "application/json"
}

@st.experimental_memo
def save_audio(url):
    yt = YouTube(url)
    video = yt.streams.filter(only_audio=True).first()
    out_file = video.download()
    base, ext = os.path.splitext(out_file)
    file_name = base + '.mp3'
    os.rename(out_file, file_name)
    print(yt.title + " has been successfully downloaded.")
    print(file_name)
    return yt.title, file_name, yt.thumbnail_url

@st.experimental_memo
def upload_to_AssemblyAI(save_location):
    CHUNK_SIZE = 5242880
    print(save_location)

    def read_file(filename):
        with open(filename, 'rb') as _file:
            while True:
                print("chunk uploaded")
                data = _file.read(CHUNK_SIZE)
                if not data:
                    break
                yield data

    upload_response = requests.post(
        upload_endpoint,
        headers=headers, data=read_file(save_location)
    )
    print(upload_response.json())

    audio_url = upload_response.json()['upload_url']
    print('Uploaded to', audio_url)

    return audio_url

@st.experimental_memo
def start_analysis(audio_url):
    print(audio_url)

    ## Start transcription job of audio file
    data = {
        'audio_url': audio_url,
        'iab_categories': True,
        'content_safety': True,
        "summarization": True,
        "summary_type": "bullets"
    }

    transcript_response = requests.post(transcript_endpoint, json=data, headers=headers)
    print(transcript_response)

    transcript_id = transcript_response.json()['id']
    polling_endpoint = transcript_endpoint + "/" + transcript_id

    print("Transcribing at", polling_endpoint)
    return polling_endpoint

@st.experimental_memo
def get_analysis_results(polling_endpoint):

    status = 'submitted'

    while True:
        print(status)
        polling_response = requests.get(polling_endpoint, headers=headers)
        status = polling_response.json()['status']
        # st.write(polling_response.json())
        # st.write(status)

        if status == 'submitted' or status == 'processing' or status == 'queued':
            print('not ready yet')
            sleep(10)

        elif status == 'completed':
            print('creating transcript')

            return polling_response

            break
        else:
            print('error')
            return False
            break

st.title("YouTube Content Analyzer")
st.markdown("With this app you can audit a Youtube channel to see if you'd like to sponsor them. All you have to do is to pass a list of links to the videos of this channel and you will get a list of thumbnails. Once you select a video by clicking its thumbnail, you can view:")
st.markdown("1. a summary of the video,")
st.markdown("2. the topics that are discussed in the video,")
st.markdown("3. whether there are any sensitive topics discussed in the video.")
st.markdown("Make sure your links are in the format: https://www.youtube.com/watch?v=HfNnuQOHAaw and not https://youtu.be/HfNnuQOHAaw")

default_bool = st.checkbox("Use a default file")

if default_bool:
    file = open("./links.txt")
else:
    file = st.file_uploader("Upload a file that includes the links (.txt)")

if file is not None:
    dataframe = pd.read_csv(file, header=None)
    dataframe.columns = ['urls']
    urls_list = dataframe['urls'].tolist()

    titles = []
    locations = []
    thumbnails = []

    for video_url in urls_list:
        # download audio
        video_title, save_location, video_thumbnail = save_audio(video_url)
        titles.append(video_title)
        locations.append(save_location)
        thumbnails.append(video_thumbnail)

    selected_video = clickable_images(thumbnails,
    titles = titles,
    div_style={"height": "400px", "display": "flex", "justify-content": "center", "flex-wrap": "wrap", "overflow-y":"auto"},
    img_style={"margin": "5px", "height": "150px"}
    )

    st.markdown(f"Thumbnail #{selected_video} clicked" if selected_video > -1 else "No image clicked")

    if selected_video > -1:
        video_url = urls_list[selected_video]
        video_title = titles[selected_video]
        save_location = locations[selected_video]

        st.header(video_title)
        st.audio(save_location)

        # upload mp3 file to AssemblyAI
        audio_url = upload_to_AssemblyAI(save_location)

        # start analysis of the file
        polling_endpoint = start_analysis(audio_url)

        # receive the results
        results = get_analysis_results(polling_endpoint)

        summary = results.json()['summary']
        topics = results.json()['iab_categories_result']['summary']
        sensitive_topics = results.json()['content_safety_labels']['summary']

        st.header("Summary of this video")
        st.write(summary)

        st.header("Sensitive content")
        if sensitive_topics != {}:
            st.subheader('ðŸš¨ Mention of the following sensitive topics detected.')
            moderation_df = pd.DataFrame(sensitive_topics.items())
            moderation_df.columns = ['topic','confidence']
            st.dataframe(moderation_df, use_container_width=True)

        else:
            st.subheader('âœ… All clear! No sensitive content detected.')

        st.header("Topics discussed")
        topics_df = pd.DataFrame(topics.items())
        topics_df.columns = ['topic','confidence']
        topics_df["topic"] = topics_df["topic"].str.split(">")
        expanded_topics = topics_df.topic.apply(pd.Series).add_prefix('topic_level_')
        topics_df = topics_df.join(expanded_topics).drop('topic', axis=1).sort_values(['confidence'], ascending=False).fillna('')

        st.dataframe(topics_df)


import numpy as np
import sys
import cv2
import onnxruntime
from yolox.data.data_augment import preproc as preprocess
from yolox.data.datasets import COCO_CLASSES
from yolox.utils import multiclass_nms, demo_postprocess, vis
import threading
from Base import BaseSR
import RPi.GPIO as GPIO
import time
from multiprocessing import Process,Value
import csv

class Short_Range(BaseSR):

    def __init__(self):

        global e
        global e1

        # 全体(GPIO)の初期化

        GPIO.setwarnings(False)

        #GPIOのモード
        #GPIO.setmode(GPIO.BOARD)#物理ピン番号でGPIOを指定
        GPIO.setmode(GPIO.BOARD)

        #----------------------------------------------------

        # 物体検出の初期化

        # 出力する動画ファイルの設定
        self.fps = 10
        self.size = (640,480)
        self.fourcc = cv2.VideoWriter_fourcc('m','p','4','v')
        self.video_name = 'VIDEO.avi'

        # 共通メモリ
        self.x_center = Value("d",320)
        self.count = Value("i",0) #カメラが終了したらモーターも終了するためのフラグ or 超音波で接近を検知したら、カメラが終了し映像を保存するためのフラグ

        # カメラ指定
        self.cap = cv2.VideoCapture(0)

        # 入力画像のサイズ
        self.input_shape = (416, 416)

        # モデルのファイル名
        self.session = onnxruntime.InferenceSession("yolox_nano_cone_best.onnx")

        #----------------------------------------------------

        # 超音波の初期化

        # PIN指定
        self.TRIG = 11
        self.ECHO = 13

        global signaloff
        global signalon

        #-----------------------------------------------------

        # モーターの初期化

        # PIN指定
        self.AIN1 = 15
        self.AIN2 = 29
        self.BIN1 = 31
        self.BIN2 = 33

        # duty比指定(0~100)
        self.duty = 50

    def object_detection(self):

        # 動画ファイルを保存するための形式指定
        video = cv2.VideoWriter(self.video_name, self.fourcc, self.fps, self.size)

        while(self.cap.isOpened()):

            # フレームを取得

            self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # バッファサイズ1
            ret, frame = self.cap.read() # 映像読み込み

            origin_img = frame
            img, ratio = preprocess(origin_img, self.input_shape)# モデルのinputが416*416で学習をしたため、カメラの映像のサイズを416*416にリサイズしている
            # 推論＋後処理
            ort_inputs = {self.session.get_inputs()[0].name: img[None, :, :, :]}
            output = self.session.run(None, ort_inputs)
            predictions = demo_postprocess(output[0], self.input_shape, p6=False)[0]

            # xyxyへの変換＋NMS
            boxes = predictions[:, :4]
            scores = predictions[:, 4:5] * predictions[:, 5:]#BoundingBoxごとのスコア
            boxes_xyxy = np.ones_like(boxes)
            boxes_xyxy[:, 0] = boxes[:, 0] - boxes[:, 2]/2.
            boxes_xyxy[:, 1] = boxes[:, 1] - boxes[:, 3]/2.
            boxes_xyxy[:, 2] = boxes[:, 0] + boxes[:, 2]/2.
            boxes_xyxy[:, 3] = boxes[:, 1] + boxes[:, 3]/2.
            boxes_xyxy /= ratio
            #boxes_xyxy = np.amax(boxes_xyxy)
            dets = multiclass_nms(boxes_xyxy, scores, nms_thr=0.40, score_thr=0.1)
            if dets is not None :#コーンが映った場合、BoundingBoxが描画される
                final_boxes, final_scores, final_cls_inds = dets[:, :4], dets[:, 4], dets[:, 5]
                # final_boxes　　認識した物体の座標(左上頂点のx,左上頂点のy,右下頂点のx,右下頂点のy)

                #座標がnumpy配列の一つの要素としてまとめられて渡されるので、区切る。
                x_left_upper = str(final_boxes)
                x_left_upper = x_left_upper.replace('[', '')
                x_left_upper = x_left_upper.replace(']', '')
                x_left_upper = x_left_upper.split()
                self.x_center.value = float(x_left_upper[0]) + float(x_left_upper[2]) / 2
                #print(np.max(final_scores))
                arg = np.argmax(final_scores)#認識した物体の中で、Coneの確率が最も高いのを取り出す。
                #print(final_cls_inds.max())

                #1つだけ認識できるようにした。もし複数物体認識したいのならvisualize.pyの#を外して、インデントを上げる。またmax()を外す。
                inference_img = vis(origin_img, final_boxes[arg], final_scores[arg], final_cls_inds.max(),
                            conf=0.5, class_names=COCO_CLASSES)#final_cls_indsに、.max()してるのは、要素を1つだけvis()に渡したいので、.max()とすることで一つだけ渡している。他のタスクとかではできない。
            cv2.imshow("Frame",frame)
            video.write(frame)

            # qキーが押されたら途中終了
            if cv2.waitKey(25) & 0xFF == ord('q') and self.count.value == 1:
                self.count.value = 1
                self.cap.release()
                print("camera finished")
                cv2.destroyAllWindows()
                break

    def motor_pid(self):
        GPIO.setup(self.AIN1,GPIO.OUT)
        GPIO.setup(self.AIN2,GPIO.OUT)
        GPIO.setup(self.BIN1,GPIO.OUT)
        GPIO.setup(self.BIN2,GPIO.OUT)
        #周波数設定
        a1 = GPIO.PWM(self.AIN1,255)#255Hz
        a2 = GPIO.PWM(self.AIN2,255)#255Hz
        b1 = GPIO.PWM(self.BIN1,255)
        b2 = GPIO.PWM(self.BIN2,255)
        #PWM起動
        a1.start(0)#Aenable接続（E）
        a2.start(0)#Aphase接続（P）
        b1.start(0)
        b2.start(0)
        """
        with open('hcsr04.csv', 'w') as fh:
            hcsr04 = csv.writer(fh)
            hcsr04.writerow(['distance'])
        """

        while True:
            print("-----------------------")
            print("center : "+ str(self.x_center.value))
            #zahyouha baai ni yotte kaeru

            print("Ultra Sound : " + str(self.reading(0)))
            """
            with open('hcsr04.csv', 'w') as fh:
                hcsr04 = csv.writer(fh)
                distance_row = [self.reading(0)]
                hcsr04.writerow(distance_row)
            """
            if self.reading(0) < 0.00000001:

                a1.ChangeDutyCycle(0)
                a2.ChangeDutyCycle(0)
                b1.ChangeDutyCycle(0)
                b2.ChangeDutyCycle(0)

                self.count.value = 1

                break

            if  270 <= self.x_center.value and self.x_center.value < 370 :
                #まっすぐ進み動作(物体が中心近くにいる際)
                print("forward")
                a1.ChangeDutyCycle(self.duty)
                a2.ChangeDutyCycle(0)
                b1.ChangeDutyCycle(0)
                b2.ChangeDutyCycle(self.duty)
                time.sleep(2)
            elif self.x_center.value < 270 :
                #回転する動作(物体がカメラの中心から左にずれている際)
                print("CCW")
                a1.ChangeDutyCycle(self.duty)
                a2.ChangeDutyCycle(0)
                b1.ChangeDutyCycle(self.duty)
                b2.ChangeDutyCycle(0)
                time.sleep(2)

            elif self.x_center.value >= 370 :
                #回転する動作（物体がカメラの中心から右にずれている際）
                print("CW")
                a1.ChangeDutyCycle(0)
                a2.ChangeDutyCycle(self.duty)
                b1.ChangeDutyCycle(0)
                b2.ChangeDutyCycle(self.duty)
                time.sleep(2)

            else:
                print("nazo")

            if self.count.value == 1:
                #fh.close()
                break

            #self.x_before = self.x_center

if __name__ == '__main__':
    cansat = Short_Range()

    p1 = Process(target=cansat.object_detection)
    p2 = Process(target=cansat.motor_pid)
    p1.start()
    p2.start()
    GPIO.cleanup()
    p1.join()
    p2.join()


#!/usr/bin/python3
""" The console
FileStorage class module
"""
import json
from models.base_model import BaseModel
from models.user import User
from models.place import Place
from models.state import State
from models.city import City
from models.amenity import Amenity
from models.review import Review

class FileStorage:
    """
    Class that serializes object/instances to a JSON file
    and deserializes JSON file to objects/instances
    """

    __file_path = "file.json"
    __objects = {}

    def all(self):
        """
        function that returns the dictionary __objects
        """
        return FileStorage.__objects

    def save(self):
        """serialise"""
        new_dict = {}
        for key, value in FileStorage.__objects.items():
            new_dict[key] = value.to_dict()
        with open(FileStorage.__file_path, "w")as f:
            json.dump(new_dict, f)

    def new(self, obj):
        """set obj """
        obj_id = obj.id
        obj_name = obj.__class__.__name__
        FileStorage.__objects[obj_name + "." + str(obj_id)] = obj

    def reload(self):
        """ deserialised """
        self.__objects = {}
        try:
            with open(self.__file_path, "r") as f:
                data = json.load(f)
                for key, value in data.items():
                    cls = value["__class__"]
                    obj = eval(cls)(**value)
                    self.__objects[key] = obj
        except FileNotFoundError:
            pass


import abc
from dataclasses import dataclass
from pathlib import Path
import random
import re
import logging
from typing import Any, Callable, Dict, List, Optional, Tuple, Union

import numpy as np
import PIL.Image
import torch
import torchvision.transforms.functional as TF

from common_fate_object_learning import io_utils

LOGGER = logging.getLogger(__name__)

BACKGROUND = 0
OCCLUSION = 1
FOREGROUND = 2

class _SampleFrame(abc.ABC):
    @abc.abstractstaticmethod
    def from_path(path: Path, name: str) -> Any:
        raise NotImplementedError

    @abc.abstractmethod
    def is_valid(self) -> bool:
        raise NotImplementedError

    @abc.abstractmethod
    def load(self, size: int) -> Any:
        raise NotImplementedError

    def _get_padding(self, image_size: Tuple[int], target_size: int):
        width, height = image_size

        target_width = max(height*2, width + width % 2)
        target_height = target_width // 2
        assert target_height * 2 == target_width

        top_pad    = (target_height - height) // 2
        bottom_pad = target_height - height - top_pad
        left_pad   = (target_width - width) // 2
        right_pad  = target_width - width - left_pad

        return left_pad, top_pad, right_pad, bottom_pad

@dataclass
class _SampleFrameTraining(_SampleFrame):
    image_path: Path
    mask_path: Path

    @staticmethod
    def from_path(path: Path, name: str):
        return _SampleFrameTraining(
            path / f"{name}.image.png",
            path / f"{name}.mask.png"
        )

    def is_valid(self) -> bool:
        return self.image_path.is_file() and self.mask_path.is_file()

    def load(self, size: int = 32):
        image = io_utils.pil_loader(self.image_path, mode="RGB")
        mask = io_utils.pil_loader(self.mask_path, mode="L")

        padding = self._get_padding(image.size, size)

        image = TF.pad(image, padding=padding, padding_mode='edge')
        mask = TF.pad(mask, padding=padding, padding_mode='constant', fill=0)

        image = TF.to_tensor(TF.resize(image, size, PIL.Image.NEAREST))
        mask = torch.from_numpy(np.asarray(TF.resize(mask, size, PIL.Image.NEAREST))).long()

        return image, mask

@dataclass
class _SampleFrameValidation(_SampleFrame):
    sample_id: int
    object_id: int
    frame_id: int
    image_path: Path
    mask_path: Path
    target_image_path: Path
    target_mask_path: Path

    @staticmethod
    def from_path(path: Path, name: str):
        match = re.match(r".*sample(\d+)_object(\d+)/frame(\d+).*", str(path / name))
        if not match:
            LOGGER.warning("Warning: Unable to parse sample path: {}", path / name)
            sample_id = None
            object_id = None
            frame_id = None
        else:
            sample_id = int(match.group(1))
            object_id = int(match.group(2))
            frame_id = int(match.group(3))

        return _SampleFrameValidation(
            sample_id,
            object_id,
            frame_id,
            path / f"{name}.image.png",
            path / f"{name}.mask.png",
            path / f"{name}.image-full.png",
            path / f"{name}.mask-full.png",
        )

    def is_valid(self):
        return self.image_path.is_file() and \
               self.mask_path.is_file() and \
               self.target_image_path.is_file() and \
               self.target_mask_path.is_file()

    def load(self, size: int = 32):
        image = io_utils.pil_loader(self.image_path, mode="RGB")
        mask = io_utils.pil_loader(self.mask_path, mode="L")
        target_image = io_utils.pil_loader(self.target_image_path, mode="RGB")
        target_mask = io_utils.pil_loader(self.target_mask_path, mode="L")

        padding = self._get_padding(image.size, size)

        image = TF.pad(image, padding=padding, padding_mode='edge')
        image = TF.to_tensor(TF.resize(image, size, PIL.Image.NEAREST))

        mask = TF.pad(mask, padding=padding, padding_mode='constant', fill=0)
        mask = torch.from_numpy(np.asarray(TF.resize(mask, size, PIL.Image.NEAREST))).long()

        target_image = TF.pad(target_image, padding=padding, padding_mode='edge')
        target_image = TF.to_tensor(TF.resize(target_image, size, PIL.Image.NEAREST))

        target_mask = TF.pad(target_mask, padding=padding, padding_mode='constant', fill=0)
        target_mask = torch.from_numpy(np.asarray(TF.resize(target_mask, size, PIL.Image.NEAREST))).long()

        return {
            "sample_id": self.sample_id,
            "object_id": self.object_id,
            "frame_id": self.frame_id,
            "image": image,
            "mask": mask,
            "target_image": target_image,
            "target_mask": target_mask
        }

class ObjectDataset(torch.utils.data.Dataset):
    """Loads object crops with segmentation masks.

    This assumes the following file structure:
    ```
    dataset/sample<sample_id>_object<object_id>/frame<frame_id>.image.png
    dataset/sample<sample_id>_object<object_id>/frame<frame_id>.mask.png
    ```

    The `*.image.png` files are the cropped objects as RGB images, the
    `*.masks.png` are grayscale images defining the object masks using the
    following code:
    - 0 = background
    - 1 = other object
    - 2 = object of interest

    The length of this dataset is the number of objects. When retrieving an
    object, this will randomly sample the given number of frames for this object.
    """

    def __init__(self,
                 path: str,
                 num_frames_per_object: int = 1,
                 size: int = 32,
                 transform: Optional[Callable] = None,
                 load_evaluation_data: bool = False,
                 old_format: bool = False) -> None:
        """Initializes the data laoder

        Args:
            path: Path to the dataset.
            num_frames_per_object: Number of frames to load per object.
            size: Return samples resized and cropped to (size, size*2).
            transform: Optional transform to apply to images and masks.
            old_format: If set to true, the old data format is used
                without folders per object. Every (image,mask) pair is then
                interpreted as individual objects.
        """
        self._path = Path(path)
        self._num_frames_per_object = num_frames_per_object
        self.size = size
        self.transform = transform
        self._load_evaluation_data = load_evaluation_data
        self._old_format = old_format

        self._load_samples()

    def _load_samples(self) -> None:
        self._samples = []

        if self._old_format:
            # Old format = No subfolder per object
            # This will interprete every image pair as individual object
            if self._num_frames_per_object <= 1:
                self._samples = self._load_sample_frames(path)
                self._samples = [List[frame] for frame in self._samples]
            return

        for sample_path in self._path.iterdir():
            if sample_path.is_dir():
                frames = self._load_sample_frames(sample_path)

                if len(frames) > self._num_frames_per_object:
                    self._samples.append(frames)

    def _load_sample_frames(self, path: Path) -> List[_SampleFrame]:
        frames = []

        for image_path in path.glob("*.image.png"):
            name = image_path.name[:-len(".image.png")]

            if not self._load_evaluation_data:
                frame = _SampleFrameTraining.from_path(image_path.parent, name)
            else:
                frame = _SampleFrameValidation.from_path(image_path.parent, name)

            if frame.is_valid():
                frames.append(frame)

        return frames

    def __len__(self):
        """Returns the number of samples in this dataset."""
        return len(self._samples)

    def __getitem__(self, index):
        """Returns the sample with the given index."""
        frames = random.sample(self._samples[index], self._num_frames_per_object)
        frames = [frame.load(self.size) for frame in frames]

        if not self._load_evaluation_data:
            images = torch.stack([image for image, _ in frames])
            masks = torch.stack([mask for _, mask in frames])

            if self.transform is not None:
                return self.transform(images, masks)

            return images, masks

        else:
            stacked_frames = {}

            for key in frames[0].keys():
                stacked_frames[key] = torch.stack([
                    frame[key] if isinstance(frame[key], torch.Tensor) else torch.tensor(frame[key])
                    for frame in frames
                ])

            if self.transform is not None:
                stacked_frames["image"], stacked_frames["mask"] = \
                    self.transform(stacked_frames["image"], stacked_frames["mask"])

                stacked_frames["target_image"], stacked_frames["target_mask"] = \
                    self.transform(stacked_frames["target_image"], stacked_frames["target_mask"])

            return stacked_frames

class ObjectDatasetValidation(torch.utils.data.Dataset):
    def __init__(self,
                 path: Union[str, Path],
                 sample_size: int = 32,
                 transform: Optional[Callable] = None):
        self._path = Path(path)
        self.sample_size = sample_size
        self.transform = transform

        self._load_index()

    def _load_index(self) -> None:
        self._samples = []

        for sample_path in self._path.iterdir():
            if sample_path.is_dir():
                self._samples += self._load_sample_frames(sample_path)

    def _load_sample_frames(self, path: Path) -> List[_SampleFrameValidation]:
        frames = []

        for image_path in path.glob("*.image.png"):
            name = image_path.name[:-len(".image.png")]
            frame = _SampleFrameValidation.from_path(image_path.parent, name)

            if frame.is_valid():
                frames.append(frame)

        return frames

    def __len__(self) -> int:
        return len(self._samples)

    def __getitem__(self, index: int) -> Dict:
        frame = self._samples[index].load(self.sample_size)

        frame["image"] = frame["image"].unsqueeze(0)
        frame["mask"] = frame["mask"].unsqueeze(0)
        frame["target_image"] = frame["target_image"].unsqueeze(0)
        frame["target_mask"] = frame["target_mask"].unsqueeze(0)

        if self.transform is not None:
            frame["image"], frame["mask"] = \
                self.transform(frame["image"], frame["mask"])

            frame["target_image"], frame["target_mask"] = \
                self.transform(frame["target_image"], frame["target_mask"])

        return frame


import sys
sys.path.insert(0, '../')
from mv3dpose.data.openpose import OpenPoseKeypoints, MultiOpenPoseKeypoints
from mv3dpose.tracking import tracking, Track
import mv3dpose.geometry.camera as camera
from os.path import isdir, join, isfile
from os import makedirs, listdir
from tqdm import tqdm
from time import time
import json
import numpy as np
import shutil

dataset_dir = '/home/user/dataset'
output_dir = join(dataset_dir, 'tracks3d')
dataset_json = join(dataset_dir, 'dataset.json')

vid_dir = join(dataset_dir, 'videos')
cam_dir = join(dataset_dir, 'cameras')
kyp_dir = join(dataset_dir, 'poses')

assert isdir(vid_dir)
assert isdir(cam_dir)

if isdir(output_dir):
    print('\n[deleting existing output directory...]')
    shutil.rmtree(output_dir)

makedirs(output_dir)

# ~~~~~~~~~~~~~~~~~~~~~~

Settings = json.load(open(dataset_json))

scale_to_mm = Settings['scale_to_mm']
n_cameras = Settings['n_cameras']

def get_optional(key, default_value):
    if key in Settings:
        return Settings[key]
    else:
        return default_value

epi_threshold = get_optional(
    'epi_threshold', 80)
max_distance_between_tracks = get_optional(
    'max_distance_between_tracks', 80)
min_track_length = get_optional(
    'min_track_length', 10)
merge_distance = get_optional(
    'merge_distance', 80)
last_seen_delay = get_optional(
    'last_seen_delay', 15)
smoothing_sigma = get_optional(
    'smoothing_sigma', 2)
smoothing_interpolation_range = get_optional(
    'smoothing_interpolation_range', 50)
do_smoothing = get_optional(
    'do_smoothing', True
)

if 'valid_frames' in Settings:
    valid_frames = Settings['valid_frames']
else:
    # take all frames in the setup
    files = listdir(join(vid_dir, 'camera00'))
    valid_frames = list(range(len(files)))

print("\n#frames", len(valid_frames))

# ~~~~~~~~~~~~~~~~~
# K E Y P O I N T S
# ~~~~~~~~~~~~~~~~~
print('\n[load keypoints]')
keypoints = []
for cid in tqdm(range(n_cameras)):
    loc = join(kyp_dir, 'camera%02d' % cid)
    assert isdir(loc), loc
    pe = OpenPoseKeypoints('frame%09d', loc)
    keypoints.append(pe)
pe = MultiOpenPoseKeypoints(keypoints)

# ~~~~~~~~~~~~~
# C A M E R A S
# ~~~~~~~~~~~~~
print('\n[load cameras]')
Calib = []  # { n_frames x n_cameras }
try:
    for t in tqdm(valid_frames):
        calib = []
        Calib.append(calib)
        for cid in range(n_cameras):
            local_camdir = join(cam_dir, 'camera%02d' % cid)
            assert isdir(local_camdir)
            cam_fname = join(local_camdir, 'frame%09d.json' % t)
            assert isfile(cam_fname), cam_fname
            cam = camera.Camera.load_from_file(cam_fname)
            calib.append(cam)
except AssertionError:
    print('\tnew version of cameras is used...')

    class CamerasPerFrame:

        def __init__(self, cam_dir, n_cameras, valid_frames):
            self.n_cameras = n_cameras
            self.n_frames = len(valid_frames)
            self.first_frame = valid_frames[0]
            self.cameras = []
            for cid in range(n_cameras):
                camfile = join(cam_dir, 'camera%02d.json' % cid)
                with open(camfile, 'r') as f:
                    cam_as_dict_list = json.load(f)

                cam_as_object_list = []
                for cam in cam_as_dict_list:
                    start_frame = cam['start_frame']
                    end_frame = cam['end_frame']
                    K = np.array(cam['K'])
                    rvec = np.array(cam['rvec'])
                    tvec = np.array(cam['tvec'])
                    distCoef = np.array(cam['distCoef'])
                    w = int(cam['w'])
                    h = int(cam['h'])
                    cam = camera.ProjectiveCamera(K, rvec, tvec, distCoef, w, h)

                    cam_as_object_list.append({
                        "start_frame": start_frame,
                        "end_frame": end_frame,
                        "cam": cam
                    })

                self.cameras.append(cam_as_object_list)

        def __getitem__(self, frame):
            """
            :param frame: frame, starting at 0!
            """
            frame += self.first_frame

            cameras = [1] * self.n_cameras
            for cid, cam_as_object_list in enumerate(self.cameras):
                for cam in cam_as_object_list:
                    start_frame = cam['start_frame']
                    end_frame = cam['end_frame']
                    if start_frame <= frame <= end_frame:
                        cameras[cid] = cam['cam']
                        break
            for cam in cameras:
                assert cam != 1
            return cameras

        def __len__(self):
            return self.n_frames

    Calib = CamerasPerFrame(cam_dir, n_cameras, valid_frames)

# ~~~~~~~~~~~~~~~~~~~~~~~
# L O A D  2 D  P O S E S
# ~~~~~~~~~~~~~~~~~~~~~~~
print('\n[load 2d poses]')
poses_per_frame = []
for frame in tqdm(valid_frames):
    predictions = pe.predict(frame)
    poses_per_frame.append(predictions)

# ~~~~~~~~~~~~~~~
# T R A C K I N G
# ~~~~~~~~~~~~~~~
print('\n[tracking]')
_start = time()
tracks = tracking(Calib, poses_per_frame,
                  epi_threshold=epi_threshold,
                  scale_to_mm=scale_to_mm,
                  max_distance_between_tracks=max_distance_between_tracks,
                  actual_frames=valid_frames,
                  min_track_length=min_track_length,
                  merge_distance=merge_distance,
                  last_seen_delay=last_seen_delay)
_end = time()
print('\telapsed', _end - _start)
print("\n\t# detected tracks:", len(tracks))

# ~~~~~~~~~~~~~~~
# S M O T H I N G
# ~~~~~~~~~~~~~~~
if do_smoothing:
    print('\n[smoothing]')
    tracks_ = []
    for track in tqdm(tracks):
        track = Track.smoothing(track,
                                sigma=smoothing_sigma,
                                interpolation_range=smoothing_interpolation_range)
        tracks_.append(track)
    tracks = tracks_

# ~~~~~~~~~~~~~~~~~
# S E R I A L I Z E
# ~~~~~~~~~~~~~~~~~
print('\n[serialize 3d tracks]')
for tid, track in tqdm(enumerate(tracks)):
    fname = join(output_dir, 'track' + str(tid) + '.json')
    track.to_file(fname)


from django.urls import path
from .views import IndexView, DetailItemView, CreateItemView, UpdateItemView, DeleteItemView

urlpatterns = [
    path('', IndexView.as_view(), name='index'),
    path('<int:pk>/', DetailItemView.as_view(), name='detail_view'),
    path('create/', CreateItemView.as_view(), name='create'),
    path('<int:pk>/update/', UpdateItemView.as_view(), name='update'),
    path('<int:pk>/delete/', DeleteItemView.as_view(), name='delete'),
]