from django.test import TestCase
from django.utils import timezone

from .models import (
        Collector, Agent, Project, Job,
        InstalledJob, RequiredJobArgument,
        OptionalJobArgument, JobInstance,
)
from .base_models import ValuesType, OpenbachFunctionParameter

class ProjectCheckerMixin:
    def assertProjectCompliant(self, expected, actual):
        self.assertEqual(expected['name'], actual['name'])
        self.assertEqual(expected.get('description', ''), actual['description'])
        self.assertCountEqual(expected.get('owners', []), actual['owners'])

        for entity in expected.get('entity', []):
            for actual_entity in actual['entity']:
                if entity['name'] == actual_entity['name']:
                    self.assertEqual(entity['description'], actual_entity['description'])
                    break
            else:
                self.fail('Found unknown entity in actual project: {}'.format(entity))

        for scenario in expected.get('scenario', []):
            for actual_scenario in actual['scenario']:
                if scenario['name'] == actual_scenario['name']:
                    self.assertScenarioCompliant(scenario, actual_scenario)
                    break
            else:
                self.fail('Found unknown scenario in actual project: {}'.format(scenario))

    def assertScenarioCompliant(self, expected, actual):
        self.assertDictEqual(expected.get('arguments', {}), actual['arguments'])
        self.assertDictEqual(expected.get('constants', {}), actual['constants'])
        self.assertEqual(expected.get('description', ''), actual['description'])
        self.assertEqual(expected['name'], actual['name'])

        expected_openbach_functions = expected.get('openbach_functions', [])
        actual_openbach_functions = actual['openbach_functions']
        self.assertEqual(len(expected_openbach_functions), len(actual_openbach_functions))

        for expected, actual in zip(expected_openbach_functions, actual_openbach_functions):
            expected = expected.copy()
            expected_id = expected.pop('id')
            self.assertEqual(expected_id, actual['id'])
            self.assertEqual(expected.pop('label', str(expected_id)), actual['label'])

            expected_wait = expected.pop('wait', {})
            actual_wait = actual.get('wait', {})
            self.assertEqual(
                    expected_wait.get('time', 0),
                    actual_wait.get('time', 0))
            self.assertCountEqual(
                    expected_wait.get('launched_ids', []),
                    actual_wait.get('launched_ids', []))
            self.assertCountEqual(
                    expected_wait.get('finished_ids', []),
                    actual_wait.get('finished_ids', []))

            openbach_function, = expected
            expected_function = expected[openbach_function]
            actual_function = expected[openbach_function]
            self.assertCountEqual(expected_function, actual_function)

class OpenbachFunctionArgumentTestCase(TestCase):
    def _check_conversions(self, field, argument, value, serialized):
        self.assertEqual(field.to_python(argument), value)
        self.assertEqual(field.get_prep_value(argument), serialized)

    def _check_interpolation(self, field, argument, expected, **parameters):
        actual = field.validate_openbach_value(argument, parameters)
        self.assertEqual(actual, expected)

    def _prepare_fields(self, *types, **named_types):
        for type_ in types:
            yield OpenbachFunctionParameter(type=type_)

        for name, expected in named_types.items():
            field = OpenbachFunctionParameter.from_type(name)
            self.assertEqual(field.type, expected)
            yield field

    def test_arguments_int(self):
        expected = {ValuesType.INTEGER.value: int}
        for field in self._prepare_fields(int, **expected):
            self._check_conversions(field, 3, 3, '3')
            self._check_conversions(field, '3', 3, '3')
            self._check_conversions(field, 3.0, 3, '3')
            self._check_interpolation(field, '$test', 3, test=3)
            self._check_interpolation(field, '$test', 3, test='3')

    def test_arguments_int_list(self):
        expected = {
                ValuesType.JOB_INSTANCE_ID.value: [int],
                ValuesType.SCENARIO_INSTANCE_ID.value: [int],
        }
        for field in self._prepare_fields([int], **expected):
            self._check_conversions(field, [1, 2, 3], [1, 2, 3], '1 2 3')
            self._check_conversions(field, '1 2 3', [1, 2, 3], '1 2 3')
            self._check_conversions(field, '12 3', [12, 3], '12 3')
            self._check_conversions(field, '123', [123], '123')
            self._check_conversions(field, 123, [123], '123')
            self._check_interpolation(field, '1 $test 3', [1, 2, 3], test=2)
            self._check_interpolation(field, '1 $test 3', [1, 2, 3], test='2')
            self._check_interpolation(field, ['1', '$test', 3], [1, 2, 3], test=2)

    def test_arguments_none(self):
        expected = {ValuesType.NONE_TYPE.value: type(None)}
        for field in self._prepare_fields(type(None), **expected):
            self._check_conversions(field, None, None, None)
            self._check_conversions(field, '', True, 'True')
            self._check_conversions(field, 'None', True, 'True')
            self._check_conversions(field, 'True', True, 'True')
            self._check_conversions(field, True, True, 'True')
            self._check_conversions(field, False, True, 'True')
            self._check_conversions(field, 'False', True, 'True')
            self._check_interpolation(field, '$test', True, test=3)

class JobTestCase(TestCase):
    def setUp(self):
        Job.objects.create(name='test_job')

    def test_arguments_create(self):
        job = Job.objects.get(name='test_job')
        arg = RequiredJobArgument.objects.create(
                name='first', type='int',
                subcommand=job.subcommands.get(name=None),
                count='1', rank=0)
        self.assertTrue(arg.check_count(1))
        self.assertFalse(arg.check_count(0))
        for i in range(2, 10):
            self.assertFalse(arg.check_count(i))

        arg = RequiredJobArgument.objects.create(
                name='second', type='str',
                subcommand=job.subcommands.get(name=None),
                count='3-6', rank=1)
        for i in range(3, 7):
            self.assertTrue(arg.check_count(i))
        for i in range(3):
            self.assertFalse(arg.check_count(i))
        for i in range(7, 10):
            self.assertFalse(arg.check_count(i))

        RequiredJobArgument.objects.create(
                name='third', type='ip',
                subcommand=job.subcommands.get(name=None),
                count='+', rank=2)

        arg = OptionalJobArgument.objects.create(
                name='optional', type='bool',
                subcommand=job.subcommands.get(name=None),
                count='*', flag='-o')
        for i in range(10):
            self.assertTrue(arg.check_count(i))

        OptionalJobArgument.objects.create(
                name='flags', type='None',
                subcommand=job.subcommands.get(name=None),
                count='0', flag='-f')

        OptionalJobArgument.objects.create(
                name='star', type='int',
                subcommand=job.subcommands.get(name=None),
                count='*', flag='-s')

        default_subcommand = job.subcommands.get(name=None)
        self.assertEqual(default_subcommand.required_arguments.count(), 3)
        self.assertEqual(default_subcommand.optional_arguments.count(), 3)

class InstalledJobTestCase(TestCase):
    def setUp(self):
        Job.objects.create(name='test_job')
        collector = Collector.objects.create(address='172.20.34.45')
        Agent.objects.create(
                address='172.20.34.45', name='Openbach_Agent',
                reachable=True, collector=collector)

    def test_install_job(self):
        agent = Agent.objects.get(name='Openbach_Agent')
        job = Job.objects.get(name='test_job')
        installed_job = InstalledJob.objects.create(
                agent=agent, job=job,
                severity=1, local_severity=1)
        self.assertEqual(installed_job.job, job)
        self.assertEqual(installed_job.agent, agent)

class JobInstanceTestCase(TestCase):
    def setUp(self):
        job = Job.objects.create(name='test_job')
        collector = Collector.objects.create(address='172.20.34.45')
        agent = Agent.objects.create(
                address='172.20.34.45', name='Openbach_Agent',
                reachable=True, collector=collector)
        InstalledJob.objects.create(
                agent=agent, job=job,
                severity=1, local_severity=1)
        RequiredJobArgument.objects.create(
                name='first', type='int',
                subcommand=job.subcommands.get(name=None),
                count='1', rank=0)
        RequiredJobArgument.objects.create(
                name='second', type='str',
                subcommand=job.subcommands.get(name=None),
                count='3-6', rank=1)
        OptionalJobArgument.objects.create(
                name='optional', type='ip',
                subcommand=job.subcommands.get(name=None),
                count='*', flag='-o')
        OptionalJobArgument.objects.create(
                name='flags', type='None',
                subcommand=job.subcommands.get(name=None),
                count='0', flag='-f')
        OptionalJobArgument.objects.create(
                name='star', type='int',
                subcommand=job.subcommands.get(name=None),
                count='*', flag='-s')

    def test_job_instance(self):
        now = timezone.now()
        installed_job = InstalledJob.objects.all()[0]
        job_instance = JobInstance.objects.create(
                job_name=installed_job.job.name,
                agent_name=installed_job.agent.name,
                agent=installed_job.agent,
                collector=installed_job.agent.collector,
                update_status=now,
                start_date=now,
                periodic=False)

        job_instance.configure({
            'first': 42,
            'second': ['riri', 'fifi', 'loulou'],
            'optional': ['8.8.8.8', '127.0.0.1', '192.168.0.1'],
        })
        job_instance.save()

class ProjectTestCase(ProjectCheckerMixin, TestCase):
    def setUp(self):
        self.project_json = {
                "name": "OpenSAND",
                "description": "OpenSAND Plateform",
                "entity": [{
                    "name": "Sat",
                    "description": "The satellite",
                    "agent": {
                        "name": "openbach-controller",
                        "address": "172.20.34.39",
                        "username": "opensand",
                        "collector": "172.20.34.39",
                    },
                    "networks": ["emu"],
                }, {
                    "name": "gw",
                    "description": "Gateway",
                    "agent": None,
                    "networks": ["emu", "lan_gw"],
                }, {
                    "name": "st1",
                    "description": "Satellite terminal 1",
                    "agent": None,
                    "networks": ["emu", "lan_st"],
                }, {
                    "name": "st2",
                    "description": "Satellite terminal 2",
                    "agent": None,
                    "networks": ["emu"],
                }, {
                    "name": "ws1",
                    "description": "Workstation 1",
                    "agent": None,
                    "networks": ["lan_st"],
                }, {
                    "name": "ws2",
                    "description": "Workstation 2",
                    "agent": None,
                    "networks": ["lan_st"],
                }, {
                    "name": "ws3",
                    "description": "Workstation 3",
                    "agent": None,
                    "networks": ["lan_gw"],
                }, {
                    "name": "ws4",
                    "description": "Workstation 4",
                    "agent": None,
                    "networks": []
                }],
                "network": ["emu", "lan_gw", "lan_st"],
                "scenario": [{
                    "name": "Ping between machines",
                    "description": "First scenario (for test)",
                    "arguments": {},
                    "constants": {},
                    "openbach_functions": [{
                        "id": 1,
                        "start_job_instance": {
                            "entity_name": "Sat",
                            "fping": {
                                "destination_ip": "172.20.0.83",
                            },
                            "offset": 5,
                        },
                        "wait": {
                            "time": 5,
                        },
                    }, {
                        "id": 2,
                        "start_job_instance": {
                            "entity_name": "Sat",
                            "hping": {
                                "destination_ip": "172.20.0.83",
                            },
                            "offset": 5,
                        },
                        "wait": {
                            "time": 5,
                        },
                    }],
                }, {
                    "name": "Congestion tests",
                    "description": "2 Iperf servs queried by 2 iperf clients",
                    "arguments": {},
                    "constants": {},
                    "openbach_functions": [{
                        "id": 1,
                        "start_job_instance": {
                            "entity_name": "Sat",
                            "pep": {
                                "sat_network": "opensand",
                                "pep_port": 3000,
                            },
                            "offset": 0,
                        },
                    }, {
                        "id": 2,
                        "start_job_instance": {
                            "entity_name": "gw",
                            "iperf": {
                                "mode": "-s",
                                "udp": True,
                                "port": 5000,
                            },
                            "offset": 0,
                        },
                    }, {
                        "id": 3,
                        "start_job_instance": {
                            "entity_name": "gw",
                            "iperf": {
                                "mode": "-s",
                                "port": 5001,
                            },
                            "offset": 0,
                        },
                    }, {
                        "id": 4,
                        "start_job_instance": {
                            "entity_name": "gw",
                            "tcpprobe_monitoring": {
                                "port": 5001,
                                "interval": 10,
                                "path": "/tcp/tcpprobe.out",
                            },
                            "offset": 0,
                        },
                    }, {
                        "id": 5,
                        "start_job_instance": {
                            "entity_name": "gw",
                            "rate_monitoring": {
                                "interval": 1,
                                "chain": "-A INPUT",
                                "jump": "ACCEPT",
                                "in_interface": "eth0",
                                "protocol": "tcp",
                                "source_port": 5001,
                            },
                            "offset": 0,
                        },
                    }, {
                        "id": 6,
                        "start_job_instance": {
                            "entity_name": "ws1",
                            "iperf": {
                                "mode": "-c 192.168.0.7",
                                "udp": True,
                                "port": 5000,
                            },
                            "offset": 0,
                        },
                        "wait": {
                            "time": 5,
                            "launched_ids": [1, 2, 3, 4, 5],
                        },
                    }, {
                        "id": 7,
                        "start_job_instance": {
                            "entity_name": "ws1",
                            "iperf": {
                                "mode": "-c 192.168.0.7",
                                "port": 5001,
                            },
                            "offset": 0,
                        },
                        "wait": {
                            "time": 5,
                            "launched_ids": [1, 2, 3, 4, 5],
                        },
                    }, {
                        "id": 8,
                        "stop_job_instances": {
                            "openbach_function_ids": [5, 6],
                        },
                        "wait": {
                            "time": 500,
                            "launched_ids": [6, 7],
                        },
                    }, {
                        "id": 9,
                        "stop_job_instances": {
                            "openbach_function_ids": [1, 2, 3, 4, 5],
                        },
                        "wait": {
                            "launched_ids": [8],
                        },
                    }],
                }],
        }

    def _create_jobs(self):
        Job.objects.create(name='fping')
        Job.objects.create(name='hping')

    def _create_arguments(self):
        for job in Job.objects.filter(name__iendswith='ping'):
            RequiredJobArgument.objects.create(
                    rank=0, name='destination_ip',
                    subcommand=job.subcommands.get(name=None),
                    type='ip', count='1')

    def _create_scenario_prerequisites(self):
        # Scenario 1
        self._create_jobs()
        self._create_arguments()

        # Scenario 2
        pep = Job.objects.create(name='pep')
        iperf = Job.objects.create(name='iperf')
        tcp = Job.objects.create(name='tcpprobe_monitoring')
        rate = Job.objects.create(name='rate_monitoring')

        RequiredJobArgument.objects.create(
                subcommand=pep.subcommands.get(name=None),
                rank=0, name='sat_network',
                type='str', count='1')
        OptionalJobArgument.objects.create(
                subcommand=pep.subcommands.get(name=None),
                flag='-p', name='pep_port',
                type='int', count='1')

        OptionalJobArgument.objects.create(
                subcommand=iperf.subcommands.get(name=None),
                flag='-s', name='mode',
                type='None', count='0')
        OptionalJobArgument.objects.create(
                subcommand=iperf.subcommands.get(name=None),
                flag='-u', name='udp',
                type='None', count='0')
        OptionalJobArgument.objects.create(
                subcommand=iperf.subcommands.get(name=None),
                flag='-p', name='port',
                type='int', count='1')

        RequiredJobArgument.objects.create(
                subcommand=tcp.subcommands.get(name=None),
                rank=0, name='port',
                type='int', count='1')
        OptionalJobArgument.objects.create(
                subcommand=tcp.subcommands.get(name=None),
                flag='-i', name='interval',
                type='int', count='1')
        OptionalJobArgument.objects.create(
                subcommand=tcp.subcommands.get(name=None),
                flag='-p', name='path',
                type='str', count='1')

        RequiredJobArgument.objects.create(
                subcommand=rate.subcommands.get(name=None),
                rank=0, name='interval',
                type='int', count='1')
        RequiredJobArgument.objects.create(
                subcommand=rate.subcommands.get(name=None),
                rank=1, name='chain',
                type='str', count='1')
        OptionalJobArgument.objects.create(
                subcommand=rate.subcommands.get(name=None),
                flag='-j', name='jump',
                type='str', count='1')
        OptionalJobArgument.objects.create(
                subcommand=rate.subcommands.get(name=None),
                flag='-i', name='in_interface',
                type='str', count='1')
        OptionalJobArgument.objects.create(
                subcommand=rate.subcommands.get(name=None),
                flag='-p', name='protocol',
                type='str', count='1')
        OptionalJobArgument.objects.create(
                subcommand=rate.subcommands.get(name=None),
                flag='--sport', name='source_port',
                type='int', count='1')

    def _test_project_fails_and_get_context_manager(self):
        name = self.project_json['name']
        description = self.project_json['description']
        project = Project.objects.create(name=name, description=description)
        with self.assertRaises(Project.MalformedError) as cm:
            project.load_from_json(self.project_json)
        return cm

    def test_scenario_fail_with_no_job(self):
        cm = self._test_project_fails_and_get_context_manager()
        self.assertEqual(
                cm.exception.error['section'],
                'scenario.Ping between machines')
        self.assertEqual(
                cm.exception.error['message']['error'],
                'No such job in the database')
        self.assertEqual(
                cm.exception.error['message']['offending_entry'],
                'openbach_functions.0.start_job_instance.fping')

    def test_scenario_fail_with_no_job_argument(self):
        self._create_jobs()
        cm = self._test_project_fails_and_get_context_manager()
        self.assertEqual(
                cm.exception.error['section'],
                'scenario.Ping between machines')
        self.assertEqual(
                cm.exception.error['message']['error'],
                'The configured job does not accept the given argument')
        self.assertEqual(
                cm.exception.error['message']['offending_entry'],
                'openbach_functions.0.start_job_instance.fping.destination_ip')

    def test_scenario_succed_with_job_arguments_but_second_fail(self):
        self._create_jobs()
        self._create_arguments()
        cm = self._test_project_fails_and_get_context_manager()
        self.assertEqual(
                cm.exception.error['section'],
                'scenario.Congestion tests')
        self.assertEqual(
                cm.exception.error['message']['error'],
                'No such job in the database')
        self.assertEqual(
                cm.exception.error['message']['offending_entry'],
                'openbach_functions.0.start_job_instance.pep')

    def test_success(self):
        self._create_scenario_prerequisites()
        name = self.project_json['name']
        description = self.project_json['description']
        project = Project.objects.create(name=name, description=description)
        project.load_from_json(self.project_json)
        self.assertProjectCompliant(self.project_json, project.json)


from typing import (
    List,
)

class PickApples:
    """
    @param a: a list of integer
    @param k: a integer
    @param l: a integer
    @return: return the maximum number of apples that they can collect.
    """
    def pick_apples(self, a: List[int], k: int, l: int) -> int:
        max_apples, n = float("-inf"), len(a)
        for i in range(n):
            left_max_l = self.find_max(a, 0, i, k)
            right_max_k = self.find_max(a, i, n, l)

            left_max_k = self.find_max(a, 0, i, l)
            right_max_l = self.find_max(a, i, n, k)

            if left_max_l != -1 and right_max_k != -1:
                max_apples = max(left_max_l + right_max_k, max_apples)

            if left_max_k != -1 and right_max_l != -1:
                max_apples = max(left_max_k + right_max_l, max_apples)

        return max_apples if max_apples != float("-inf") else -1

    def find_max(self, a, start, end, len):
        if len > end - start:
            return -1
        left, right = start, start + len
        sum_window = sum(a[i] for i in range(left, right))
        max_sum = sum_window

        while right < end:
            sum_window += a[right]
            sum_window -= a[left]
            max_sum = max(sum_window, max_sum)
            left += 1
            right += 1
        return max_sum


import numpy as np
import pandas as pd
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Reshape, Flatten, Conv2D, Conv2DTranspose, LeakyReLU, Dropout
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.datasets import mnist

(x_train, _), (_, _) = mnist.load_data()

x_train = (x_train.astype(np.float32) - 127.5) / 127.5
x_train = np.expand_dims(x_train, axis=3)

generator = Sequential()
generator.add(Dense(7 * 7 * 128, input_dim=100))
generator.add(LeakyReLU())
generator.add(Reshape((7, 7, 128)))
generator.add(Conv2DTranspose(64, kernel_size=4, strides=2, padding='same'))
generator.add(LeakyReLU())
generator.add(Conv2DTranspose(1, kernel_size=4, strides=2, padding='same', activation='tanh'))

discriminator = Sequential()
discriminator.add(Conv2D(64, kernel_size=4, strides=2, padding='same', input_shape=(28, 28, 1)))
discriminator.add(LeakyReLU())
discriminator.add(Conv2D(128, kernel_size=4, strides=2, padding='same'))
discriminator.add(LeakyReLU())
discriminator.add(Flatten())
discriminator.add(Dropout(0.4))
discriminator.add(Dense(1, activation='sigmoid'))

discriminator.compile(loss='binary_crossentropy', optimizer=Adam(lr=0.0002, beta_1=0.5), metrics=['accuracy'])

discriminator.trainable = False
gan = Sequential([generator, discriminator])
gan.compile(loss='binary_crossentropy', optimizer=Adam(lr=0.0002, beta_1=0.5))

epochs = 50
batch_size = 128
steps_per_epoch = x_train.shape[0] // batch_size

for epoch in range(epochs):
    for step in range(steps_per_epoch):
        noise = np.random.normal(0, 1, size=(batch_size, 100))
        real_images = x_train[np.random.randint(0, x_train.shape[0], size=batch_size)]

        generated_images = generator.predict(noise)

        X = np.concatenate([real_images, generated_images])
        y_dis = np.zeros(2 * batch_size)
        y_dis[:batch_size] = 0.9

        discriminator.trainable = True
        d_loss = discriminator.train_on_batch(X, y_dis)

        noise = np.random.normal(0, 1, size=(batch_size, 100))
        y_gen = np.ones(batch_size)

        discriminator.trainable = False
        g_loss = gan.train_on_batch(noise, y_gen)

    print(f'Epoch: {epoch+1}/{epochs}, Ayırt Edici Kayıp: {d_loss[0]}, Ayırt Edici Doğruluk: {d_loss[1]*100:.2f}%, Üreteci Kayıp: {g_loss}')


import time
import requests
from bs4 import BeautifulSoup as bs

# timeout retry times limit
RETRY_LIMIT = 5
# sleep seconds
SLEEP_SECOND = 1
# timeout limit
TIMEOUT_LIMIT = 5

# 自定义的请求方法
# 主要是为了方便retry
def retry_requests(method, url, params=None, timeout=TIMEOUT_LIMIT, msg=''):
    headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate',
        'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,ja;q=0.6',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive',
        'Host': 'www.csrc.gov.cn',
        'Pragma': 'no-cache',
        'Upgrade-Insecure-Requests': '1',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
    }

    retry = 0
    while retry < RETRY_LIMIT:
        try:
            if method.lower() == 'get':
                resp = requests.get(url, headers=headers, params=params, timeout=timeout)
                return resp
            elif method.lower() == 'post':
                resp = requests.post(url, headers=headers, data=params, timeout=timeout)
                return resp
            else:
                return
        except requests.RequestException or requests.Timeout or requests.ReadTimeout or requests.ConnectionError as exc:
            # 网络异常
            # 直接retry
            retry = retry + 1
            if retry >= RETRY_LIMIT:
                logging.error(exc)
                logging.error('failed(%s): %s %s' % (retry, url, msg))
            time.sleep(SLEEP_SECOND)  # 停5秒再retry
        except Exception as exc:
            # 解析异常
            # 需要关注
            logging.error(exc)
            retry = retry + 1
            if retry >= RETRY_LIMIT:
                logging.error('failed(%s): %s %s' % (retry, url, msg))
            else:
                logging.error('retry(%s): %s %s' % (retry, url, msg))
            time.sleep(SLEEP_SECOND)  # 停5秒再retry
        else:
            # 正常通过 跳出while循环
            retry = RETRY_LIMIT
    return

# 拼接url
def connect_urls(forward, backward):
    if backward.startswith('./'):
        return forward + backward.replace('./', '')
    elif backward.startswith('../'):
        # 去掉一层
        if forward.endswith('/'):
            forward = forward[:-1]
        forward = forward[:forward.rfind('/')]
        backward = backward[3:]
        return connect_urls(forward, backward)
    else:
        return forward + '/' + backward

# 读取本地html
def read_html(html_path, encoding='utf-8'):
    with open(html_path, 'r', encoding=encoding) as html_file:
        html_content = html_file.read()
        soup = bs(html_content, 'lxml')
        return soup


from datetime import datetime
from typing import Any, Callable
from zoneinfo import ZoneInfo

import orjson
from pydantic import BaseModel, validator

def orjson_dumps(v: Any, *, default: Callable[[Any], Any] | None) -> str:
    return orjson.dumps(v, default=default).decode()

def convert_datetime_to_gmt(dt: datetime) -> str:
    if not dt.tzinfo:
        dt = dt.replace(tzinfo=ZoneInfo("UTC"))

    return dt.strftime("%Y-%m-%dT%H:%M:%S%z")

class ORJSONModel(BaseModel):
    class Config:
        json_loads = orjson.loads
        json_dumps = orjson_dumps
        json_encoders = {datetime: convert_datetime_to_gmt}
        allow_population_by_field_name = True

    # not sure if that's a good practice
    @validator("*", pre=True)
    def empty_str_to_none(cls, v):
        if v == "":
            return None
        return v


from flask import Flask, render_template, request, url_for, redirect
from peewee import *
from model import *

db=MySQLDatabase('conf',user='root', passwd='***')

app=Flask(__name__)

@app.before_request
def before_request():
	db.connect()

@app.teardown_request
def after_request(exception):
	db.close()

@app.route('/')
def index():
	return render_template('home.html', confessions=Confession.select().order_by(Confession.post_date.desc()))

@app.route('/post_new/')
def post_new_function():
	return render_template('new_conf.html')

@app.route('/create', methods=['POST'])
def create():
	Confession.create(
		text=request.form['confession_text']
		)
	return redirect(url_for('index'))

if __name__=='__main__':
	app.jinja_env.auto_reload = True
	app.config['TEMPLATES_AUTO_RELOAD'] = True
	app.run(debug=True)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

'''
收集控的决策问题
自底向上
O(nC)
'''

def getMaxValue(Num, Capacity, Weight, Value):
    V = [0] * (Capacity+1)
    for p in range(1, Capacity+1):
        maxV = 0
        for i in range(Num):
            w = Weight[i]
            if p >= w:
                m = V[p-w] + Value[i]
                maxV = max(maxV, m)
        V[p] = maxV

    return V[Capacity]

n = int(input(""))

for i in range(n):
    line1 = input("").split()

    num = int(line1[0])
    cap = int(line1[1])

    value  = []
    weight = []

    line2 = input("").split()
    line3 = input("").split()
    for i in range(num):
        value.append(int(line2[i]))
        weight.append(int(line3[i]))

    value = getMaxValue(num, cap, weight, value)
    print(value)


results = {}
ops = [' + ', ' - ', ' * ', ' // ']
for i in ops:
    for j in ops:
        for k in ops:
            expression = "4{:s}4{:s}4{:s}4".format(i, j, k)
            res = eval(expression)
            results[res] = expression.replace('//', '/') + " = {:d}".format(res)
num=int(input())
for i in range(num):
    val = int(input())
    if val not in results:
        print("no solution")
    else:
        print(results[val])


# Jacob Muller, jacobmuller@ufl.edu

import prime_factors
import headline
import bucket_sort

# Settings

# If 0, it will pick a random number
primeNumber = 0

# Bucket sorts. If integers list is empty, will generate a random list with numbers between 1 and 10000.
numBuckets = 5
integers = {}

if __name__ == '__main__':
    print("===================---===================")
    prime_factors.checkPrime(primeNumber)
    print("===================---===================")
    bucket_sort.sortBuckets(numBuckets, integers)
    print("===================---===================")
    headline.getHeadline()


from tkinter import *
import multiprocessing
import threading
import time
from runpy import run_path
import tkinter.messagebox
from tkinter.filedialog import *
# make_app -> add_task -> setting -> ui_update -> run_path

data = []
task_frame = []

def make_app():
    app = Tk()
    app.geometry('200x300')
    Button(app,text='Add',name='add',command=add_task).pack(side=BOTTOM)
    return app

def add_task():
    f = Frame(app,bg='#f2f2f2')
    task_frame.append(f)
    Label(f,name='task_file',text='script',bg='#f2f2f2').pack(anchor=NW)
    Label(f,name='task_time',text='00:00',bg='#f2f2f2').pack(side=LEFT)
    Button(f,name='setting',text='...',width=3,command=lambda :setting(f)).pack(side=RIGHT)
    f.pack(fill=X,padx=1,pady=1)

def setting(f):
    print(task_frame)
    for x in task_frame:
        if x.children['task_file']['text'] == 'script':
            if x != f:
                tkinter.messagebox.showerror('Err','setting first')
                return
            else:break
    t = Toplevel(f)
    v = StringVar(t,value='12:00')
    Label(t,name='file_path',text='File path').grid(row=0,column=0,sticky=W)
    Entry(t,name='path_ipt').grid(row=1,column=0)
    Button(t,name='find_path',text='...',width=3,command=lambda :find_path(t)).grid(row=1,column=1)
    Label(t,name='time',text='Time').grid(row=2,column=0,stick=W)
    Entry(t,name='time_ipt',textvariable=v).grid(row=3,column=0)
    Button(t,name='save',text='Save',command=lambda :(
                                                        save(t),
                                                        t.destroy()
                                                    )
           ).grid(row=4,column=0,columnspan=2)

def find_path(t):
    path = askopenfilename()
    file_name = path.split('/')[-1]
    v=StringVar(value=file_name)
    t.children['path_ipt']['textvariable'] = v
# can only run current path script

def save(t):
    d = {}
    path_ipt = t.children['path_ipt'].get()
    time_ipt = t.children['time_ipt'].get()
    d['path_ipt'] = path_ipt
    d['time_ipt'] = time_ipt
    d['execute'] = False
    # d['data_exsit'] = False
    data.append(d)
    print(data)

def ui_update():
    def _task_update():
        # f['task_file']=data['path_ipt']
        # f['task_time']=data['time_ipt']
        # app.task_Frame -> Frame.Label = f['task_file']
        # app.children.items() = all task frames + Add button
        tasks = [t[1] for t in app.children.items() if t[0] != 'add']
        for t,d in zip(tasks,data):
            t.children['task_file']['text'] = d['path_ipt']
            t.children['task_time']['text'] = d['time_ipt']
            if d['execute'] ==True:
                t['bg'] = '#EDFDF!'
            else:
                t['bg'] = '#F5F7FA'
            for ch in multiprocessing.active_children():
                if ch.name == d['path_ipt']:
                    t['bg'] = '#E9F2FD'
                    break

    def _restrict():
        # tasks = [t[1] for t in app.children.items() if t[0] != 'add']
        # for t in tasks:
        #     if t.children['task_file'] == None:
            # if d['path_ipt'] and not d['data_exsit']:
        # for d in data:
        #     if not d['path_ipt'] and not d['data_exsit']:
        #         tkinter.messagebox.showerror('ERR','Setting first')
        #         d['data_exsit'] = True

        pass

    def _task_time_check():
        now = time.ctime().split()[-2]
        for d in data:
            if d['time_ipt'] <= now and not d['execute']:
                p = multiprocessing.Process(name=d['path_ipt'],target=lambda :run_path(d['path_ipt']))
                p.start()
                d['execute'] = True

    def _task_status_update():
        #data--filepath--framename
        for d in data:
            if  d['execute'] ==True:
                file=d['path_ipt']
                for child in app.children.items():
                    if child[0] != 'add':
                        f = child[1]
                        if f['task_file']['text'] == file:
                            f['bg']='#EDFDF!'
        pass

    def _main():
        while True:
            time.sleep(0.5)
            _task_update()
            _task_time_check()
            _restrict()
            _task_status_update()

    t = threading.Thread(target=_main)
    t.start()

app = make_app()
app.after(0,ui_update)
app.mainloop()


#!/usr/bin/env python
import roslib; roslib.load_manifest('laser_assembler')
import rospy; from laser_assembler.srv import *
from sensor_msgs.msg import PointCloud2

def assemble_voxel_pc(): #Assembles point clouds recived from voxel grid filter. Topic subscribed to set in "vx300".
    rospy.wait_for_service("assemble_scans2")
    assemble_PC = rospy.ServiceProxy('assemble_scans2', AssembleScans2)
    pub = rospy.Publisher('/assembled_pc_scan', PointCloud2, queue_size=2)

    try:
        resp = assemble_PC(rospy.Time(0,0), rospy.get_rostime())
        pub.publish(resp.cloud)
        rospy.loginfo('New cloud added to object point cloud')
    except rospy.serviceException as e:
        rospy.loginfo('Didnt manage to assemble cloud...')

    return


#this is the logical engine for the game
from visuals import *
from random import randint

userClick = [] # array to hold the user click positions
minePositions = [] # array to hold the positions of the mines

# this function determines which box was clicked
def onClick(cordinates):
    x = cordinates.getX()
    y = cordinates.getY()
    x = getcenterX(x)
    y = getcenterY(y)

    #Determines which grid was clicked
    rectangle = whichGrid(x,y)
    if rectangle not in userClick:
        colourRec(rectangle,findMine(rectangle))
        userClick.append(rectangle)

#Determines which grid was clicked
def whichGrid(x,y):
    for i in grids:
        if i.getCenter().getX() == x and i.getCenter().getY() == y:
            return i

# This function determines the x value of the center of the rectangle clicked
def getcenterX(clickX):
    for center in centerX:
        if clickX-center <5:
            return center

#This function determines the y value of the center of the rectangle clicked
def getcenterY(clickY):
    for center in centerY:
        if clickY-center <5:
            return center

# This function checks if the clicked on square already contains a mine
def findMine(rectangle):
    if rectangle in minePositions:
        return "green"
    else:
        return "red"

# This function places the mines in the grids
def placeMine():
    for i in range(10):
        print(len(grids))
        place = randint(0,len(grids))

        #record the mine position
        minePositions.append(whichGrid(centerX[place],centerY[place]))
    print(minePositions)

# This function runs the game loop
def main():
    drawInterface()
    placeMine()

    #WARNING this should be last in the function
    while True:
        click = window.getMouse()
        onClick(click)
    #place the mines in the game

#running the game
main()

'''
if click poisition isn't in user clicks
    check mines and change colour

'''


from functools import reduce
import random

# Two groups of size 10
# Rest will be whatever left remains
GROUP_SIZES = [10, 10, 10]

def to_groups(seq, group_sizes):
    groups = {}
    seq_index = 0
    group_index = 1

    total_sizes = reduce(lambda x, y: x + y, group_sizes)

    if total_sizes < len(seq):
        group_sizes.append(len(seq) - total_sizes)

    for size in group_sizes:
        elements_taken = 0
        group_name = "Group {}".format(group_index)
        groups[group_name] = []
        while elements_taken < size and seq_index < len(seq):
            groups[group_name].append(seq[seq_index])
            seq_index += 1
            elements_taken += 1
        group_index += 1

    return groups

def get_stats(teams):
    teams_count = len(teams)
    total_minutes = teams_count * 6
    total_hours = total_minutes / 60

    stats = {"teams_count": teams_count,
             "total_minutes": total_minutes,
             "total_hours": total_hours}

    return stats

teams = open("teams").read().split("\n")

teams = [team.strip() for team in teams if team.strip() != ""]
random.shuffle(teams)
print(teams)

groups = to_groups(teams, GROUP_SIZES)

print(sum([len(groups[group]) for group in groups]))

stats = get_stats(teams)

result = []

result.append("Total number of teams: {}\n".format(stats["teams_count"]))
result.append("Total minutes of presenting: {}\n".format(stats["total_minutes"]))
result.append("Total hours of presenting: {}\n".format(stats["total_hours"]))

groups_order = sorted(groups.keys())

for key in groups_order:
    result.append("## " + key)
    result.append("\n" + "\n".join(list(map(lambda x: "* " + x, groups[key]))))
    result.append("\n")

handler = open("schedule.md", "w")
handler.write("\n".join(result))
handler.close()


import argparse
import os
import threading
from time import gmtime, strftime, time

from misc import config, merge_datasets, utils
from scrapers.scraper_base import HouseScraper
from scrapers.scraper_factory import ScraperFactory

def init_tmp_folder(scrapers: list, delete_all: bool = False):
    """
    Initializes the temporary folder to dump the data on

    Parameters
    ----------
    scrapers : list
        List of scrapers' ids that we do not  want to remove temporary
        files for
    delete_all : bool, opt
        Flag to delete all temporary files
    """
    if delete_all:
        utils.create_directory(config.TMP_DIR)
        return
    elif not utils.directory_exists(config.TMP_DIR):
        utils.create_directory(config.TMP_DIR)
        return
    else:
        directories = utils.get_directories(config.TMP_DIR)
        for id in scrapers:
            if os.path.join(config.TMP_DIR, id) in directories:
                # don't delete the scrapers we want to keep
                directories.remove(os.path.join(config.TMP_DIR, id))
        for directory in directories:
            utils.delete_directory(directory)

def scrape_web(scraper: HouseScraper, urls: list = None):
    """
    Monitors the elapsed time needed to scrape a real estate listing web

    Parameters
    ----------
    scraper : HouseScraper
        The scraper object that is going to scrape the web
    urls : list, opt
        List of URLs the scraper has to work with.
    """
    start_time = time()
    scraper.scrape(urls)
    end_time = time()
    elapsed_seconds = end_time - start_time
    utils.log(
        f'[{scraper.id}] Elapsed time: {strftime("%H:%M:%S", gmtime(elapsed_seconds))}')

def join_results():
    """
    Performs the actions to merge the partial datasets in one; then zips the whole dataset and
    images associated.
    """
    merge_datasets.merge_idealista_files()
    merge_datasets.merge_idealista_folders()

    merge_datasets.merge_fotocasa_files()
    merge_datasets.merge_fotocasa_folders()

    merge_datasets.merge_fotocasa_idealista()
    merge_datasets.zip_everything()

def main(scrapers_ids: list, urls: dict):
    """
    Launches several threads to scrape multiple real estate listing webs; then joins
    the results in a single CSV file

    Parameters
    ----------
    scrapers_ids : list
        List of the selected pages' IDs to scrape
    urls : dict
        Dictionary with scraper id <-> list of URLs to scrape
    """

    utils.log('Starting web-scraping')
    init_tmp_folder(scraper_ids)
    scraper_threads = list()
    for id in scrapers_ids:
        scraper_urls = urls.get(id)
        scraper_thread = threading.Thread(target=scrape_web, args=(
            ScraperFactory.create_scraper(id), scraper_urls))
        scraper_threads.append(scraper_thread)
        scraper_thread.start()

    for scraper_thread in scraper_threads:
        scraper_thread.join()

    utils.delete_directory(os.path.join(config.TMP_DIR, config.CHROME_SESSION))

    utils.log('Finished web-scraping')
    utils.log('Joining results...')

    join_results()

    utils.log('... Results joined')

if __name__ == '__main__':
    argparser = argparse.ArgumentParser(
        description='Will scrape the selected pages. If no pages selected, then it will scrape every page')
    argparser.add_argument(
        '-i', '--idealista', help='launches the idealista scraper', action='store_true')
    argparser.add_argument(
        '-f', '--fotocasa', help='launches the fotocasa scraper', action='store_true')
    argparser.add_argument(
        '--urls-fotocasa', help='urls to scrape with fotocasa', required=False, type=str, nargs='+')
    argparser.add_argument(
        '--urls-idealista', help='urls to scrape with idealista', required=False, type=str, nargs='+')
    argparser.add_argument('-m', '--merge', help='merges the data files without launching the scrapers',
                           action='store_true')
    argparser.add_argument(
        '-r', '--reset', help='resets the dataset and temporary files', action='store_true')
    args = argparser.parse_args()

    scraper_ids = list()
    urls = dict()
    if args.idealista:
        scraper_ids.append(config.IDEALISTA_ID)
    if args.fotocasa:
        scraper_ids.append(config.FOTOCASA_ID)
    if args.urls_fotocasa:
        urls[config.FOTOCASA_ID] = args.urls_fotocasa
    if args.urls_idealista:
        urls[config.IDEALISTA_ID] = args.urls_idealista

    if not scraper_ids:
        scraper_ids = [config.IDEALISTA_ID, config.FOTOCASA_ID]

    if args.reset:
        utils.create_directory(config.TMP_DIR)
        utils.create_directory(config.DATASET_DIR)

    if args.merge:
        utils.log('Joining and zipping the scraping results')
        join_results()
    else:
        utils.log(f'Scraping {scraper_ids}')
        main(scrapers_ids=scraper_ids, urls=urls)


from django.urls import path, re_path
from main import views
from django.conf.urls import url

urlpatterns = [
    path('todos/', views.todo, name='todos'),
    url(r'^todos/(?P<id>\d+)/delete/$', views.delete_task, name='delete'),
    path('todos/new/', views.new_task, name='new_task'),
    path('todos/completed', views.comp_todo, name='completed_todos'),
    re_path(r'^todos/(\d+)/completed/$', views.comp_todo),
]


class Person:

    def __init__(self, name, surname):
        self.name = name
        self.surname = surname

    def get_fullname(self):
        return self.name.capitalize() + ' ' + self.surname.capitalize()

person = Person(name='anar', surname='veliyev')
person1 = Person(name='koroglu', surname='mirzeyev')
print(person.get_fullname())
print(person1.get_fullname())


#from mcar_sarsa_semigrad_TileSutton import ValueFunction, run_episode, getAction
import mcar_sarsa_semigrad_TileSutton
from mcar_sarsa_semigrad_TileSutton import ValueFunction, run_episode, getOptimalAction, run_rollout
import gym
import time
import numpy as np
from rbf import RBF, normalize_obs

import matplotlib.pyplot as plt

class Constant_Feature_Map():
    def __init__(self):
        self.n_features = 1
    def map(self, state):
        return np.array([1.0])

class Rbf_Position_Feature_Map():
    def __init__(self, rbf):
        self.n_features = len(rbf.c)
        self.rbf = rbf
    def map(self, state):
        #just map position
        #print(state)
        #print(state[0])
        return np.array(self.rbf.get_rbf_activations([state[0]]))

class Rbf_2D_Feature_Map():
    def __init__(self, rbf):
        self.n_features = len(rbf.c)
        self.rbf = rbf
    def map(self, state):
        #just map position
        #print(state)
        #print(state[0])
        return np.array(self.rbf.get_rbf_activations(state))

def compute_feature_counts(feature_map, states, discount, env):
    fcounts = np.zeros(feature_map.n_features)
    for i in range(len(states)):
        #normalize state features
        f_normed = normalize_obs(states[i], env)
        fcounts += discount ** i * feature_map.map(f_normed)
    return fcounts

#rewards = []
if __name__ == "__main__":

    reps = 40  #number of episodes to train learner on
    env = gym.make('MountainCar-v0')
    numOfTilings = 8
    alpha = 0.5

    # use optimistic initial value, so it's ok to set epsilon to 0
    EPSILON = 0
    discount = 1.0 #using no discount factor for now

    valueFunction = ValueFunction(alpha, numOfTilings)

    ##feature map
    features = []
    centers = np.array([[0.0, 0.0], [0.0, 0.25], [0.0, 0.5], [0.0, 0.75], [0.0, 1.0],
                        [0.25, 0.0], [0.25, 0.25], [0.25, 0.5], [0.25, 0.75], [0.25, 1.0],
                        [0.5, 0.0], [0.5, 0.25], [0.5, 0.5], [0.5, 0.75], [0.5, 1.0],
                        [0.75, 0.0], [0.75, 0.25], [0.75, 0.5], [0.75, 0.75], [0.75, 1.0],
                        [1.0, 0.0], [1.0, 0.25], [1.0, 0.5], [1.0, 0.75], [1.0, 1.0]])
    widths = 0.15*np.ones(len(centers))

    rbf = RBF(centers, widths, env.action_space.n)
    fMap = Rbf_2D_Feature_Map(rbf)

    #generate plot of rbf activations

    x = np.linspace(0,1)
    y = np.ones(len(x))
    activations = []
    for i,x_i in enumerate(x):
        activations.append(fMap.map([x_i,y[i]]))
    print(activations)
    plt.plot(x, activations)
    plt.show()

    for i in range(reps):
        print(">>>>iteration",i)

        steps, states_visited = run_episode(env, valueFunction, 1, False, EPSILON)

        #compute feature counts
        fcounts = compute_feature_counts(fMap, states_visited, discount, env)
        print("steps = ", steps)
        print("feature count = ", fcounts)

        features.append(fcounts)

    features = np.array(features)
    legends = [str(c) for c in centers]
    for f in range(len(features[0])):
        plt.figure(f)
        plt.plot(range(1,reps+1), features[:,f])
        plt.legend([legends[f]])
        plt.xlabel("Number of episodes")
        plt.ylabel("Feature Counts")

    plt.show()


import logging

from cfgm_common import get_bgp_rtgt_max_id
from cfgm_common import get_bgp_rtgt_min_id

from vnc_cfg_api_server.resources import RouteTargetServer
from vnc_cfg_api_server.tests import test_case

logger = logging.getLogger(__name__)

class TestRouteTargetBase(test_case.ApiServerTestCase):
    @classmethod
    def setUpClass(cls, *args, **kwargs):
        cls.console_handler = logging.StreamHandler()
        cls.console_handler.setLevel(logging.DEBUG)
        logger.addHandler(cls.console_handler)
        super(TestRouteTargetBase, cls).setUpClass(*args, **kwargs)

    @classmethod
    def tearDownClass(cls, *args, **kwargs):
        logger.removeHandler(cls.console_handler)
        super(TestRouteTargetBase, cls).tearDownClass(*args, **kwargs)

    @property
    def api(self):
        return self._vnc_lib

    def test_route_target_format_name(self):
        # list of tested route target names with succeed or not and parsed
        # result
        tested_values = [
            (':::', False, None),
            ('not-enough-part-in-rt', False, None),
            ('to:much:part:in:rt', False, None),
            ('bad-prefix:1:1', False, None),
            ('target:non-digit-asn:1', False, None),
            ('target:1:non-digit-target', False, None),
            ('target:1:1', True, (1, 1)),
            ('target:1.1.1.1:1', True, ('1.1.1.1', 1)),
            (['target', '1.1.1.1', '1'], True, ('1.1.1.1', 1)),
            (['target', '1', 1], True, (1, 1)),
        ]
        for rt_name, expected_succeed, expected_result in tested_values:
            succeed, result = RouteTargetServer._parse_route_target_name(
                rt_name)
            if expected_succeed:
                if not succeed:
                    self.fail("Cannot parse route target '%s'" % rt_name)
                self.assertEqual(result, expected_result)
            if not expected_succeed and succeed:
                self.fail("Succeed to parse route target '%s'" % rt_name)

    def test_route_target_is_in_system_range(self):
        # RT name, global ASN, expected result
        tested_values = [
            ('target:1:1', 42, True),
            ('target:42:1', 42, True),
            # We now allow suffix 'L' for an ASN
            ('target:40L:10', 42, True),
            # Don't allow target value to be greater than 0xFFFF
            # when ASN is appended with 'L'
            ('target:40L:70000', 42, False),
            # Test with same ASN as global ASN(42). But target value
            # being greater than get_bgp_rtgt_min_id
            ('target:42:%d' % (get_bgp_rtgt_min_id(42) + 1000), 42, False),
            # Test with same ASN as global ASN(42). But target value
            # being greater than get_bgp_rtgt_max_id
            ('target:42:%d' % (get_bgp_rtgt_max_id(42) + 1000), 42, True),
            # Test with ASN different from global ASN(42).
            # Target value can be either greater than get_bgp_rtgt_max_id
            # or greater than get_bgp_rtgt_max_id
            ('target:40:%d' % (get_bgp_rtgt_min_id(42) + 1000), 42, True),
            ('target:40:%d' % (get_bgp_rtgt_max_id(42) + 1000), 42, True)
        ]

        for rt_name, global_asn, expected_result in tested_values:
            ok, result, _ = RouteTargetServer.validate_route_target(
                rt_name,
                global_asn)
            if not ok:
                self.assertEqual(ok, expected_result,
                                 "For rt_name: %s, expected result is %s" %
                                 (rt_name, expected_result))
            else:
                self.assertEqual(result, expected_result,
                                 "Route target: %s and global ASN: %d" %
                                 (rt_name, global_asn))


from datetime import timedelta
from django.utils import timezone

def compute_report(store_status_data, business_hours_data, store_timezone_data):
    report_data = {}

    for store_timezone in store_timezone_data:
        store_id = store_timezone.store_id
        timezone_str = store_timezone.timezone_str

        store_status = store_status_data.filter(store_id=store_id)
        business_hours = business_hours_data.filter(store_id=store_id)

        report_data[store_id] = {
            'uptime_last_hour': 0,
            'uptime_last_day': 0,
            'uptime_last_week': 0,
            'downtime_last_hour': 0,
            'downtime_last_day': 0,
            'downtime_last_week': 0,
        }

        current_time = timezone.now().astimezone(timezone.get_timezone(timezone_str))
        last_hour_threshold = current_time - timedelta(hours=1)
        last_day_threshold = current_time - timedelta(days=1)
        last_week_threshold = current_time - timedelta(weeks=1)

        for business_hour in business_hours:
            start_time = current_time.replace(hour=business_hour.start_time_local.hour, minute=business_hour.start_time_local.minute)
            end_time = current_time.replace(hour=business_hour.end_time_local.hour, minute=business_hour.end_time_local.minute)

            total_duration = end_time - start_time
            active_duration = timedelta()
            inactive_duration = timedelta()

            for status_entry in store_status:
                status_time = status_entry.timestamp_utc.astimezone(timezone.get_timezone(timezone_str))

                if status_time >= end_time:
                    break

                if status_time >= start_time:
                    if status_time <= end_time:
                        active_duration += timedelta(minutes=60)
                    else:
                        active_duration += end_time - status_time
                else:
                    inactive_duration += min(status_time, end_time) - max(status_time, start_time)

            uptime_last_hour = min(active_duration, timedelta(minutes=60))
            uptime_last_day = min(active_duration, total_duration)
            uptime_last_week = min(active_duration, total_duration * 7)

            downtime_last_hour = min(inactive_duration, timedelta(minutes=60))
            downtime_last_day = min(inactive_duration, total_duration)
            downtime_last_week = min(inactive_duration, total_duration * 7)

            report_data[store_id]['uptime_last_hour'] += uptime_last_hour.total_seconds() // 60
            report_data[store_id]['uptime_last_day'] += uptime_last_day.total_seconds() // 3600
            report_data[store_id]['uptime_last_week'] += uptime_last_week.total_seconds() // 3600

            report_data[store_id]['downtime_last_hour'] += downtime_last_hour.total_seconds() // 60
            report_data[store_id]['downtime_last_day'] += downtime_last_day.total_seconds() // 3600
            report_data[store_id]['downtime_last_week'] += downtime_last_week.total_seconds() // 3600

    return report_data


from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework import status
from django.http import Http404, HttpResponse
from django.forms.models import model_to_dict

from .models import Product, Subcategory, Category, Supplier
from historical.models import History
from .serializers import ProductSerializer, ImageSerialiser, CategorySerializer, SubcategorySerializer, SupplierSerializer

import mimetypes
from base64 import b64decode, b64encode

class AddProductView(APIView):
    permission_classes = (IsAuthenticated,)

    def post(self, request, format=None):
        if 'name' in request.data:
            request.data['name'] = request.data['name'].title()

        serializer = ProductSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        action = 'ADDED: '+request.data['name']
        history = History.objects.create(name=request.user.name, action=action)
        history.save()
        return Response(serializer.data)

class ProductView(APIView):
    permission_classes = (IsAuthenticated,)

    def update_action(self, object_before, object_after):
        object_difference = {
            key: 'Before: '+str(object_before[key])+' After: '+str(object_after[key])+'. ' for key in object_before if object_before[key] != object_after[key]
        }
        if object_difference:
            action = 'UPDATE:'
            for key in object_difference:
                action += key.capitalize()+' '+object_difference[key]
            return action
        else:
            return False

    def get_object(self, pk):
        try:
            return Product.objects.get(pk=pk)
        except Product.DoesNotExist:
            raise Http404

    def put(self, request, pk, format=None):
        product = self.get_object(pk)
        object_before = model_to_dict(product)

        serializer = ProductSerializer(
            product, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            object_after = model_to_dict(product)
            action = self.update_action(object_before, object_after)
            if action:
                history = History.objects.create(
                    name=request.user.name, action=action)
                history.save()

            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def get(self, request, pk, format=None):
        product = self.get_object(pk)

        serializer = ProductSerializer(product)
        return Response(serializer.data)

class AllProductsView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
        search_item = request.query_params.items()

        filters = {
            ('name__icontains' if key == 'search_item' else 'is_archived'): (not int(value) if key == 'is_active' else value)
            for (key, value) in search_item
        }

        products = Product.objects.filter(**filters)

        serializer = ProductSerializer(products, many=True)
        return Response(serializer.data)

class ProductCountView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
        active = Product.objects.filter(is_archived=False)
        inactive = Product.objects.filter(is_archived=True)
        categories = Category.objects.all()

        counts = {
            "active": len(active),
            "inactive": len(
                inactive),
            "categories": len(categories)
        }

        response = Response()

        response.data = {
            "active": len(active),
            "inactive": len(
                inactive),
            "categories": len(categories)
        }
        return response

class ProductImages(APIView):
    # permission_classes = (IsAuthenticated,)

    def get_object(self, pk):
        try:
            return Product.objects.get(pk=pk)
        except Product.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        product = self.get_object(pk)
        try:
            image = product.photo
            return HttpResponse(image, content_type="image/png")
        except:
            raise Http404

    # def get(self, request, pk, format=None):
    #     product = self.get_object(pk)
    #     try:
    #         value = product.photo
    #         mime_type, encoding = mimetypes.guess_type(str(value))
    #         if not mime_type:
    #             mime_type = 'image/png'
    #         data = value.file.read()
    #         image_data = bytes(
    #             'data:' + mime_type + ';base64,', encoding='UTF-8') + b64encode(data)
    #         return HttpResponse(image_data)
    #     except:
    #         raise Http404

class CategoryView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
        category = Category.objects.all()
        serializer = CategorySerializer(category, many=True)
        return Response(serializer.data)

class SubcategoryView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, pk, format=None):
        subcategory = Subcategory.objects.filter(category_id=pk)
        serializer = SubcategorySerializer(subcategory, many=True)
        return Response(serializer.data)

class AddSupplierView(APIView):
    permission_classes = (IsAuthenticated,)

    def post(self, request, format=None):
        serializer = SupplierSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        action = 'ADDED: '+request.data['name']
        history = History.objects.create(name=request.user.name, action=action)
        history.save()
        return Response(serializer.data)

class SupplierView(APIView):
    permission_classes = (IsAuthenticated,)

    def update_action(self, object_before, object_after):
        object_difference = {
            key: 'Before: '+str(object_before[key])+' After: '+str(object_after[key])+'. ' for key in object_before if object_before[key] != object_after[key]
        }
        if object_difference:
            action = 'UPDATE: '
            for key in object_difference:
                action += key.capitalize()+' '+object_difference[key]
            return action
        else:
            return False

    def get_object(self, pk):
        try:
            return Supplier.objects.get(pk=pk)
        except Supplier.DoesNotExist:
            raise Http404

    def put(self, request, pk, format=None):
        supplier = self.get_object(pk)
        object_before = model_to_dict(supplier)
        serializer = SupplierSerializer(
            supplier, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            object_after = model_to_dict(supplier)
            action = self.update_action(object_before, object_after)
            if action:
                history = History.objects.create(
                    name=request.user.name, action=action)
                history.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def get(self, request, pk, format=None):
        supplier = self.get_object(pk)

        serializer = SupplierSerializer(supplier)
        return Response(serializer.data)

class AllSuppliersView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
        suppliers = Supplier.objects.all()

        serializer = SupplierSerializer(suppliers, many=True)
        return Response(serializer.data)

class PublicProductView(APIView):
    def get(self, request, format=None):
        query_params = request.query_params
        a_to_z = 'name'

        filters = {}
        if('search_item' in query_params):
            filters['name__contains'] = query_params['search_item']

        if ('supplier_id' in query_params):
                filters['supplier_id'] = query_params['supplier_id']
        if ('category_id' in query_params):
            filters['category_id'] = query_params['category_id']
        if ('subcategory_id' in query_params):
            filters['subcategory_id'] = query_params['subcategory_id']
        filters['is_archived'] = 0

        if 'order_by' in query_params:
            if query_params['order_by'] == 'z_a':
                a_to_z = '-'+a_to_z

        products = Product.objects.filter(**filters).order_by(a_to_z)

        serializer = ProductSerializer(products, many=True)
        return Response(serializer.data)

class PublicSubcategoryView(APIView):
    def get(self, request, pk, format=None):
        subcategory = Subcategory.objects.get(pk=pk)

        serializer = SubcategorySerializer(subcategory)
        return Response(serializer.data)

class PublicSubcategoriesView(APIView):
    def get(self, request, format=None):
        search_item = request.query_params.items()
        filters = {
            ('name__icontains' if key == 'name' else key): value
            for (key, value) in search_item
        }
        subcategory = Subcategory.objects.filter(**filters)
        serializer = SubcategorySerializer(subcategory, many=True)
        return Response(serializer.data)

class PublicSupplierView(APIView):
    def get(self, request, format=None):
        search_item = request.query_params.items()
        a_to_z = 'name'

        filters = {
            ('name__icontains' if key == 'name' else key): value
            for (key, value) in search_item
        }

        if 'order_by' in filters:
            if filters['order_by'] == '0':
                a_to_z = '-'+a_to_z
            del filters['order_by']

        suppliers = Supplier.objects.filter(**filters).order_by(a_to_z)

        serializer = SupplierSerializer(suppliers, many=True)
        return Response(serializer.data)

# class ListProducts(APIView):
#     def get(self, request):
#         token = request.COOKIES.get('jwt')

#         if not token:
#             raise AuthenticationFailed('Unauthenticated!')

#         try:
#             payload = jwt.decode(token, 'secret', algorithms=['HS256'])
#         except jwt.ExpiredSignatureError:
#             raise AuthenticationFailed('Unauthenticated!')

#         product = Product.objects.all()
#         serializer = ProductSerializer(product, many=True)
#         return Response(serializer.data)


# You will probably need more methods from flask but this one is a good start.
from flask import render_template, request, jsonify, make_response
import datetime

# Import things from Flask that we need.
from accounting import app, db

# Import our models
from models import Contact, Invoice, Policy
from utils import PolicyAccounting

# Routing for the server.
@app.route("/")
def index():
    # You will need to serve something up here.
    return render_template('index.html')

@app.route("/invoice")
def test():
    return render_template('invoice.html')

@app.route("/invoices", methods=['POST'])
def get_invoice():
    if request.json or request.post:
        data = dict()
        policy_id = int(request.json['policy_id'])
        query_date = datetime.datetime.strptime(request.json['query_date'], '%d/%m/%Y').date()
        pa = PolicyAccounting(policy_id)
        data['policy_number'] = pa.get_policy_number()
        data['account_balance'] = pa.return_account_balance(query_date)
        data['invoices'] = pa.get_invoices(query_date)
        return jsonify(data)
    else:
        return make_response(jsonify({'error': 'Bad request'}), 400)


from dataclasses import dataclass
from trystructure_namespace_clusters.org.oasis_open.docs.ns.emix.pkg_2011.pkg_06.power.energy_real_type import EnergyRealType

__NAMESPACE__ = "http://docs.oasis-open.org/ns/emix/2011/06/power"

@dataclass
class EnergyReal(EnergyRealType):
    class Meta:
        name = "energyReal"
        namespace = "http://docs.oasis-open.org/ns/emix/2011/06/power"


from db.run_sql import run_sql
from models.fittnes_class import Fitnes_class
from models.member import Member
from models.gym import Gym

def save(fittnes_class):
    sql = "INSERT INTO fittnes_classes(name, fittnes_level, duration) VALUES ( %s, %s, %s ) RETURNING id"
    values = [fittnes_class.name, fittnes_class.fittnes_level, fittnes_class.duration]
    results = run_sql( sql, values )
    fittnes_class.id = results[0]['id']
    return fittnes_class

def select_all():
    fittnes_classes = []

    sql = "SELECT * FROM fittnes_classes"
    results = run_sql(sql)

    for row in results:
        fittnes_class = Fitnes_class(row['name'], row['fittnes_level'], row['duration'], row['id'])
        fittnes_classes.append(fittnes_class)
    return fittnes_classes

def select(id):
    fittnes_class = None
    sql = "SELECT * FROM fittnes_classes WHERE id = %s"
    values = [id]
    result = run_sql(sql, values)[0]

    if result is not None:
        fittnes_class = Fitnes_class(result['name'], result['fittnes_level'], result['duration'], result['id'] )
    return fittnes_class

def update(fittnes_class):
    sql = "UPDATE fittnes_classes SET (name, fittnes_level, duration) = (%s, %s, %s) WHERE id = %s"
    values = [fittnes_class.name, fittnes_class.fittnes_level, fittnes_class.duration, fittnes_class.id]
    print(values)
    run_sql(sql, values)

def delete_all():
    sql = "DELETE FROM fittnes_classes"
    run_sql(sql)

def delete(id):
    sql = "DELETE FROM fittnes_classes WHERE id = %s"
    values = [id]
    run_sql(sql, values)

def members(fittnes_class):
    members = []
    sql ="SELECT * FROM members  INNER JOIN gyms ON gyms.member_id = members.id WHERE gyms.fittnes_class_id = %s"
    values = [fittnes_class.id]
    result = run_sql(sql, values)

    for row in result:
        member = Member(row['first_name'], row['last_name'], row['date_of_birth'], row['email_address'], row['id'])
        members.append(member)
    return members


class Solution:
    def isPalindrome(self, s: str) -> bool:
        alpha = ""
        for c in s:
            if c.isalnum():
                alpha += c.lower()
        return True if alpha[:] == alpha[::-1] else False

s = Solution()
print(s.isPalindrome("A man, a plan, a canal: Panama"))


#!/usr/bin/env python3

import sys

# Write a program that predicts if a protein is trans-membrane
# Trans-membrane proteins have the following properties
#	Signal peptide: https://en.wikipedia.org/wiki/Signal_peptide
#	Hydrophobic regions(s): https://en.wikipedia.org/wiki/Transmembrane_protein
#	No prolines in hydrophobic regions (alpha helix)
# Hydrophobicity is measued via Kyte-Dolittle
#	https://en.wikipedia.org/wiki/Hydrophilicity_plot
# For our purposes:
#	Signal peptide is 8 aa long, KD > 2.5, first 30 aa
#	Hydrophobic region is 11 aa long, KD > 2.0, after 30 aa

#1. function for kd hydrophobicity
#for each AA, add it's value to a total and divide by the number of AA
def kd(seq): #kd = kite-doolittle = way of calc hydropho
	kdsum = 0 #should this go here?
	for i in range(len(seq)):
		if seq[i] == 'I'   : kdsum += 4.5
		elif seq[i] == 'V' : kdsum += 4.2
		elif seq[i] == 'L' : kdsum += 3.8
		elif seq[i] == 'F' : kdsum += 2.8
		elif seq[i] == 'C' : kdsum += 2.5
		elif seq[i] == 'M' : kdsum += 1.9
		elif seq[i] == 'A' : kdsum += 1.8
		elif seq[i] == 'G' : kdsum -= 0.4
		elif seq[i] == 'T' : kdsum -= 0.7
		elif seq[i] == 'S' : kdsum -= 0.8
		elif seq[i] == 'W' : kdsum -= 0.9
		elif seq[i] == 'Y' : kdsum -= 1.3
		elif seq[i] == 'P' : kdsum -= 1.6 #what do I do about the proline?
		elif seq[i] == 'H' : kdsum -= 3.2
		elif seq[i] == 'E' : kdsum -= 3.5
		elif seq[i] == 'Q' : kdsum -= 3.5
		elif seq[i] == 'D' : kdsum -= 3.5
		elif seq[i] == 'N' : kdsum -= 3.5
		elif seq[i] == 'K' : kdsum -= 3.9
		elif seq[i] == 'R' : kdsum -= 4.5
	return kdsum/len(seq)
#this doesn't work

#2. function that checks for a proline
def proline(seq):
	for c in seq:
		if c == 'P' : return True
		else 		: pass
#print(kd('R'))

#2. get all the sequences:
proteins = [] #sequences
ids = [] #name of the proteins

with open(sys.argv[1]) as fp:  #put file name in command line - python3 Work/learning_python/classwork.py
	seq = [] #sequence of AA - here so we can look at one sequence at a time
	for line in fp.readlines(): #read every line
		line = line.rstrip()
		if line.startswith('>'): #this is the standard beginning of a  new section/definition (new protein + seq in this case )
			words = line.split() #lets you collect multiple lines of sequence, as many lines needed until next >
			ids.append(words[0][1:])
			if len(seq) > 0 : proteins.append(''.join(seq))
			seq = [] #now know what each sequence is
		else : #if it doesn't start with >, it is a sequence ...
			seq.append(line) #...so add that line to seq
	proteins.append(''.join(seq)) #add your sequence (made from mashing the lines between >) to proteins

#3. look for hydrophobic regions in all sequences
w = 11
s = 8
for id, seq in zip(ids, proteins): #go through ids and proteins together
	#calculate hydrophobicity
	hd_region = False
	sig_pep = False
	for i in range(len(seq[29:]) - w + 1 ) :
		pep = seq[i:i+w]
		if kd(pep) > 2 and not proline(pep) : hd_region = True
		#print(i, kd(seq[i:i+w]))
	for i in range(len(seq[:29]) - s + 1)  :
		if kd(pep) > 2.5 : sig_pep = True
		#print(sig_pep)
	#want to say if they are both true
	if hd_region == True and sig_pep == True : print(id) #could say hd_region and sig_pep - check itself, and is a boolean

#also tried .append
#can use 'in' to ask if something is in your sequence
"""
python3 Programs/transmembrane.py Data/at_prots.fa
AT1G75120.1
AT1G10950.1
AT1G75110.1
AT1G74790.1
AT1G12660.1
AT1G75130.1
"""


import math
from typing import Tuple, Dict
from kesslergame import KesslerController
import numpy as np
from func import *
from kesslergame import Ship

# 距離5分割
class Controller(KesslerController):
    """
         A ship controller class for Kessler. This can be inherited to create custom controllers that can be passed to the
        game to operate within scenarios. A valid controller contains an actions method that takes in a ship object and ass
        game_state dictionary. This action method then sets the thrust, turn_rate, and fire commands on the ship object.
        """

    def __init__(self):
        genes2 = [-422.56833678, -128.5440438, 390.55000786, -389.1460838, -79.66763919,
                  157.80320246, 94.08457887, 73.67425189, 129.10263867, 126.69284636,
                  108.57530471, 161.21374993, 440.06088036, -32.43618814, -269.25471835,
                  23.97717829, 179.54120818, 180, 11.01848299, 105.48515518,
                  124.83245825, 60.12989947, 84.42780692, 155.87859715, 12.61680382,
                  74.824144, 145.83796102, -5.56917356, 79.90114877, 170.21185764, ]
        gene = [-164.53175401560333, 0.11381500132402, 99.55962719106978, 652.0695605148196, 958.2536948627446,
                113.17313354331807]
        """
        Create your fuzzy logic controllers and other objects here
        """
        left1 = gene[0]
        left2 = gene[1]
        center = gene[2]
        right2 = gene[3]
        right1 = gene[4]
        center_angle = gene[5]

        def membership1(x):
            if x <= left1:
                return [1.0, 0.0, 0.0, 0.0, 0.0]
            elif x <= left2:
                return np.array([1.0 - (x - left1) / (left2 - left1), (x - left1) / (left2 - left1), 0.0, 0.0, 0.0])
            elif x <= center:
                return np.array([0.0, (center - x) / (center - left2),
                                 (x - left2) / (center - left2), 0.0, 0.0])
            elif x <= right2:
                return np.array([0.0, 0.0, (right2 - x) / (right2 - center), (x - center) / (right2 - center), 0.0])
            elif x <= right1:
                return np.array([0.0, 0.0, 0.0, (right1 - x) / (right1 - right2), (x - right2) / (right1 - right2)])
            else:
                return np.array([0.0, 0.0, 0.0, 0.0, 1.0])

        def membership2(angle):
            angle = abs(angle)
            if angle <= center_angle:
                return np.array([1.0 - angle / center_angle, angle / center_angle, 0.0])
            elif angle <= 180:
                return np.array([0.0, 2 - angle / center_angle, angle / center_angle - 1])

        self.membership1 = membership1
        self.membership2 = membership2

        def mems(x, angle):
            nonlocal genes2
            genes_out = np.array(genes2).copy()

            out0 = np.array([genes_out[0], genes_out[15]])
            out1 = np.array([genes_out[1], genes_out[16]])
            out2 = np.array([genes_out[2], genes_out[17]])
            out3 = np.array([genes_out[3], genes_out[18]])
            out4 = np.array([genes_out[4], genes_out[19]])
            out5 = np.array([genes_out[5], genes_out[20]])
            out6 = np.array([genes_out[6], genes_out[21]])
            out7 = np.array([genes_out[7], genes_out[22]])
            out8 = np.array([genes_out[8], genes_out[23]])
            out9 = np.array([genes_out[9], genes_out[24]])
            out10 = np.array([genes_out[10], genes_out[25]])
            out11 = np.array([genes_out[11], genes_out[26]])
            out12 = np.array([genes_out[12], genes_out[27]])
            out13 = np.array([genes_out[13], genes_out[28]])
            out14 = np.array([genes_out[14], genes_out[29]])

            k = membership1(x)
            p = membership2(angle)
            rule0 = k[0] * p[0]
            rule1 = k[0] * p[1]
            rule2 = k[0] * p[2]
            rule3 = k[1] * p[0]
            rule4 = k[1] * p[1]
            rule5 = k[1] * p[2]
            rule6 = k[2] * p[0]
            rule7 = k[2] * p[1]
            rule8 = k[2] * p[2]
            rule9 = k[3] * p[0]
            rule10 = k[3] * p[1]
            rule11 = k[3] * p[2]
            rule12 = k[4] * p[0]
            rule13 = k[4] * p[1]
            rule14 = k[4] * p[2]
            out = ((rule0 * out0) + (rule1 * out1) + (rule2 * out2) + (rule3 * out3) + (rule4 * out4) + (
                    rule5 * out5) + (rule6 * out6) + (
                           rule7 * out7) + (rule8 * out8) + (rule9 * out9) + (rule10 * out10) + (rule11 * out11) + (
                           rule12 * out12) + (rule13 * out13) + (rule14 * out14))
            return out

        self.mems = mems

        center_x = 500
        center_y = 400

    def actions(self, ownship: Dict, input_data: Dict[str, Tuple]) -> Tuple[float, float, bool]:
        # timeout(input_data)
        # 隕石と機体の位置関係のセクション
        ast_list = np.array(input_data["asteroids"])
        # (x,y)で表す，機体からの距離
        dist_xylist = [np.array(ownship['position']) - np.array(ast['position']) for ast in ast_list]
        dist_avoid_list = dist_xylist.copy()
        dist_list1 = [math.sqrt(xy[0] ** 2 + xy[1] ** 2) for xy in dist_xylist]

        # よける部分に関しては画面端のことを考える，弾丸はすり抜けないから狙撃に関しては考えない
        sidefromcenter = 500 - ownship['position'][0]
        below_center = 400 - ownship['position'][1]
        for xy in dist_avoid_list:
            if xy[0] > 500:
                xy[0] -= 1000
            elif xy[0] < -500:
                xy[0] += 1000
            if xy[1] > 400:
                xy[1] -= 800
            elif xy[1] < -400:
                xy[1] += 800
        dist_avoid_list = [math.sqrt(xy[0] ** 2 + xy[1] ** 2) for xy in dist_avoid_list]

        sorted2_idx = np.argsort(dist_avoid_list)
        sorteddict = ast_list[sorted2_idx]
        # ここから考えるのは近傍5つの隕石
        search_list = sorteddict[0:5]
        search_dist = np.array([math.dist(ownship['position'], ast['position']) for ast in search_list])
        angle_dist = [np.array(ast['position']) - np.array(ownship['position']) for ast in search_list]
        angle_dist = [angle360(math.degrees((np.arctan2(near_ang[1], near_ang[0])))) - ownship['heading'] for near_ang
                      in angle_dist]
        aalist = []
        for ang in angle_dist:
            if ang > 180:
                ang -= 360
            elif ang < -180:
                ang += 360
            aalist.append(ang)

        angdiff_front = min(aalist, key=abs)
        angdiff = aalist[0]
        fire_bullet = abs(angdiff_front) < 15 and min(dist_list1) < 400
        avoidance = np.min(dist_avoid_list)

        if len(input_data['ships']) >= 2:
            angle_ships = ast_angle(ownship['position'], input_data['ships'][2 - ownship['id']]['position'])
            dist = math.dist(ownship['position'], input_data['ships'][2 - ownship['id']]['position'])
            if (dist <= avoidance):
                if angle_ships > 180:
                    angle_ships -= 360
                elif angle_ships < -180:
                    angle_ships += 360
                avoidance = dist
                angdiff = abs(angle_ships)

        rule = self.mems(avoidance, angdiff)

        thrust = rule[0]
        turn_rate = rule[1] * np.sign(angdiff)
        if ownship["speed"] >= 0:
            self.str_move = "Moving forward"
        else:
            self.str_move = "Moving backwards"
        if thrust > ownship['thrust_range'][1]:
            thrust = ownship['thrust_range'][1]
        elif thrust < ownship['thrust_range'][0]:
            thrust = ownship['thrust_range'][0]
        if turn_rate > ownship['turn_rate_range'][1]:
            turn_rate = ownship['turn_rate_range'][1]
        elif turn_rate < ownship['turn_rate_range'][0]:
            turn_rate = ownship['turn_rate_range'][0]
        # 前後，回転，射撃のタプルをリターンする
        return thrust, turn_rate, fire_bullet

    @property
    def name(self) -> str:
        return "OMU-Let's"

    @property
    def explanation(self) -> str:
        return self.str_move


import os
from opt import get_opts
import torch
from torch import nn
from collections import defaultdict
from einops import repeat
from torch.utils.data import DataLoader
from datasets import dataset_dict
from torchvision import transforms as T
# models
# from models.nerf import *
from models.nerf_warp import *
from models.rendering_warp import *
# from models.encoder import *
from models.discriminator import discriminator
from random import randint
# from models.vae_components import EncoderBlock,ResNetEncoder
from torch.nn import functional as F
# optimizer, scheduler, visualization
from utils import *
# losses
from losses import loss_dict
# from stage1.unet_components import Enc
from datasets.ray_sample import FlexGridRaySampler,ImgToPatch
# metrics
from metrics import *
# pytorch-lightning
from pytorch_lightning.callbacks import ModelCheckpoint
from pytorch_lightning import LightningModule, Trainer
from pytorch_lightning.loggers import TestTubeLogger

torch.manual_seed(0)

class NeRFSystem(LightningModule):
    def __init__(self, hparams):
        super().__init__()
        self.hparams = hparams
        self.discriminators = []
        self.use_D = hparams.use_D
        self.use_contrastive = hparams.contrastive
        self.valid,self.fake = torch.ones(1, 1),torch.zeros(1,1)
        # self.loss = loss_dict['depth'](coef=1)
        self.loss = loss_dict['nerft'](coef=1).to(self.device)
        if self.use_contrastive:
            self.contrastive_loss = loss_dict['contrastive']()
        self.mutex_loss = loss_dict['mutex']()
        self.x_kernel = torch.Tensor([[1,0,-1],[2,0,-2],[1,0,-1]])[None,None,:,:]
        self.models_to_train = []
        self.enc_out_dim=self.hparams.enc_out_dim
        self.latent_dim=self.hparams.latent_dim
        self.img2patch = ImgToPatch(FlexGridRaySampler(hparams.sample_wh,img_wh=hparams.img_wh,scale_anneal=5e-4), hparams.sample_wh)

        if len(self.use_D) > 0:
            self.discriminator = discriminator()
            self.discriminators += [self.discriminator]

        self.embedding_xyz = PosEmbedding(hparams.N_emb_xyz-1, hparams.N_emb_xyz)
        self.embedding_dir = PosEmbedding(hparams.N_emb_dir-1, hparams.N_emb_dir)
        self.embeddings = {'xyz': self.embedding_xyz,
                           'dir': self.embedding_dir}
        if hparams.encode_t:
            self.embedding_t = torch.nn.Embedding(hparams.N_vocab, hparams.N_tau)
            self.embeddings['t'] = self.embedding_t
            self.models_to_train += [self.embedding_t]

        self.nerf_coarse = NeRFWarp('coarse',
                                in_channels_xyz=6*hparams.N_emb_xyz+3,
                                in_channels_dir=6*hparams.N_emb_dir+3,
                                in_channels_f=self.latent_dim)
        self.models = {'coarse': self.nerf_coarse}
        if hparams.N_importance > 0:
            self.nerf_fine = NeRFWarp('fine',
                                  in_channels_xyz=6*hparams.N_emb_xyz+3,
                                  in_channels_dir=6*hparams.N_emb_dir+3,
                                  encode_appearance=hparams.encode_a,
                                  in_channels_a=hparams.N_a,
                                  encode_transient=hparams.encode_t,
                                  in_channels_t=hparams.N_tau,
                                  beta_min=hparams.beta_min,
                                  in_channels_f=self.latent_dim)
            self.models['fine'] = self.nerf_fine
        self.models_to_train += [self.models]

    def get_progress_bar_dict(self):
        items = super().get_progress_bar_dict()
        items.pop("v_num", None)
        return items

    def forward(self, rays, ts,proj_mat, full_code_B=None,pixels_i=None, **kwargs): # TODO
        """Do batched inference on rays using chunk."""
        B = rays.shape[0]
        results = defaultdict(list)
        for i in range(0, B, self.hparams.chunk):
            rendered_ray_chunks = \
                render_rays(self.models,
                            self.embeddings,
                            rays[i:i+self.hparams.chunk],
                            ts[i:i+self.hparams.chunk],
                            self.hparams.N_samples,
                            self.hparams.use_disp,
                            self.hparams.perturb,
                            self.hparams.noise_std,
                            self.hparams.N_importance,
                            self.hparams.chunk, # chunk size is effective in val mode
                            self.train_dataset.white_back,
                            proj_mat=proj_mat,
                            full_code_B=full_code_B,
                            pixels_i=pixels_i[:,i:i+self.hparams.chunk],
                            **kwargs)

            for k, v in rendered_ray_chunks.items():
                results[k] += [v]

        for k, v in results.items():
            results[k] = torch.cat(v, 0)
        return results

    def setup(self, stage):
        dataset = dataset_dict[self.hparams.dataset_name]
        kwargs = {'root_dir': self.hparams.root_dir}
        kwargs['perturbation'] = self.hparams.data_perturb
        kwargs['img_wh'] = tuple(self.hparams.img_wh)
        kwargs['sample_wh'] = self.hparams.sample_wh
        kwargs['img2patch'] = self.img2patch
        kwargs['use_edge'] = self.hparams.use_edge
        self.train_dataset = dataset(split='train', **kwargs)
        self.val_dataset = dataset(split='val', **kwargs)
        if self.train_dataset.use_edge:
            print("Using Recurring Edge Constraint (REC).")
        # self.images_dataset = dataset_dict['wholeImage']

    def configure_optimizers(self):
        self.optimizer_G = get_optimizer(self.hparams, self.models_to_train)
        scheduler_G = get_scheduler(self.hparams, self.optimizer_G)
        if len(self.use_D):
            hparams = self.hparams
            hparams.lr=1e-4
            self.optimizer_D = get_optimizer(hparams, self.discriminators)
            scheduler_D = get_scheduler(hparams, self.optimizer_D)
            return [self.optimizer_G,self.optimizer_D], [scheduler_G,scheduler_D]
        return [self.optimizer_G],[scheduler_G]

    def train_dataloader(self):
        return DataLoader(self.train_dataset,
                          shuffle=True,
                          num_workers=4,
                          batch_size=self.hparams.batch_size,
                          pin_memory=True)

    def val_dataloader(self):
        return DataLoader(self.val_dataset,
                          shuffle=False,
                          num_workers=4,
                          batch_size=1, # validate one image (H*W rays) at a time
                          pin_memory=True)

    def training_step(self, batch, batch_nb,optimizer_idx=0):
        if self.hparams.use_patch:
            rays, rgbs, ts, original = batch['rays'], batch['rgbs'], batch['ts'], batch['original']
            full_code_B = batch['full_code_B']
            pixels_i = batch['pixels_i'].flatten(1,2)[:,:,None,:]
            # depth_gt = batch['depth_gt'].transpose(-1,-2).view(self.hparams.batch_size,1,self.hparams.sample_wh,self.hparams.sample_wh)
            proj_mat = batch['proj_mat']
            if 'edge' in batch.keys():
                edge = batch['edge'].transpose(-1,-2).view(self.hparams.batch_size,3,self.hparams.sample_wh,self.hparams.sample_wh)
            else:
                edge = None
            rays = rays.squeeze()
            rgbs = rgbs.transpose(-1,-2).view(self.hparams.batch_size,3,self.hparams.sample_wh,self.hparams.sample_wh)
            ts = ts.squeeze()
            original = original.transpose(-1,-2).view(self.hparams.batch_size,3,self.hparams.sample_wh,self.hparams.sample_wh)
        results = self(rays, ts,proj_mat,full_code_B,pixels_i=pixels_i)
        ts=ts.view(self.hparams.batch_size,1,self.hparams.sample_wh,self.hparams.sample_wh)
        # if 'B' in self.use_D or (self.use_contrastive and optimizer_idx == 0):
        for key in results.keys():
            shape = results[key].shape
            C = 1 if len(shape)==1 else shape[1]
            if shape[0] == self.hparams.batch_size*self.hparams.sample_wh ** 2:
                results[key] = results[key].t().view(C,self.hparams.batch_size,self.hparams.sample_wh,self.hparams.sample_wh).transpose(0,1)
        img_pred_static = results['_rgb_fine_static']
        img_pred_transient = results['_rgb_fine_transient']
        if optimizer_idx == 0 or len(self.use_D)==0: # Train generator
            loss_d = self.loss(results, rgbs, BG_edge=edge)
            pred = results['rgb_fine']
            loss = sum(l for l in loss_d.values())
            mut_loss = self.mutex_loss(img_pred_static*(1-results['beta']),img_pred_transient*results['beta'],self.x_kernel.to(self.device))
            loss += mut_loss
            self.log(f'mut/',mut_loss,prog_bar=True)

            for k, v in loss_d.items():
                self.log(f'train/{k}', v, prog_bar=True)
            self.log('train/loss', loss)
            with torch.no_grad():
                psnr_ = psnr(pred, original)
                if self.global_step % 250 == 0:
                    stack = torch.cat([img_pred_static,img_pred_transient*results['beta'],pred, original],0) # (3, 3, H, W)
                    self.logger.experiment.add_images('train/Bpred_Rpred_Mixpred_GT', stack, self.global_step)
            self.log('lr', get_learning_rate(self.optimizer_G))
            self.log('train/psnr', psnr_, prog_bar=True)

        return loss

    def validation_step(self, batch, batch_nb):
        rays, rgbs, ts, original = batch['rays'], batch['rgbs'], batch['ts'], batch['original']
        full_code_B = batch['full_code_B']
        proj_mat = batch['proj_mat']
        rays = rays[0]
        rgbs = rgbs.squeeze() # (H*W, 3)
        ts = ts[0]
        results = defaultdict(list)
        index_w, index_h = torch.meshgrid([torch.linspace(-1,1,self.hparams.img_wh[0]),
                                         torch.linspace(-1,1,self.hparams.img_wh[1])])
        pixels_i = torch.dstack([index_w,index_h]).flatten(0,1)[None,:,None,:].to(self.device)
        results = self(rays, ts, proj_mat, full_code_B,pixels_i=pixels_i, output_transient=False)
        log = dict()
        typ = 'fine' if 'rgb_fine' in results else 'coarse'
        W, H = self.hparams.img_wh
        stack = torch.stack([results[f'rgb_fine'].T.view(3,H,W), original.T.view(3,H,W)]) # (2, 3, H, W)
        self.logger.experiment.add_images('val/pred_GT', stack, self.global_step)

        psnr_ = psnr(results[f'rgb_{typ}'].unsqueeze(0), original)
        log['val_psnr'] = psnr_

        return log

    def validation_epoch_end(self, outputs):
        mean_psnr = torch.stack([x['val_psnr'] for x in outputs]).mean()
        self.log('val/psnr', mean_psnr, prog_bar=True)

def main(hparams):
    system = NeRFSystem(hparams)
    os.makedirs(f'ckpts/{hparams.exp_name}/',exist_ok=True)
    checkpoint_callback = \
        ModelCheckpoint(filepath=os.path.join(f'ckpts/{hparams.exp_name}/',
                                               '{epoch:d}'),
                        monitor='val/psnr',
                        mode='max',
                        save_top_k=1,
                        save_last=True)
        # save_top_k = -1:all models; 0:no model; k: top k models on monitor

    logger = TestTubeLogger(save_dir="logs",
                            name=hparams.exp_name,
                            debug=False,
                            create_git_tag=False,
                            log_graph=False)

    trainer = Trainer(max_epochs=hparams.num_epochs,
                      checkpoint_callback=checkpoint_callback,
                      resume_from_checkpoint=hparams.ckpt_path,
                      logger=logger,
                      weights_summary=None,
                      progress_bar_refresh_rate=hparams.refresh_every,
                      gpus=hparams.gpus,
                      gradient_clip_val=0.5,
                      accelerator='ddp' if (',' in hparams.gpus) else None,
                      num_sanity_val_steps=1,
                      benchmark=True,
                      profiler="simple" if len(hparams.gpus)==1 else None)
                    #   profiler="simple" if hparams.num_gpus==1 else None)

    trainer.fit(system)

if __name__ == '__main__':
    hparams = get_opts()
    main(hparams)