import os
import sys
import argparse
import tensorflow as tf
from tensorflow.python.saved_model import builder as saved_model_builder

from detection import mtcnn

def convert_model_from_caffe_to_tensorflow(caffe_model_dir, output_dir):
    print('Converting mtcnn model from caffe to tensorflow')
    if not os.path.isdir(output_dir):
        os.makedirs(output_dir)
    with tf.Graph().as_default():
        sess = tf.Session(config=tf.ConfigProto(log_device_placement=False))
        with sess.as_default():
            _, _, _ = mtcnn.create_mtcnn(sess, caffe_model_dir)
            saver = tf.train.Saver()
            save_path = saver.save(sess, os.path.join(output_dir, 'model.ckpt'))
            print('save model to  %s' % save_path)

def export_serving_model(model_dir, export_path, export_version):
    print('Begin export mtcnn model to %s' % export_path)
    export_path = os.path.join(
        tf.compat.as_bytes(export_path),
        tf.compat.as_bytes(str(export_version)))
    __export_serving_mtcnn_pnet(model_dir, export_path, export_version)
    __export_serving_mtcnn_rnet(model_dir, export_path, export_version)
    __export_serving_mtcnn_onet(model_dir, export_path, export_version)

    # Export model graph
    model_graph_path = bytes.decode(os.path.join(export_path, tf.compat.as_bytes('graph')))
    print('Exporting model graph to %s' % model_graph_path)
    with tf.Graph().as_default():
        with tf.Session() as sess:
            print('Loading model from directory: %s' % model_dir)
            _, _, _ = mtcnn.create_mtcnn(sess, model_dir)
            train_writer = tf.summary.FileWriter(model_graph_path, graph=sess.graph)
            train_writer.close()
            print('Done model graph export!')
    print('Done export!')

def __export_serving_mtcnn_pnet(model_dir, export_path, export_version):
    with tf.Graph().as_default():
        with tf.Session() as sess:
            # Load the model
            print('Loading model from directory: %s' % model_dir)
            _, _, _ = mtcnn.create_mtcnn(sess, model_dir)
            export_path = os.path.join(
                tf.compat.as_bytes(export_path),
                tf.compat.as_bytes('pnet'))
            # print('Exporting trained model to %s' % export_path)
            print('Exporting Proposal Net model to: %s' % export_path)

            builder = saved_model_builder.SavedModelBuilder(export_path)

            pnet_input = tf.get_default_graph().get_tensor_by_name('pnet/input:0')
            pnet_prob = tf.get_default_graph().get_tensor_by_name('pnet/prob1:0')
            pnet_biasadd = tf.get_default_graph().get_tensor_by_name('pnet/conv4-2/BiasAdd:0')

            pnet_info_inputs = tf.saved_model.utils.build_tensor_info(pnet_input)
            pnet_prob_info = tf.saved_model.utils.build_tensor_info(pnet_prob)
            pnet_biasadd_info = tf.saved_model.utils.build_tensor_info(pnet_biasadd)

            prediction_signature = (
                tf.saved_model.signature_def_utils.build_signature_def(
                    inputs={'input': pnet_info_inputs},
                    outputs={'prob': pnet_prob_info, 'biasadd': pnet_biasadd_info},
                    method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME))

            legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')
            builder.add_meta_graph_and_variables(
                sess, [tf.saved_model.tag_constants.SERVING],
                signature_def_map={
                    'mtcnn_pnet': prediction_signature
                },
                legacy_init_op=legacy_init_op)
            builder.save()
    print('Export Proposal Net serving model success, version %d' % export_version)

def __export_serving_mtcnn_rnet(model_dir, export_path, export_version):
    with tf.Graph().as_default():
        with tf.Session() as sess:
            # Load the model
            print('Loading model from directory: %s' % model_dir)
            _, _, _ = mtcnn.create_mtcnn(sess, model_dir)
            export_path = os.path.join(
                tf.compat.as_bytes(export_path),
                tf.compat.as_bytes('rnet'))
            # rnet_saver = tf.train.Saver(sharded=True)
            print('Exporting Refine Net model to: %s' % export_path)

            builder = saved_model_builder.SavedModelBuilder(export_path)

            rnet_input = tf.get_default_graph().get_tensor_by_name('rnet/input:0')
            rnet_prob = tf.get_default_graph().get_tensor_by_name('rnet/prob1:0')
            rnet_conv52 = tf.get_default_graph().get_tensor_by_name('rnet/conv5-2/conv5-2:0')

            rnet_info_inputs = tf.saved_model.utils.build_tensor_info(rnet_input)
            rnet_prob_info = tf.saved_model.utils.build_tensor_info(rnet_prob)
            rnet_conv52_info = tf.saved_model.utils.build_tensor_info(rnet_conv52)

            prediction_signature = (
                tf.saved_model.signature_def_utils.build_signature_def(
                    inputs={'input': rnet_info_inputs},
                    outputs={'prob': rnet_prob_info, 'conv52': rnet_conv52_info},
                    method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME))

            legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')
            builder.add_meta_graph_and_variables(
                sess, [tf.saved_model.tag_constants.SERVING],
                signature_def_map={
                    'mtcnn_rnet': prediction_signature
                },
                legacy_init_op=legacy_init_op)
            builder.save()
            # print('Done Refine Net export!')
            print('Export Refine Net serving model success, version %d' % export_version)

def __export_serving_mtcnn_onet(model_dir, export_path, export_version):
    with tf.Graph().as_default():
        with tf.Session() as sess:
            # Load the model
            print('Loading model from directory: %s' % model_dir)
            _, _, _ = mtcnn.create_mtcnn(sess, model_dir)
            export_path = os.path.join(
                tf.compat.as_bytes(export_path),
                tf.compat.as_bytes('onet'))
            # onet_saver = tf.train.Saver(sharded=True)
            print('Exporting Output Net model to: %s' % export_path)

            builder = saved_model_builder.SavedModelBuilder(export_path)

            onet_input = tf.get_default_graph().get_tensor_by_name('onet/input:0')
            onet_prob = tf.get_default_graph().get_tensor_by_name('onet/prob1:0')
            onet_conv62 = tf.get_default_graph().get_tensor_by_name('onet/conv6-2/conv6-2:0')
            onet_conv63 = tf.get_default_graph().get_tensor_by_name('onet/conv6-3/conv6-3:0')

            onet_info_inputs = tf.saved_model.utils.build_tensor_info(onet_input)
            onet_prob_info = tf.saved_model.utils.build_tensor_info(onet_prob)
            onet_conv62_info = tf.saved_model.utils.build_tensor_info(onet_conv62)
            onet_conv63_info = tf.saved_model.utils.build_tensor_info(onet_conv63)

            prediction_signature = (
                tf.saved_model.signature_def_utils.build_signature_def(
                    inputs={'input': onet_info_inputs},
                    outputs={'prob': onet_prob_info, 'conv62': onet_conv62_info, 'conv63': onet_conv63_info},
                    method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME))

            legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')
            builder.add_meta_graph_and_variables(
                sess, [tf.saved_model.tag_constants.SERVING],
                signature_def_map={
                    'mtcnn_onet': prediction_signature
                },
                legacy_init_op=legacy_init_op)
            builder.save()
            print('Export Refine Net serving model success, version %d' % export_version)

def export_binary_model(caffe_model_dir, export_path):
    print('Converting mtcnn model from caffe to binary')
    if not os.path.isdir(export_path):
        os.makedirs(export_path)
    model_file = os.path.join(export_path, 'mtcnn.pb')
    with tf.Graph().as_default():
        sess = tf.Session(config=tf.ConfigProto(log_device_placement=False))
        with sess.as_default():
            _, _, _ = mtcnn.create_mtcnn(sess, caffe_model_dir)
            output_graph_def = tf.graph_util.convert_variables_to_constants(sess, sess.graph_def,
                                                                            output_node_names=['pnet/prob1',
                                                                                'pnet/conv4-2/BiasAdd',
                                                                                'rnet/prob1',
                                                                                'rnet/conv5-2/conv5-2',
                                                                                'onet/prob1',
                                                                                'onet/conv6-2/conv6-2',
                                                                                'onet/conv6-3/conv6-3'])
            with tf.gfile.FastGFile(model_file, mode='wb') as f:
                f.write(output_graph_def.SerializeToString())
            print('save model to  %s' % model_file)

def main(args):
    if args.type == 'convert':
        convert_model_from_caffe_to_tensorflow(args.model_dir, args.export_path)
    elif args.type == 'binary':
        export_binary_model(args.model_dir, args.export_path)
    elif args.type == 'serving':
        export_serving_model(args.model_dir, args.export_path, args.export_version)

def parse_arguments(argv):
    parser = argparse.ArgumentParser()

    parser.add_argument('--type', type=str,
                        choices=['convert', 'binary', 'serving'],
                        help='Which type for model to export')
    parser.add_argument('--model_dir', type=str,
                        help='Directory containing caffe model(.npy)')
    parser.add_argument('--export_path', type=str,
                        help='Directory for model to export')
    parser.add_argument('--export_version', type=int,
                        help='version number of the export model.')

    return parser.parse_args(argv)

if __name__ == '__main__':
    main(parse_arguments(sys.argv[1:]))


import numpy as np
import scipy
from scipy.signal import savgol_filter

def getFitGuess(t, data, contrast):
    # Guess the parameters of the peaks in data based on variable 't'
    smooth_data = savgol_filter(data, 51, 3)  # window size 51, polynomial order 3
    locs, non = scipy.signal.find_peaks(smooth_data)
    num_pks = len(locs)
    initial_guess = np.zeros(1, num_pks + 1)
    for i in range(num_pks):
        initial_guess[2 * i - (2 - i)] = t[locs[i]]  # peak location
        initial_guess[2 * i - (2 - i) + 1] = 7  # width
        initial_guess[2 * i - (2 - i) + 2] = -np.abs(smooth_data[locs[i]] - np.min(smooth_data))

    initial_guess[num_pks * 3 + 1] = np.min(smooth_data)  # offset
    return smooth_data, num_pks, initial_guess,locs


import platform
import unittest.mock
from pathlib import Path

import pytest

import solara
import solara.components.file_browser

HERE = Path(__file__)

def test_file_browser_callback_no_select():
    on_directory_change = unittest.mock.MagicMock()
    on_file_open = unittest.mock.MagicMock()
    on_file_name = unittest.mock.MagicMock()  # backwards compat test
    on_path_select = unittest.mock.MagicMock()

    @solara.component
    def Test():
        return solara.FileBrowser(
            HERE.parent, on_path_select=on_path_select, on_directory_change=on_directory_change, on_file_open=on_file_open, on_file_name=on_file_name
        )

    div, rc = solara.render_fixed(Test())
    on_directory_change.assert_not_called()
    on_file_open.assert_not_called()
    on_path_select.assert_not_called()

    list: solara.components.file_browser.FileListWidget = div.children[1]
    with pytest.raises(NameError, match=".*foo.*"):
        list.test_click("foo")
    # select ..
    list.test_click("..")
    on_directory_change.assert_called_once()
    on_file_open.assert_not_called()
    on_path_select.assert_not_called()
    assert "conftest.py" in list

    # select conftest.py
    list.test_click("conftest.py")
    conftest_path = Path(HERE).parent.parent / "conftest.py"
    on_file_open.assert_called_with(conftest_path)
    on_file_name.assert_called_with(str(conftest_path))
    on_path_select.assert_not_called()
    assert list.clicked is not None
    assert list.clicked["name"] == "conftest.py"

    list.clicked = None
    on_file_open.assert_called_once()
    on_path_select.assert_not_called()

    list.test_click("unit")
    assert list.clicked is None

def test_file_browser_callback_can_select():
    on_directory_change = unittest.mock.MagicMock()
    on_file_open = unittest.mock.MagicMock()
    on_path_select = unittest.mock.MagicMock()

    @solara.component
    def Test():
        return solara.FileBrowser(
            HERE.parent, on_path_select=on_path_select, on_directory_change=on_directory_change, on_file_open=on_file_open, can_select=True
        )

    div, rc = solara.render_fixed(Test())
    on_directory_change.assert_not_called()
    on_file_open.assert_not_called()
    on_path_select.assert_not_called()

    list: solara.components.file_browser.FileListWidget = div.children[1]
    assert "file_browser_test.py" in list

    # select ..
    list.test_click("..")
    on_directory_change.assert_not_called()
    on_file_open.assert_not_called()
    on_path_select.assert_called_with(HERE.parent.parent)

    # change to ..
    list.test_click("..", double_click=True)
    on_directory_change.assert_called_once()
    on_file_open.assert_not_called()
    on_path_select.assert_called_with(None)
    assert "conftest.py" in list

    list.test_click("conftest.py")
    conftest_path = Path(HERE).parent.parent / "conftest.py"
    on_path_select.assert_called_with(conftest_path)

    # enter the current directory again
    list.test_click("unit", double_click=True)
    # we shouldn't have a file with the same name selected any more
    on_path_select.assert_called_with(None)
    assert list.double_clicked is None

    # open conftest
    list.test_click("conftest.py", double_click=True)
    conftest_path = Path(HERE).parent / "conftest.py"
    on_file_open.assert_called_with(conftest_path)

    list.clicked = None
    on_path_select.assert_called_with(None)

    # go up
    list.test_click("..", double_click=True)
    assert "conftest.py" in list

    # go up again
    list.test_click("..", double_click=True)
    assert "conftest.py" not in list

def test_file_browser_scroll_pos():
    @solara.component
    def Test():
        return solara.FileBrowser(HERE.parent)

    div, rc = solara.render_fixed(Test())

    list: solara.components.file_browser.FileListWidget = div.children[1]
    assert "file_browser_test.py" in list

    # select ..
    list.test_click("..")
    assert "unit" in list
    list.scroll_pos = 10

    # go to unit
    list.test_click("unit")

    # and back to ..
    list.test_click("..")
    assert list.scroll_pos == 10

@pytest.mark.skipif(platform.system() == "Windows", reason="Windows doesn't support chmod")
def test_file_browser_no_access(tmpdir: Path):
    on_directory_change = unittest.mock.MagicMock()
    on_file_open = unittest.mock.MagicMock()
    on_path_select = unittest.mock.MagicMock()

    path_no_read = tmpdir / "no_read"
    path_no_read.mkdir()
    mode = path_no_read.stat().mode  # type: ignore
    path_no_read.chmod(000)

    @solara.component
    def Test():
        return solara.FileBrowser(tmpdir, on_path_select=on_path_select, on_directory_change=on_directory_change, on_file_open=on_file_open, can_select=True)

    try:
        div, rc = solara.render_fixed(Test())

        list: solara.components.file_browser.FileListWidget = div.children[1]
        # select is ok
        list.test_click("no_read")

        # enter is not
        on_path_select.assert_called_with(path_no_read)
        list.test_click("no_read", double_click=True)
        on_directory_change.assert_not_called()
    finally:
        path_no_read.chmod(mode)

def test_file_browser_filter():
    def directory_filter(path: Path) -> bool:
        return path.is_dir() and not path.name.startswith("_")

    @solara.component
    def Test():
        return solara.FileBrowser(HERE.parent.parent, filter=directory_filter)

    div, rc = solara.render_fixed(Test())

    list: solara.components.file_browser.FileListWidget = div.children[1]
    items = list.files
    names = {k["name"] for k in items}
    assert names == {"unit", "ui", "integration", ".."}

def test_file_browser_test_change_directory():
    div, rc = solara.render_fixed(solara.FileBrowser(HERE.parent))
    list: solara.components.file_browser.FileListWidget = div.children[1]
    assert "file_browser_test.py" in list
    rc.render(solara.FileBrowser(HERE.parent.parent))
    assert "file_browser_test.py" not in list

def test_file_browser_control_directory():
    import solara

    def directory_filter(path: Path) -> bool:
        return path.is_dir() and not path.name.startswith("_")

    BASE_PATH = HERE.parent.parent

    @solara.component
    def Page():
        def set_directory(path: Path) -> None:
            directory.value = path if str(path).startswith(str(BASE_PATH)) else BASE_PATH

        directory = solara.use_reactive(BASE_PATH, set_directory)
        solara.FileBrowser(directory, filter=directory_filter)

    _, rc = solara.render(Page(), handle_error=False)
    file_list = rc.find(solara.components.file_browser.FileListWidget).widget
    mock = unittest.mock.MagicMock()
    file_list.observe(mock, "files")
    items = file_list.files
    names = {k["name"] for k in items}
    assert names == {"unit", "ui", "integration", ".."}
    file_list.test_click("..")
    assert mock.call_count == 0
    file_list.test_click("integration")
    items = file_list.files
    names = {k["name"] for k in items}
    assert names != {"unit", "ui", "integration", ".."}
    assert mock.call_count == 1


import pygame
import random

W = 1000
H = 800

white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
off_white_f = (220, 0, 200)
off_white_w = (200, 0, 100)

pygame.init()
pygame.mixer.init()
win = pygame.display.set_mode((W,H))
pygame.display.set_caption("Demo V9")
clock = pygame.time.Clock()

class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        #self.image = pygame.image.load("PUTINV2.png")
        self.image = pygame.Surface((30,30))
        self.image.fill(blue)
        self.rect = self.image.get_rect()
        self.rect.x = 500
        self.rect.y = 400
        self.grav = 10
        self.direct = 1
        self.timer = 0
        self.respawn = False
        self.x = 500
        self.y = 400
        self.ammo = 200
        self.mag = 15
        self.wep = (1, 15, 20, 20)
        self.rtimer = 0
        self.rel = False
        self.stimer = 0
        self.s = 5
    def update(self):
        self.change_x = 0
        self.change_y = 0
        key = pygame.key.get_pressed()
        if key[pygame.K_d]:
            self.direct = 1
            self.change_x = -15
            self.rect.x += 15
            collision = pygame.sprite.spritecollide(self, all_sprites, False)
            if collision:
                self.rect.x -= 15
                if self.change_x == -15:
                    self.change_x = 0
            else:
                self.rect.x -= 15
        if key[pygame.K_a]:
            self.direct = 2
            self.change_x = 15
            self.rect.x -= 15
            collision = pygame.sprite.spritecollide(self, all_sprites, False)
            if collision:
                self.rect.x += 15
                if self.change_x == 15:
                    self.change_x = 0
            else:
                self.rect.x += 15
        if self.timer < 4:
            self.timer += 1
        if key[pygame.K_SPACE] and self.timer == 4 and self.mag > 0 and self.rel == False:
            self.shoot(self.wep[0])
            self.mag += -1
            self.timer = 0
        if key[pygame.K_r] and self.mag != self.wep[1] and self.ammo + self.mag - self.wep[1] >= 0 and self.rel == False:
            self.ammo += self.mag - self.wep[1]
            self.rel = True
        if self.rel == True and self.rtimer < self.wep[2]:
            self.rtimer += 1
        if self.rtimer == self.wep[2]:
            self.mag = self.wep[1]
            self.rel = False
            self.rtimer = 0

        self.change_y -= self.grav
        global jump
        if jump <= 30 and jump > 21:
            self.change_y += 20
            jump -= 1
        if jump <= 21 and jump > 15:
            self.change_y += 15
            jump -= 1
        if jump <= 15 and jump > 10:
            jump -= 1
        if jump <= 10:
            jump = 0

        hit = pygame.sprite.spritecollide(self, epew, False)
        if hit:
            self.s += -1
            if self.s < 0:
                game.respawn()

        if self.stimer != 40:
            self.stimer += 1
        if self.stimer == 40:
            if self.s < 5:
                self.s += 1
            self.stimer = 0

        global jnum
        self.rect.y += 10
        floored = pygame.sprite.spritecollide(self, all_sprites, False)
        if floored:
            self.rect.y += -10
            if self.change_y <= 0:
                self.change_y = 0
            if jnum != 1:
                jnum = 1

        else:
            self.rect.y += -10

        self.rect.y += 10
        flooredM = pygame.sprite.spritecollide(self, mov_sprites, False)
        if flooredM:
            self.rect.y += -10
            if self.change_y <= 0:
                self.change_y = 0
                self.change_x += -wall0.moveX()
            if jnum != 1:
                jnum = 1
        else:
            self.rect.y += -10

        get = pygame.sprite.spritecollide(self, item, True)
        if get:
            self.ammo += 30

        if self.respawn == True:
            self.change_x = self.rect.x - self.x
            self.change_y = self.rect.y - self.y
            self.respawn = False
        self.x += self.change_x
        self.y += self.change_y

    def moveX(self):
        x = self.change_x
        return x
    def moveY(self):
        x = self.change_y
        return x
    def check(self):
        self.respawn = True
    def setcheck(self, pos):
        self.checkpoint = pos
        self.x = self.checkpoint[0]
        self.y = self.checkpoint[1]
    def shoot(self, wep):
        self.i = wep
        rngy = random.randint(-1 * self.wep[3], self.wep[3])
        if self.i == 1:
            e = Bullet((self.rect.x, self.rect.y + rngy), self.direct)
            pew.add(e)

class Wall(pygame.sprite.Sprite):
    def __init__(self, pos, size = (500, 30)):
        pygame.sprite.Sprite.__init__(self)
        #self.image = pygame.image.load("PUTINV2.png")
        self.image = pygame.Surface(size)
        self.image.fill(white)
        self.rect = self.image.get_rect()
        self.rect.x = pos[0]
        self.rect.y = pos[1]
    def update(self):
        self.change_x = player.moveX()
        self.change_y = player.moveY()

        hit = pygame.sprite.spritecollide(self, epew, True)
        hit2 = pygame.sprite.spritecollide(self, pew, True)

        self.rect.x += self.change_x
        self.rect.y += self.change_y

class Ammokit(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self)
        #self.image = pygame.image.load("PUTINV2.png")
        self.image = pygame.Surface((10,10))
        self.image.fill(off_white_f)
        self.rect = self.image.get_rect()
        self.rect.x = pos[0]
        self.rect.y = pos[1]
    def update(self):
        self.change_x = player.moveX()
        self.change_y = player.moveY()

        self.rect.x += self.change_x
        self.rect.y += self.change_y

class WallM(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self)
        #self.image = pygame.image.load("PUTINV2.png")
        self.image = pygame.Surface((300,30))
        self.image.fill(white)
        self.rect = self.image.get_rect()
        self.rect.x = pos[0]
        self.rect.y = pos[1]
        self.timer = 0
        self.speed = 0
    def update(self):
        self.change_x = player.moveX()
        self.change_y = player.moveY()

        if self.timer != 200:
            self.timer += 1
        if self.timer <= 100 and self.timer >= 0:
            self.speed = 10
            self.change_x += self.speed
        if self.timer <= 200 and self.timer > 100:
            self.speed = -10
            self.change_x += self.speed
        if self.timer == 200:
            self.timer = 0

        hit = pygame.sprite.spritecollide(self, epew, True)
        hit2 = pygame.sprite.spritecollide(self, pew, True)

        self.rect.x += self.change_x
        self.rect.y += self.change_y
    def moveX(self):
        x = self.speed
        return x

class Bullet(pygame.sprite.Sprite):
    def __init__(self, pos, direct):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((10,10))
        self.image.fill(white)
        self.rect = self.image.get_rect()
        self.rect.x = pos[0]
        self.rect.y = pos[1]
        self.direct = direct
    def update(self):
        self.change_x = player.moveX()
        self.change_y = player.moveY()
        if self.direct == 1:
            self.change_x += 25
        if self.direct == 2:
            self.change_x += -25
        if self.rect.x > 1000 or self.rect.x < 0:
            self.kill()
        if self.rect.y > 800 or self.rect.y < 0:
            self.kill()

        self.rect.x += self.change_x
        self.rect.y += self.change_y

class Turret(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((30,30))
        self.image.fill(red)
        self.rect = self.image.get_rect()
        self.rect.x = pos[0]
        self.rect.y = pos[1]
        self.health = 5
        self.timer = 0
    def update(self):
        self.change_x = player.moveX()
        self.change_y = player.moveY()

        hit = pygame.sprite.spritecollide(self, pew, True)
        if hit:
            self.health -= 1
        if self.health <= 0:
            drop = random.randint(1,2)
            if drop == 2:
                a = Ammokit((self.rect.x, self.rect.y + 20))
            self.kill()

        if self.timer != 50:
             self.timer += 1
        if self.timer == 3:
            if player.rect.x < self.rect.x:
                self.direct = 2
            if player.rect.x > self.rect.x:
                self.direct = 1
            self.shoot(self.direct)
        if self.timer == 6:
            if player.rect.x < self.rect.x:
                self.direct = 2
            if player.rect.x > self.rect.x:
                self.direct = 1
            self.shoot(self.direct)
        if self.timer == 9:
            if player.rect.x < self.rect.x:
                self.direct = 2
            if player.rect.x > self.rect.x:
                self.direct = 1
            self.shoot(self.direct)
        if self.timer == 12:
            if player.rect.x < self.rect.x:
                self.direct = 2
            if player.rect.x > self.rect.x:
                self.direct = 1
            self.shoot(self.direct)
        if self.timer == 50:
            self.timer = 0

        self.rect.x += self.change_x
        self.rect.y += self.change_y

    def shoot(self, direct):
        rngy = random.randint(-15, 15)
        e = Bullet((self.rect.x, self.rect.y + rngy), direct)
        epew.add(e)

class Trooper(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((30,30))
        self.image.fill(red)
        self.rect = self.image.get_rect()
        self.rect.x = pos[0]
        self.rect.y = pos[1]
        self.health = 10
        self.timer = 0
        self.dir = 1
    def update(self):
        self.change_x = player.moveX()
        self.change_y = player.moveY()

        hit = pygame.sprite.spritecollide(self, pew, True)
        if hit:
            self.health -= 1
        if self.health <= 0:
            drop = random.randint(1,2)
            if drop == 2:
                a = Ammokit((self.rect.x, self.rect.y + 20))
            self.kill()

        if self.timer != 25:
             self.timer += 1
        if self.timer == 25:
            if player.rect.x < self.rect.x:
                self.direct = 2
            if player.rect.x > self.rect.x:
                self.direct = 1
            self.shoot(self.direct)
            self.timer = 0

        if self.dir == 1:
            self.change_x -= 5
        if self.dir == 2:
            self.change_x += 5

        if self.dir == 1:
            self.rect.x -= 50
            self.rect.y += 10
            floored = pygame.sprite.spritecollide(self, all_sprites, False)
            if floored:
                self.rect.x += 50
                self.rect.y -= 10
            else:
                self.rect.x += 50
                self.rect.y -= 10
                self.dir = 2
        if self.dir == 2:
            self.rect.x += 50
            self.rect.y += 10
            floored = pygame.sprite.spritecollide(self, all_sprites, False)
            if floored:
                self.rect.x -= 50
                self.rect.y -= 10
            else:
                self.rect.x -= 50
                self.rect.y -= 10
                self.dir = 1

        self.rect.x += self.change_x
        self.rect.y += self.change_y

    def shoot(self, direct):
        e = Bullet((self.rect.x, self.rect.y - 15), direct)
        epew.add(e)
        e = Bullet((self.rect.x, self.rect.y), direct)
        epew.add(e)
        e = Bullet((self.rect.x, self.rect.y + 15), direct)
        epew.add(e)

class Checkpoint(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((30,30))
        self.image.fill(off_white_w)
        self.rect = self.image.get_rect()
        self.rect.x = pos[0]
        self.rect.y = pos[1]
    def update(self):
        self.change_x = player.moveX()
        self.change_y = player.moveY()

        self.rect.x += self.change_x
        self.rect.y += self.change_y

        hit = pygame.sprite.spritecollide(self, player_inst, False)
        if hit:
            player.setcheck((self.rect.x, self.rect.y))

class Door1(pygame.sprite.Sprite):
    def __init__(self, pos, locked = False):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((30,50))
        self.image.fill(off_white_w)
        self.rect = self.image.get_rect()
        self.rect.x = pos[0]
        self.rect.y = pos[1]
        self.state = locked
        self.opening = False
        self.timer = 0
    def update(self):
        self.change_x = player.moveX()
        self.change_y = player.moveY()

        self.rect.x += 30
        self.rect.y += 50
        hit = pygame.sprite.spritecollide(self, player_inst, False)
        if hit and self.state == False:
            self.rect.x += -30
            self.rect.y += -50
            self.opening = True
        else:
            self.rect.x += -30
            self.rect.y += -50
        self.rect.x += -30
        self.rect.y += 50
        hit = pygame.sprite.spritecollide(self, player_inst, False)
        if hit and self.state == False:
            self.rect.x += 30
            self.rect.y += -50
            self.opening = True
        else:
            self.rect.x += 30
            self.rect.y += -50
        if self.opening == True and self.timer != 5:
            self.timer += 1
            self.change_y += -10
        hitp = pygame.sprite.spritecollide(self, pew, True)
        if hitp and self.state == True:
            self.opening = True
        hit2 = pygame.sprite.spritecollide(self, epew, True)

        self.rect.x += self.change_x
        self.rect.y += self.change_y

class Door2(pygame.sprite.Sprite):
    def __init__(self, pos, locked = False):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((30,50))
        self.image.fill(off_white_w)
        self.rect = self.image.get_rect()
        self.rect.x = pos[0]
        self.rect.y = pos[1]
        self.state = locked
        self.opening = False
        self.timer = 0
    def update(self):
        self.change_x = player.moveX()
        self.change_y = player.moveY()

        self.rect.x += 30
        hit = pygame.sprite.spritecollide(self, player_inst, False)
        if hit and self.state == False:
            self.rect.x += -30
            self.opening = True
        else:
            self.rect.x += -30
        self.rect.x += -30
        hit = pygame.sprite.spritecollide(self, player_inst, False)
        if hit and self.state == False:
            self.rect.x += 30
            self.opening = True
        else:
            self.rect.x += 30
        if self.opening == True and self.timer != 5:
            self.timer += 1
            self.change_y += 10
        hitp = pygame.sprite.spritecollide(self, pew, True)
        if hitp and self.state == True:
            self.opening = True
        hit2 = pygame.sprite.spritecollide(self, epew, True)

        self.rect.x += self.change_x
        self.rect.y += self.change_y

class Game():
    def __init__(self):
        self.O2 = 100
        self.health = 10
        self.shield = 5
        self.lvl = 1
        self.menu = 0
    def lvlclr(self):
        all_sprites.empty()
        mov_sprites.empty()
        pew.empty()
        epew.empty()
        enemies.empty()
        player.kill()
        self.menu = 1
    def lvl_1(self):
        global gen
        gen = 1
    def lvl_2(self):
        global gen
        gen = 2
    def respawn(self):
        player.check()
    #def lvl_1(self):
        #Generate all of zone 1

font = pygame.font.SysFont("Times New Roman", 20)
gen = 0
jump = 0
jnum = 0
game = Game()
game.lvl_2()

all_sprites = pygame.sprite.Group()
mov_sprites = pygame.sprite.Group()
player_inst = pygame.sprite.Group()
pew = pygame.sprite.Group()
epew = pygame.sprite.Group()
enemies = pygame.sprite.Group()
item = pygame.sprite.Group()
if gen == 1:
    player = Player()
    player_inst.add(player)

    wall = Wall((400, 600))
    all_sprites.add(wall)
    tur = Turret((600, 570))
    enemies.add(tur)
    wall = Wall((250, 800))
    all_sprites.add(wall)
    wall0 = WallM((100, 900))
    mov_sprites.add(wall0)
    wall = Wall((450, 750))
    all_sprites.add(wall)
    wall = Wall((550, 620))
    all_sprites.add(wall)
    d1 = Door1((500, 500))
    all_sprites.add(d1)
    d2 = Door2((500, 550))
    all_sprites.add(d2)
    c1 = Checkpoint((450, 570))
    enemies.add(c1)
if gen == 2:
    player = Player()
    player_inst.add(player)

    wall = Wall((400, 600))
    all_sprites.add(wall)
    wall = Wall((950, 700))
    all_sprites.add(wall)
    c1 = Checkpoint((1200, 670))
    enemies.add(c1)
    tur = Turret((1100, 670))
    enemies.add(tur)
    wall = Wall((1150, 550))
    all_sprites.add(wall)
    tur = Turret((1700, 420))
    enemies.add(tur)
    wall = Wall((1600, 450))
    all_sprites.add(wall)
    wall0 = WallM((2150, 450))
    mov_sprites.add(wall0)
    wall = Wall((3500, 450))
    all_sprites.add(wall)
    Tr = Trooper((3600, 420))
    enemies.add(Tr)

Quit = False
while not Quit:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            Quit = True
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w and jump == 0 and jnum > 0:
                jump = 30
                jnum += -1
            if event.key == pygame.K_q:
                game.respawn()
    Scoreboard = font.render("Ammo: " + str(player.mag) + "/" + str(player.ammo), True, white)
    board = font.render("Shield: " + player.s * " [X] ", True, white)
    player_inst.update()
    item.update()
    pew.update()
    epew.update()
    all_sprites.update()
    mov_sprites.update()
    enemies.update()
    win.fill(black)
    player_inst.draw(win)
    item.draw(win)
    pew.draw(win)
    epew.draw(win)
    win.blit(Scoreboard, (50, 10))
    win.blit(board, (50, 40))
    all_sprites.draw(win)
    mov_sprites.draw(win)
    enemies.draw(win)
    pygame.display.flip()
    clock.tick(30)
pygame.quit()
quit()


# -*- coding: UTF-8 -*-
from urllib import request
from http import cookiejar
import urllib.parse
import urllib.request, json
import pymysql
import types
import time
import datetime
import requests
from tkinter import *

if __name__ == '__main__':

    #连接数据库
    db=pymysql.connect("192.168.2.61","root","123456","piano_teaching");
    cursor=db.cursor()
    sql = """select week_ordinal,weekday,nickname,date_format(time_start, '%H:%i:%s'),date_format(time_end, '%H:%i:%s'),point_start_per,point_lenght_per,course_type from piano_teaching.v_timetable_excel order by week_ordinal,weekday,time_start;"""
    cursor.execute(sql)
    results = cursor.fetchall()
    course_list=[]
    g_height = 700
    g_width = 200
    root = Tk()
    i = 0
    fms=[]
    timestamp = time.time()
    timestruct = time.localtime(timestamp)
    print (time.strftime('%Y-%m-%d %H:%M:%S', timestruct))

    for result in results:
        #获取当前时间
        #now = time.strftime("%Y-%m-%d %H:%M:%S")
        #URL参数
        g_week_ordinal = result[0]
        g_weekday = result[1]
        g_nickname = result[2]
        g_time_start = result[3]
        g_time_end = result[4]
        g_point_start_per = result[5]
        g_point_lenght_per = result[6]
        g_course_type = result[7]

        str_print = g_nickname+'\n'+g_time_start+'--'+g_time_end
        print(str_print)
        if g_course_type == 3:
           g_color = 'green'
        elif g_course_type == 2:
            g_color = 'yellow'
        else:
           g_color = 'red'

        #print(g_weekday,int(g_point_lenght_per*g_height),g_point_lenght_per )

        #Frame(height = int(g_point_lenght_per*g_height),width = g_width,bg = 'green').place(x=(g_weekday - 1)* g_width, y= int(g_point_start_per*g_height), anchor=NW)
        fm = Frame(height = int(g_point_lenght_per*g_height),width = g_width,bg = g_color,borderwidth = 0)
        fm.pack_propagate(0)
        fm.place(x=(int(g_weekday) - 1)* (g_width+10), y= int(g_point_start_per*g_height), anchor=NW)
        if int(g_point_lenght_per*g_height) >= 35:
           Label(fm,text=str_print,borderwidth=1).pack()


from django.urls import path
from . import views

urlpatterns = [
    path('',views.index,name='index'),
    path('search/',views.post_search, name='search'),
    path('category/<int:pk>/',views.post_category,name="cat"),
    path('global_news/',views.global_news, name='global_news'),
    path('article/<slug:slug>/',views.article, name='article'),
    path('contact/',views.contact, name='contact'),
    path('login/',views.login, name='login'),
    path('register/',views.register, name='register'),
    path('provide/',views.provide, name='provide'),
    path('feedback/',views.feedback, name='feedback'),
    path('ipaddress/',views.ipaddress, name='ipaddress'),
    path('404/',views.not_found, name='404'),
]

# handler404 = views.test


from keras import backend as K
from keras.layers import Input, Dense, Flatten, Activation, Dropout, Bidirectional, Permute, multiply
from keras.layers.recurrent import LSTM
from keras.callbacks import CSVLogger
from keras.models import Sequential, Model, load_model
from keras.applications.vgg19 import VGG19
from keras.applications.vgg16 import VGG16
from keras.applications.inception_v3 import InceptionV3
from keras.applications.resnet50 import ResNet50
from keras.applications.xception import Xception
from keras.optimizers import SGD
from keras.utils import np_utils
from sklearn.model_selection import train_test_split
from keras.callbacks import ModelCheckpoint
import os
import time
import numpy as np
from video_classification.generator.cnn_feature_extractor import CNN_Feature_extractor

K.set_image_dim_ordering('tf')

NUM_EPOCHS = 60
VERBOSE = 1
HIDDEN_UNITS = 256

def attention_block(inputs, time_steps):
    a = Permute((2, 1))(inputs)
    a = Dense(time_steps, activation='softmax')(a)
    a_probs = Permute((2, 1), name='attention_vec')(a)
    output_attention_mul = multiply([inputs, a_probs], name='attention_mul')
    return output_attention_mul

def generate_batch(x_samples, y_samples, batch_size, expected_frames):
    num_batches = len(x_samples) // batch_size

    while True:
        for batchIdx in range(0, num_batches):
            start = batchIdx * batch_size
            end = (batchIdx + 1) * batch_size
            x_data = []
            for k in range(start, end):
                x = np.load(x_samples[k])
                frames = x.shape[0]
                if frames > expected_frames:
                    x = x[0:expected_frames, :]
                    x_data.append(x)
                elif frames < expected_frames:
                    temp = np.zeros(shape=(expected_frames, x.shape[1]))
                    temp[0:frames, :] = x
                    x_data.append(temp)
                else:
                    x_data.append(x)

            yield np.array(x_data), y_samples[start:end]

class BidirectionalLSTMVideoClassifier(object):
    def __init__(self, cnn_model_name, model_file=None):
        self.num_input_tokens = None
        self.nb_classes = None
        if model_file is None:
            self.model = None
        else:
            self.model = load_model(model_file)
        self.cnn_model_name = cnn_model_name.lower()

    def cnn_lstm(self):
        model = Sequential()
        model.add(Bidirectional(LSTM(units=HIDDEN_UNITS, return_sequences=False),
                                input_shape=(self.expected_frames, self.num_input_tokens)))
        model.add(Dense(512, activation='relu'))
        model.add(Dropout(0.5))
        model.add(Dense(self.nb_classes))
        model.add(Activation('softmax'))
        model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])

        return model

    def cnn_attention_lstm(self):
        inputs = Input(shape=(self.expected_frames, self.num_input_tokens,))
        attention_inputs = attention_block(inputs, self.expected_frames)
        lstm_out = Bidirectional(LSTM(HIDDEN_UNITS, return_sequences=False))(attention_inputs)
        x = Dense(512, activation='relu')(lstm_out)
        x = Dropout(0.5)(x)
        x = Dense(self.nb_classes, activation='softmax')(x)
        model = Model(input=[inputs], output=x)
        model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
        print(model.summary())
        return model

    def cnn_lstm_attention(self):
        inputs = Input(shape=(self.expected_frames, self.num_input_tokens,))
        lstm_out = Bidirectional(LSTM(HIDDEN_UNITS, return_sequences=True))(inputs)
        attention_mul = attention_block(lstm_out, self.expected_frames)
        attention_mul = Flatten()(attention_mul)
        x = Dense(512, activation='relu')(attention_mul)
        x = Dropout(0.5)(x)
        x = Dense(self.nb_classes, activation='softmax')(x)
        model = Model(input=[inputs], output=x)
        model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
        print(model.summary())
        return model

    def predict(self, video_path, config_file):
        config = np.load(config_file).item()
        if self.cnn_model_name == 'vgg16':
            cnn_model = VGG16(include_top=False, weights='imagenet')
        elif self.cnn_model_name == 'vgg19':
            cnn_model = VGG19(include_top=False, weights='imagenet')
        elif self.cnn_model_name == 'inceptionv3':
            cnn_model = InceptionV3(include_top=False, weights='imagenet')
        elif self.cnn_model_name == 'resnet50':
            cnn_model = ResNet50(include_top=False, weights='imagenet')
        else:
            cnn_model = Xception(include_top=False, weights='imagenet')

        feature_extractor = CNN_Feature_extractor(self.cnn_model_name)
        x = feature_extractor.extract_cnn_features_live(cnn_model, video_path)
        expected_frames = config['expected_frames']
        labels_idx2word = dict([(idx, word) for word, idx in config['labels'].items()])
        frames = x.shape[0]
        if frames > expected_frames:
            x = x[0 : expected_frames, :]
        elif frames < expected_frames:
            temp = np.zeros(shape=(expected_frames, x.shape[1]))
            temp[0 : frames, :] = x
            x = temp
        predicted_class = np.argmax(self.model.predict(np.array([x]))[0])
        predicted_label = labels_idx2word[predicted_class]
        return predicted_label

    def fit(self, input_path, output_path, data_set_name='UCF-101', test_size=0.3,
            attention='cnn_lstm', do_feature_extraction=False):
        batch_size = 128
        if self.cnn_model_name == 'vgg16':
            print('vgg16')
            cnn_model = VGG16(include_top=False, weights='imagenet')
        elif self.cnn_model_name == 'vgg19':
            print('vgg19')
            cnn_model = VGG19(include_top=False, weights='imagenet')
        elif self.cnn_model_name == 'inceptionv3':
            print('inceptionv3')
            cnn_model = InceptionV3(include_top=False, weights='imagenet')
        elif self.cnn_model_name == 'resnet50':
            print('resnet50')
            cnn_model = ResNet50(include_top=False, weights='imagenet')
            batch_size = 16
        else:
            print('xception')
            cnn_model = Xception(include_top=False, weights='imagenet')
            batch_size = 16

        cnn_model.compile(optimizer=SGD(), loss='categorical_crossentropy', metrics=['accuracy'])

        feature_dir_name = data_set_name + '-' + self.cnn_model_name + '-HiDimFeatures'

        labels = dict()
        feature_extractor = CNN_Feature_extractor(self.cnn_model_name)
        x_samples, y_samples = feature_extractor.extract_cnn_features(input_path,
                                                               output_dir_path=feature_dir_name,
                                                               model=cnn_model,
                                                               data_set_name=data_set_name)
        if do_feature_extraction:
            return
        x_sample_0 = np.load(x_samples[0])
        print(x_sample_0.shape)
        self.num_input_tokens = x_sample_0.shape[1]
        frames_list = []
        for x in x_samples:
            frames = np.load(x).shape[0]
            frames_list.append(frames)
        self.expected_frames = int(np.mean(frames_list))
        print('expected frames: ', self.expected_frames)

        for y in y_samples:
            if y not in labels:
                labels[y] = len(labels)

        for i in range(len(y_samples)):
            y_samples[i] = labels[y_samples[i]]

        self.nb_classes = len(labels)

        y_samples = np_utils.to_categorical(y_samples, self.nb_classes)

        config = dict()
        config['labels'] = labels
        config['nb_classes'] = self.nb_classes
        config['num_input_tokens'] = self.num_input_tokens
        config['expected_frames'] = self.expected_frames

        np.save(os.path.join(output_path, 'config'), config)

        t1 = time.time()
        if attention == 'cnn_lstm_attention':
            model = self.cnn_lstm_attention()
            csv_logger = CSVLogger(os.path.join(output_path, '{}_cnn_lstm_attention.log'.format(self.cnn_model_name)), append=True, separator=';')
        elif attention == 'cnn_attention_lstm':
            model = self.cnn_attention_lstm()
            csv_logger = CSVLogger(os.path.join(output_path, '{}_cnn_attention_lstm.log'.format(self.cnn_model_name)), append=True,
                                   separator=';')
        else:
            model = self.cnn_lstm()
            csv_logger = CSVLogger(os.path.join(output_path, '{}_cnn_lstm.log'.format(self.cnn_model_name)), append=True, separator=';')

        Xtrain, Xtest, Ytrain, Ytest = train_test_split(x_samples, y_samples, test_size=test_size,
                                                        random_state=None)

        train_gen = generate_batch(Xtrain, Ytrain, batch_size, self.expected_frames)
        test_gen = generate_batch(Xtest, Ytest, batch_size, self.expected_frames)

        train_num_batches = len(Xtrain) // batch_size
        test_num_batches = len(Xtest) // batch_size

        history = model.fit_generator(generator=train_gen, steps_per_epoch=train_num_batches,
                                      epochs=NUM_EPOCHS,
                                      verbose=1, validation_data=test_gen, validation_steps=test_num_batches,
                                      callbacks=[csv_logger])

        model_file_path = os.path.join(output_path, attention.replace('cnn', self.cnn_model_name) + '.h5')
        model.save(model_file_path)
        accu = history.history['val_acc'][-1]
        print('cnn-{}, attention-{}: accuracy-{}, time={}'.format(self.cnn_model_name, attention, accu, time.time()-t1))

        return accu


from typing import Callable, Dict, List, Optional, Tuple, Union

import torch

from torch_geometric.data import Data, FeatureStore, GraphStore, HeteroData
from torch_geometric.data.data import BaseData
from torch_geometric.loader import NeighborLoader
from torch_geometric.loader.utils import get_input_nodes
from torch_geometric.sampler import NeighborSampler
from torch_geometric.sampler.base import SubgraphType
from torch_geometric.typing import EdgeType, InputNodes, OptTensor

import poptorch

from poptorch_geometric.collate import FixedSizeCollater
from poptorch_geometric.collate import CombinedBatchingCollater
from poptorch_geometric import OverSizeStrategy
from poptorch_geometric.fixed_size_options import FixedSizeOptions

class PyGFixedSizeNeighborLoader(torch.utils.data.DataLoader):
    def __init__(
            self,
            data: Union[Data, HeteroData, Tuple[FeatureStore, GraphStore]],
            num_neighbors: Union[List[int], Dict[EdgeType, List[int]]],
            input_nodes: InputNodes = None,
            input_time: OptTensor = None,
            replace: bool = False,
            directed: bool = True,
            disjoint: bool = False,
            temporal_strategy: str = 'uniform',
            time_attr: Optional[str] = None,
            transform: Optional[Callable] = None,
            transform_sampler_output: Optional[Callable] = None,
            is_sorted: bool = False,
            filter_per_worker: bool = True,
            subgraph_type: SubgraphType = SubgraphType.directional,
            batch_size: int = 1,
            neighbor_sampler: Optional[NeighborSampler] = None,
            over_size_strategy: OverSizeStrategy = OverSizeStrategy.
            TrimNodesAndEdges,
            fixed_size_options: FixedSizeOptions = None,
            add_pad_masks: Optional[bool] = False,
            follow_batch: Optional[Union[List[str], Tuple[str, ...]]] = None,
            exclude_keys: Optional[Union[List[str], Tuple[str, ...]]] = None,
            options: Optional[poptorch.Options] = None,
            **kwargs,
    ):
        kwargs['batch_size'] = batch_size
        self.neighbour_loader = NeighborLoader(
            data,
            num_neighbors,
            input_nodes=input_nodes,
            input_time=input_time,
            replace=replace,
            subgraph_type=subgraph_type,
            directed=directed,
            disjoint=disjoint,
            temporal_strategy=temporal_strategy,
            time_attr=time_attr,
            transform=transform,
            transform_sampler_output=transform_sampler_output,
            is_sorted=is_sorted,
            filter_per_worker=filter_per_worker,
            neighbor_sampler=neighbor_sampler,
            **kwargs)
        self.input_type, input_nodes = get_input_nodes(data, input_nodes)

        if fixed_size_options is None:
            fixed_size_options = FixedSizeOptions.from_loader(
                self.neighbour_loader)

        collater_args = {}
        collater_args['fixed_size_options'] = fixed_size_options
        collater_args['add_masks_to_batch'] = add_pad_masks
        collater_args['follow_batch'] = follow_batch
        collater_args['exclude_keys'] = exclude_keys
        collater_args['trim_nodes'] = (over_size_strategy in (
            OverSizeStrategy.TrimNodes, OverSizeStrategy.TrimNodesAndEdges))
        collater_args['trim_edges'] = (over_size_strategy in (
            OverSizeStrategy.TrimEdges, OverSizeStrategy.TrimNodesAndEdges))

        kwargs['options'] = options
        collater = self._create_collater(**collater_args)
        super().__init__(dataset=range(input_nodes.size(0)),
                         collate_fn=collater,
                         **kwargs)

    def __collate__(self, index):
        out = self.nativeCollate(index)
        out = self.fixedSizeCollate(out)
        return out

    def _create_collater(self, **collater_args):
        self.fixed_size_collater = FixedSizeCollater(**collater_args)
        return self.__collate__

    def nativeCollate(self, index):
        out = self.neighbour_loader(index)
        return out

    def fixedSizeCollate(self, data_list: List[BaseData]):

        # Some keys are not handled correctly by FixedSizeCollater
        # so they need to be temporarily removed
        sample_batch_size = data_list[self.input_type].pop(
            "batch_size") if self.input_type else data_list.pop("batch_size")
        input_id = data_list[self.input_type].pop(
            "input_id") if self.input_type else data_list.pop("input_id")

        out = self.fixed_size_collater([data_list])

        # Restore previously removed keys
        if self.input_type:
            out[self.input_type].batch_size = sample_batch_size
            out[self.input_type].input_id = input_id
        else:
            out.batch_size = sample_batch_size
            out.input_id = input_id
        return out

class FixedSizeNeighborLoader(PyGFixedSizeNeighborLoader, poptorch.DataLoader):
    r"""A data loader which merges data objects from a
    :py:class:`torch_geometric.loader.NeighborLoader` to a mini-batch and pads
    node and edge features so tensors across all batches have constant shapes.

    Args:
        data (Any): A :class:`~torch_geometric.data.Data`,
            :class:`~torch_geometric.data.HeteroData`, or
            (:class:`~torch_geometric.data.FeatureStore`,
            :class:`~torch_geometric.data.GraphStore`) data object.
        num_neighbors (List[int] or Dict[Tuple[str, str, str], List[int]]): The
            number of neighbours to sample for each node in each iteration.
            If an entry is set to :obj:`-1`, all neighbors will be included.
            In heterogeneous graphs, it may also take a dictionary denoting
            the number of neighbours to sample for each individual edge type.
        input_nodes (torch.Tensor or str or Tuple[str, torch.Tensor]): The
            indices of nodes for which neighbours are sampled to create
            mini-batches.
            Needs to be either given as a :obj:`torch.LongTensor` or
            :obj:`torch.BoolTensor`.
            If set to :obj:`None`, all nodes will be considered.
            In heterogeneous graphs, this needs to be passed as a tuple that
            holds the node type and node indices. (default: :obj:`None`)
        input_time (torch.Tensor, optional): Optional values to override the
            timestamp for the input nodes given in :obj:`input_nodes`. If not
            set, it will use the timestamps in :obj:`time_attr` as default (if
            present). The :obj:`time_attr` needs to be set for this to work.
            (default: :obj:`None`)
        replace (bool, optional): If set to :obj:`True`, will sample with
            replacement. (default: :obj:`False`)
        subgraph_type (SubgraphType or str, optional): The type of the returned
            subgraph.
            If set to :obj:`"directional"`, the returned subgraph only holds
            the sampled (directed) edges which are necessary to compute
            representations for the sampled seed nodes.
            If set to :obj:`"bidirectional"`, sampled edges are converted to
            bidirectional edges.
            If set to :obj:`"induced"`, the returned subgraph contains the
            induced subgraph of all sampled nodes.
            (default: :obj:`"directional"`)
        disjoint (bool, optional): If set to :obj:`True`, each seed node will
            create its own disjoint subgraph.
            If set to :obj:`True`, mini-batch outputs will have a :obj:`batch`
            vector holding the mapping of nodes to their respective subgraph.
            This will get automatically set to :obj:`True` in the case of
            temporal sampling. (default: :obj:`False`)
        temporal_strategy (str, optional): The sampling strategy when using
            temporal sampling (:obj:`"uniform"`, :obj:`"last"`).
            If set to :obj:`"uniform"`, it will sample uniformly across
            neighbours that fulfill temporal constraints.
            If set to :obj:`"last"`, will sample the last `num_neighbors` that
            fulfill temporal constraints.
            (default: :obj:`"uniform"`)
        time_attr (str, optional): The name of the attribute that denotes
            timestamps for the nodes in the graph.
             If set, temporal sampling will be used so that neighbours are
            guaranteed to fulfill temporal constraints; that is, neighbours have
            an earlier or equal timestamp than the centre node.
            (default: :obj:`None`)
        transform (callable, optional): A function/transform that takes in
            a sampled mini-batch and returns a transformed version.
            (default: :obj:`None`)
        transform_sampler_output (callable, optional): A function/transform
            that takes in a :class:`torch_geometric.sampler.SamplerOutput` and
            returns a transformed version. (default: :obj:`None`)
        is_sorted (bool, optional): If set to :obj:`True`, assumes that
            :obj:`edge_index` is sorted by column.
            If :obj:`time_attr` is set, additionally requires that rows are
            sorted by to time within individual neighbourhoods.
            This avoids internal re-sorting of the data and can improve
            runtime and memory efficiency. (default: :obj:`False`)
        filter_per_worker (bool, optional): This is left for argument
            compatibility with :obj:`NeighborLoader`. The passed value is
            ignored, FixedSizeNeighborLoader acts like filter_per_worker=True
        fixed_size_options (FixedSizeOptions, optional): A
            :py:class:`poptorch_geometric.fixed_size_options.FixedSizeOptions`
            object which holds the maximum number of nodes, edges and other
            options required to pad the mini-batches, produced by the data
            loader, to a fixed size.
        batch_size (int, optional): The number of nodes per mini-batch to
            load. (default: :obj:`1`)
        over_size_strategy (OverSizeStrategy, optional): The
            behaviour if a sample cannot fit in the fixed-size mini-batch.
            By default, if the required number of samples cannot fit into the
            fixed-sized mini-batch, nodes and edges will be removed from the
            mini-batch to achieve the specified fixed size.
            (default: `poptorch_geometric.OverSizeStrategy.TrimNodesAndEdges`)
        add_pad_masks (bool, optional): If :obj:`True`, mask objects
            are attached to mini-batch result. They represents three levels of
            padding:

            - :obj:`graphs_mask`: graph level mask
            - :obj:`nodes_mask`: node level mask
            - :obj:`edges_mask`: edge level mask

            Mask objects indicate which elements in the mini-batch are real
            (represented by :obj:`True`) and which were added as
            padding (represented by :obj:`False`).
            (default: :obj:`True`)
        options (poptorch.Options, optional): The additional PopTorch options
            to be passed to :py:class:`poptorch.DataLoader`.
            (default: :obj:`None`)
        exclude_keys (list or tuple, optional): The keys to exclude
            from the graphs in the output batch. (default: :obj:`None`)
        **kwargs (optional): Additional arguments of
            :class:`torch.utils.data.DataLoader`, such as :obj:`shuffle`,
            :obj:`drop_last` or :obj:`num_workers`.

    """

    def __init__(
            self,
            data: Union[Data, HeteroData, Tuple[FeatureStore, GraphStore]],
            num_neighbors: Union[List[int], Dict[EdgeType, List[int]]],
            input_nodes: InputNodes = None,
            input_time: OptTensor = None,
            subgraph_type: SubgraphType = SubgraphType.directional,
            replace: bool = False,
            directed: bool = True,
            disjoint: bool = False,
            temporal_strategy: str = 'uniform',
            time_attr: Optional[str] = None,
            transform: Optional[Callable] = None,
            transform_sampler_output: Optional[Callable] = None,
            is_sorted: bool = False,
            filter_per_worker: bool = True,  # Ignored
            batch_size: int = 1,
            neighbor_sampler: Optional[NeighborSampler] = None,
            over_size_strategy: OverSizeStrategy = OverSizeStrategy.
            TrimNodesAndEdges,
            fixed_size_options: FixedSizeOptions = None,
            add_pad_masks: Optional[bool] = True,
            follow_batch: Optional[Union[List[str], Tuple[str, ...]]] = None,
            exclude_keys: Optional[Union[List[str], Tuple[str, ...]]] = None,
            options: Optional[poptorch.Options] = None,
            **kwargs,
    ):
        self.batch_size = batch_size

        if options is None:
            # Create IPU default options
            options = poptorch.Options()

        super().__init__(
            data,
            num_neighbors,
            input_nodes=input_nodes,
            input_time=input_time,
            replace=replace,
            directed=directed,
            disjoint=disjoint,
            subgraph_type=subgraph_type,
            temporal_strategy=temporal_strategy,
            time_attr=time_attr,
            transform=transform,
            transform_sampler_output=transform_sampler_output,
            is_sorted=is_sorted,
            filter_per_worker=True,
            batch_size=batch_size,
            neighbor_sampler=neighbor_sampler,
            over_size_strategy=over_size_strategy,
            fixed_size_options=fixed_size_options,
            add_pad_masks=add_pad_masks,
            follow_batch=follow_batch,
            exclude_keys=exclude_keys,
            options=options,
            **kwargs,
        )

    def _create_collater(self, **collater_args):
        collater = super()._create_collater(**collater_args)
        return CombinedBatchingCollater(mini_batch_size=self.batch_size,
                                        collater=collater)


#!C:/Python27/python
from os import *
from cgi import *
import cgitb
from lib.Entity import Entity

# cgitb.enable()

class Category(Entity):
    def __init__(self, *qInfo, **kwargs):
        super(Category, self).__init__()
        for dictionary in qInfo:
            for key in dictionary:
                setattr(self, 'c_' + key, dictionary[key])

        for key in kwargs:
            setattr(self, key, kwargs[key])

    def sanitizeParams(self):
        return {k[2:]: v
            for k, v in self.__dict__.items()
            if k.startswith('c_')
        }

    def getCategories(self):
        """ insert new question """
        query = ("SELECT c_id, c_text FROM category WHERE active = 1")
        return self.executeQuery(query, ())

    def test(self):
        return self.__dict__.items()

def main():
    info = { }
    ctype="text/html"
    print("Content-Type: %s; charset=utf-8\n\n" % ctype)
    print(Category(info).getCategories())

if __name__ == '__main__':
        main()


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

# Copyright © 2020 Koninklijke Philips N.V. All Rights Reserved.

# A copyright license is hereby granted for redistribution and use of the
# Software in source and binary forms, with or without modification, provided
# that the following conditions are met:
# • Redistributions of source code must retain the above copyright notice, this
#   copyright license and the following disclaimer.
# • Redistributions in binary form must reproduce the above copyright notice,
#   this copyright license and the following disclaimer in the documentation
#   and/ or other materials provided with the distribution.
# • Neither the name of Koninklijke Philips N.V. nor the names of its
#   subsidiaries may be used to endorse or promote products derived from the
#   Software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
# OF THE POSSIBILITY OF SUCH DAMAGE.

"""
Tile Processor
"""
try:
    import numpy as np
    from PIL import Image, ImageTk
    from constants import Constants
    from pixel_engine_connector import PixelEngineConnector
    from tile import Tile
    import io
except ImportError as exp:
    print(exp)

class TileProcessor:
    """
    This class is responsible for processing tiles as per the request of tkinter display
    bounding box.
    """
    def __init__(self, input_file, args_level, args_backend, args_display_view):
        """
        The constructor initializes pixel engine connector class.
        :param input_file: IsyntaxFilePath
        :param args_backend: The requested backend
        """
        self._tile_list = []
        self._prev_tile_list = []
        self._level_info = []
        self._level = 0
        self.pixel_engine_connector = PixelEngineConnector(input_file, args_backend,
                                                           args_display_view)
        self.create_level_info(args_level)
        # self.generate_image_properties()

    def get_sub_image(self, sub_image, sub_image_size):
        """
        This method returns the sub image (LABEL or MACRO image) data.
        :param sub_image: Requested sub image LABEL or MACRO image
        :param sub_image_size: Requested sub image size
        :return: Requested sub image data
        """
        isyntax_facade_obj = self.pixel_engine_connector.get_isyntax_facade_obj()
        for image in range(isyntax_facade_obj.num_images):
            image_type = isyntax_facade_obj[image].image_type
            if image_type == sub_image:
                sub_image = Image.open(io.BytesIO(isyntax_facade_obj[image].image_data))
                sub_image = sub_image.resize((sub_image_size[0],
                                              sub_image_size[1]), Image.ANTIALIAS)
                sub_image = ImageTk.PhotoImage(sub_image)
        return sub_image

    def get_max_levels(self):
        """
        Queries maximum number of levels in isyntax file through pixel_engine_connector
        :return: Maximum number of levels of isyntax file
        """
        return self.pixel_engine_connector.get_max_levels()

    def get_level(self):
        """
        Method to return the current level
        :return: Returns the current level
        """
        return self._level

    def set_level(self, new_level):
        """
        Method to set level
        :param new_level: Desired level
        :return: None
        """
        self._level = new_level

    def set_prev_tile_list(self, new_tile_list):
        """
        Method to update prev_tile_list
        :param new_tile_list: Updated new tile list
        :return: None
        """
        self._prev_tile_list = new_tile_list

    def get_level_info_list(self):
        """
        Method to get level info list
        :return: Level info list which holds the tiles of all the levels.
        """
        return self._level_info

    def remove_tiles(self, redundant_tiles):
        """
        Removes the redundant tiles from canvas
        :param redundant_tiles: List of redundant tiles which needs to be removed
        :return:None
        """
        for row_col in redundant_tiles:
            if row_col in self._level_info[self.get_level()][3]:
                tile = self._level_info[self.get_level()][4][row_col]
                if tile.get_image() is not None:
                    tile.set_image(None)

    def processing_tiles(self, bounding_box_range, current_row_col,flg):
        """
        Processes bounding box and check for redundant tiles, common tiles, tiles to be fetched.
        :param bounding_box_start_row: Starting row of bounding box
        :param bounding_box_start_col: Starting column of bounding box
        :param bounding_box_end_row: Ending row of bounding box
        :param bounding_box_end_col: Ending column of bounding box
        :param current_row: Current tile, row in which event occurred
        :param current_col: Current tile, column in which event occurred
        :return: List of new tiles that need to be displayed
        """
        # Preparing a list of tiles that lies in the bounding box
        current_tiles = []
        for col in range(bounding_box_range[1], bounding_box_range[3] + 1):
            for row in range(bounding_box_range[0], bounding_box_range[2] + 1):
                current_tiles.append((row, col))

        # Checking for intersecting tiles from previous update
        previous_tiles = self._prev_tile_list

        # common between previous and current
        common_tiles = list(set(previous_tiles) & set(current_tiles))

        # the tiles which are not required in current
        redundant_tiles = list(set(previous_tiles) ^ set(common_tiles))
        # Removing unused tiles from cache
        self.remove_tiles(redundant_tiles)
        self._prev_tile_list = current_tiles

        # rearrange to get highlighted tile first
        tiles_tobe_fetched = self.rearrange_current_tiles(current_tiles, current_row_col)

        self._tile_list = []
        self.update_list(tiles_tobe_fetched,flg)

        display_list = self.tile_extract(self._tile_list, self._level)
        return display_list

    def update_list(self, tiles_tobe_fetched,flg=False):
        """
        Prepares tile list that needs to be fetched from pixel engine
        :param tiles_tobe_fetched: List of tiles that needs to be fetched from the pixel engine
        :return: None
        """
        tile_list = []
        for row_col in tiles_tobe_fetched:
            if row_col in self._level_info[self._level][3]:
                tile = self._level_info[self._level][4][row_col]
                if tile.get_image() is None or flg is True:
                    tile_list.append(tile)
        self._tile_list = tile_list

    def tile_extract(self, tile_list, level):
        """
        Method to extract new tiles
        :param tile_list: The list of tiles that needs to be extracted
        :param level: The level at which these tiles should be extracted
        :return: Data of tiles that are fetched from the system.
        """
        if not tile_list:
            return 0
        tiles = []
        display_list = []
        tile_size = Constants.tile_width * Constants.tile_height * Constants.sample_per_pixel

        for tile in tile_list:
            tiles.append(tile.get_view_range())

        regions = self.pixel_engine_connector.get_source_view().\
            request_regions(tiles,
                            self.pixel_engine_connector.get_source_view().data_envelopes(level),
                            False, [254, 254, 254])
        remaining_regions = len(regions)
        while remaining_regions > 0:
            regions_ready = self.pixel_engine_connector.get_pe().wait_any()
            remaining_regions -= len(regions_ready)
            for region in regions_ready:
                level = region.range[4]
                tile = self.get_tile(tile_list, region.range)
                new_tile = np.empty(tile_size, dtype=np.uint8)
                region.get(new_tile)
                regions.remove(region)
                tile.set_image(
                    (Image.frombuffer('RGB', (Constants.tile_width, Constants.tile_height),
                                      new_tile, 'raw', 'RGB', 0, 1)))
                tile.set_image(ImageTk.PhotoImage(tile.get_image()))
                paste_can_img_x = int((region.range[0] / 2 ** level) - self._level_info[level][1] /
                                      2 ** level)
                paste_can_img_y = int((region.range[2] / 2 ** level) - self._level_info[level][2] /
                                      2 ** level)
                display_list.append([paste_can_img_x, paste_can_img_y, tile.get_image()])
        return display_list

    @staticmethod
    def rearrange_current_tiles(tiles_tobe_fetched, current_row_col):
        """
        Setting current tile as first tile in the list
        :param tiles_tobe_fetched: List of tiles that needs to fetched
        :param current_row: Current tile, row in which event occurred
        :param current_col: Current tile, column in which event occurred
        :return: Rearranged tiles to be fetched
        """
        if (current_row_col[0], current_row_col[1]) in tiles_tobe_fetched:
            tiles_tobe_fetched.insert(0, tiles_tobe_fetched.pop(
                tiles_tobe_fetched.index((current_row_col[0], current_row_col[1]))))
        return tiles_tobe_fetched

    def create_level_info(self, args_level):
        """
        Method to create tile as object of LevelTileInfo
        This method creates view range for every tile and create tile as an object of LevelTileInfo.
        :return: None
        """
        level_info = []
        for level in range(self.pixel_engine_connector.get_max_levels()):
            tiles = []
            x_start = self.pixel_engine_connector.get_source_view().dimension_ranges(level)[0][0]
            x_end = (self.pixel_engine_connector.get_source_view().dimension_ranges(level)[0][2] +
                     Constants.tile_width * (2 ** level))
            y_start = self.pixel_engine_connector.get_source_view().dimension_ranges(level)[1][0]
            y_end = (self.pixel_engine_connector.get_source_view().dimension_ranges(level)[1][2] +
                     Constants.tile_height * (2 ** level))
            row_col = []
            col = 0
            for y_pix in range(y_start, y_end, Constants.tile_height * (2 ** level)):
                row = 0
                for x_pix in range(x_start, x_end, Constants.tile_width * (2 ** level)):
                    view_range = [x_pix,
                                  ((x_pix + Constants.tile_width * (2 ** level)) - 2 ** level),
                                  y_pix,
                                  ((y_pix + Constants.tile_height * (2 ** level)) - 2 ** level),
                                  level]
                    tiles.append(Tile(view_range, None))
                    row_col.append((row, col))
                    row = row + 1
                col = col + 1
                if 0 <= args_level <= self.pixel_engine_connector.get_max_levels():
                    self._level = args_level
                else:
                    self._level = level
                # self._level = level
            level_info.append((level, x_start, y_start, row_col,
                               dict(zip(row_col, tiles))))
        self._level_info = level_info

    @staticmethod
    def get_tile(tile_list, view_range):
        """
        This method returns tile object for the given view range.
        :param tile_list: The list of tiles that needs to be extracted.
        :param view_range: The view range of the tile
        :return: Tile object for the view range requested.
        """
        for tile in tile_list:
            if view_range == tile.get_view_range():
                return tile
        return -1


import datetime

from django import forms
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _

from axpay.money import models as money_models
from axpay.money import utils as money_utils

class ContributorFilterForm(forms.Form):
    placeholders = {
        'user_search': _("user"),
    }

    user_search = forms.CharField(
        label=_("Payer name"),
        required=False,
        initial='',
    )
    product = forms.ModelChoiceField(
        label=_("Contains product"),
        queryset=money_models.Product.objects,
        empty_label=_("(Any product)"),
        required=False,
    )

    def __init__(self, *args, **kwargs):
        super(ContributorFilterForm, self).__init__(*args, **kwargs)
        for field_name, placeholder in self.placeholders.items():
            self.fields[field_name].widget.attrs['placeholder'] = placeholder

    def filter(self, qs, initial=True):
        data = getattr(self, 'cleaned_data', {})

        if data.get('product'):
            qs = qs.filter(ordered_items__product_price__product=data['product'])
        if data.get('user_search'):
            lookup = data['user_search']
            qs = qs.filter(full_name__icontains=lookup)

        return qs.distinct()


#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   832. 翻转图像.py
@Contact :   muyisanshuiliang@hotmail.com

@Modify Time      @Author               @Version
------------      -------               --------
2021/2/24 15:43   muyisanshuiliang      3.9
@Desciption:
---------------------------------------------------------------
给定一个二进制矩阵 A，我们想先水平翻转图像，然后反转图像并返回结果。
水平翻转图片就是将图片的每一行都进行翻转，即逆序。例如，水平翻转 [1, 1, 0] 的结果是 [0, 1, 1]。
反转图片的意思是图片中的 0 全部被 1 替换， 1 全部被 0 替换。例如，反转 [0, 1, 1] 的结果是 [1, 0, 0]。

示例 1：
输入：[[1,1,0],[1,0,1],[0,0,0]]
输出：[[1,0,0],[0,1,0],[1,1,1]]
解释：首先翻转每一行: [[0,1,1],[1,0,1],[0,0,0]]；
     然后反转图片: [[1,0,0],[0,1,0],[1,1,1]]

示例 2：
输入：[[1,1,0,0],[1,0,0,1],[0,1,1,1],[1,0,1,0]]
输出：[[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]]
解释：首先翻转每一行: [[0,0,1,1],[1,0,0,1],[1,1,1,0],[0,1,0,1]]；
     然后反转图片: [[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]]

提示：
1 <= A.length = A[0].length <= 20
0 <= A[i][j] <= 1
'''

# import lib
from typing import List

class Solution:
    def flipAndInvertImage(self, A: List[List[int]]) -> List[List[int]]:

        # 解法一：笨办法
        # result = []
        # for y in range(len(A)):
        #     x_l = list(range(len(A[y])))
        #     x_l.reverse()
        #     x_result = []
        #     for x in x_l:
        #         if A[y][x] == 1:
        #             x_result.append(0)
        #         else:
        #             x_result.append(1)
        #     result.append(x_result)
        # return result

        # 解法二：先翻转，再取值
        # rows = len(A)
        # cols = len(A[0])
        # for row in range(rows):
        #     A[row] = A[row][::-1]
        #     for col in range(cols):
        #         A[row][col] ^= 1
        # return A

        # 解法三：翻转的同时修改数值，A, B = 1 - B, 1 - A
        # N = len(A)
        # for i in range(N):
        #     for j in range((N + 1) // 2):
        #         A[i][j], A[i][N - 1 - j] = 1 - A[i][N - 1 - j], 1 - A[i][j]
        # return A

        # 解法四：额外的存储空间
        # M, N = len(A), len(A[0])
        # res = [[0] * N for _ in range(M)]
        # for i in range(M):
        #     for j in range(N):
        #         res[i][j] = 1 - A[i][N - 1 - j]
        # return res

        return [[1 - A[i][len(A) - 1 - j] for j in range(len(A[i]))] for i in range(len(A))]

l = list(range(5))
l.reverse()
print(l)

solution = Solution()
print(solution.flipAndInvertImage([[1, 1, 0, 0], [1, 0, 0, 1], [0, 1, 1, 1], [1, 0, 1, 0]]))
print(solution.flipAndInvertImage([[1, 1, 0], [1, 0, 1], [0, 0, 0]]))