from schedules import *
import cfg
from datetime import datetime
import telebot
from arg import *
from dateutil.tz import tzoffset
from groups import group

def chooseSched(groupNumb):

    for i in group:
        for j in range(len(group[i])):
            if str(group[i][j]) == str(groupNumb):

                print(groupNumb)
                global schedule
                schedule = sched[i][j]

timezone = 2
offset = tzoffset(None, timezone * 3600)  # offset in seconds

def time_update():
    global now,hour,minute
    now = datetime.now(offset)
    hour = int(now.strftime("%H"))
    minute = int(now.strftime("%M"))

bot = telebot.TeleBot(cfg.TOKEN)

def day_change(arg):
    return arg + count

def hours_para():

    h1 = [[9, 0], [10, 30], [12, 30], [14, 0], [15, 30], [16, 50]]
    h2 = [[10, 20], [11, 50], [13, 50], [15, 20], [16, 50], [17, 0]]

    if hour < h1[0][0]:
        return 0, (h1[0][0] - hour)*60+h1[0][1]-minute

    for i in range(0, 5):
        left = (h2[i][0] - hour)*60+h2[i][1]-minute
        if left >= 0:
            if left >80:
                break
            print('here1')
            return i+1, left
    if (hour == h1[5][0] and minute > h1[4][1]) or (hour >= h2[5][0]):
        return 6, None
    else:
        return None,None

def hours_break():
    h1 = [[10, 20], [11, 50], [13, 50], [15, 20]]
    h2 = [[10, 30], [12, 30], [14, 0], [15, 30]]
    for i in range(0, 4):
        left = (h2[i][0] - hour) * 60 + h2[i][1] - minute
        if left >= 0:
            print('here2')
            return i + 1, left

def week_now(change=0):
    week = (int(now.strftime("%V")) + change) % 2
    # Учебный год начинаться с четной недели (не совпадает)
    if week == 1:
        return schedule[1]
    elif week == 0:
        return schedule[0]

def number_of_para(arg):
    return (week_now().get(now.weekday())).get(arg)

def para_today_by_arg(key=0):

    para_numb, left = hours_para()
    print(para_numb)
    if para_numb is not None:
        numb = key + para_numb
    else:
        break_numb, left = hours_break()
        if key == 0:
            return "Сейчас перемена после пары №" + str(break_numb) + "\n\nДо следующей пары осталось: *" + str(left) + \
                   "* минут"
        elif key > 0:
            numb = break_numb + key
        else:
            numb = break_numb + key + 1
    if numb <= 0:
        return "Пары ещё не начались" + "\nДо первой пары: *"+str(left) + "* минут"
    elif numb <= 5:
        para = number_of_para(numb)
        if para is not None:
            return "*" + "Пара №" + str(numb) + "*\n*У первой подгруппы:*\n" + para[0] + "\n*У второй подгруппы:*\n" + para[1] + \
                   "\nДо конца пары: *" + str(left) + "* минут"
        else:
            return "\nУ первой и второй подгруппы сейчас нет пар"
    elif numb >= 6:
        return "*Пары уже закончились*"

def para_today_by_number(numb):
    para = number_of_para(numb)
    return "*Пара №" + str(numb) + "\nУ подгруппы А:* \n" + para[0] + "\n*У подгруппы В: *\n" + para[1]

def para_by_key_word(day):
    if now.weekday() > day >= 0:
        another_week = 1
        day = day_change(day)
    else:
        day = day_change(day)
        another_week = day // 7

    def output(numb, key=0):
        return "\n*" + str(numb) + " пара" +"*\n" + "*Подгруппа А:*\n" + \
               (week_now(another_week).get(key % 7)).get(numb)[0] + "\n*Подгруппа В:*\n" + \
               (week_now(another_week).get(key % 7)).get(numb)[1] + "\n"

    out = "\n"
    for i in range(1, 6):
        out += output(i, day)
    return out

chatId = None

def checkAddNewGroup(chat_id, id_input):
    for i in group:
        for j in group[i]:
            if str(j) == str(id_input):
                with open("chatid.txt", "a", encoding="utf8") as f:
                    f.write("{chat_id}:{id_input}\n".format(chat_id=str(chat_id), id_input=str(id_input)))
                return 1
    return 0

def checkChatId(chat_id):
    with open("chatid.txt", "r", encoding="utf8") as f:
        for line in f:
            if str(chat_id) in line:

                grp = line.split(":")[1]
                grp = grp.replace("\n", "")
                return str(grp)
    return 0

def checkReplaceOldGroup(chat_id, id_input):

    for i in group:
        for j in group[i]:
            if str(j) == str(id_input):
                with open("chatid.txt", "r", encoding="utf8") as f:
                    id_list = f.readlines()
                    amountOfLines = range(len(id_list))
                    for i in amountOfLines:
                        grp = id_list[i].split(":")
                        if str(chat_id) == grp[0]:
                            changed = [chat_id, id_input]
                            changedIndex = i

                            writeToFile = ""
                            for l in amountOfLines:
                                if l != changedIndex:
                                    writeToFile += id_list[l].split(":")[0]+str(":")+id_list[l].split(":")[1]
                                else:
                                    writeToFile += str(changed[0])+str(":")+str(changed[1])+"\n"
                            with open("chatid.txt","w",encoding="utf8") as f:
                                f.write(writeToFile)
                            return str(id_input)
    return 0

@bot.message_handler(commands=['help', 'start', 'para'])
def first(message):
    first_buttons = telebot.types.ReplyKeyboardMarkup(True, True)
    first_buttons.row('Какая сейчас пара?', 'Какая следующая пара')
    first_buttons.row('Какие пары сегодня?', 'Какие пары завтра?')
    bot.send_message(message.chat.id, 'Что Вы хотите узнать?', reply_markup=first_buttons)

def listener(message):
    time_update()

    msg_txt = ""
    chat_id = ""

    for m in message:
        chat_id = m.chat.id

        if m.content_type == 'text':
            msg_txt = m.text.lower()

    def the_day(value):
        return (now.weekday() + value) % 7

    msg_txt = msg_txt.replace('?', '')
    msg_txt = msg_txt.replace('!', '')

    split_msg = msg_txt.split()

    for i in ['пара', 'пары', 'расписание']:
        for j in split_msg:
            if i == j:

                grp = checkChatId(chat_id)
                stop = False
                for k in split_msg:
                    if k == 'группа':
                        if grp == 0:
                            for g in split_msg:
                                if checkAddNewGroup(chat_id, g) == 1:
                                    bot.send_message(chat_id, 'Успех')
                                    print("Успех")
                                    break
                            else:
                                bot.send_message(chat_id, 'Провал')
                                print("Провал")
                            stop = True
                        else:
                            result = 0
                            for g in split_msg:
                                result = checkReplaceOldGroup(chat_id, g)
                                if result != 0:
                                    bot.send_message(chat_id, 'Группа успешно изменена на {}'.format(result))
                                    stop = True
                                    break
                            if result == 0:
                                bot.send_message(chat_id, 'Неверно указана группа или другая ошибка')
                                stop = True
                                break

                if stop is True:
                    break

                grp = checkChatId(chat_id)

                if grp == 0:
                    bot.send_message(chat_id, 'Чата id{} нет в базе.\nУкажите вашу группу написав: \n"расписание группа [номер группы]"\n\nНапример: Расписание группа 209'.format(chat_id))
                    break
                else:
                    chooseSched(grp)

                    msg_txt = msg_txt.replace(i, '')
                    global count
                    count = msg_txt.count('после') - msg_txt.count('поза') - msg_txt.count('перед') - msg_txt.count('до')

                    msg_txt = (msg_txt.strip())
                    msg_txt += " "
                    print(msg_txt)

                    def check():
                        i=-1
                        while i<12:
                            for slovo in arg[i]:
                                if slovo in msg_txt:

                                    if i <= 1:
                                        return para_by_key_word(the_day(i))
                                    elif i <= 8:
                                        return para_by_key_word(i-2)
                                    elif i == 9:
                                        return para_today_by_number(int(slovo))
                                    elif i <= 11:
                                        return para_today_by_arg(i-10)
                            i += 1
                        else:
                            return 0

                    send = check()
                    if str((int(now.strftime("%V"))) % 2) == 1:
                        kindOfWeek = "чётная неделя"
                    else:
                        kindOfWeek = "нечётная неделя"
                    if send != 0:
                        bot.send_message(chat_id, "`альфа тест\nВнимание!!!!\nКабинеты могут быть указаны НЕВЕРНО!\n`" + str(send)+\
                                         "\n\n`сейчас "+ kindOfWeek+"`", parse_mode= 'Markdown')
                    break

bot.set_update_listener(listener)

try:
    bot.polling(none_stop=True)
except:
    pass


import unittest
import sys

from zen import *
from zen.algorithms.community import *

import numpy as np

#TODO Test empty community / communityset

class CommunityTestCase(unittest.TestCase):

	def setUp(self):
		self.NUM_NODES = 5

		self.G = Graph()
		for i in range(self.NUM_NODES):
			self.G.add_node(i)

		self.fake_community = Community(0, self.G,
				{i for i in range(self.NUM_NODES)})

		self.non_probabilistic = Community(0, self.G, set(range(self.NUM_NODES)))

		self.probabilistic = Community(0, self.G, set(range(self.NUM_NODES)),
							{i: 1.0 / (i + 1) for i in range(self.NUM_NODES)})

		self.empty = Community(0, self.G, set())

	def test_has_node(self):

		# Test presence of all inserted nodes in the community
		for i in range(self.NUM_NODES):
			self.assertTrue(self.fake_community.has_node_index(i))
			self.assertTrue(i in self.fake_community)

		# Test absence of nodes
		self.assertFalse(self.fake_community.has_node_index(self.NUM_NODES))
		self.assertFalse(self.NUM_NODES in self.fake_community)

	def test_empty(self):
		self.assertEqual(len(self.empty), 0)
		self.assertFalse(self.empty.has_node_index(0))
		self.assertFalse(0 in self.empty)

	def test_assoc_prob(self):
		# Communities with no probability info always return 1 on nodes that
		# are part of the community
		for i in range(self.NUM_NODES):
			self.assertEqual(self.non_probabilistic.assoc_prob(i), 1.0)
			self.assertEqual(self.non_probabilistic.assoc_prob_(i), 1.0)

		# Communities with probability info are expected to return it for nodes
		# in that are part of the community
		for i in range(self.NUM_NODES):
			self.assertEqual(self.probabilistic.assoc_prob(i), 1.0 / (i + 1))
			self.assertEqual(self.probabilistic.assoc_prob_(i), 1.0 / (i + 1))

		# If the node is not part of the community, then 0 should be returned
		# regardless of whether there is probability information
		self.assertEqual(self.non_probabilistic.assoc_prob(self.NUM_NODES), 0.0)
		self.assertEqual(self.non_probabilistic.assoc_prob_(self.NUM_NODES), 0.0)
		self.assertEqual(self.probabilistic.assoc_prob(self.NUM_NODES), 0.0)
		self.assertEqual(self.probabilistic.assoc_prob_(self.NUM_NODES), 0.0)

class CommunitySetTestCase(unittest.TestCase):

	def setUp(self):
		self.G = Graph()
		self.NUM_NODES = 10

		for i in range(self.NUM_NODES):
			self.G.add_node(i)

		# Communities, with nodes that belong to it:
		# 0: 0,1 / 1: 2,3 / 2: 4,5 / 3: 6,7 / 4: 8,9
		fake_community_table = np.array([i / 2 for i in range(self.NUM_NODES)])
		self.cmnties = CommunitySet(self.G, fake_community_table, self.NUM_NODES / 2)

	def test_community_idx(self):

		# Test that the nodes belong to the expected community
		for i in range(self.NUM_NODES):
			self.assertEqual(i / 2, self.cmnties.node_community_indices(i)[0])
			self.assertEqual(i / 2, self.cmnties.node_community_indices_(i)[0])

		# Test that an exception is raised for nodes that are not in the set
		self.assertRaises(ZenException, self.cmnties.node_community_indices_, self.NUM_NODES)
		self.assertRaises(KeyError, self.cmnties.node_community_indices, self.NUM_NODES)

	def test_share_community(self):

		# Test that communities are shared as expected (by how cmnties is built)
		for i in range(0, self.NUM_NODES, 2):
			self.assertTrue(self.cmnties.share_community(i, i + 1))
			self.assertTrue(self.cmnties.share_community_(i, i + 1))

		# Test reflexivity of community sharing
		for i in range(self.NUM_NODES):
			self.assertTrue(self.cmnties.share_community(i, i))
			self.assertTrue(self.cmnties.share_community_(i, i))

		# Test symmetry of community sharing
		for i in range(self.NUM_NODES - 1):
			if(self.cmnties.share_community(i, i + 1)):
				self.assertTrue(self.cmnties.share_community(i + 1, i))
			else:
				self.assertFalse(self.cmnties.share_community(i + 1, i))

			if(self.cmnties.share_community_(i, i + 1)):
				self.assertTrue(self.cmnties.share_community_(i + 1, i))
			else:
				self.assertFalse(self.cmnties.share_community_(i + 1, i))

		#Test that no node shares a community with a node not in the graph
		for i in range(self.NUM_NODES):
			self.assertFalse(self.cmnties.share_community(i, self.NUM_NODES))
			self.assertRaises(ZenException, self.cmnties.share_community_, i, self.NUM_NODES)

	def test_community(self):
		for i in range(self.NUM_NODES):

			com_idx = self.cmnties.node_communities_(i)[0]
			com_obj = self.cmnties.node_communities(i)[0]

			# Test that the communities returned contain the objects they are
			# supposed to
			self.assertTrue(com_idx.has_node_index(i))
			self.assertTrue(i in com_obj)

			if i % 2 == 1:
				other = i - 1
			else:
				other = i + 1

			self.assertTrue(com_idx.has_node_index(other))
			self.assertTrue(other in com_idx)

			# Test that the given community indices are as expected
			self.assertEqual(com_idx.community_idx, self.cmnties.node_community_indices_(i)[0])
			self.assertEqual(com_obj.community_idx, self.cmnties.node_community_indices(i)[0])

			# Test that the communities contain only the expected nodes
			self.assertEqual(len(com_idx), 2)
			self.assertEqual(len(com_obj), 2)

	#TODO communities
	def test_communities(self):
		pass

	#TODO iteration
	def test_iteration(self):
		pass

	def test_len(self):
		self.assertEqual(len(self.cmnties), self.NUM_NODES / 2)

class OverlappingCommunitySetTestCase(unittest.TestCase):

	def setUp(self):
		self.G = Graph()
		self.NUM_NODES = 8
		self.NUM_COMMUNITIES = 3
		self.COMMUNITY_SIZE = 4

		for i in range(self.NUM_NODES):
			self.G.add_node(i)

		# Communities with their nodes:
		# 0: [0, 1, 2, 3]
		# 1: [2, 3, 4, 5]
		# 2: [4, 5, 6, 7]
		fake_community_table = np.empty(self.NUM_COMMUNITIES, dtype=set)
		fake_community_table[0] = set([0,1,2,3])
		fake_community_table[1] = set([2,3,4,5])
		fake_community_table[2] = set([4,5,6,7])

		self.cmnties = OverlappingCommunitySet(self.G, fake_community_table,
												self.NUM_COMMUNITIES)

	def test_community_idx(self):

		for i in range(0, 4):
			self.assertTrue(0 in self.cmnties.node_community_indices(i))
			self.assertTrue(0 in self.cmnties.node_community_indices_(i))

		for i in range(2, 6):
			self.assertTrue(1 in self.cmnties.node_community_indices(i))
			self.assertTrue(1 in self.cmnties.node_community_indices_(i))

		for i in range(4, 8):
			self.assertTrue(2 in self.cmnties.node_community_indices(i))
			self.assertTrue(2 in self.cmnties.node_community_indices_(i))

		# Test that an exception is raised for nodes that are not in the set
		self.assertRaises(ZenException, self.cmnties.node_community_indices_, self.NUM_NODES)
		self.assertRaises(KeyError, self.cmnties.node_community_indices, self.NUM_NODES)

	def test_share_community(self):

		# Test that communities are shared as expected (by how cmnties is built)
		for i in range(0, self.NUM_NODES, 2):
			self.assertTrue(self.cmnties.share_community(i, i + 1))
			self.assertTrue(self.cmnties.share_community_(i, i + 1))

		# Test reflexivity of community sharing
		for i in range(self.NUM_NODES):
			self.assertTrue(self.cmnties.share_community(i, i))
			self.assertTrue(self.cmnties.share_community_(i, i))

		# Test symmetry of community sharing
		for i in range(self.NUM_NODES - 1):
			if(self.cmnties.share_community(i, i + 1)):
				self.assertTrue(self.cmnties.share_community(i + 1, i))
			else:
				self.assertFalse(self.cmnties.share_community(i + 1, i))

			if(self.cmnties.share_community_(i, i + 1)):
				self.assertTrue(self.cmnties.share_community_(i + 1, i))
			else:
				self.assertFalse(self.cmnties.share_community_(i + 1, i))

		#Test that no node shares a community with a node not in the graph
		for i in range(self.NUM_NODES):
			self.assertFalse(self.cmnties.share_community(i, self.NUM_NODES))
			self.assertRaises(ZenException, self.cmnties.share_community_, i, self.NUM_NODES)

	def test_community(self):
		for i in range(self.NUM_NODES):

			comms_idx = self.cmnties.node_communities_(i)
			comms_obj = self.cmnties.node_communities(i)

			# Test that the communities returned contain the objects they are
			# supposed to, and that the given community indices are as expected
			for comm in comms_idx:
				self.assertTrue(comm.has_node_(i))
				self.assertTrue(comm.community_idx in self.cmnties.node_community_indices_(i))

			for comm in comms_obj:
				self.assertTrue(i in comm)
				self.assertTrue(comm.community_idx in self.cmnties.node_community_indices(i))

	#TODO communities
	def test_communities(self):
		pass

	#TODO iteration
	def test_iteration(self):
		pass

	def test_len(self):
		self.assertEqual(len(self.cmnties), self.NUM_COMMUNITIES)

class CommunityDetectionTestCase(unittest.TestCase):

	def setUp(self):
		self.algorithms = [ lpa,
							label_rank,
							spectral_modularity,
							louvain ]
		#Algorithms that are supposed to work on graphs that were not compacted
		self.noncontiguous_algorithms = [	lpa,
											label_rank,
											louvain,
											slpa ]

		self.empty = Graph()

		self.disconnected = Graph()
		self.disconnected.add_edge(0, 1)
		self.disconnected.add_edge(2, 3)

		self.k3 = Graph()
		self.k3.add_edge(0, 1)
		self.k3.add_edge(1, 2)
		self.k3.add_edge(2, 0)

		self.noncontiguous = Graph()
		self.noncontiguous.add_node(0)
		self.noncontiguous.add_node(1)
		self.noncontiguous.add_node(2)
		self.noncontiguous.add_node(3)
		self.noncontiguous.add_edge(0, 2)
		self.noncontiguous.add_edge(2, 3)
		self.noncontiguous.rm_node(1)

		self.isolated = Graph()
		self.isolated.add_node(0)
		self.isolated.add_node(1)
		self.isolated.add_node(2)
		self.isolated.add_edge(1, 2)

		self.selfloop = Graph()
		self.selfloop.add_node(0)
		self.selfloop.add_node(1)
		self.selfloop.add_node(2)
		self.selfloop.add_edge(0, 1)
		self.selfloop.add_edge(0, 2)
		self.selfloop.add_edge(1, 2)
		self.selfloop.add_edge(0, 0)

	def __algorithm_test_empty(self, algorithm):
		# Test that no communities are detected on an empty graph
		cset = algorithm(self.empty)
		self.assertEqual(len(cset.communities()), 0)

	def __algorithm_test_disconnected(self, algorithm):
		# Test that two communities are detected on a disconnected graph with
		# two components
		cset = algorithm(self.disconnected)
		self.assertEqual(len(cset.communities()), 2)

	def __algorithm_test_k3(self, algorithm):
		# Test that one community is detected on a K3
		cset = algorithm(self.k3)
		self.assertEqual(len(cset.communities()), 1)

	def __algorithm_test_noncontiguous_nidc(self, algorithm):
		# Test that the algorithm doesn't fail if the node indices are not
		# contiguous
		try:
			algorithm(self.noncontiguous)
		except Exception as e:
			self.fail("Noncontiguous test failed with " + e.__class__.__name__ +
						": \"" + str(e) + "\"")

	def __algorithm_test_selfloop(self, algorithm):
		# Test that the algorithm doesn't fail on graphs containing self-loops
		try:
			algorithm(self.selfloop)
		except Exception as e:
			self.fail("Self-loop test failed with " + e.__class__.__name__ +
						": \"" + str(e) + "\"")

	def __algorithm_test_isolated(self, algorithm):
		# Test that the algorithm doesn't fail on graphs containing isolated nodes
		try:
			algorithm(self.isolated)
		except Exception as e:
			self.fail("Isolated node test failed with " + e.__class__.__name__ +
						": \"" + str(e) + "\"")

	def test_sanity_algorithms(self):
		# Some simple graphs with obvious answers
		for alg in self.algorithms:

			try:
				self.__algorithm_test_empty(alg)
				self.__algorithm_test_disconnected(alg)
				self.__algorithm_test_k3(alg)
				self.__algorithm_test_selfloop(alg)
				self.__algorithm_test_isolated(alg)
			except Exception as e:
				e.args = () + (e.args[0] + " (in algorithm " + alg.__name__ + ")",)
				e.args += e.args[1:]
				raise

		for alg in self.noncontiguous_algorithms:
			self.__algorithm_test_noncontiguous_nidc(alg)

if __name__ == '__main__':
	unittest.main()


#!/usr/bin/python3
# coding: utf-8
# author: Werner
# email: me@werner.wiki
# date: 2020.03.05

import re
from urllib import parse
from http import HTTPStatus

import requests

from settings import *

class Proxy(object):

    def __init__(self, handler):
        self.handler = handler
        self.url = self.handler.path[1:]
        parse_result = parse.urlparse(self.url)
        self.scheme = parse_result.scheme
        self.netloc = parse_result.netloc
        self.site = self.scheme + '://' + self.netloc
        self.path = parse_result.path

    def proxy(self):
        """
        处理、转发请求，获取响应并在处理后转发，
        :return:
        """
        self.process_request()
        content_length = int(self.handler.headers.get('Content-Length', 0))
        data = self.handler.rfile.read(content_length)
        try:
            r = requests.request(method=self.handler.command, url=self.url, headers=self.handler.headers,
                                 data=data, verify=False, allow_redirects=False)
        except BaseException as error:
            self.process_error(error)
        else:
            self.process_response(r)

    def process_request(self):
        """
        处理请求
        :return:
        """
        self.modify_request_header('Referer', lambda x: x.replace(SERVER, ''))
        self.modify_request_header('Origin', self.site)
        self.modify_request_header('Host', self.netloc)
        self.modify_request_header('Accept-Encoding', 'identity')
        self.modify_request_header('Connection', 'close')

    def process_response(self, r):
        """
        处理响应
        :param r: requests.models.Response
        :return:
        """
        self.handler.send_response(r.status_code)
        content = self.revision_link(r.content, r.encoding)
        if 'location' in r.headers._store:    # 跟随30x跳转
            self.handler.send_header('Location', self.revision_location(r.headers._store['location'][1]))
        if 'content-type' in r.headers._store:
            self.handler.send_header('Content-Type', r.headers._store['content-type'][1])
        if 'set-cookie' in r.headers._store:
            self.revision_set_cookie(r.headers._store['set-cookie'][1])
        self.handler.send_header('Content-Length', len(content))
        self.handler.send_header('Access-Control-Allow-Origin', '*')
        self.handler.send_header('Connection', 'close')
        self.handler.end_headers()
        self.handler.wfile.write(content)

    def process_error(self, error):
        """
        处理错误
        :param error:
        :return:
        """
        self.handler.send_error(HTTPStatus.BAD_REQUEST, str(error))

    def modify_request_header(self, header, value):
        """
        修改请求头
        :param header: str
        :param value: str or function
        :return:
        """
        target_header = None
        for _header in self.handler.headers._headers:
            if _header[0] == header:
                target_header = _header
                break
        if target_header is not None:
            self.handler.headers._headers.remove(target_header)
            if callable(value):
                new_header_value = value(target_header[1])
            else:
                new_header_value = value
            self.handler.headers._headers.append((header, new_header_value))

    def revision_location(self, location):
        """
        修正跳转链接
        :param location:
        :return:
        """
        if location.startswith('http://') or location.startswith('https://'):
            new_location = SERVER + location
        elif location.startswith('//'):
            new_location = SERVER + self.scheme + ':' + location
        elif location.startswith('/'):
            new_location = SERVER + self.site + location
        else:
            new_location = SERVER + self.site + self.path + '/' + location
        return new_location

    def revision_link(self, body, coding):
        """
        修正响应内容中的链接
        :return:
        """
        if coding is None:    # 当coding为空时认为是二进制数据
            return body
        rules = [
            ("'{}http://", SERVER),
            ('"{}http://', SERVER),
            ("'{}https://", SERVER),
            ('"{}https://', SERVER),
            ('"{}//', SERVER + self.scheme + ':'),
            ("'{}//", SERVER + self.scheme + ':'),
            ('"{}/', SERVER + self.site),
            ("'{}/", SERVER + self.site),
        ]
        for rule in rules:
            body = body.replace(rule[0].replace('{}', '').encode('utf-8'), rule[0].format(rule[1]).encode('utf-8'))
        return body

    def revision_set_cookie(self, cookies):
        """
        修正Set-Cookie响应头
        :param cookies: 用`, `连接了所有cookie后的字符串，麻烦的地方在于expires中也有`, `
        :return:
        """
        cookie_list = list()
        half_cookie = None
        for _cookie in cookies.split(', '):
            if half_cookie is not None:
                cookie_list.append(', '.join([half_cookie, _cookie]))
                half_cookie = None
            elif 'Expires' in _cookie or 'expires' in _cookie:
                half_cookie = _cookie
            else:
                cookie_list.append(_cookie)
        for _cookie in cookie_list:
            self.handler.send_header('Set-Cookie', self.revision_response_cookie(_cookie))

    def revision_response_cookie(self, cookie):
        """
        修正 Set-Cookie 中的 domain、path 和 secure 等
        :param cookie:
        :return:
        """
        cookie = re.sub(r'domain\=[^,;]+', 'domain=.{}'.format(DOMAIN), cookie, flags=re.IGNORECASE)
        cookie = re.sub(r'path\=\/', 'path={}/'.format('/' + self.site), cookie, flags=re.IGNORECASE)
        if SCHEME == 'http':
            cookie = re.sub(r'secure;?', '', cookie, flags=re.IGNORECASE)
        return cookie


# Pattern: for 4
# 1
# 2*2
# 3*3*3
# 4*4*4*4
# 4*4*4*4
# 3*3*3
# 2*2
# 1

n = int(input())

if(n <= 0):
    print('Wrong Input')
else:
    for i in range(1, n+1):
        if(i == 0):
            print(i)
        else:
            print('*'.join([str(i) for j in range(i)]))
    for i in reversed(range(1, n+1)):
        if(i == 0):
            print(i)
        else:
            print('*'.join([str(i) for j in range(i)]))


"""Plot!"""
# pylint: disable=abstract-class-instantiated
import datetime
import sys

import numpy as np
import pandas as pd
from pandas.io.sql import read_sql
from paste.request import parse_formvars
from pyiem.util import get_dbconn

sys.path.append("/opt/datateam/htdocs/td")
from common import CODES, COPYWRITE, getColor, send_error  # noqa

LINESTYLE = [
    "-",
    "-",
    "-",
    "-",
    "-",
    "-",
    "-",
    "-",
    "-.",
    "-.",
    "-.",
    "-.",
    "-.",
    "-",
    "-.",
    "-.",
    "-.",
    "-.",
    "-.",
    "-.",
    "-.",
    "-.",
    "-.",
    "-.",
]
BYCOL = {"daily": "day", "monthly": "month", "yearly": "year"}

def make_plot(form, start_response):
    """Make the plot"""
    uniqueid = form.get("site", "ISUAG")

    sts = datetime.datetime.strptime(
        form.get("date", "2014-01-01"), "%Y-%m-%d"
    )
    days = int(form.get("days", 1))
    ets = sts + datetime.timedelta(days=days)
    pgconn = get_dbconn("td")
    by = form.get("by", "daily")
    ungroup = int(form.get("ungroup", 0))
    df = read_sql(
        f"SELECT date_trunc('{BYCOL[by]}', date)::date as v, "
        "coalesce(plotid, location) as datum, "
        "avg(water_table_depth) as depth from water_table_data "
        "WHERE siteid = %s and date between %s and %s "
        "GROUP by v, datum ORDER by v ASC",
        pgconn,
        params=(uniqueid, sts.date(), ets.date()),
    )
    if len(df.index) < 3:
        return send_error(
            start_response, "by", "No / Not Enough Data Found, sorry!"
        )
    linecol = "datum"
    if ungroup == 0:
        # Generate the plotid lookup table
        plotdf = read_sql(
            "SELECT * from wellids where siteid = %s",
            pgconn,
            params=(uniqueid,),
            index_col="wellid",
        )

        def lookup(row):
            """Likely better means in pandas for this, but alas"""
            try:
                return plotdf.loc[row["datum"], "y%s" % (row["v"].year,)]
            except KeyError:
                return row["datum"]

        df["treatment"] = df.apply(lookup, axis=1)
        del df["datum"]
        df = df.groupby(["treatment", "v"]).mean()
        df.reset_index(inplace=True)
        linecol = "treatment"

    # Begin highcharts output
    start_response("200 OK", [("Content-type", "application/javascript")])
    title = "Water Table Depth for Site: %s (%s to %s)" % (
        uniqueid,
        sts.strftime("%-d %b %Y"),
        ets.strftime("%-d %b %Y"),
    )
    s = []
    plot_ids = df[linecol].unique()
    plot_ids.sort()
    if ungroup == 0:
        plot_ids = plot_ids[::-1]
    df["ticks"] = pd.to_datetime(df["v"]).astype(np.int64) // 10**6
    for i, plotid in enumerate(plot_ids):
        df2 = df[df[linecol] == plotid]
        v = df2[["ticks", "depth"]].to_json(orient="values")
        s.append(
            """{
            """
            + getColor(plotid, i)
            + """,
            name: '"""
            + CODES.get(plotid, plotid)
            + """',
            data: """
            + v
            + """
        }"""
        )
    series = ",".join(s)
    res = (
        """
$("#hc").highcharts({
    """
        + COPYWRITE
        + """
    title: {text: '"""
        + title
        + """'},
    chart: {zoomType: 'x'},
    yAxis: {title: {text: 'Depth below ground (mm)'},
        reversed: true
    },
    plotOptions: {
        line: {turboThreshold: 0}
    },
    xAxis: {
        type: 'datetime'
    },
    tooltip: {
        dateTimeLabelFormats: {
            hour: "%b %e %Y, %H:%M",
            minute: "%b %e %Y, %H:%M"
        },
        shared: true,
        valueDecimals: 0,
        valueSuffix: ' mm'
    },
    series: ["""
        + series
        + """]
});
    """
    )
    return res.encode("utf-8")

def application(environ, start_response):
    """Do Something"""
    form = parse_formvars(environ)
    return [make_plot(form, start_response)]


import tensorflow as tf
from numpy.random import RandomState
#定义训练数据batch大小
batch_size = 16

#定义神经网络的各层的参数 这边定义2层的隐藏层
w1 = tf.Variable(tf.random_normal([2,4],stddev=1,seed=1))
w2 = tf.Variable(tf.random_normal([4,4],stddev=1,seed=1))
w3 = tf.Variable(tf.random_normal([4,1],stddev=1,seed=1))

#定义输入信息
x = tf.placeholder(tf.float32,shape=(None,2),name='x_input')
y_ = tf.placeholder(tf.float32,shape=(None,1),name='y_input')

#定义计算过程
c1 = tf.matmul(x,w1)
c2 = tf.matmul(c1,w2)
y = tf.matmul(c2,w3)

#定义损失函数
cross_entropy = -tf.reduce_mean(
    y_ * tf.log(tf.clip_by_value(y,1e-10,1.0)))
train_step = tf.train.AdadeltaOptimizer(0.001).minimize(cross_entropy)

#随机生成数据
data_size = 256
rd = RandomState(1)
X = rd.rand(data_size,2)
#定义x_1 + x_2 >= 1 => _y =0 or x_1 + x_2 < 1 => _y = 1
Y = [[int(x_1+x_2<1)] for (x_1,x_2) in X]

with tf.Session() as sess:
    init_parm = tf.global_variables_initializer()
    sess.run(init_parm)
    #print(sess.run(w1))
    #print(sess.run(w2))
    #print(sess.run(w3))

    #设置循环次数
    STEPS_NUM = 5000
    for i in range(STEPS_NUM):
        start = (i*batch_size) % data_size
        end = min(start+batch_size,data_size)

        #根据获取的样本对参数进行更新
        #print(X[start:end])
        #print(Y[start:end])
        sess.run(train_step,feed_dict={x:X[start:end],y_:Y[start:end]})

        #每迭代1000次查看一下交叉商
        if i%1000 == 0:
            total_cross_entropy = sess.run(cross_entropy,feed_dict={x:X,y_:Y})
            print("after %d trian steps,cross_entropy is %g"%(i,total_cross_entropy))

    print(sess.run(w1))
    print(sess.run(w2))
    print(sess.run(w3))


import pygame as py
from auxiliar.constantes import *

class Plataforma (py.sprite.Sprite):

    def __init__(self,pos, stage_dict_configs: dict) -> None:
        super().__init__()
        #me traigo el diccionario de plataforma
        self.__plataform_configs = stage_dict_configs.get('plataforma')
        #cargo la imagen de la plataforma
        self.image = py.image.load(self.__plataform_configs["plataforma_img"]).convert_alpha()
        self.rect = self.image.get_rect(midbottom=pos)
        self.plataform_group = py.sprite.Group()

        self.rect_ground_collition_top = py.Rect(self.rect.x, self.rect.y, self.rect.w, altura_rect)
        self.rect_ground_collition_bottom = py.Rect(self.rect.x, self.rect.y + self.rect.h - altura_rect, self.rect.w, altura_rect)

    def update(self, screen: py.surface.Surface):

        self.draw(screen)

    def draw(self, screen: py.surface.Surface):

        if (DEBUG):
            py.draw.rect(screen,ROJO,self.rect)

        screen.blit(self.image, self.rect)

        if (DEBUG):
            py.draw.rect(screen,VERDE,self.rect_ground_collition_top)
            py.draw.rect(screen,VERDE,self.rect_ground_collition_bottom)


import argparse
import os

from . import api, model

__version__ = "0.8.1"

def board_list_handler(api_credentials, _args):
    return api.Boards(**api_credentials).list()

def list_handler(api_credentials, args):
    list_ids = api.Lists(**api_credentials)
    list_ids.board_id = args.board_id
    return list_ids.list()

def card_create_handler(api_credentials, args):
    if args.cards_csv:
        cards_list = model.cards_from_csv(args.cards_csv)
    else:
        cards_list = [model.card_from_dict(args.__dict__)]

    return [api.Cards(**api_credentials).create(card) for card in cards_list]

def main():
    parser = argparse.ArgumentParser(description="Interacts with Trello Restful API")
    parser.add_argument("--api_key", default=os.environ.get("TRELLO_API_KEY"))
    parser.add_argument("--api_token", default=os.environ.get("TRELLO_API_TOKEN"))

    subparsers = parser.add_subparsers(help="service help")

    boards = subparsers.add_parser("boards")
    board_actions = boards.add_subparsers()

    board_list = board_actions.add_parser("list")
    board_list.set_defaults(func=board_list_handler)

    lists = subparsers.add_parser("lists")
    lists.add_argument("--board_id", dest="board_id")
    lists.set_defaults(func=list_handler)

    cards = subparsers.add_parser("cards")
    card_actions = cards.add_subparsers()

    card_create = card_actions.add_parser("create")
    card_csv = card_create.add_argument_group("create from csv")
    card_csv.add_argument(
        "-f", "--from-csv", dest="cards_csv", type=argparse.FileType("r")
    )

    card_model = card_create.add_argument_group("create from cli")
    card_model.add_argument("--name", dest="name", type=str)
    card_model.add_argument("--desc", dest="desc", type=str)
    card_model.add_argument("--idList", dest="idList", type=str)

    card_create.set_defaults(func=card_create_handler)
    args = parser.parse_args(
        "cards create --name test --desc test --idList abc123".split()
    )

    args = parser.parse_args()

    api_credentials = {"api_key": args.api_key, "api_token": args.api_token}

    try:
        print(args.func(api_credentials, args))
    except AttributeError:
        parser.print_help()


import cv2
import numpy as np
import scipy.io as sio
from matplotlib import pyplot as plt
from sklearn.preprocessing import MinMaxScaler
import glob

files = glob.glob('../../saved_numpy_arrays/RGB_as_numpy/*.npy')

n = 10
def get_distribution(leftside, rightside):
    hist,bins = np.histogram(leftside,256,[0,256])
    hist2,bins2 = np.histogram(rightside,256,[0,256])

    return hist, hist2

#center_frame = int(np.ceil(file_npy.shape[0] / 2))

def loop_through_video(file_npy):
    means = np.zeros([file_npy.shape[0]])
    stds = np.zeros([file_npy.shape[0]])
    for i in range(n, len(file_npy)-n):
        left_ravel = get_left_raveled_images(i, file_npy)
        right_ravel = get_right_raveled_images(i, file_npy)
        l_mean, l_std = np.mean(left_ravel), np.std(left_ravel)
        r_mean, r_std = np.mean(right_ravel), np.std(right_ravel)
        means[i] = np.abs(l_mean - r_mean)
        stds[i] = np.abs(l_std - r_std)

    return means, stds

def get_left_raveled_images(center_frame, file_npy):
    left_ravel = np.zeros([37632])
    for i in range(center_frame - n, center_frame, 1):
        raveled_image = np.ravel(file_npy[i])
        left_ravel += raveled_image

    left_ravel = np.round(left_ravel / n)
    return left_ravel

def get_right_raveled_images(center_frame, file_npy):
    right_ravel = np.zeros([37632]) # 112*112*3
    for i in range(center_frame, center_frame + n, 1):
        raveled_image = np.ravel(file_npy[i])
        right_ravel += raveled_image

    right_ravel = np.round(right_ravel / n)
    return right_ravel

def normalise(X):
    X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
    X_scaled = X_std * (X.max() - X.min()) + X.min()

    return X_scaled

def plot_results(gt_scores, means, stds, fileName):
    fig, axs = plt.subplots(3, 1)
    t = np.arange(0, gt_scores.shape[0], 1)
    plt.subplots_adjust(hspace=1)

    axs[0].plot(t, stds, label='stds')
    axs[0].plot(t, means, label='means')
    axs[0].set_xlabel('frames')
    axs[0].set_ylabel('abs residual')
    axs[0].legend(loc='upper left', shadow=True)

    axs[1].plot(t, gt_scores, label='gt_scores')
    axs[1].set_xlabel('frames')
    axs[1].set_ylabel('gt_score')
    axs[1].legend(loc='upper left', shadow=True)

    axs[2].plot(t, means, label='means')
    axs[2].plot(t, stds, label='stds')
    axs[2].plot(t, gt_scores, label='gt_scores')
    axs[2].set_xlabel('frames')
    axs[2].set_ylabel('gt_scres with residual')
    axs[2].legend(loc='upper left', shadow=True)
#    plt.gca().set_position([0, 0, 1, 1])
    from os.path import expanduser
    home = expanduser("~")

    fig.savefig(home+'/Pictures/'+fileName+'.png')

def get_plots_for_all_videos():
    for i in range(len(files)):
        fileName = files[i].split('/')[-1].split('.')[0]
        file_npy = np.load('../../saved_numpy_arrays/RGB_as_numpy/'+fileName+'.npy')
        means, stds = loop_through_video(file_npy)
        scaler = MinMaxScaler()
        means = scaler.fit_transform(means)
        stds = scaler.fit_transform(stds)
        print(fileName)
        gt_scores = sio.loadmat('../../SumMe/GT/'+fileName+'.mat').get('gt_score')
        plot_results(gt_scores, means, stds, fileName)

get_plots_for_all_videos()

#left_hist, right_hist = get_distribution(left, right)
#from scipy.stats import ks_2samp
#ks_2samp(left_hist, right_hist)


import unittest

from mock import patch

from gripit.services.interaction_manager import InteractionManager

class TestInteractionManager(unittest.TestCase):
    @patch('gripit.services.interaction_manager.LightIndicator', autospec=True)
    @patch('gripit.services.interaction_manager.JobFactory', autospec=True)
    @patch('gripit.services.interaction_manager.JobRunner', autospec=True)
    @patch('gripit.services.gpio.GPIO', autospec=True)
    def setUp(self, MockGPIO, MockJobRunner, MockJobFactory, MockLightIndicator):
        self.mock_light_indicator = MockLightIndicator(MockGPIO)
        self.mock_job_runner = MockJobRunner()
        self.mock_job_factory = MockJobFactory()

        self.interaction_manager = InteractionManager(MockGPIO)

    def test_update_will_create_and_start_reading_job_if_press_time_is_not_longer_then_3_seconds(self):
        press_time = 2

        self.interaction_manager.update(press_time)

        self.mock_job_factory.create_reading_job.assert_called()
        self.mock_job_runner.start.assert_called_with(self.mock_job_factory.create_reading_job())

    def test_update_will_create_and_start_address_auto_assignment_job_if_press_time_is_longer_then_3_seconds(self):
        press_time = 5

        self.interaction_manager.update(press_time)

        self.mock_job_factory.create_auto_assignment_job.assert_called()
        self.mock_job_runner.start.assert_called_with(self.mock_job_factory.create_auto_assignment_job())

    def test_update_will_stop_reading_job_if_job_already_running(self):
        press_time = 3
        self.mock_job_runner.is_idle.return_value = False

        self.interaction_manager.update(press_time)

        self.mock_job_runner.stop.assert_called()

    def test_update_will_turn_on_light_if_job_not_already_running(self):
        press_time = 2

        self.interaction_manager.update(press_time)

        self.mock_light_indicator.turn_on.assert_called()

    def test_update_will_turn_off_light_if_job_already_running(self):
        press_time = 2
        self.mock_job_runner.is_idle.return_value = False

        self.interaction_manager.update(press_time)

        self.mock_light_indicator.turn_off.assert_called()


import os
import re

import numpy as np
import copy
import codecs
import json
from glob import glob
import cv2
import shutil

# labelme_path = '/home/walt/Downloads/dataset/已标注-11/dev/shm/1672670153410605_bea9298c-3371-4f99-98f7-b271859acf11/1591039045110456321/'
labelme_path = '/mnt/sdb1/datasets/20230214_10_yanshou/img/'
saved_path = '/mnt/sdb2/dataset/20230208/dev/xml'

from functools import reduce
import operator
import math

# 文件计数器
counter = 0

def Walk(path, suffix:list):
    file_list = []
    suffix = [s.lower() for s in suffix]
    if not os.path.exists(path):
        print("not exist path {}".format(path))
        return []

    if os.path.isfile(path):
        return [path,]

    for root, dirs, files in os.walk(path):
        for file in files:
            if os.path.splitext(file)[1].lower()[1:] in suffix:
                file_list.append(os.path.join(root, file))

    file_list.sort(key=lambda x:int(re.findall('\d+', os.path.splitext(os.path.basename(x))[0])[0]))

    return file_list

with codecs.open(labelme_path + "xml" + ".xml", "w", "utf-8") as xml:
    # 3.获取待处理文件
    files = Walk(labelme_path, ['json'])
    print(files)
    # 4.读取标注信息并写入 xml
    xml.write('<dataset>\n')
    xml.write('<images>\n')
    for json_file_ in files:
        # json_filename = labelme_path + json_file_ + ".json"
        # print(json_filename)
        json_file = json.load(open(json_file_, "r", encoding="utf-8"))

        # 获取文件名
        fileName = json_file["image_name"]
        if "-" in fileName:
            fileName = fileName.split(' ')[0]
            xml.write('\t<image' + " file ='" + str(fileName) + ".jpg"+ "'>\n")
        else:
            xml.write('\t<image' + " file ='" + str(fileName)  + "'>\n")

        # cubePoints是一个数组，数组每一项是一个字典{x:  ,y:  }
        top, left, width, height = 0, 0, 0, 0
        if "cubePoints" in json_file:
            for pointInLists in json_file['cubePoints']:
                point_x_list = []
                point_y_list = []
                point_list = []
                '''
                int()函数是可以将字符串转换为整形，但是这个字符串如果是带小数得,就会转换报错
                '''
                for pointInList in pointInLists:
                    pointX = int(float(pointInList["x"]))
                    pointY = int(float(pointInList["y"]))
                    point_list.append([pointX, pointY])

                point_x_list = np.array(point_list)[:, 0].tolist()
                point_y_list = np.array(point_list)[:, 1].tolist()
                point_x_list2 = point_x_list.copy()
                point_y_list2 = point_y_list.copy()
                point_x_list.sort()
                point_y_list.sort()

                top = point_y_list[0]
                left = point_x_list[0]
                width = point_x_list[-1] - left
                height = point_y_list[-1] - top

                point_desk_leg = []
                index=0
                for pointInList in pointInLists:
                    if index > 3:
                        pointX_leg = int(float(pointInList["x"]))
                        pointY_leg = int(float(pointInList["y"]))
                        point_desk_leg.append([pointX_leg, pointY_leg])
                    index+=1

                # <box top='100' left='5' width='387' height='296'>
                xml.write('\t\t<box' + " top='" + str(top) + "' left='" + str(left) + "' width='" + str(width) + "' height='" + str(height) + "'>\n")
                # unlabelled
                xml.write('\t\t\tunlabelled\n')

                # <part name='0' x='114' y='16'/>
                for index in range(len(point_desk_leg)):
                    xml.write('\t\t\t<part ' + "name='" + str(index) + "' x='" + str(point_desk_leg[index][0]) + "' y='" + str(point_desk_leg[index][1]) + "'/>\n")
                    index += 1

                xml.write('\t\t</box>\n')
            xml.write('\t</image>\n')
    xml.write('</images>\n')
    xml.write('</dataset>\n')

print("counter:", counter)


import logging
import socket

from functools import wraps

from django.core.cache.backends.memcached import PyLibMCCache

LOGGER = logging.getLogger(__name__)
LOGGER.addHandler(logging.NullHandler())

def get_addresses(servers):
    "Lookup hostname to determine server address(es)."
    # For each string, try to get the port, perform DNS lookup.
    addresses = []
    for server in servers:
        try:
            host, port = server
        except ValueError:
            try:
                host, port = server.split(':')
                port = int(port)
            except (ValueError, TypeError):
                host, port = server, None

        _, _, addrs = socket.gethostbyname_ex(host)

        for addr in addrs:
            if port is not None:
                addr += ':' + str(port)
            addresses.append(addr)

    # Return a list of strings of "addr[:port]".
    return addresses

def clear_client_on_error(f):
    "Try memcache operation, on failure, clear cache and retry once."
    @wraps(f)
    def wrapper(self, *args, **kwargs):
        for i in range(2):
            try:
                return f(self, *args, **kwargs)
            except:
                if i == 1:
                    raise
                setattr(self, '_client', None)
    return wrapper

class AutoDiscoverPyLibMCCache(PyLibMCCache):
    """
    Handle multiple servers in a single A record.

    Simple auto-discover for use with Kubernetes.
    """

    def __init__(self, server, params):
        super(AutoDiscoverPyLibMCCache, self).__init__(server, params)
        for method_name in ('set', 'set_many', 'get', 'get_many', 'delete'):
            method = getattr(self, method_name)
            setattr(self, method_name, clear_client_on_error(method))

    @property
    def _cache(self):
        this = getattr(self, '_local', self)
        client = getattr(this, '_client', None)

        if client is None:
            client = self._lib.Client(get_addresses(self._servers))

            if self._options:
                client.behaviors = self._options.get(
                    'behaviors', self._options)

            setattr(this, '_client', client)

        return client


import socket
import sys
from argparse import ArgumentParser
from platform import node
from socket import gaierror
from urllib.error import URLError

try:
    import PySimpleGUIQt as Qt
except ImportError:
    try:
        shell = get_ipython().__class__.__name__
        Qt = pyqt5
    except:
        raise

from inspy_logger import LEVELS as LOG_LEVELS, getLogger
from inspy_logger import InspyLogger
from inspyred_print import Color, Format
from requests import get
from requests.exceptions import ConnectionError
from urllib3.exceptions import MaxRetryError
from threading import Thread

from ip_reveal.assets.ui_elements.backgrounds import NEON_DARK_FP
from ip_reveal.assets.ui_elements.icons import app_main_24x24
from ip_reveal.assets.ui_elements.icons import app_quit_50x50_fp
from ip_reveal.assets.ui_elements.icons import app_refresh_50x50_fp

from ip_reveal import config

#import ip_reveal.timers as timer
import humanize
from inspyre_toolbox.live_timer import Timer
from ip_reveal.tools import commify

quit_icon = app_quit_50x50_fp
refresh_icon = app_refresh_50x50_fp

end = Format().end_mod
color = Color()
red = color.red

update_window_timer = None

timer = Timer()
timer.start()

cached_ext_ip = None
ip_hist = []

inet_down = False
log_device = None
args = None
config = config

def get_hostname():
    """
    get_hostname

    Fetch the system's apparent hostname and return it to the caller

    Returns:
        str: The system's apparent hostname contained within a string.
    """

    # Prepare the logger
    _log = getLogger(log_name + '.get_hostname')
    _debug = _log.debug

    # Fetch the hostname from platform.node
    hostname = node()
    _debug(f'Checked hostname and found it is: {hostname}')

    # Return this to the caller
    return hostname

def push_notification(old_ip, new_ip):
    """

    Push a notification through the GUI with a sound.

    Args:
        old_ip (str):
            The IP that was held previously.

        new_ip (str):
            The new - currently held - IP address

    Returns:
        None

    """
    from ip_reveal.popups import ip_change_notify

    ip_change_notify(old_ip, new_ip)

def get_external():
    """
    get_external

    Fetch the system's apparent hostname and return it to the caller in the form of a string.

    Returns:
        str: The system's apparent external IP-Address in the form of a string.
    """
    global cached_ext_ip, inet_down, ip_hist

    # Prepare the logger
    _log = getLogger(log_name + '.get_external')
    _debug = _log.debug

    # Try contacting IPIFY.org with a basic request and read the returned text.
    #
    # If we are unable to connect to this outside service, it's likely that Internet connection has dropped. There
    # are - however, instances where this service is down, and for these reasons we want to have at least one
    # alternative to control for failure on a Singular -free- AI API.

    # Fetch the external IP-Address from IPIFY.org
    try:
        external = get('https://api.ipify.org').text
        _debug(f'Checked external IP and found it is: {external}')

    # Catch the "ConnectionError" exception that is raised when the "requests" package is unable to reach
    # "IPIFY.org", simply reporting this occurred (if the logger is listening) before (maybe first; attempt connection
    # to another service?)
    except (ConnectionError, MaxRetryError, gaierror, URLError) as e:
        if not inet_down:
            _log.warning("Unable to establish an internet connection.")
            inet_down = True
        external = None

    if external is None:
        return False

    if not cached_ext_ip:
        cached_ext_ip = external
        if cached_ext_ip != external:
            push_notification(cached_ext_ip, external)
            cached_ext_ip = external

    if len(ip_hist) == 0:
        _debug("Added first IP to history list.")
        ip_hist.append(external)
        _debug(f"IP History: {ip_hist}")

    # Return the text result we get from the API to the caller.
    return external

def get_internal():
    """
    get_internal

    Fetch the system's local IP-Address and return it to the caller in the form of a string.

    Returns:
        str: The system's local IP-Address contained within a string.
    """

    # Set up a logger
    _log = getLogger(log_name + '.get_internal')

    # Alias the debug entry call
    _debug = _log.debug

    # Start a socket
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # Attempt a connection to an arbitrary host
    try:
        # doesn't even have to be reachable
        s.connect(('10.255.255.255', 1))

        # Fetch our IP from this socket's metadata
        IP = s.getsockname()[0]

    # Should we raise an exception we won't bother handling it, we'll just return the loopback address to the caller.
    except Exception:
        IP = '127.0.0.1'

    # No matter the result, let's remember to close the socket.
    finally:
        s.close()

    # Announce that we've found an IP
    _debug(f'Checked internal IP and found: {IP}')

    # Return a string containing the result to the caller.
    return IP

def update_window(values=None):
    global log_device, args
    from ip_reveal.popups import ip_change_notify
    """

    A function that handles the following processes for updating the IP Reveal window:

      * Updating all relevant fields
      * Resetting accumulators
      * Incrementing refresh stats (if opted in)
      * Fetching the information for external and internal IP addresses
      * Calls a refresh on the timer.

    NOTE:
        It is not advisable to utilize this function in a loop without limiting how often it's run. You could end up
        DoSing yourself or others.

    Returns:
        None

    """
    global acc, refresh_num, timer, cached_ext_ip, ip_hist

    # Start the logger for this operation
    _log = getLogger(log_name + '.update_window')

    # If set to do so; spit out some debug data
    u_debug = _log.debug
    u_debug('TIMEOUT - Refreshing window...')
    u_debug(f'acc = {acc}')

    # Spit out some more useful info, if allowed.
    u_debug('Reset acc accumulator new value: 0')
    u_debug('Incrementing refresh count...')

    # For stats purposes only; increment our count of window refreshes.
    refresh_num += 1

    # Grab our fresh data for diplaying to the window
    ip = get_external()

    if not ip:
        ip = "Offline"

    local_ip = get_internal()
    hostname = get_hostname()

    # Call a 'refresh()' on our timer object. This will start another cycle to keep track of. This allows the timer
    # routine to always track the time since last data fetching
    timer.reset()

    t_color = "red" if ip == "Offline" else "green"
    # Update the relevant fields with our fresh data
    window['EXTIP_OUT'].update(ip, text_color=t_color)
    window['INTIP_OUT'].update(local_ip)
    window['HOSTNAME_OUT'].update(hostname)
    window['TIME_SINCE_Q_OUT'].update("Just now...")

    # Make some notes in the debug log that might be useful
    u_debug(f'Updated window with new values: {values}')
    u_debug(f'This was refresh number {refresh_num}')

    if ip != cached_ext_ip:
        ip_change_notify(cached_ext_ip, ip, args.mute_all)
        cached_ext_ip = ip
        ip_hist.append(ip)

def safe_exit(win, exit_reason):
    _log = getLogger(log_name + '.safe_exit')

    tmp_hist = []
    for ip in ip_hist:
        if ip not in tmp_hist:
            tmp_hist.append(ip)

    _log.info(f"During operation you switched IP addresses {len(ip_hist) - 1} times.")
    _log.info(f"Held IP addresses: {tmp_hist}")
    _log.info(f"Exiting safely. Reason: {exit_reason}")
    _log.info(f"The IP address was refreshed {refresh_num} times")
    _log.info(f"Window underwent {total_acc} cycles")
    print(timer.start_time)

    win.close()
    sys.exit()

# Set up a name for our logging device
log_name = "IPReveal"

# Declare a variable named 'acc' for our accumulator and set it at int(0)
acc = 0

# For statistics tracking; declare a variable called 'refresh_num' and start it at 0
refresh_num = 0

# ...and one that will hold our total cycle count
total_acc = 0

# Set up a placeholder variable for our window object
window = None

# Set up two variables that will act as caches for the external and internal IPs
cached_ext_ip = None
cached_int_ip = None

acc2 = 0

def main():
    global total_acc, acc, refresh_num, window, log_device, args

    # Timer text
    t_text = "Just now..."

    # Qt.theme('DarkBlue3')

    parser = ArgumentParser(
        'ip-reveal', description='A program that will show you your external IP address.')

    parser.add_argument('-l', '--log-level',
                        nargs='?',
                        choices=LOG_LEVELS,
                        default='info'
                        )

    # Argument to mute sounds
    parser.add_argument('-m', '--mute-all',
                        action='store_true',
                        required=False,
                        help="Starts the program with all program audio muted.",
                        default=False
                        )

    # Argument to implicitly set the refresh rate
    parser.add_argument('-r', '--refresh-interval',
                        type=int,
                        default=30,
                        help='Specify the number of seconds you want to have pass before IP-Reveal refreshes your IP '
                             'information. (Defaults to 30)',
                        action='store')

    parser.add_argument('-V', '--version', action='version', version='1.2'
                        )

    sub_parsers = parser.add_subparsers(
        dest='subcommands', help='The sub-commands for IP Reveal')

    ext_ip_parse = sub_parsers.add_parser('get-external',
                                          help='Return the external IP to the command-line and nothing else.')
    host_parse = sub_parsers.add_parser(
        'get-host', help='Return the hostname to the command-line and nothing else.')
    local_parse = sub_parsers.add_parser('get-local',
                                         help='Return the local IP-Address to the command-line and nothing '
                                              'else.')
    test_audio_parse = sub_parsers.add_parser('test-audio',
                                              help="To ensure you get notifications you can test IP-Reveal's audio "
                                                   "engine with this command.")
    test_audio_parse.add_argument('-c', '--countdown',
                                  action='store',
                                  type=int,
                                  default=3,
                                  help="Enter the number to countdown from before starting the test.")
    test_audio_parse.add_argument('-f', '--full',
                                  help='Run the full range of audio tests provided by the audio engine',
                                  action='store_true',
                                  default=False)

    args = parser.parse_args()

    config.args = args

    # Set up the logging device
    log_device = InspyLogger(log_name, args.log_level).device

    # Start the logging device
    log = log_device.start(mute=args.subcommands)
    debug = log.debug

    # Announce that we did that
    debug('Started my logger!')
    log = getLogger(log_name + '.Main')
    # Alias the log.debug signature for ease-of-use
    debug = log.debug

    # See if we got one of the subcommands assigned.
    if args.subcommands == 'get-external':
        print(get_external())
        exit()
    elif args.subcommands == 'get-host':
        print(get_hostname())
        exit()
    elif args.subcommands == 'get-local':
        print(get_internal())
        exit()
    elif args.subcommands == 'test-audio':
        from ip_reveal.assets.sounds import run_audio_test
        run_audio_test(args.countdown, args.full, args.log_level)
        exit()

    status_bar_layout = [

    ]

    bg_color = "340245"
    size = (220, 50)
    alpha = 1
    text_background_color = "pink" if alpha >= 1 else "white"
    layout = [
        [
            Qt.Text(
                'External IP:',
                background_color=text_background_color,
                text_color="black",
                relief=Qt.RELIEF_GROOVE,
                size_px=size,
                auto_size_text=True,
                justification='center',
            ),
            Qt.Text(
                get_external(),
                relief=Qt.RELIEF_SUNKEN,
                key='EXTIP_OUT',
                background_color=text_background_color,
                text_color="black",
                size_px=size,
                auto_size_text=True,
                justification='center',
            ),
        ],
        [
            Qt.Text(
                'Internal IP:',
                background_color=text_background_color,
                text_color="black",
                relief=Qt.RELIEF_GROOVE,
                size_px=size,
                auto_size_text=True,
                justification='center',
            ),
            Qt.Text(
                get_internal(),
                key='INTIP_OUT',
                relief=Qt.RELIEF_SUNKEN,
                background_color=text_background_color,
                text_color="black",
                size_px=size,
                auto_size_text=True,
                justification='center',
            ),
        ],
        [
            Qt.Text(
                'Hostname:',
                background_color=text_background_color,
                text_color="black",
                relief=Qt.RELIEF_GROOVE,
                size_px=size,
                auto_size_text=True,
                justification='center',
            ),
            Qt.Text(
                get_hostname(),
                key='HOSTNAME_OUT',
                relief=Qt.RELIEF_SUNKEN,
                background_color=text_background_color,
                text_color="black",
                size_px=size,
                auto_size_text=True,
                justification='center',
            ),
        ],
        [
            Qt.Text(
                'Last checked',
                background_color=text_background_color,
                text_color="black",
                relief=Qt.RELIEF_GROOVE,
                size_px=size,
                auto_size_text=True,
                justification='center',
            ),
            Qt.Text(
                t_text,
                key="TIME_SINCE_Q_OUT",
                relief=Qt.RELIEF_SUNKEN,
                background_color=text_background_color,
                text_color="black",
                size_px=size,
                auto_size_text=True,
                justification='center',
            ),
        ],
        [
            Qt.Button(
                '',
                key='MAIN_CLOSE_BUTTON',
                image_filename=app_quit_50x50_fp,
                image_size=(50, 50),
                button_color=(None, "#ff0000"),
                tooltip="Quit IP Reveal",
            ),
            Qt.Button(
                '',
                key='MAIN_REFRESH_BUTTON',
                image_filename=app_refresh_50x50_fp,
                image_size=(50, 50),
                button_color=(None, "#ff0000"),
                tooltip="Refresh",
            ),
        ],
    ]

    # Assemble the above widget into a window.
    window = Qt.Window('IP-Reveal by Inspyre Softworks', layout=layout,
                       background_image=NEON_DARK_FP,
                       icon=app_main_24x24,
                       size=(300, 400),
                       alpha_channel=alpha,
                       grab_anywhere=True,
                       background_color="white"
                       )

    # Start our main GUI loop.
    while True:
        event, values = window.read(timeout=100)

        # Set up a child logger that will log window events.
        w_log = getLogger(log_name + '.MainWindow')
        w_debug = w_log.debug

        # Increment the cycle count
        acc += 1
        total_acc += 1

        t = int(timer.get_elapsed(seconds=True))
        t_text = humanize.naturaldelta(t)

        window['TIME_SINCE_Q_OUT'].update(f"{t_text} ago...")

        # If the accumulator is at 325 counts, alert the user, update the window, and reset the accumulator
        if t == args.refresh_interval:
            w_debug('Calling function to update the window...')

            window['TIME_SINCE_Q_OUT'].update('Refreshing...')
            update_win = Thread(target=update_window)

            update_win.start()
            w_debug('Updated window!')

        # If the 'Close' button is pressed: we exit.
        if event is None or event == 'MAIN_CLOSE_BUTTON':
            e_reason = f"It seems the user closed the window, received {values}"
            if event == 'MAIN_CLOSE_BUTTON':
                e_reason = 'The close button was pressed'
            safe_exit(window, exit_reason=e_reason)

            w_log.info("User initiated closing")

            break

        if event == 'MAIN_REFRESH_BUTTON':
            w_debug('Calling a refresh on the window')
            update_window()
            w_debug('All seems well!')


from unittest.mock import patch

from odoo import fields
from odoo.addons.base.models.ir_model import MODULE_UNINSTALL_FLAG
from odoo.addons.purchase_stock.models.purchase_order_line import PurchaseOrderLine
from odoo.tests.common import tagged

from .common import PurchaseTestCommon

@tagged('post_install', '-at_install')
class TestUninstallPurchaseStock(PurchaseTestCommon):
    def test_qty_received_method(self):
        partner = self.env['res.partner'].create({'name': 'Test Partner'})
        purchase_order = self.env['purchase.order'].create({
            'partner_id': partner.id,
            'state': 'purchase',
            'order_line': [fields.Command.create({
                'product_id': self.product_1.id,
            })],
        })
        order_line = purchase_order.order_line
        stock_move = order_line.move_ids

        self.assertEqual(order_line.product_id.detailed_type, 'product')

        stock_move.quantity = 1
        stock_move.picked = True
        stock_move.picking_id.button_validate()

        self.assertEqual(purchase_order.order_line.qty_received, 1)

        stock_moves_option = self.env['ir.model.fields.selection'].search([
            ('field_id.model', '=', 'purchase.order.line'),
            ('field_id.name', '=', 'qty_received_method'),
            ('value', '=', 'stock_moves'),
        ])

        original_compute = PurchaseOrderLine._compute_qty_received
        def _compute_qty_received(records):
            records.read()
            with self.assertQueryCount(0):
                original_compute(records)
                records.flush_recordset()

        with patch.object(PurchaseOrderLine, '_compute_qty_received', _compute_qty_received):
            stock_moves_option.sudo().with_context(**{
                MODULE_UNINSTALL_FLAG: True
            }).unlink()

        self.assertEqual(order_line.qty_received_method, 'manual')
        self.assertEqual(order_line.qty_received, 1)


import argparse
from pathlib import Path
from time import sleep
from typing import List

from pydantic import BaseModel

from openai import Client

class MassTime(BaseModel):
    day: str  # "Monday"
    time: int  # 1630 is 4:30pm. All times local

def get_mass_times(client: Client, bulletin_pdf: Path) -> List[MassTime]:
    uploaded_bulletin = client.files.create(purpose="assistants", file=bulletin_pdf)

    assistant = client.beta.assistants.create(
        name="Masstime Extractor",
        instructions="You are an assistant for extracting information from Catholic Church bulletins. You read PDF files and can answer questions from them.",
        model="gpt-4-1106-preview",
        tools=[{"type": "retrieval"}],
    )

    thread = client.beta.threads.create()
    client.beta.threads.messages.create(
        thread_id=thread.id,
        content="What are the regular Mass Times at this Parish?  Provide output as a valid JSON array in which every object in the array represents a single mass time.  Include attributes for the day of the week and the time of day.",
        role="user",
        file_ids=[uploaded_bulletin.id],
    )

    run = client.beta.threads.runs.create(
        thread_id=thread.id, assistant_id=assistant.id
    )

    while run.status in ["queued", "in_progress", "cancelling"]:
        print(run.status)
        sleep(5)
        run = client.beta.threads.runs.retrieve(thread_id=thread.id, run_id=run.id)
    print(run.status)

    messages = client.beta.threads.messages.list(thread_id=thread.id)

    print(messages)
    return []

def parse_args():
    parser = argparse.ArgumentParser(description="Extract Masstimes from a single file")
    parser.add_argument("pdf_path", type=str, help="The location of the PDF file.")

    args = parser.parse_args()
    return args

if __name__ == "__main__":
    args = parse_args()
    pdf_path = Path(args.pdf_path)
    if not pdf_path.exists():
        raise IOError(f"File {pdf_path} does not exist")

    client = Client()

    mass_times = get_mass_times(client, Path(args.pdf_path))

    for mass_time in mass_times:
        print(mass_time)


# -*- coding: utf-8 -*-
import requests
from typing import Optional, Union

EMPTY = ""

class CoderHub:
    def __init__(self):
        # الـ API
        self.host = "https://api.coderhub.sa/api"

        # جلب تحدي يتم وضع ايدي التحدي
        self.get_challenge_url = self.host + "/challenges/detail/{challenge_id}"

        # جلب جميع التحديات او عبر البحث (يتم وضع المراد البحث عنه في word)
        self.challenges_url = (
            self.host + "/challenges/filtered-list/?page_size=9999999999&query={word}"
        )

        # جلب جميع لغات البرمجة
        self.programming_languages_url = self.host + "/challenges/programming-languages"

        # جلب لوحة المتصدرين تستقبل ايدي اللغة ورقم الصفحة حقت المتصدرين ونوع البحث
        # البحث يكون ["ALL", "DAILY", "WEEKLY"]
        self.leaderBoard_url = (
            self.host
            + "/leaderboard/?language={lang_id}&offset={page}&limit=10&type={search_type}"
        )

        # جلب الملف التعريفي الخاص باسم المستخدم
        self.profile_url = self.host + "/profile/public/{username}"

        # جلب احصائيات المستخدم (تستقبل ايدي المستخدم)
        self.user_statistics = (
            self.host + "/profile/public/get-user-statistics/{user_id}"
        )

    def get_challenges(self, difficulty: Optional[Union[str, None]] = None) -> dict:
        """ارجاع جميع التحديات او عبر مستوى صعوبتها.

        المتغيرات:
            difficulty (str, None, optional): مستوى صعوبة التحديات. Defaults to None.

        الاخطاء:
            Exception: مستوى صعوبة خاطئ

        المخرجات:
            dict: قاموس يحتوي التحديات
        """
        # حلب جميع التحديات
        challenges = requests.get(self.challenges_url.format(word=EMPTY)).json()
        # انشاء مصفوفة بمستوى صعوبة التحديات
        difficulty_list = set(
            map(
                lambda challenge: challenge["type_of_level"]["name"],
                challenges["result"],
            )
        )
        # اذا تم طلب مستوى صعوبة معين
        if difficulty:
            # اذا كان مستوى الصعوبة المطلوب في مصفوفة المستويات
            if difficulty in difficulty_list:
                # عمل فلتر للتحديات وجلب فقط الحديات التي لديها نفس مستوى الصعوبة
                result = list(
                    filter(
                        lambda challenge: challenge["type_of_level"]["name"]
                        == difficulty,
                        challenges["result"],
                    )
                )
                # ارجاع التحديات مع عددها
                return {"count": len(result), "result": result}
            else:
                # اظهار خطأ اذا كان مستوى الصعوبة غير موجود
                raise Exception(f"difficulty must be {' or '.join(difficulty_list)}")
        else:
            # ارجاع جميع التحديات مع عددها
            return challenges

    def search_challenges(self, word: str) -> dict:
        """البحث عن تحدي

        المتغيرات:
            word (str): الكلمة او النص الذي تريد البحث عنه

        الاخطاء:
            Exception: عدم وجود نتائج جول الكلمة التي تبحث عنها

        المخرجات:
            dict: قاموس يحتوي النتائج
        """
        # جلب التحديات التي تحتوي على الكلمة او النص الذي تبحث عنه
        data = requests.get(self.challenges_url.format(word=word)).json()
        # اذ لم يكن العدد يساوي صفر
        if data.get("count"):
            # ارجاع التحديات
            return data
        else:
            # ارجاع خطاء بعدم وجود تحديات متطابقة
            raise Exception("There are no challenges available about '%s'" % word)

    def get_challenge_by_id(self, challenge_id: str) -> dict:
        """ارجاع محتوى التحدي عبر الايدي الخاص به

        المتغيرات:
            id (str): ايدي التحدي

        الاخطاء:
            Exception: ايدي تحدي خاطئ

        المخرجات:
            dict: محتوى التحدي
        """
        # حلب التحدي عبر الايدي الخاص به
        challenge_response = requests.get(
            self.get_challenge_url.format(challenge_id=challenge_id)
        )
        # اذا كان الرسبونس صحيح
        if challenge_response.ok:
            # ارحاع محتوى التحدي
            return challenge_response.json()
        else:
            # ارجاع خطاء الايدي غير صحيح
            raise Exception("Invalid challenge id: %s not found" % challenge_id)

    def get_languages(self, language: Optional[Union[str, None]] = None) -> dict:
        """ارجاع جميع لغات البرمجة التي يدعمها الموقع او لغة محددة

        المتغيرات:
            language (str, None, optional): اللغة التي تريدها. Defaults to None.

        الاخطاء:
            Exception: اللغة غير موجودة

        المخرجات:
            dict: اللغة او اللغات
        """
        # جلب جميع لغات البرمجة التي بالموقع
        languages = list(
            map(
                lambda lang: {
                    "id": lang["id"],
                    "name": lang["name"].lower(),
                    "version": lang["version"],
                },
                requests.get(self.programming_languages_url).json(),
            )
        )
        # اذا تم طلب لغة معينة
        if language:
            # عمل فلتر باسم اللغة المطلوبة
            languages = list(
                filter(lambda lang: lang["name"] == language.lower(), languages)
            )
            # اذا لم تكن المصفوفة فارغة
            if languages:
                return languages[0]
            else:
                # ارجاع خطاء اللغة المطلوبة غير موجودة
                raise Exception(f"Invalid language, '{language}' not found")
        else:  # اذ لم يتم طلب لغة يتم ارجاع حميع اللغات
            return {"result": languages}

    def get_leaderBoard(
        self,
        language: str,
        search_type: Optional[Union[str]] = "ALL",
        page: Optional[Union[int]] = 0,
    ) -> dict:
        """ارجاع 10 متصدرين من كل صفحة
            نوع البحث يجب ان يكون من هاذه المصفوفة [ALL, DAILY, WEEKLY]

        المتغيرات:
            language (str): لغة البرمجة التي تريد منها المتصدرين
            search_type (Optional[Union[str]], optional): نوع البحث. Defaults to "ALL".
            page (Optional[Union[int]], optional): رقم الصفحة التي تريد جلب المتصدرين منها. Defaults to 0.

        الاخطاء:
            Exception: Unknown language, لغة برمجة غير موجودة
            Exception: invalid search type, نوع البحث غير موجود

        المخرجات:
            dict: قاموس يحتوي المتصدرين
        """
        # جعل اسم اللغة بحروف صغير وجعل نوع البحث بحروف كبيرة
        language, search_type = language.lower(), search_type.upper()
        # تعريف مصفوفة تحتوي انواع البحث
        types = ["ALL", "DAILY", "WEEKLY"]
        # جلب اللغات الموجودة بالموقع
        languages = self.get_languages()
        # استخراج اسم كل لغة
        languages_names = list(map(lambda lang: lang["name"], languages["result"]))
        # استخراج ايدي كل لغة
        languages_ids = list(map(lambda lang: lang["id"], languages["result"]))
        # اذا كانت اللغة موجودة في لغات الموقع
        if language in languages_names:
            # اذا كان نوع البحث المطلوب بين الانواع الموجودة
            if search_type in types:
                # جلب ايدي اللغة المطلوبة
                id = languages_ids[languages_names.index(language)]
                # جلب قائمة المتصدرين
                leaderboard = requests.get(
                    self.leaderBoard_url.format(
                        lang_id=id, page=page, search_type=search_type
                    )
                ).json()["leaderboard"]
                return {"leaderboard": leaderboard}
            else:
                # ارجاع خطاء بعدم وجود هذا النوع
                raise Exception(
                    "Invalid search type, '%s' not found, search_type should be  %s"
                    % (search_type, " or ".join(types))
                )
        else:
            # ارجاع خطاء بعدم وجود اللغة
            raise Exception(
                "Unknown language, '%s' not found, language should be  %s"
                % (language, " or ".join(languages_names))
            )

    def get_profile(self, username: str) -> dict:
        """ارجاع الملف التعريفي الخاص باسم المستخدم

        المتغيرات:
            username (str): اسم المستخدم الذي تريد الملف التعريفي الخاص به

        الاخطاء:
            Exception: ['user profile is not public', 'user profile is not found']

        المخرجات:
            dict: قاموس يحتوي الملف التعريفي
        """
        # جلب البروفايل باسم المستخدم المعطى
        data = requests.get(self.profile_url.format(username=username.lower())).json()
        # اذا كان هناك وصف للخطاء
        if "detail" in data.keys():
            # ارجاع الوصف
            raise Exception(data["detail"])
        else:
            # اذ لم يوجد خطاء يتم ارجاع البروفايل
            return data

    def get_user_statistics(self, username: str) -> dict:
        """ارجاع إحصائيات المستخدم

        المتغيرات:
            username (str): اسم المستخدم الذي تريد إحصائياته

        المخرجات:
            dict: قاموس يحتوي إحصائيات المستخدم
        """
        # لم يتم التاكد من اسم المستخدم لان يتم التحقق في دالة جلب البروفايل
        # جلب ايدي المستخدم
        user_id = self.get_profile(username=username)["user_information"]["id"]
        # جلب احصائيات المستخدم عبر الايدي الخاص به
        data = requests.get(self.user_statistics.format(user_id=user_id)).json()
        # ارجاع البروفايل
        return data


'''
Module ML pipeline
'''
#pylint: disable=wrong-import-position

import sys
import warnings

warnings.filterwarnings('ignore')

import pickle
import re

import nltk
import numpy as np
import pandas as pd

nltk.download('popular')
nltk.download('stopwords')

from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
from nltk.tokenize import word_tokenize

from lightgbm import LGBMClassifier
from optuna.distributions import IntUniformDistribution
from optuna.integration import OptunaSearchCV

from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.metrics import precision_recall_fscore_support
from sklearn.model_selection import train_test_split
from sklearn.multioutput import MultiOutputClassifier
from sklearn.pipeline import Pipeline

from sqlalchemy import create_engine

def load_data(database_filepath):
    """
    The messages stored in an sqlite database are loaded to a dataframe.
    The dataframe is split into a feature matrix an labels

    Arguments:
        database_filepath -- Path to the sqlite database containing the messages

    Returns:
        Feature matrix X, labels Y and the categories
    """

    # load data from database
    engine = create_engine('sqlite:///' + database_filepath)
    df = pd.read_sql_table('Messages', engine)

    X = df['message']
    Y = df.drop(columns=['message', 'genre'])

    return X, Y, Y.columns

def tokenize(text):
    """
    Cleans, tokenizes and lemmatizes the input
    Punctuation, URLs and english stopwords are removed
    Text converted to lowercase

    Arguments:
        text -- Text to be prepared

    Returns:
        Lemmata of the cleaned tokens of the text
    """

    stop_words = stopwords.words("english")
    lemmatizer = WordNetLemmatizer()

    # normalize case and remove punctuation
    text = re.sub(r"[^a-zA-Z0-9]", " ", text.lower())

    # Replace URLs by the string "URL"
    url_regex = r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
    detected_urls = re.findall(url_regex, text)
    for url in detected_urls:
        text = text.replace(url, "URL")

    # tokenize text
    tokens = word_tokenize(text)

    # lemmatize and remove stop words
    lemmatized = [lemmatizer.lemmatize(word) for word in tokens if word not in stop_words]

    return lemmatized

def build_model():
    """
    Creates the model to be used to label the messages.
    CountVectorizer and TfidfTransformer are integrated in the pipeline

    Returns:
        Best LGBMClassifier model found by OptunaSearchCV
    """

    # Define a pipeline, parameter distributions for optuna and search for the best model
    pipeline = Pipeline([
                                ('vect', CountVectorizer(tokenizer = tokenize)),
                                ('tfidf', TfidfTransformer()),
                                ('clf', MultiOutputClassifier(LGBMClassifier(random_state=42, objective='binary', n_jobs=-1)))
                            ])
    optuna_param_dist = {
                        'clf__estimator__num_leaves': IntUniformDistribution(20,40),
                        'clf__estimator__max_depth': IntUniformDistribution(3,15),
                        'clf__estimator__min_data_in_leaf': IntUniformDistribution(10,100)
                    }
    clf = OptunaSearchCV(pipeline, optuna_param_dist, cv=5, random_state=42, verbose=2, n_jobs=-1)

    return clf

def evaluate_model(model, X_test, Y_test, category_names):
    """
    The predictions for the test set are evaluted.
    Precision, Recall, F1-Score, Support and Averages are computed and returned as a dataframe

    Arguments:
        model -- the fitted model to be used for predictions
        X_test -- The test set
        y_test -- The lables for the tests set
        category_names -- The categories a message can be associated with

    """
    Y_hat = model.predict(X_test)

    row_list = []
    for col_number, col_name in enumerate(category_names):
        for label in np.unique(Y_hat.ravel()):
            # Get the precision, reacall, f_score and support for column number col_number
            pre_rec_f1_supp = precision_recall_fscore_support(  y_true = Y_test.iloc[:,col_number],
                                                                y_pred = Y_hat[:,col_number]
                                                                )

            # Collect the results.
            # The dicts are collected in row_list which is converted to a Dataframe at the end.
            result = { 'Label': col_name, 'Value': label, 'Precision': pre_rec_f1_supp[0][label],
                        'Recall': pre_rec_f1_supp[1][label], 'F-1 Score': pre_rec_f1_supp[2][label],
                        'Support': pre_rec_f1_supp[3][label]
                        }
            row_list.append(result)
    # Add averages to the result
    for avg in ['micro', 'macro', 'weighted']:
        average = precision_recall_fscore_support(y_true = Y_test, y_pred = Y_hat, average=avg)
        result = {
                    'Label': 'Average', 'Value': avg, 'Precision': average[0], 'Recall': average[1],
                    'F-1 Score': average[2], 'Support': '-'
                    }
        row_list.append(result)

    res_df=pd.DataFrame(row_list)
    res_df.set_index(['Label', 'Value'], inplace=True)
    print(res_df)

def save_model(model, model_filepath):
    """
    The model is saved as a pickle file.

    Arguments:
        model -- the final model
        model_filepath -- Filepath of the pickle file to save the model
    """
    with open(model_filepath, 'wb') as file:
        pickle.dump(model, file)

def main():
    """
    * Loads data from the SQLite database
    * Splits the dataset into training and test sets
    * Builds a text processing and machine learning pipeline
    * Trains and tunes a model using GridSearchCV
    * Outputs results on the test set
    * Exports the final model as a pickle file
    """
    if len(sys.argv) == 3:
        database_filepath, model_filepath = sys.argv[1:]
        print('Loading data...\n    DATABASE: {}'.format(database_filepath))
        X, Y, category_names = load_data(database_filepath)
        X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)

        print('Building model...')
        model = build_model()

        print('Training model...')
        model.fit(X_train, Y_train)

        print('Evaluating model...')
        evaluate_model(model, X_test, Y_test, category_names)

        print('Saving model...\n    MODEL: {}'.format(model_filepath))
        save_model(model, model_filepath)

        print('Trained model saved!')

    else:
        print('Please provide the filepath of the disaster messages database '\
              'as the first argument and the filepath of the pickle file to '\
              'save the model to as the second argument. \n\nExample: python '\
              'train_classifier.py ../data/DisasterResponse.db classifier.pkl')

if __name__ == '__main__':
    main()


#!/usr/bin/python3

# https://github.com/asermartinez/mysql-folders-backup
# Version 1.0
# 04-2018

# See README.md for details

import datetime
import glob2
import os
import shlex
import subprocess
import tarfile

# *** CONFIGURE ***
backup_dir = "/home/aser/www/backups"  # Set the destination for backups.
db_name = "/home/aser/dbname.txt"  # Set Full Path to File with databases names, one per line.
folder_name = "/home/aser/foldername.txt"  # Set Full Path to File with folders to backup, one per line.
upload = "yes" # Set to "no" if you do not want to upload to dropbox.
# *** END ***

message_start = " Starting ".center(80, "=")
message_end = " End ".center(80, "=")

backup_dir = os.path.normpath(backup_dir)  # Normalize path, eliminating double slashes, etc.

def make_tarfile(output_filename, source_dir):
    """
    Using tarfile to backup folders
    """
    with tarfile.open(output_filename, "w:bz2") as tar:
        tar.add(source_dir, arcname=os.path.basename(source_dir))

def backup_sql():
    """
    Make mysql dump of databases in db_name file
    Creates .sql.bz2 file in backup_dir
    """
    print("\n" + " Mysql dump... ".center(80, "-"))
    with open(db_name) as databases_list_file:
        db_list = databases_list_file.readlines()
        for db in db_list:
            db = db.rstrip()  # deletes white space or new line character at the end of line
            os.chdir(backup_dir)
            dump_name = db + "-" + datetime.datetime.now().strftime("%Y-%m-%d") + ".sql"
            subprocess.call(shlex.split('mysqldump --databases {} --result-file={}'.format(db, dump_name)))
            subprocess.call(shlex.split('bzip2 -f %s' % dump_name))
            dump_name = dump_name + ".bz2"
            print("\nBackup File created: {}".format(backup_dir + "/" + dump_name))

def backup_folder():
    """
    Make tar file from folders in folder_name file
    Creates tar.bz2 file in backup_dir
    """
    print("\n" + " Back up of folders... ".center(80, '-'))

    with open(folder_name) as directory_list_file:
        folder_list = directory_list_file.readlines()
        for folder in folder_list:
            folder = folder.rstrip()  # deletes white space or new line character at the end of line
            folder = os.path.normpath(folder) # Normalize path, eliminating double slashes, etc.
            os.chdir(backup_dir)
            tar_name = os.path.basename(folder) + "-" + datetime.datetime.now().strftime("%Y-%m-%d") + ".tar.bz2"
            make_tarfile(tar_name, folder)
            print("\nBackup File created: {}".format(backup_dir + "/" + tar_name))

os.system("clear")

if os.path.exists(db_name) and os.path.exists(folder_name):
    print("\n\nDatabases file and Folders file found...")
    print("..." + db_name + "...")
    print("..." + folder_name + "...")
    print("\n" + message_start)
    print("\n")
    subprocess.call("date")
    backup_sql()
    backup_folder()
    os.chdir(backup_dir)
    files = glob2.glob("*-{}".format(datetime.datetime.now().strftime("%Y-%m-%d") + "*.bz2"))
    if upload == "yes":
        try:
            for file in files:
                subprocess.call(shlex.split("dropbox_uploader.sh upload {} /".format(file)))
        except FileNotFoundError:
            print("\n\ndropbox_uploader.sh not found.".center(20, "*"))
    print("\n")
    subprocess.call("date")
    print("\n" + message_end)
else:
    print("\n" + message_start + "\n")
    print("Databases file and Folders file not found.")
    print("Set db_name & folder_name in the script...")
    print("\n" + message_end + "\n")


# -*- coding: utf-8 -*-

import os
import codecs

def rename(rootDir):
    for dir in os.listdir(rootDir):
        path = os.path.join(rootDir, dir)
        if os.path.isdir(path):
            rename(path)
        else:
            if path[-2:] != '.h' and path[-4:] != '.cpp':
                continue
            print(dir)
            os.rename(path, os.path.join(rootDir, input()))
            print()

# rename("go/include")

nameList = []
srcList = {}

def get_name_list(rootDir):
    global nameList
    for dir in os.listdir(rootDir):
        path = os.path.join(rootDir, dir)
        if os.path.isdir(path):
            get_name_list(path)
        else:
            if path[-2:] != '.h':
                continue
            nameList.append(dir[:-2])

# get_name_list("go/include")

def get_src_list(rootDir):
    global srcList
    for dir in os.listdir(rootDir):
        path = os.path.join(rootDir, dir)
        if os.path.isdir(path):
            get_src_list(path)
        else:
            if path[-2:] != '.h' and path[-4:] != '.cpp':
                continue
            srcList[dir] = path

# get_src_list("tm")

def rename_by_include(rootDir):
    global nameList
    for dir in os.listdir(rootDir):
        path = os.path.join(rootDir, dir)
        if os.path.isdir(path):
            rename_by_include(path)
        else:
            if path[-4:] != '.cpp':
                continue
            for name in nameList:
                if name.lower() == dir[:-4]:
                    os.rename(path, os.path.join(rootDir, name + ".cpp"))
                    break

# rename_by_include("go/src")

def rename_in_file(rootDir):
    global nameList
    global srcList
    for dir in os.listdir(rootDir):
        path = os.path.join(rootDir, dir)
        if os.path.isdir(path):
            rename_in_file(path)
        else:
            if path[-2:] != '.h' and path[-4:] != '.cpp':
                continue
            file = codecs.open(srcList[dir.lower()], 'r', 'utf-8')
            print(srcList[dir.lower()])
            content = file.readlines()
            file.close()
            file = codecs.open(path, 'w', 'utf-8')
            for line in content:
                if line[:8] == "#include":
                    newLine = line[10:-4]
                    flag = True
                    for name in nameList:
                        if name.lower() == newLine:
                            newLine = "#include \"" + name + ".h\"\n"
                            flag = False
                            break
                    if flag:
                        newLine = line
                    file.write(newLine)
                elif line[-3:] == "_H\n":
                    file.write(line)
                else:
                    file.write(line[0])
                    for i in range(1, len(line)):
                        if line[i - 1] == 'G' and line[i] == 'O':
                            file.write('o')
                        else:
                            file.write(line[i])
            file.close()

# rename_in_file("go")

def generate_list(rootDir):
    global nameList
    for dir in os.listdir(rootDir):
        path = rootDir + "/" + dir
        if os.path.isdir(path):
            generate_list(path)
        else:
            if path[-2:] != '.h' and path[-4:] != '.cpp':
                continue
            print("    " + path[3:] + " \\")

def generate_pro_list():
    print("HEADERS += \\")
    generate_list("go/include")
    print()
    print("SOURCES += \\")
    generate_list("go/src")

generate_pro_list()


import os
from tqdm import tqdm

ok_dir = "temporary_data"
tail_dir = "final_data"
error_dir = "error"

ok_codes = os.listdir(ok_dir)
tail_codes = []

years = ['2022','2021','2020','2019','2018','2017']
years.reverse()

for code in tqdm(ok_codes):
     with open(os.path.join(ok_dir,code),encoding='utf8') as f:
         lines = f.readlines()
         lines.reverse()
         for i in range(len(lines)):
             if lines[i][-17:-13] in years:
                 break
         if lines[i][-17:-13] != "2017":
             with open('error.txt','a') as f:
                 f.write(f'{code}\n')

         lines = lines[i:]
         lines.reverse()
         with open(os.path.join(tail_dir,code),"w+",encoding="utf8") as f:
             f.write("".join(lines))

with open('error.txt') as f:
    error_code = f.readlines()
    error_code = [i.strip() for i in error_code]

for code in tqdm(error_code):
    with open(os.path.join(tail_dir,code),encoding="utf8") as f:
        with open(os.path.join(error_dir,code),"w+",encoding="utf8") as ff:
            ff.write(f.read())