### 注意：该代码仅能在开发板中运行
import numpy as np
import cv2
import os
from prepare_functions import get_bgr_image, preprocess_onboard, postprocess
from hobot_dnn import pyeasy_dnn as dnn

# 记得要安装一些包
# sudo pip3 install scipy opencv-contrib-python

def get_hw(pro):
    if pro.layout == "NCHW":
        return pro.shape[2], pro.shape[3]
    else:
        return pro.shape[1], pro.shape[2]

dataroot = "data/unet"
imgpath = os.path.join(dataroot, "mra_img_12.jpg")
binpath = os.path.join(dataroot, "model_output/unet.bin")

# 加载图像和BIN模型
img = get_bgr_image(imgpath)
models = dnn.load(binpath)

# 图像数据预处理，这里对几个地方进行解释：
# models[0]：BPU支持加载多个模型，这里只有一个unet，因此[0]表示访问第一个模型
# inputs[0]：模型输入可能多种，unet的输入只有一个，因此[0]表示获取第一个输入的参数
model_h, model_w = get_hw(models[0].inputs[0].properties)

datain = preprocess_onboard(img, model_h, model_w) # 1x256x256x3

# 模型推理：相比于onnx推理，这里不用再重新构造一个inputs
t1 = cv2.getTickCount()
outputs = models[0].forward(datain)
t2 = cv2.getTickCount()
print('time consumption {0} ms'.format((t2-t1)*1000/cv2.getTickFrequency()))

pro = models[0]
print(type(pro.name), pro.name)
print(type(pro.estimate_latency), pro.estimate_latency)

# 后处理并保存结果，这里对几个地方进行解释
# outputs数据类型为tuple，每个元素的数据类型是pyDNNTensor
# 因此想要获取输出的矩阵的话，需要调用buffer
pred = postprocess(outputs[0].buffer) # outputs[0].buffer: (1, 2, 256, 256)
cv2.imwrite(os.path.join(dataroot, "pred_bin.png"), pred[0])


from django import forms
from django.forms.widgets import RadioSelect, CheckboxSelectMultiple
from pollequiz.run.models import QuizTake

class TakeForm(forms.ModelForm):
    class Meta:
        model = QuizTake
        fields = [
            'taker_name',
        ]

class QuestionForm(forms.Form):
    def __init__(self, question, *args, **kwargs):
        super(QuestionForm, self).__init__(*args, **kwargs)
        choice_list = [(ans.id, ans.text) for ans in question.get_answers_list()]
        if question.q_type == 'sing':
            self.fields["answers"] = forms.ChoiceField(choices=choice_list, widget=RadioSelect)
        elif question.q_type == 'mult':
            self.fields["answers"] = forms.ChoiceField(choices=choice_list, widget=CheckboxSelectMultiple)


from collections import deque
import errno
import fcntl
import functools
import itertools
import logging
import os
import random
import select
import sys
import time
import freetype
from functionfs.gadget import (
    GadgetSubprocessManager,
    ConfigFunctionFFSSubprocess,
)
from gpiochip2 import (
    EXPECT_PRECONFIGURED,
    GPIO_V2_LINE_FLAG,
    GPIOChip,
)
import ZODB
import ZODB.FileStorage
from f_ccid import ICCDFunction
from smartcard import (
    Card,
    MASTER_FILE_IDENTIFIER,
)
from smartcard.app.openpgp import (
    OpenPGPRandomPassword,
    PINQueueConnection,
)
from smartcard.utils import transaction_manager
from .framebuffer import Framebuffer
from .waveshare_epaper import WaveShareEPaper

logger = logging.getLogger(__name__)

# status 1 is used by unhandled exceptions
# status 2 is unused as of this writing, but typically is a way to signal a
# parameter error, so leave it free.
SYSTEM_SHUTDOWN_EXIT_STATUS = 3
class SystemShutdown(SystemExit):
    def __init__(self):
        super().__init__(SYSTEM_SHUTDOWN_EXIT_STATUS)

# Periodically, generate new PINs, all the time that the device is enumerated by
# a host (...and the OpenPGP application is unghostified in ZODB object cache).
# The current and previous pins are both valid.
# The correct pin appears in a certain cell.
# The correct cell can be changed by PIN change, with a specially-formatted PIN
# (others rejected).
# When card application exits: Display a power-down message
# When not enumerated/plugged: Display a "connect to host" message

DISPLAY_ROW_NAME = ('A', 'B', 'C', 'D')
DISPLAY_COLUMN_NAME = ('1', '2', '3')

class ICCDFunctionWithRandomPinDisplay(ICCDFunction):
    _column_width = 75
    _line_height = 21
    _line_height_with_margin = _line_height + 3
    _column_name_height = 18
    _column_name_x_offset = 28
    _row_name_width = 16
    _column_x_offset = 25
    _column_name_to_x = {
        '1': 0 * _column_width + _column_x_offset,
        '2': 1 * _column_width + _column_x_offset,
        '3': 2 * _column_width + _column_x_offset,
    }
    _row_name_to_y = {
        'A': 1 * _line_height_with_margin,
        'B': 2 * _line_height_with_margin,
        'C': 3 * _line_height_with_margin,
        'D': 4 * _line_height_with_margin,
    }
    _can_generate = False
    __connection = None
    __db = None
    # Any 2-bytes value is fine, this is not what is used to
    # select the application. We are using it internally to look it up.
    __OPENPGP_FILE_IDENTIFIER = b'\x12\x34'
    __PIN_GENERATION_DELAY = 30
    __next_pin_generation = 0

    __battery_capacity_path = '/sys/class/power_supply/battery/capacity'
    __battery_x = 218
    __battery_y = 4
    __battery_width = 32
    __battery_height = 11
    __battery_last_state = (None, None)

    def __init__(
        self,
        path,
        zodb_path,
        display,
        fontface,
        slot_count=1,
        gpiochip=None,
    ):
        super().__init__(path=path, slot_count=slot_count)
        self.__zodb_path = zodb_path
        self.__display = display
        self.__fontface = fontface
        self.__framebuffer = Framebuffer( # XXX: use PIL instead of custom framebuffer ?
            # Note: framebuffer and display disagree on what is height and
            # width, but are otherwise happy.
            width=display.height,
            height=display.width,
        )
        # Each item is a mapping from cell ids to contained PIN for the whole
        # generated table. Cell ids are a row name followed by a column name.
        self.__pin_queue = deque([], 2)
        # Probe GPIO pin 4 state before opening it.
        battery_gpio_info = gpiochip.getLineInfo(4)
        self.__has_battery = has_battery = (
            os.path.exists(self.__battery_capacity_path) and
            battery_gpio_info['flags'] & GPIO_V2_LINE_FLAG.INPUT and
            not battery_gpio_info['flags'] & GPIO_V2_LINE_FLAG.USED
        )
        self.__exit_message_x = 85
        self.__exit_message_y = 45
        self.__exit_message = 'Exited'
        if has_battery:
            self.__battery_gpio = battery_gpio = gpiochip.openLines(
                line_list=[4],
                flags=(
                    GPIO_V2_LINE_FLAG.INPUT |
                    GPIO_V2_LINE_FLAG.EDGE_RISING |
                    GPIO_V2_LINE_FLAG.EDGE_FALLING |
                    GPIO_V2_LINE_FLAG.BIAS_DISABLED
                ),
                consumer='python-smartcard'.encode('ascii'),
                expect_preconfigured=EXPECT_PRECONFIGURED.DIRECTION,
            )
            fcntl.fcntl(
                battery_gpio,
                fcntl.F_SETFL,
                fcntl.fcntl(battery_gpio, fcntl.F_GETFL) | os.O_NONBLOCK,
            )

    def updateDisplay(self, wait=True):
        display = self.__display
        display.blit(
            image=self.__framebuffer.pixelbuffer,
            x=0,
            y=0,
        )
        display.swap(wait=wait)

    def _blank(self, color):
        # Battery need a redraw
        self.__battery_last_state = (None, None)
        self.__framebuffer.blank(color=color)

    def printAt(
        self,
        x,
        y,
        text,
        width=None,
        color=Framebuffer.COLOR_XOR,
    ):
        self.__framebuffer.printLineAt(
            self.__fontface,
            x=x,
            y=y,
            text=text,
            width=width,
            height=self._line_height,
            color=color,
        )

    def displayReadyUnplugged(self):
        self._blank(color=Framebuffer.COLOR_OFF)
        self.printAt(
            x=35,
            y=45,
            text="Ready, unplugged",
        )
        self.displayBattery()
        self.updateDisplay(wait=False)

    def displayBattery(self):
        if not self.__has_battery:
            return False
        with open(self.__battery_capacity_path, 'rb') as capacity:
            capacity = int(capacity.read().decode('ascii'))
        for level, threshold in enumerate((
            5,  # Under this, will automatically shutdown unless charging
            10, # 0/4 level
            25, # 1/4 level
            50, # 2/4 level
            75, # 3/4 level
            90, # 4/4 level
        )):
            if capacity < threshold:
                break
        charging = self.__battery_gpio.value
        state = (level, charging)
        if state == self.__battery_last_state:
            return False
        self.__battery_last_state = state
        fb = self.__framebuffer
        battery_middle, battery_middle_remainder = divmod(self.__battery_height, 2)
        fb.rect( # battery bump
            self.__battery_x,
            self.__battery_y + battery_middle - 2,
            self.__battery_x + 2,
            self.__battery_y + battery_middle + 2 + battery_middle_remainder,
            color=fb.COLOR_ON,
            fill=True,
        )
        fb.rect( # battery body and draw area
            self.__battery_x + 2,
            self.__battery_y,
            self.__battery_x - 2 + self.__battery_width,
            self.__battery_y + self.__battery_height,
            color=fb.COLOR_ON,
            fill=True,
        )
        if not charging and level == 0:
            self.__exit_message_x = 60
            self.__exit_message_y = 45
            self.__exit_message = "Low battery"
            raise SystemShutdown
        bar_width = (self.__battery_width - 4) // 4
        for index in range(4):
            fb.rect(
                self.__battery_x + 2 + index       * bar_width + 1,
                self.__battery_y + 1,
                self.__battery_x + 2 + (index + 1) * bar_width - 1,
                self.__battery_y - 1 + self.__battery_height,
                color=fb.COLOR_OFF,
                fill=level > (4 - index),
            )
        if charging:
            # Draw the lightning bolt as two filled triangles
            left_x = self.__battery_x + 4
            left_y = self.__battery_y + 6
            right_x = self.__battery_x + self.__battery_width - 4
            right_y = self.__battery_y + 6
            middle_x = left_x + (right_x - left_x) // 2
            middle_top = self.__battery_y + 2
            middle_half_width = 4
            line = fb.line
            for offset in range(middle_half_width + 1):
                line(
                    left_x, left_y,
                    middle_x, middle_top + offset,
                    color=Framebuffer.COLOR_ON,
                )
            for offset in range(middle_half_width):
                line(
                    middle_x, middle_top + middle_half_width + offset,
                    right_x, right_y,
                    color=Framebuffer.COLOR_ON,
                )
            # top left outline
            line(
                left_x, left_y,
                middle_x, middle_top,
                color=Framebuffer.COLOR_OFF,
            )
            # center left outline
            line(
                left_x, left_y,
                middle_x - 1, middle_top + middle_half_width,
                color=Framebuffer.COLOR_OFF,
            )
            # bottom left outline
            line(
                middle_x - 1, middle_top + middle_half_width,
                middle_x, middle_top + middle_half_width + middle_half_width,
                color=Framebuffer.COLOR_OFF,
            )
            # top right outline
            line(
                middle_x, middle_top,
                middle_x + 1, middle_top + middle_half_width,
                color=Framebuffer.COLOR_OFF,
            )
            # center right outline
            line(
                middle_x + 1, middle_top + middle_half_width,
                right_x, right_y,
                color=Framebuffer.COLOR_OFF,
            )
            # bottom right outline
            line(
                middle_x, middle_top + middle_half_width + middle_half_width,
                right_x, right_y,
                color=Framebuffer.COLOR_OFF,
            )
        return True

    def __generatePinTable(self, tries_left, force=False):
        if not self._can_generate and not force:
            return
        fb = self.__framebuffer
        self._blank(color=fb.COLOR_ON)
        # Column headers background
        fb.rect(
            0, 0,
            self._row_name_width, fb.height - 1,
            color=fb.COLOR_OFF,
            fill=True,
        )
        fb.rect(
            self._row_name_width, 0,
            fb.width - 1, self._column_name_height,
            color=fb.COLOR_OFF,
            fill=True,
        )
        # Rounded corners
        fb.rect(
            self._row_name_width + 1, self._column_name_height + 1,
            self._row_name_width + 1 + 8, self._column_name_height + 1 + 8,
            color=fb.COLOR_OFF,
            fill=True,
        )
        fb.circle(
            self._row_name_width + 1 + 8, self._column_name_height + 1 + 8,
            8,
            color=fb.COLOR_ON,
            fill=True,
        )
        fb.rect(
            fb.width - 1 - 8, self._column_name_height + 1,
            fb.width - 1, self._column_name_height + 1 + 8,
            color=fb.COLOR_OFF,
            fill=True,
        )
        fb.circle(
            fb.width - 1 - 8, self._column_name_height + 1 + 8,
            8,
            color=fb.COLOR_ON,
            fill=True,
        )
        fb.rect(
            self._row_name_width + 1, fb.height - 1 - 8,
            self._row_name_width + 1 + 8, fb.height - 1,
            color=fb.COLOR_OFF,
            fill=True,
        )
        fb.circle(
            self._row_name_width + 1 + 8, fb.height - 1 - 8,
            8,
            color=fb.COLOR_ON,
            fill=True,
        )
        fb.rect(
            fb.width - 1 - 8, fb.height - 1 - 8,
            fb.width - 1, fb.height - 1,
            color=fb.COLOR_OFF,
            fill=True,
        )
        fb.circle(
            fb.width - 1 - 8, fb.height - 1 - 8,
            8,
            color=fb.COLOR_ON,
            fill=True,
        )
        # Column headers captions
        for caption, x in self._column_name_to_x.items():
            self.printAt(
                x + self._column_name_x_offset, 0,
                caption,
                width=15,
                color=Framebuffer.COLOR_ON,
            )
        for caption, y in self._row_name_to_y.items():
            self.printAt(
                3, y,
                caption,
                width=15,
                color=Framebuffer.COLOR_ON,
            )
        # 3-tries background
        fb.circle(
            8, 8, 8,
            color=Framebuffer.COLOR_ON,
            fill=True,
        )
        fb.circle(
            34, 8, 8,
            color=Framebuffer.COLOR_ON,
            fill=True,
        )
        fb.rect(
            8, 0,
            34, 16,
            color=Framebuffer.COLOR_ON,
            fill=True,
        )
        for index, center_x in ((0, 8), (1, 21), (2, 34)):
            if tries_left <= index:
                # Try failed: cross
                fb.line(
                    center_x - 4, 4,
                    center_x + 4, 12,
                    color=Framebuffer.COLOR_OFF,
                )
                fb.line(
                    center_x - 3, 4,
                    center_x + 4, 11,
                    color=Framebuffer.COLOR_OFF,
                )
                fb.line(
                    center_x - 4, 5,
                    center_x + 3, 12,
                    color=Framebuffer.COLOR_OFF,
                )
                fb.line(
                    center_x + 4, 4,
                    center_x - 4, 12,
                    color=Framebuffer.COLOR_OFF,
                )
                fb.line(
                    center_x + 3, 4,
                    center_x - 4, 11,
                    color=Framebuffer.COLOR_OFF,
                )
                fb.line(
                    center_x + 4, 5,
                    center_x - 3, 12,
                    color=Framebuffer.COLOR_OFF,
                )
            else:
                # Try still available: circle
                fb.circle(
                    center_x, 8, 5,
                    color=Framebuffer.COLOR_OFF,
                    fill=False,
                )
        # Generate random PINs and display them
        pin_dict = {}
        for row_name, column_name in itertools.product(
            DISPLAY_ROW_NAME,
            DISPLAY_COLUMN_NAME,
        ):
            pin_dict[
                row_name + column_name
            ] = value = '%06i' % random.randint(0, 999999)
            self.printAt(
                self._column_name_to_x[column_name],
                self._row_name_to_y[row_name],
                value,
                width=self._column_width,
                color=Framebuffer.COLOR_OFF,
            )
        self.displayBattery()
        self.updateDisplay(wait=False)
        self.__pin_queue.append(pin_dict)

    def __enter__(self):
        try:
            result = super().__enter__()
            self.__enter()
            return result
        except Exception:
            self.__unenter()
            raise

    def __enter(self):
        self.displayReadyUnplugged()
        logger.info('Initialising the database...')
        # Note: access __pin_queue outside of DB declaration to get the
        # intended __ mangling.
        pin_queue = self.__pin_queue
        class DB(ZODB.DB):
            klass = functools.partial(
                PINQueueConnection,
                openpgp_kw={
                    'pin_queue': pin_queue,
                    'row_name_set': DISPLAY_ROW_NAME,
                    'column_name_set': DISPLAY_COLUMN_NAME,
                },
            )
        self.__db = db = DB(
            storage=ZODB.FileStorage.FileStorage(
                file_name=self.__zodb_path,
            ),
            pool_size=1,
        )
        logger.info('Opening a connection to the database...')
        self.__connection = connection = db.open(
            transaction_manager=transaction_manager,
        )
        root = connection.root
        try:
            card = root.card
        except AttributeError:
            logger.info(
                'Database does not contain a card, building an new one...',
            )
            with transaction_manager:
                card = root.card = Card(
                    name='py-openpgp'.encode('ascii'),
                )
                openpgp = OpenPGPRandomPassword(
                    identifier=self.__OPENPGP_FILE_IDENTIFIER,
                )
                openpgp.activateSelf()
                card.createFile(
                    card.traverse((MASTER_FILE_IDENTIFIER, )),
                    openpgp,
                )
        else:
            logger.info('Card data found, using it.')
        self.__card = card
        logger.info('Inserting the OpenPGP card into slot 0...')
        # TODO: some way of removing/inserting multiple cards ?
        # Ex: one card per thread with a threaded tranaction manager, and some
        # UI on the gadget to let the user select the card to plug.
        self.slot_list[0].insert(card)
        # XXX: Do slow operations now, to avoid timeouts later. Especially, the
        # DWC2 accepts receiving transfer requests while USB bus is active, but
        # rejects them at any other time - including when USB bus is suspended
        # by host. This means than once the UDC is bound to the gadget, we are
        # in a race against the HCD to submit our transfers before the USB idle
        # delay expires.
        logger.debug('Loading OpenPGP from database...')
        with transaction_manager:
            self.__card.traverse(
                path=(MASTER_FILE_IDENTIFIER, self.__OPENPGP_FILE_IDENTIFIER),
            ).getPIN1TriesLeft()
        logger.debug('Waiting for screen to be ready...')
        self.__display.wait()

    def __unenter(self):
        if self.__connection is not None:
            self.__connection.close()
            self.__connection = None
        if self.__db is not None:
            self.__db.close()
            self.__db = None
        self._blank(color=Framebuffer.COLOR_OFF)
        self.printAt(
            x=self.__exit_message_x,
            y=self.__exit_message_y,
            text=self.__exit_message,
        )
        self.updateDisplay()

    def __exit__(self, exc_type, exc_value, traceback):
        self.__unenter()
        return super().__exit__(exc_type, exc_value, traceback)

    def _onBatteryEvent(self):
        # purge all available gpio events
        self.__battery_gpio.read()
        if self.displayBattery():
            self.updateDisplay(wait=False)

    def processEventsForever(self):
        logger.info('All ready, serving until keyboard interrupt')
        # A bit overkill for just 1 or 2 handlers and 0 or 1 timeout handlers...
        event_dict = {
            self.eventfd.fileno(): (select.EPOLLIN, self.processEvents),
        }
        timeout_handler_list = []
        epoll_timeout = None
        if self.__has_battery:
            event_dict[self.__battery_gpio.fileno()] = (
                select.POLLIN | select.POLLPRI,
                self._onBatteryEvent,
            )
            # Check battery level every minute
            epoll_timeout = 60
            timeout_handler_list.append(self._onBatteryEvent)
        with select.epoll() as epoll:
            for fd, (event_mask, _) in event_dict.items():
                epoll.register(fd, event_mask)
            poll = epoll.poll
            while self._open:
                try:
                    event_list = poll(epoll_timeout)
                except OSError as exc:
                    if exc.errno != errno.EINTR:
                        raise
                else:
                    if event_list:
                        for event_fd, _ in event_list:
                            _, event_handler = event_dict[event_fd]
                            event_handler()
                    else:
                        for event_handler in timeout_handler_list:
                            event_handler()

    def processEvents(self):
        super().processEvents()
        now = time.time()
        if self.__next_pin_generation <= now or not self.__pin_queue:
            self.__next_pin_generation = now + self.__PIN_GENERATION_DELAY
            with transaction_manager:
                tries_left = self.__card.traverse(
                    path=(MASTER_FILE_IDENTIFIER, self.__OPENPGP_FILE_IDENTIFIER),
                ).getPIN1TriesLeft()
            self.__generatePinTable(
                tries_left=tries_left,
            )

    def onUnbind(self):
        self.displayReadyUnplugged()
        self._can_generate = False
        super().onUnbind()

    def onEnable(self):
        self._can_generate = True
        self.__next_pin_generation = 0
        super().onEnable()

    def onDisable(self):
        self.displayReadyUnplugged()
        self._can_generate = False
        super().onDisable()

def main():
    parser = GadgetSubprocessManager.getArgumentParser(
        description='Emulate a reader with a smartcard inserted which '
        'contains an OpenPGP application.',
    )
    parser.add_argument(
        '--filestorage',
        required=True,
        help='Path to a ZODB FileStorage file, for smartcard persistence.',
    )
    parser.add_argument(
        '--serial',
        help='String to use as USB device serial number',
    )
    parser.add_argument(
        '--verbose',
        default='warning',
        choices=['critical', 'error', 'warning', 'info', 'debug'],
        help='Set verbosity level (default: %(default)s). '
        'WARNING: "debug" level will display all APDU-level exchanges with '
        'the host, which will include secret keys during import, PINs during '
        'verification and modification, cipher- and clear-text for '
        'en/decryption operations.',
    )
    args = parser.parse_args()
    logging.basicConfig(
        stream=sys.stderr,
    )
    logging.getLogger('smartcard').setLevel(
        level=args.verbose.upper(),
    )
    logger.setLevel(
        level=args.verbose.upper(),
    )
    display = WaveShareEPaper()
    gpiochip = GPIOChip('/dev/gpiochip0', 'w+b')
    gadget = GadgetSubprocessManager(
        args=args,
        config_list=[
            {
                'function_list': [
                    functools.partial(
                        ConfigFunctionFFSSubprocess,
                        getFunction=functools.partial(
                            ICCDFunctionWithRandomPinDisplay,
                            display=display,
                            # TODO: argument, auto-detection of default...
                            fontface=freetype.Face('/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf'),
                            slot_count=1,
                            zodb_path=os.path.abspath(args.filestorage),
                            gpiochip=gpiochip,
                        ),
                    ),
                ],
                'MaxPower': 500,
                'lang_dict': {
                    0x409: {
                        'configuration': 'python-usb-f-iccd reader with openpgp card',
                    },
                },
            }
        ],
        idVendor=0x1d6b,
        idProduct=0x0104,
        lang_dict={
            0x409: {
                'serialnumber': args.serial,
                'product': 'python-smartcard-app-openpgp',
                'manufacturer': 'Vincent Pelletier',
            },
        },
    )
    with display, gpiochip, gadget:
        gadget.waitForever()
    # CCID function may request special actions to do after exiting. For example
    # it may request a shutdown when it detects the battery is discharging below
    # a certain threshold.
    exit_status = gadget.getFunction(0, 0).getExitStatus()
    if exit_status == SYSTEM_SHUTDOWN_EXIT_STATUS:
        os.system('poweroff')


from django.core.serializers import get_serializer
from rest_framework import status, generics
from rest_framework.response import Response
import logging

from mFactor.api.cart.utils import CartMixin
from mFactor.api.unit.models import Unit
from mFactor.api.cart.serializers import CartSerializer, CartUnitSerializer, CartDeleteSerializer, CartSelectAllSerializer

logger = logging.getLogger('django')

class CartSelectAllView(CartMixin, generics.GenericAPIView):
    serializer_class = CartSelectAllSerializer

    def put(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        selected = serializer.validated_data['selected']

        cart_dict = self.get_cart(request)

        for sku_key in cart_dict:
            cart_dict[sku_key][1] = True

        response = Response(serializer.data)
        self.post_cart(request, cart_dict, response)

        return response

class CartView(CartMixin, generics.GenericAPIView):
    serializer_class = CartSerializer

    def get(self, request):
        cart_dict = self.get_cart(request)

        sku_list = cart_dict.keys()
        skus = list()

        try:
            skus = Unit.objects.filter(sku__in=sku_list)
        except Exception as e:
            logger.error(f'Query Error:[message: {e}]')

        for sku in skus:
            sku.quantity = cart_dict[sku][0]
            sku.selected = cart_dict[sku][1]

        serializer = CartUnitSerializer(skus, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        attrs = serializer.validated_data
        sku, quantity, selected = attrs['sku'], attrs['quantity'], attrs['selected']

        cart_dict = self.get_cart(request)

        cart_dict[sku] = [quantity, selected]

        response = Response(serializer.data)
        self.post_cart(request, cart_dict, response)

        return response

    def put(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        attrs = serializer.validated_data
        sku, quantity, selected = attrs['sku'], attrs['quantity'], attrs['selected']

        cart_dict = self.get_cart(request)

        cart_dict[sku] = [quantity, selected]

        response = Response(serializer.data)
        self.post_cart(request, cart_dict, response)

        return response

    def delete(self, request):
        serializer = CartDeleteSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        sku = serializer.validated_data['sku']

        cart_dict = self.get_cart(request)

        try:
            cart_dict.pop(sku)
        except Exception:
            return Response({'message': 'Unit is not in cart'}, status=status.HTTP_404_NOT_FOUND)

        response = Response(serializer.data)
        self.post_cart(request, cart_dict, response)


import cirq
import math
import numpy as np

def single_qubit_tomography(sampler, qubit, circuit, repetitions):
    qc_z = cirq.Circuit(circuit, cirq.ops.measure(qubit, key='z'))
    results = sampler.run(qc_z, repetitions=repetitions)
    rho_11 = np.mean(results.measurements['z'])
    rho_00 = 1.0 - rho_11

    qc_x = cirq.Circuit(circuit, cirq.ops.H(qubit), cirq.ops.measure(qubit, key='z'))
    results = sampler.run(qc_x, repetitions=repetitions)
    rho_01_re = -(2*np.mean(results.measurements['z'])-1)/2

    qc_y = cirq.Circuit(circuit, cirq.rz(math.pi/2).on(qubit), cirq.H(qubit), cirq.ops.measure(qubit, key='z'))
    results = sampler.run(qc_y, repetitions=repetitions)
    rho_01_im = (2*np.mean(results.measurements['z'])-1)/2

    rho_01 = rho_01_re + rho_01_im*1j
    rho_10 = np.conj(rho_01)

    rho = np.array([[rho_00, rho_01],
                    [rho_10, rho_11]])

    return rho

def ut(q0, w, w0, w1, n, t, num):
    for x in range(num-1):
        yield cirq.rx(2*w1*(t/n)*math.cos(w*x*(t/n))).on(q0)
        yield cirq.rz(-w0*(t/n)).on(q0)
    yield cirq.measure(q0, key='out')

w0 = 25
w1 = 2
w = 25.5
t = 4
n = 80

sim = cirq.Simulator()
p1 = [0]
q0 = cirq.NamedQubit('0')
for num in np.arange(1, 81):
    circuit = cirq.Circuit(ut(q0, w, w0, w1, n, t, num))
    state_sim = sim.run(circuit, repetitions=1000)
    p1.append(state_sim.histogram(key='out')[1]/1000)

t= np.arange(0, 4.05, 0.05)
plt.plot(t, p1)
plt.show()
sampler = cirq.Simulator()
qubit = cirq.NamedQubit('qubit')
qc = cirq.Circuit([cirq.ry(math.pi/4).on(qubit), cirq.rz(math.pi/8).on(qubit)])
repetitions = 10000

print(qc)
print(single_qubit_tomography(sampler, qubit, qc, repetitions))

result = cirq.experiments.single_qubit_state_tomography(sampler, qubit, qc, repetitions)
print(result.data)


# simulation_tool.py
'''
本文件是写的界面与部分界面的设置
'''
from UI.simulation_exe_Form import Ui_Form  # 用designer设计的界面类
from PyQt5 import QtCore, QtGui, QtWidgets  # Qt的核心部件
from matplotlib import pyplot as plt  # 输出网络连接图需要的模块
import networkx as nx  # 输出网络连接图需要的模块
import pylab  # 输出网络连接图需要的模块

import sys  # 需要的部分内容
import os  # 需要的部分内容
import traceback
from time import sleep  # 测试可能需要的东西
from datetime import datetime  # 基本的仿真时间
from random import seed
seed(9527)

import xml.dom.minidom  # 系统使用的xml操作类
from xml.dom.minidom import parseString  # 用于转换符合xml文件标准的字符串为dom对象

import external_func  # 自己编写的外部函数模块
from external_func.read_file import read_xml_to_module  # 单独引用一下读取模块中的总和函数
from external_func.__scripts import read_scripts, run_script  # 单独引用一下脚本模块中读取与运行的函数

import members  # 自己编写的成员模块
from members.read_file import read_network, read_member, read_component_methods  # 读取网络与成员所需的函数

import pattren  # 自己编写的格局模块
from pattren.read_file import read_pattern  # 读取格局所需的函数

from other_tools import read_xml, write_xml, copy_file  # 读取与生成xml文件的方法
from record_maker import save_member_round_record, save_global_attribute_record  # 生成每一轮仿真纵览信息和所有成员的细节信息

inherited = bool()  # 仿真继承标志位

class MyThread(QtCore.QThread):
    _signal = QtCore.pyqtSignal(int)

    def __init__(self, generation_upper, global_dict):
        super(MyThread, self).__init__()
        self.current_generation = 0
        self.generation_upper = generation_upper
        self.global_dict = global_dict
        self.flag = False

    def run(self):
        while self.current_generation < self.generation_upper:
            if self.flag:
                self.current_generation += 1
                if inherited:
                    pass
                else:
                    load_old(self.global_dict)
                run_script(self.global_dict, self.current_generation)
                print("in Thread, current_generation:{}".format(self.current_generation))
                external_func.round_method(self.global_dict)
                for global_attr_func in external_func.global_attribute_func_ptrs:
                    global_attr_func(self.global_dict)
                self._signal.emit(self.current_generation)
                sleep(0.001)
            else:
                continue

def load_old(global_dict):
    external_func.global_attribute_dict = external_func.old_global_attribute_dict.copy()
    for k, v in external_func.global_attribute_dict.items():
        global_dict[v['aName']] = v['val']
    read_member(members.member_dom)
    read_network(members.member_dom)

class uf_Form(QtWidgets.QWidget, Ui_Form):

    def __init__(self, global_dict):
        super(uf_Form, self).__init__()
        # 加载UI
        self.MyThread = MyThread(0, global_dict)
        self.global_dict = global_dict
        self.setupUi(self)
        # 对UI中的部分控件进行设置
        self.setupUiAgain()
        # 加载本界面需要的一些资源
        self.setupResoure()
        # 设置所有的信号
        self.set_all_signal()
        # 设置所有的槽函数
        self.set_all_slot()
        # 设置不可更改窗口大小
        self.setFixedSize(self.width(), self.height())
        self.current_generation = 0
        self.flag = "waiting"
        self.start_moment = None
        self.end_moment = 0

    def set_all_slot(self):
        """
        设置所有的槽函数
        :return: no return
        """
        # 添加行按钮槽函数
        self.add_script_button.clicked.connect(self.slot_btn_add_oneRow)
        # 删除行按钮槽函数
        self.delete_script_button.clicked.connect(self.slot_btn_delete_oneRow)
        # 加载脚本按钮槽函数
        self.load_script_button.clicked.connect(self.slot_btn_load_script)
        # 重新设置脚本按钮槽函数
        self.reset_script_button.clicked.connect(self.slot_btn_reset_script)
        # 设置成员文件路径按钮槽函数
        self.members_filedialog_btn.clicked.connect(self.slot_btn_set_members_path)
        # 设置仿真定义文件路径按钮槽函数
        self.record_filedialog_btn.clicked.connect(self.slot_btn_set_record_path)
        # 设置表格脚本函数路径双击槽函数
        self.script_table_widget.itemDoubleClicked.connect(self.slot_btn_load_script_file_path)
        # 设置存储路径函数
        self.def_xml_filedialog_btn.clicked.connect(self.slot_btn_set_definition_path)
        # 设置轮方法槽函数
        self.start_btn.clicked.connect(self.emit_round_method)
        # 设置暂停槽函数
        self.pause_btn.clicked.connect(self.slot_btn_pause)
        # 设置终止槽函数
        self.stop_btn.clicked.connect(self.slot_terminate_simulation)
        # 设置显示网络函数
        self.show_nw_btn.clicked.connect(self.slot_btn_show_network)
        # 设置测试用按钮
        self.testButton.clicked.connect(self.slot_test_button)
        self.testButton.hide()
        ...

    def set_all_signal(self):
        self.MyThread._signal.connect(self.slot_return_from)
        # self.MyThread.finished.connect(a)
        ...

    def setupResoure(self):
        """
        设置窗口需要的各种资源
        :return: no return
        """
        # 播放按钮的图标
        self.start_btn_icon = QtGui.QIcon(r'.\UI\播放按钮.ico')
        # 暂停按钮的图标
        self.pause_btn_icon = QtGui.QIcon(r'.\UI\暂停.ico')
        # 停止按钮的图标
        self.stop_btn_icon = QtGui.QIcon(r'.\UI\停止.ico')
        # 初始化设置，将播放按钮图标设置为启动仿真的按钮
        self.start_btn.setIcon(self.start_btn_icon)
        self.pause_btn.setIcon(self.pause_btn_icon)
        # 初始化设置，将停止按钮的图标设置为停止仿真的按钮
        self.stop_btn.setIcon(self.stop_btn_icon)

    def setupUiAgain(self):
        """
        设置窗口中各种元素的编辑于排版
        :return:
        """
        # 脚本注册表的所有内容均靠左对齐
        self.script_table_widget.horizontalHeaderItem(0).setTextAlignment(QtCore.Qt.AlignLeft)
        self.script_table_widget.horizontalHeaderItem(1).setTextAlignment(QtCore.Qt.AlignLeft)
        self.script_table_widget.horizontalHeaderItem(2).setTextAlignment(QtCore.Qt.AlignLeft)
        # 设置脚本注册表三列的宽度
        self.script_table_widget.setColumnWidth(0, 100)
        self.script_table_widget.setColumnWidth(1, 200)
        self.script_table_widget.setColumnWidth(2, 538)
        # 设置脚本注册表行标可视
        self.script_table_widget.verticalHeader().setVisible(True)
        self.pause_btn.setEnabled(False)
        # 设置日期编辑栏获取当前日期
        self.modify_dateEdit.setDate(QtCore.QDate.currentDate())
        # self.script_table_widget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)

    def all_fill(self):
        """
        判断脚本注册表内容是否填满。
        :return: bool
        """
        # 获取行列数值
        rows_num = self.script_table_widget.rowCount()
        columns_num = self.script_table_widget.columnCount()
        # 双层循环判断对比
        for row in range(rows_num):
            for col in range(columns_num):
                # 如果循环的当前表格对应的item的内容为空，则返回False，表示未填满
                if self.script_table_widget.item(row, col).text() is "":
                    return False
        # 均通过判断，说明表格已经被填满，具备保存逻辑
        return True

    def slot_btn_load_script_file_path(self):
        """
        槽函数，用来保存已经注册的所有脚本函数为XML文件。
        :return:
        """
        # 判断当前表格可编辑，则表示未保存已有内容
        if self.add_script_button.isEnabled() and self.delete_script_button.isEnabled():
            # 获取单圈选中的表格里item对象
            item = self.script_table_widget.selectedItems()[0]
            # 双层循环嵌套遍历表格
            for row in range(self.script_table_widget.rowCount()):
                for col in range(self.script_table_widget.columnCount()):
                    # 判断选中的表格里item是否为第二列，即需要设置脚本函数所在文件路径的列且内容为空
                    if item == self.script_table_widget.item(row, col) and col == 2 and item.text() == "":
                        # 打开文件对话框，选择.py文件
                        py_scripts_path = QtWidgets.QFileDialog.getOpenFileName(self, "选择脚本py文件", "./",
                                                                                "XML Files (*.py);;All Files (*)")
                        # 当成功选择了一个文件时，设置路径
                        if py_scripts_path[0] is not "":
                            item.setText(py_scripts_path[0])
                        # 服务信息更新显示
                        self.service_msg_log_text.append(
                            str(datetime.now()) + ': ' + 'Read script from: ' + py_scripts_path[0])
                        return

    def slot_btn_load_script(self):
        """
        保存已经设置的脚本信息为xml文件槽函数
        :return:
        """
        # 设置将表格中的内容按列保存为xml
        if self.all_fill() and self.save_scripts_to_xml():
            # 设置脚本表格不可编辑
            self.script_table_widget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
            self.add_script_button.setEnabled(False)
            self.delete_script_button.setEnabled(False)
            # 一点提示信息
            self.script_setting_widget_status_label.setText("Script loaded.")
            QtWidgets.QMessageBox.information(self, 'Success', 'Scripts save succeed.')
            read_scripts(xml_dom=read_xml(external_func.scripts_file_path))
        else:
            QtWidgets.QMessageBox.warning(self, 'failure', 'Scripts save failed.\n Please check the form.')

    def slot_btn_reset_script(self):
        """
        重新设定脚本列表
        :return: no return
        """
        # 设置脚本表格可双击编辑
        self.script_table_widget.setEditTriggers(QtWidgets.QAbstractItemView.DoubleClicked)
        # 一点提示信息
        QtWidgets.QMessageBox.information(self, 'Reset', 'You can reset Scripts now.')
        # 设置添加按钮与删除按钮可用
        self.add_script_button.setEnabled(True)
        self.delete_script_button.setEnabled(True)
        # 更改一下标签状态
        self.script_setting_widget_status_label.setText("Script setting. ")

    def slot_btn_add_oneRow(self):
        """
        表格加一行槽函数
        :return: no return
        """
        # 首先获取一下行列数
        rows_num = self.script_table_widget.rowCount()
        columns_num = self.script_table_widget.columnCount()
        # 表格行数+1
        self.script_table_widget.setRowCount(self.script_table_widget.rowCount() + 1)
        # 对新添加的一行，每一列赋一个新的item
        for col in range(columns_num):
            item_data = QtWidgets.QTableWidgetItem("")
            self.script_table_widget.setItem(rows_num, col, item_data)

    def slot_btn_delete_oneRow(self):
        """
        删除脚本表一行
        :return: no return
        """
        # 表格数-1，已有的item会自动删除
        self.script_table_widget.setRowCount(self.script_table_widget.rowCount() - 1)

    def slot_btn_set_definition_path(self):
        """
        设置仿真定义文件路径
        :return: no return
        """
        try:
            xml_definition_path = QtWidgets.QFileDialog.getOpenFileName(self, "选择仿真定义xml文件", "./",
                                                                        "XML Files (*.xml);;All Files (*)")
            if xml_definition_path[0] == '' and xml_definition_path[0] == '':
                return
            self.def_xml_path_edit.setText(xml_definition_path[0])
            definition_dom = read_xml(xml_definition_path[0])
            external_func.external_func_file_path = xml_definition_path[0]
            read_xml_to_module(definition_dom, self.global_dict)
            external_func.round_method_dict['attributes']['num'] = 16549
            member_path_label = definition_dom.getElementsByTagName("memberModelFilePath")[0]
            self.members_xml_path_edit.setText(member_path_label.firstChild.data)
            def_id_label = definition_dom.getElementsByTagName("simulationExecutionMetaModel")[0]
            self.definition_ID_edit.setText(def_id_label.firstChild.data)
            member_meta_label = definition_dom.getElementsByTagName("memberMetaModelFilePath")[0]
            self.meta_member_ID_edit.setText(member_meta_label.firstChild.data)
            generation_label = definition_dom.getElementsByTagName("simulationRoundNumber")[0]
            self.generation_Edit.setText(generation_label.firstChild.data)
            self.MyThread.generation_upper = int(generation_label.firstChild.data)
            inherited_label = definition_dom.getElementsByTagName("inherited")[0]
            global inherited
            if int(inherited_label.firstChild.data):  # 如果继承数据
                self.inherited_Edit.setText("True")
                inherited = True
            else:
                self.inherited_Edit.setText("False")
                inherited = False
                self.step_size_Edit.setText("1")  # 如果不继承，则说明每一轮仿真都是从最初始状态开始的，那么步长将不存在意义
                self.step_size_Edit.setEnabled(False)
            # 根据这个路径来读取成员
            member_dom = read_xml(self.members_xml_path_edit.text())
            # 服务信息更新显示
            self.service_msg_log_text.append(
                str(datetime.now()) + ': ' + 'Read member from: ' + self.members_xml_path_edit.text())
            # 解析成员
            # global net_p2p, net_p2a, net_p2m, net_p2c, net_c2m, net_c2c
            # net_p2p, net_p2a, net_p2m, net_p2c, net_c2m, net_c2c = net_work_read(member_dom)
            # global primitives, advisers, monitorMembers, collectives
            # primitives, advisers, monitorMembers, collectives = member_read(member_dom)
            # 读取一下各个成员的数目与基本信息，并在界面上显示
            id_role_dict, member_number, p_number, c_number, a_number, m_number = format_members_id_role(member_dom)
            read_member(member_dom)
            read_network(member_dom)
            read_pattern(member_dom)
            read_component_methods(member_dom)

            members.member_dom = member_dom
            members.member_file_path = self.members_xml_path_edit.text()
            members.member_num = member_number
            self.reset_member_tableWidget(member_number, id_role_dict)
            self.primitive_num_edit.setText(str(p_number))
            self.adviser_num_edit.setText(str(a_number))
            self.monitor_num_edit.setText(str(m_number))
            self.collective_num_edit.setText(str(c_number))
            self.service_msg_log_text.append(
                str(datetime.now()) + ': ' + "Primitive:{}|Adviser:{}|Monitor:{}|Collective:{}".format(
                    p_number, a_number, m_number, c_number
                ))

            self.service_msg_log_text.append(
                str(datetime.now()) + ': ' + 'Read definition from: ' + member_path_label.firstChild.data)
        except Exception:
            raise
            # QtWidgets.QMessageBox.critical(self, "error", traceback.print_exc())
            # self.def_xml_path_edit.clear()
            # self.service_msg_log_text.append(str(datetime.now()) + ': ' + 'Setting definition file error. ')

    def slot_btn_set_members_path(self):
        """
        读取所有成员的路径的槽函数
        :return: no return
        """
        try:
            # 打开文件对话框
            xml_members_path = QtWidgets.QFileDialog.getOpenFileName(self, "选择仿真成员xml文件", "./",
                                                                     "XML Files (*.xml);;All Files (*)")
            self.members_xml_path_edit.setText(xml_members_path[0])
            # 根据这个路径来读取成员
            member_dom = read_xml(self.members_xml_path_edit.text())
            members.member_file_path = self.members_xml_path_edit.text()
            # 服务信息更新显示
            self.service_msg_log_text.append(
                str(datetime.now()) + ': ' + 'Read member from: ' + self.members_xml_path_edit.text())
            # 解析成员
            # global net_p2p, net_p2a, net_p2m, net_p2c, net_c2m, net_c2c
            # net_p2p, net_p2a, net_p2m, net_p2c, net_c2m, net_c2c = net_work_read(member_dom)
            # global primitives, advisers, monitorMembers, collectives
            # primitives, advisers, monitorMembers, collectives = member_read(member_dom)
            # 读取一下文件中的成员基本信息与数目，并在界面上刷新显示
            id_role_dict, member_number, p_number, c_number, a_number, m_number = format_members_id_role(member_dom)
            read_member(member_dom)
            read_network(member_dom)
            read_pattern(member_dom)
            read_component_methods(member_dom)

            members.member_dom = member_dom
            members.member_file_path = self.members_xml_path_edit.text()
            members.member_num = member_number
            self.reset_member_tableWidget(member_number, id_role_dict)
            self.primitive_num_edit.setText(str(p_number))
            self.adviser_num_edit.setText(str(a_number))
            self.monitor_num_edit.setText(str(m_number))
            self.collective_num_edit.setText(str(c_number))
            self.service_msg_log_text.append(
                str(datetime.now()) + ': ' + "Primitive:{}|Adviser:{}|Monitor:{}|Collective:{}".format(
                    p_number, a_number, m_number, c_number
                ))
        except:
            QtWidgets.QMessageBox.critical(self, "Error", traceback.print_exc())
            self.members_xml_path_edit.clear()
            self.service_msg_log_text.append(str(datetime.now()) + ': ' + 'Setting member XML file error. ')
            raise

    def slot_btn_pause(self):
        self.flag = "waiting"
        self.start_btn.setEnabled(True)
        self.pause_btn.setEnabled(False)
        self.MyThread.flag = False
        self.MyThread.wait()

    def slot_return_from(self, current):
        # 一个迭代的仿真结束了，需要判断一下仿真是否需要继承数据。
        self.current_generation = current
        # print("in widget, current_generation:{}".format(self.current_generation))
        self.exe_progress_bar.setValue(self.current_generation / external_func.round_number * 100)
        if current == external_func.round_number:
            self.slot_btn_pause()
            self.end_moment = datetime.now()
            self.service_msg_log_text.append(str(self.end_moment) + ": Simulation task completed.")
            record_dom = read_xml(self.record_dir_path_edit.text() + "/Simulation_Record.xml")
            record_dom_root = record_dom.getElementsByTagName("Result")[0]
            record_dom_root.setAttribute("EndMoment", str(self.end_moment))
            record_dom_root.setAttribute("TimeConsuming", str(self.end_moment - self.start_moment))
            write_xml(self.record_dir_path_edit.text() + "/Simulation_Record.xml", record_dom)
        if current % int(self.step_size_Edit.text()) == 0:
            self.MyThread.flag = False
            save_member_round_record(self.record_dir_path_edit.text(), current, self.global_dict,
                                     len(self.generation_Edit.text()))
            save_global_attribute_record(self.record_dir_path_edit.text(), current, self.global_dict)
            self.MyThread.flag = True

    def slot_btn_show_network(self):
        for i in range(members.network_list.__len__()):
            edge_labels = dict([((u, v,), format(d['strength'], '.2f'))
                                for u, v, d in members.network_list[i].edges(data=True)])
            plt.figure(members.network_list[i].graph['ID'])
            plt.title(members.network_list[i].graph['ID']+' network')
            pos = nx.spring_layout(members.network_list[i])
            nx.draw_networkx_edge_labels(members.network_list[i], pos, edge_labels=edge_labels)
            nx.draw(members.network_list[i], pos=pos, node_size=200, with_labels=True, font_weight='bold',
                    edge_cmap=plt.cm.Reds,font_size =9, font_color='g',node_color = 'c', edge_color = 'r')
            # plt.get_current_fig_manager().window.state('zoomed')
        pylab.show()

    def save_scripts_to_xml(self):
        """
        保存脚本列表设置到xml文件中，保存成功为True，失败为False。
        :return:bool
        """
        # 设置保存路径，为本项目下的external_file文件夹

        save_path = "external_module_file"
        # 设置文件名
        file_name = "script.xml"
        # 保存表格中的内容
        doc = xml.dom.minidom.Document()
        SCRIPTS = doc.createElement('Scripts')
        doc.appendChild(SCRIPTS)
        for row in range(self.script_table_widget.rowCount()):
            SCRIPT = doc.createElement('Script')
            SCRIPT.setAttribute("id", str(row))
            for col in range(self.script_table_widget.columnCount()):
                # 在第一列，需要判断输入的迭代数是否合法
                if col == 0:
                    the_round = self.script_table_widget.item(row, col).text()
                    try:
                        # 需要判断一下在round列中的输入是不是int且不大于回合数设置
                        if int(the_round) < int(self.generation_Edit.text()):
                            SCRIPT.setAttribute("round", the_round)
                        else:
                            QtWidgets.QMessageBox.critical(self, "error",
                                                           "in row: {}\nOver generation.".format(str(row + 1)))
                            return False
                    except ValueError:
                        QtWidgets.QMessageBox.critical(self, "error",
                                                       "in row: {}\nRound number error.".format(str(row + 1)))
                        return False
                # 第二列，单纯保存一下名字就可以了
                elif col == 1:
                    the_name = self.script_table_widget.item(row, col).text()
                    SCRIPT.setAttribute("funcName", the_name)
                # 第三列，需要分离出文件名与文件所在路径
                elif col == 2:
                    the_path = self.script_table_widget.item(row, col).text()
                    module_name = the_path.split('/')[-1].split('.')[0]
                    SCRIPT.setAttribute("moduleName", module_name)
                    script_path = '/'.join(the_path.split('/')[0:-1])
                    SCRIPT.setAttribute("path", script_path)
                # 其他未知错误
                else:
                    QtWidgets.QMessageBox.critical(self, "error",
                                                   "in row: {}\nRound number error.".format(str(row + 1)))
            SCRIPTS.appendChild(SCRIPT)
        # 保存
        write_xml(save_path + '/' + file_name, doc)
        self.service_msg_log_text.append(str(datetime.now()) + ': ' + "Setting scripts succeed." + "({})".format(
            str(self.script_table_widget.rowCount())))
        return True

    def reset_member_tableWidget(self, length, id_role_dict):
        """
        重新设置成员表格信息
        :param length: 成员数
        :param id_role_dict: 成员信息字典
        :return:
        """
        self.member_tableWidget.setRowCount(length)
        item = self.member_tableWidget.horizontalHeaderItem(0)
        item.setText(QtCore.QCoreApplication.translate("Form", "Member"))
        item = self.member_tableWidget.horizontalHeaderItem(1)
        item.setText(QtCore.QCoreApplication.translate("Form", "Role"))
        self.member_tableWidget.setHorizontalHeaderItem(1, item)
        temp_arrow = 0
        for id, role in zip(id_role_dict['id'], id_role_dict['role']):
            id_item, role_item = QtWidgets.QTableWidgetItem(), QtWidgets.QTableWidgetItem()
            id_item.setText(QtCore.QCoreApplication.translate("Form", id))
            role_item.setText(QtCore.QCoreApplication.translate("Form", role))
            self.member_tableWidget.setItem(temp_arrow, 0, id_item)
            self.member_tableWidget.setItem(temp_arrow, 1, role_item)
            temp_arrow += 1

    def slot_btn_set_record_path(self):
        """
        设置仿真结果路径保存的槽函数
        :return: no return
        """
        dir_record_path = QtWidgets.QFileDialog.getExistingDirectory(self, "选择仿真记录文件夹", os.getcwd())
        now = datetime.now()
        str_now = now.strftime("%Y-%m-%d %H-%M-%S")
        if dir_record_path == "":
            self.service_msg_log_text.append(str_now + ': ' + 'Unselect record save path.')
        else:
            self.record_dir_path_edit.setText(
                dir_record_path + "/" + str_now
            )
            self.service_msg_log_text.append(
                str(datetime.now()) + ': ' + 'Set record dictionary to: ' + dir_record_path)
            if not os.path.exists(self.record_dir_path_edit.text()):
                os.mkdir(self.record_dir_path_edit.text())
            # 需要有一个清空当前文件夹内容的操作
            # 需要初始化生成一个xml基础文件
            res = "<%s>""</%s>" % ("Result", "Result")
            record_dom = parseString(res)
            root = record_dom.getElementsByTagName("Result")[0]
            first_record_node = record_dom.createElement("Record")
            for v in external_func.global_attribute_dict.values():
                first_record_node.setAttribute(v['aName'], str(self.global_dict[v['aName']]))
            first_record_node.setAttribute("round", str(self.current_generation))
            root.appendChild(first_record_node)
            write_xml(self.record_dir_path_edit.text() + "/Simulation_Record.xml", record_dom)

    def start_check(self):
        if self.members_xml_path_edit.text() is "" or \
                self.def_xml_path_edit.text() is "" or \
                self.record_dir_path_edit.text() is "" or \
                self.version_edit.text() is "" or \
                self.step_size_Edit.text() is "" or \
                self.ex_ID_edit.text() is "" or \
                self.step_size_Edit.text() is "":
            return False
        else:
            record_dom = read_xml(self.record_dir_path_edit.text() + "/Simulation_Record.xml")
            record_dom_root = record_dom.getElementsByTagName("Result")[0]
            record_dom_root.setAttribute("ID", self.ex_ID_edit.text())
            record_dom_root.setAttribute("version", self.version_edit.text())
            record_dom_root.setAttribute("MetaMemberID", self.meta_member_ID_edit.text())
            record_dom_root.setAttribute("DefinitionID", self.definition_ID_edit.text())
            record_dom_root.setAttribute("RecordStepSize", self.step_size_Edit.text())
            record_dom_root.setAttribute("Inherited", str(eval(self.inherited_Edit.text())))
            record_dom_root.setAttribute("Datetime", self.modify_dateEdit.text())
            self.start_moment = datetime.now()
            record_dom_root.setAttribute("StartMoment", str(self.start_moment))
            write_xml(self.record_dir_path_edit.text() + "/Simulation_Record.xml", record_dom)
            return True

    def emit_round_method(self):
        if self.flag == "waiting" and self.start_check():
            self.flag = "running"
            self.start_btn.setEnabled(False)
            self.pause_btn.setEnabled(True)
            self.MyThread.flag = True
            save_member_round_record(self.record_dir_path_edit.text(), 0, self.global_dict,
                                     len(self.generation_Edit.text()))
            # 添加一个把脚本保存到仿真记录路径下的代码
            copy_file("external_file_for_cEvolution/script.xml", self.record_dir_path_edit.text() + '/')
            self.MyThread.start()
            self.service_msg_log_text.append(str(self.start_moment) + ": Simulation task started.")

    def slot_test_button(self):
        # 任何可能用来测试的功能
        save_global_attribute_record(self.record_dir_path_edit.text(), 0, self.global_dict)
        pass

    def slot_terminate_simulation(self):
        # 加一步状态检测
        if self.flag == "running":
            # 加一步询问
            reply = QtWidgets.QMessageBox.question(self, "Terminate Simulation",
                                                   "Are you sure you want to teminate this simulation?",
                                                   QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)

            if reply == QtWidgets.QMessageBox.Yes:
                self.MyThread.terminate()
                self.end_moment = datetime.now()
                self.service_msg_log_text.append(str(self.end_moment) + ": Simulation task terminated.")
                record_dom = read_xml(self.record_dir_path_edit.text() + "/Simulation_Record.xml")
                record_dom_root = record_dom.getElementsByTagName("Result")[0]
                record_dom_root.setAttribute("EndMoment", str(self.end_moment))
                record_dom_root.setAttribute("TimeConsuming", str(self.end_moment - self.start_moment))
                write_xml(self.record_dir_path_edit.text() + "/Simulation_Record.xml", record_dom)
                self.current_generation = 0
                self.flag = "waiting"
                self.start_btn.setEnabled(True)
                self.pause_btn.setEnabled(False)
                self.MyThread.flag = False
                self.MyThread.current_generation = 0
                self.start_moment = None
                self.end_moment = None

def format_members_id_role(xml_dom: xml.dom.minidom.Document):
    """
    格式化成员的id与角色，本函数仅用于获取仿真成员xml文件中的部分简单信息包含成员id，成员角色，各类成员的数量
    :param xml_dom: xml文件的dom对象
    :return: key为id与role的dict，成员总个数，primitive成员的数量，collective成员的数量，adviser成员的数量，monitor成员的数量
    """
    root = xml_dom.documentElement  # 获取dom对象的根
    # 初始化id_role字典
    id_role_dict = {
        'id': list(),
        'role': list()
    }
    member_info_labels = root.getElementsByTagName('memberInfo')  # 获取memberInfo标签
    primitive_number = len(root.getElementsByTagName('primitiveInfo'))  # 获取primitiveInfo标签
    collective_number = len(root.getElementsByTagName('collectiveInfo'))  # 获取collectiveInfo标签
    adviser_number = len(root.getElementsByTagName('adviserInfo'))  # 获取adviserInfo标签
    monitorMember_number = len(root.getElementsByTagName('monitorMemberInfo'))  # 获取monitorMemberInfo标签
    for one_member_info_label in member_info_labels:
        id_role_dict['id'].append(one_member_info_label.getAttribute('成员ID'))
        id_role_dict['role'].append(one_member_info_label.getAttribute('成员类型'))
    return id_role_dict, len(
        member_info_labels), primitive_number, collective_number, adviser_number, monitorMember_number

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = uf_Form(globals())
    window.setWindowTitle('众智网络仿真执行工具软件')
    window.show()
    exit(app.exec_())


import torch
import numpy as np
from scipy.special import softmax
from torch.utils.data import Dataset, DataLoader, TensorDataset
from data import get_dataset
from scipy.spatial.distance import cdist
from .net import DisentangleGen, DisentangleEncoder

def compose_frnk_linearize(frnk_feats):
    return frnk_feats.reshape(-1)

class InfiniteDataset(Dataset):
    def __init__(self, length, encoder_fn, train_feats, train_labels, train_attrs_bin, test_attrs_bin,
                 new_class_offset=0, device=None, use_context=False, batch_size=128, reshape=True, **args):
        """
        :param length: dataset length
        :param encoder_fn: function that take a batch of image features X and return two tensor containing attribute_embedding and
        context_embedding
        :param train_feats:
        :param train_labels:
        :param train_attrs_bin:
        :param test_attrs_bin:
        :param new_class_offset:
        :param device:
        :param use_context: if True, each output of the encoder will be considered a tuple formed by attribute-tensor and context-tensor
        :param args:
        """
        super().__init__(**args)
        self._len = length
        self._encoder = encoder_fn
        self._train_feats = train_feats
        self._train_attrs = train_attrs_bin
        self._test_attrs = test_attrs_bin
        self._new_class_offset = new_class_offset
        self._nb_attributes = train_attrs_bin.shape[1]
        self._device = device
        self._reshape = reshape
        # Extract attirbute embeddings for training set.

        ds = TensorDataset(torch.tensor(train_feats).float(), torch.tensor(train_labels).long())
        dl = DataLoader(ds, batch_size=batch_size, shuffle=False, num_workers=0, pin_memory=True, drop_last=False)

        enc = self._encoder(next(iter(dl))[0].to(device))
        multiple_outputs = True
        if use_context:
            if isinstance(enc[0], torch.Tensor):
                multiple_outputs = False
        else:
            if isinstance(enc, torch.Tensor):
                multiple_outputs = False

        nb_examples = len(ds)
        cntx_encodings = None
        if multiple_outputs:
            if use_context:
                attr_encodings = [torch.zeros((nb_examples, *e[0].shape[1:])) for e in enc]
                cntx_encodings = [torch.zeros((nb_examples, *e[1].shape[1:])) for e in enc]
                def add_fn(tensors, i):
                    for t, AE, CE in zip(tensors, attr_encodings, cntx_encodings):
                        AE[i*batch_size : i*batch_size+len(t[0])] = t[0].detach().cpu()
                        CE[i*batch_size : i*batch_size+len(t[1])] = t[1].detach().cpu()
            else:
                attr_encodings = [torch.zeros((nb_examples, *e.shape[1:])) for e in enc]
                def add_fn(tensors, i):
                    for t, AE in zip(tensors, attr_encodings):
                        AE[i * batch_size:i * batch_size + len(t)] = t.detach().cpu()
        else:
            if use_context:
                attr_encodings = [torch.zeros((nb_examples, *enc[0].shape[1:]))]
                cntx_encodings = [torch.zeros((nb_examples, *enc[1].shape[1:]))]
                def add_fn(tensor, i):
                    attr_encodings[0][i*batch_size : i*batch_size+len(tensor[0])] = tensor[0].detach().cpu()
                    cntx_encodings[0][i*batch_size : i*batch_size+len(tensor[1])] = tensor[1].detach().cpu()
            else:
                attr_encodings = [torch.zeros((nb_examples, *enc.shape[1:]))]
                def add_fn(tensor, i):
                    attr_encodings[0][i*batch_size : i*batch_size+len(tensor)] = tensor.detach().cpu()

        i=0
        for X in dl:
            X = X[0].to(device)
            tensors =  self._encoder(X)
            add_fn(tensors, i)
            i+=1

        # Find valid examples for each attribute.
        idx_active_attr = []
        train_examples_attrs_bin = train_attrs_bin[train_labels]
        for att in range(self._nb_attributes):
            idx_active_attr.append(np.where(train_examples_attrs_bin[:, att] == 1)[0])
        self._idx_active_attr = idx_active_attr

        self.attr_encodings = attr_encodings
        self.cntx_encodings = cntx_encodings
        if self._reshape:
            self.attr_encodings = [AE.view(AE.shape[0], self._nb_attributes, -1) for AE in attr_encodings]

    def __len__(self):
        return self._len

    def __getitem__(self, i):
        cls = np.random.randint(len(self._test_attrs))
        return self.get_item_with_class(cls)

    def get_items_with_class(self, Y):
        ATTR_ENCS, CNTX_ENCS, CLS = [], [], []
        for cls in Y:
            if self.cntx_encodings is not None:
                a_enc, c_enc, y = self.get_item_with_class(cls)
                ATTR_ENCS.append(a_enc); CNTX_ENCS.append(c_enc); CLS.append(y)
            else:
                a_enc, y = self.get_item_with_class(cls)
                ATTR_ENCS.append(a_enc); CLS.append(y)
        nb_examples = len(ATTR_ENCS)
        nb_outs = len(ATTR_ENCS[0])
        # TODO: Finire qua
        ATTR_ENCS = [[ATTR_ENCS[i][j] for i in range(nb_examples)] for j in range(nb_outs)]
        ATTR_ENCS = [torch.stack(E, dim=0) for E in ATTR_ENCS]
        if self.cntx_encodings is not None:
            CNTX_ENCS = [[CNTX_ENCS[i][j] for i in range(nb_examples)] for j in range(nb_outs)]
            CNTX_ENCS = [torch.stack(E, dim=0) for E in CNTX_ENCS]
            return  ATTR_ENCS, CNTX_ENCS, torch.tensor(CLS)
        return ATTR_ENCS, torch.tensor(CLS)

    def get_item_with_class(self, cls):
        attr = self._test_attrs[cls]
        attr_indices, = np.where(attr)

        frnk_attr_enc = [torch.zeros_like(E[0]) for E in self.attr_encodings]
        if self._reshape:
            frnk_attr_enc = [AE.view([self._nb_attributes, -1]) for AE in frnk_attr_enc]

        cntx_enc = None
        if self.cntx_encodings is not None:
            cntx_enc = [[] for E in self.cntx_encodings]
        for attr_idx in attr_indices:
            try:
                example_idx = self._idx_active_attr[attr_idx][np.random.randint(len(self._idx_active_attr[attr_idx]))]
            except ValueError as t:
                continue # In this case there are no  examples with this attribute
            for i in range(len(self.attr_encodings)):
                frnk_attr_enc[i][attr_idx, :] = self.attr_encodings[i][example_idx, attr_idx, :]
                if self.cntx_encodings is not None:
                    cntx_enc[i].append(self.cntx_encodings[i][attr_idx])

        for i in range(len(self.attr_encodings)):
            if self._reshape:
                frnk_attr_enc[i] = frnk_attr_enc[i].view((-1,))

            if self.cntx_encodings is not None:
                # adding a random context to the list of features:
                cntx_enc[i] = cntx_enc[i][np.random.randint(len(cntx_enc[i]))]

        cls = cls + self._new_class_offset
        if self.cntx_encodings is not None:
            return frnk_attr_enc, cntx_enc, torch.tensor(cls)
        return frnk_attr_enc, torch.tensor(cls)

class ProbabilisticInfiniteDataset(Dataset):
    def __init__(self, length, encoder_fn, train_feats, train_labels, train_attrs_bin, test_attrs_bin,
                 new_class_offset=0, device=None, use_context=False, **args):
        """
        :param length: dataset length
        :param encoder_fn: function that take a batch of image features X and return two tensor containing attribute_embedding and
        context_embedding
        :param train_feats:
        :param train_labels:
        :param train_attrs_bin:
        :param test_attrs_bin:
        :param new_class_offset:
        :param device:
        :param use_context: if True, the last output of the encoder will be considered a context (disconnected from attribute vector dimension)
        :param args:
        """
        super().__init__(**args)
        self._len = length
        self._encoder = encoder_fn
        self._train_feats = train_feats
        self._train_attrs = train_attrs_bin
        self._test_attrs = test_attrs_bin
        self._new_class_offset = new_class_offset
        self._nb_attributes = train_attrs_bin.shape[1]
        self._device = device
        # Extract attirbute embeddings for training set.
        ds = TensorDataset(torch.tensor(train_feats).float(), torch.tensor(train_labels).long())
        dl = DataLoader(ds, batch_size=128, shuffle=False, num_workers=6, pin_memory=False, drop_last=False)

        enc = self._encoder(next(iter(dl))[0].to(device))
        if isinstance(enc, tuple) or isinstance(enc, set) or isinstance(enc, list):
            encodings = [[] for _ in range(len(enc))]
            def add_fn(tensors):
                for t, E in zip(tensors, encodings):
                    E.append(t.detach().cpu())
        else:
            encodings = [[]]
            def add_fn(tensor):
                encodings[0].append(tensor.detach().cpu())

        for X in dl:
            X = X[0].to(device)
            tensors =  self._encoder(X)
            add_fn(tensors)
        encodings = [torch.cat(E, dim=0) for E in encodings]

        cntx_encodings = None
        if use_context:
            cntx_encodings = encodings[-1]
            encodings = encodings[:-1]
        self.encodings = [E.view(E.shape[0], self._nb_attributes, -1) for E in encodings]
        self.cntx_encodings = cntx_encodings

        # Find valid examples for each attribute.
        idx_active_attr = []
        train_examples_attrs_bin = train_attrs_bin[train_labels]
        for att in range(self._nb_attributes):
            idx_active_attr.append(np.where(train_examples_attrs_bin[:, att] == 1)[0])
        self._idx_active_attr = idx_active_attr

        idx_with_label = []
        for label in sorted(set(train_labels)):
            idx_with_label.append(np.where(train_labels == label)[0])

        D = cdist([av for av in test_attrs_bin], [av for av in train_attrs_bin], 'cityblock')
        self.class_attribute_similarity = self._nb_attributes - D
        if np.all(train_attrs_bin == train_attrs_bin):
            np.fill_diagonal(self.class_attribute_similarity, 0)
        #self.probs = softmax(S, axis=1)

        # Precompute all the similarities (and so - probabilities) of each test-class to all the train classes based on
        # attribute vector distances.
        # We do this for each test-class, and we repeat this for each attribute because we want to mask/prune the similarities
        # with train-classes not having that attribute active.
        P = []
        for test_cls in range(len(test_attrs_bin)):
            attr_to_train_cls_probs = []
            for attr_id in range(self._nb_attributes):
                # Create a mask with lenght equal to the number of training classes,
                # having 1 for classes having the current attribute 'attr_id" active.
                classes_mask = np.asarray(self._train_attrs[:, attr_id] == 1, 'int')
                # Mask the similarities between train and test classes, so that similarity for
                # classes having current attribute 'attr_id' NOT ACTIVE will be zeroed.
                masked_similarities = self.class_attribute_similarity[test_cls] * classes_mask
                # We normalize the masked similarity to compute the probability
                prob = softmax(masked_similarities)
                attr_to_train_cls_probs.append(prob)
            P.append(np.array(attr_to_train_cls_probs))
        self._probs = P
        self._idx_active_attr = idx_active_attr
        self._idx_with_label = idx_with_label

    def __len__(self):
        return self._len

    def __getitem__(self, i):
        cls = np.random.randint(len(self._test_attrs))
        return self.get_item_with_class(cls)

    def get_items_with_class(self, Y):
        ENCS, CLS = [], []
        for cls in Y:
            enc, y = self.get_item_with_class(cls)
            #AE.append(ae[None, :]); CE.append(ce[None, :]), CLS.append(y)
            ENCS.append(enc); CLS.append(y)
        nb_examples = len(ENCS)
        nb_outs = len(ENCS[0])
        ENCS = [[ENCS[i][j] for i in range(nb_examples)] for j in range(nb_outs)]
        ENCS = [torch.stack(E, dim=0) for E in ENCS]
        return  ENCS,  torch.tensor(CLS)

    def get_item_with_class(self, cls):
        attr = self._test_attrs[cls]
        attr_indices, = np.where(attr)

        frnk_enc = [np.zeros_like(E[0]).reshape([self._nb_attributes, -1]) for E in self.encodings]
        contexts = []
        for attr_id in attr_indices:
            try:
                # classes_mask = np.asarray(self._train_attrs[:, attr_id] == 1, 'int')
                # masked_similarities = self.class_attribute_similarity[cls] * classes_mask
                # prob1 = softmax(masked_similarities)
                prob = self._probs[cls][attr_id]
                rnd_similar_cls = np.random.choice(np.arange(len(prob)), p=prob)
                example_id = self._idx_with_label[rnd_similar_cls][np.random.randint(len(self._idx_with_label[rnd_similar_cls]))]

            except ValueError as t:
                # In this case there are no  examples with this attribute
                # t.with_traceback()
                # raise t
                continue
            for i in range(len(self.encodings)):
                frnk_enc[i][attr_id, :] = self.encodings[i][example_id, attr_id, :]
                if self.cntx_encodings is not None:
                    contexts.append(self.cntx_encodings[attr_id])

        for i in range(len(self.encodings)):
            frnk_enc[i] = torch.tensor(frnk_enc[i].reshape(-1))

        if self.cntx_encodings is not None:
            # adding a random context to the list of features:
            frnk_enc.append(contexts[np.random.randint(len(contexts))])
        cls = cls + self._new_class_offset
        return frnk_enc, torch.tensor(cls)

class AsyncInfiniteDataset(Dataset):
    def __init__(self, len, encoder_fn, train_feats, train_labels, train_attrs_bin, test_attrs_bin,
                 ka_dim, kc_dim,
                 new_class_offset=0, device=None, **args):
        """
        :param len: dataset length
        :param encoder_fn: function that take a batch of image features X and return two tensor containing attribute_embedding and
        context_embedding
        :param train_feats:
        :param train_labels:
        :param train_attrs_bin:
        :param test_attrs_bin:
        :param new_class_offset:
        :param device:
        :param args:
        """
        super().__init__(**args)
        self._len = len
        self._encoder = encoder_fn
        self._train_feats = train_feats
        self._train_attrs = train_attrs_bin
        self._test_attrs = test_attrs_bin
        self._new_class_offset = new_class_offset
        self._nb_attributes = train_attrs_bin.shape[1]
        self._ka_dim = ka_dim
        self._kc_dim = kc_dim
        valid = []

        train_examples_attrs_bin = train_attrs_bin[train_labels]
        for att in range(self._nb_attributes):
            valid.append(np.where(train_examples_attrs_bin[:, att] == 1)[0])
        self._valid = valid

        # Extract attirbute embeddings for training set.
        self._dataset = TensorDataset(torch.tensor(train_feats).float(), torch.tensor(train_labels).long())
        self._attr_encoding = {}
        self._cntx_encoding = {}
        self.device = device

        # self._cntx_encoding = torch.cat(cntx_encoding)
        # self._attr_encoding = attr_encoding.view([attr_encoding.shape[0], self._nb_attributes, -1])

        # Find valid examples for each attribute.

    # def compute_encodings(self, i):
    #     x, y = self._dataset[i]
    #     x = x.to(self.device)
    #     ae, ce = self._encoder(x)
    #     ae = ae.detach().cpu().view([self._nb_attributes, -1])
    #     ce =  ce.detach().cpu()
    #     self._attr_encoding[i] = ae
    #     self._cntx_encoding[i] = ce
    #     return ae, ce
    #
    # def encoding(self, i):
    #     try:
    #         return self._attr_encoding[i], self._cntx_encoding[i]
    #     except KeyError:
    #         return self.compute_encodings(i)
    #
    # def attr_encoding(self, i):
    #     return self.encoding(i)[0]
    #
    # def cntx_encoding(self, i):
    #     return self.encoding(i)[1]
    def encode(self, idx):
        x, y = self._dataset[idx]
        x = x.to(self.device)
        ae, ce = self._encoder(x)
        ae = ae.detach().view([len(x), self._nb_attributes, -1])
        ce =  ce.detach()
        return ae, ce

    def clear_cache(self):
        self._attr_encoding.clear()
        self._cntx_encoding.clear()

    def __len__(self):
        return self._len

    # def __getitem__(self, i):
    #     cls = np.random.randint(len(self._test_attrs))
    #     return self.get_item(cls)

    def __getitem__(self, i):
        return self.encoding(i)

    #
    # def get_items_with_class(self, Y):
    #     AE, CE, CLS = [], [], []
    #     for cls in Y:
    #         ae, ce, y = self.get_item_with_class(cls)
    #         AE.append(ae[None, :]);
    #         CE.append(ce[None, :]), CLS.append(y)
    #     return torch.cat(AE), torch.cat(CE), torch.tensor(CLS)
    #

    def get_items_with_class(self, Y):
        attribute_vectors = self._test_attrs[Y]
        #attribute_vectors = self._test_attrs[torch.unique(Y)]

        attr_indices = []
        for attr_vec in attribute_vectors:
            attr_indices.append(np.where(attr_vec)[0])

        #attr_indices = (torch.tensor(attr_vec)==1).nonzero()

        random_idx = np.random.randint(len(self._dataset), size=128)
        _, random_cntx_enc = self.encode(random_idx)

        data_indices = []
        for i, attr_idx in enumerate(attr_indices):
            data_idx = []
            for a_id in attr_idx:
                try:
                    data_id = self._valid[a_id][np.random.randint(len(self._valid[a_id]))]
                    data_idx.append(data_id)
                except ValueError as t:
                    # In this case there are no  examples with this attribute
                    continue
            data_indices.append(torch.tensor(data_idx))
        selected_data_indices = torch.cat(data_indices, dim=0).unique()
        selected_attr_emb, selected_cntx_emb = self.encode(selected_data_indices)
        data_id_to_selected_attr_id = {int(index):i for i, index in enumerate(selected_data_indices)}

        frankenstein_attr_enc = torch.zeros([len(Y), self._nb_attributes, self._ka_dim]).float()
        for i, (attr_idx, data_idx) in enumerate(zip(attr_indices, data_indices)):
            for a_id, data_id in zip(attr_idx, data_idx):
                frankenstein_attr_enc[i, a_id, :] = selected_attr_emb[data_id_to_selected_attr_id[int(data_id)], :][a_id]

        frankenstein_attr_enc = frankenstein_attr_enc.reshape(len(Y), -1)
        Y = Y + self._new_class_offset
        return torch.tensor(frankenstein_attr_enc), random_cntx_enc, torch.tensor(Y)

    def get_item_with_class(self, cls):
        attr = self._test_attrs[cls]
        attr_indices = np.where(attr)[0]

        random_idx = np.random.randint(len(self._dataset))
        random_cntx_enc = self.cntx_encoding(random_idx)
        frankenstein_attr_enc = np.zeros([self._nb_attributes, self._ka_dim], dtype='float32')
        for attr_idx in attr_indices:
            try:
                emb = self._valid[attr_idx][np.random.randint(len(self._valid[attr_idx]))]
            except ValueError as t:
                # In this case there are no  examples with this attribute
                # t.with_traceback()
                # raise t
                continue
            frankenstein_attr_enc[attr_idx, :] = self.attr_encoding(emb)[attr_idx, :]

        frankenstein_attr_enc = frankenstein_attr_enc.reshape(-1)
        cls = cls + self._new_class_offset
        return torch.tensor(frankenstein_attr_enc), random_cntx_enc, torch.tensor(cls)

def FrankensteinDataset(per_class_samples, encoder_fn, train_feats, train_labels, train_attrs_bin, test_attrs_bin,
                        new_class_offset=0, device=None):
        nb_attributes = train_attrs_bin.shape[1]
        # Extract attirbute embeddings for training set.
        ds = TensorDataset(torch.tensor(train_feats).float(), torch.tensor(train_labels).long())
        dl = DataLoader(ds, batch_size=128, shuffle=False, num_workers=6, pin_memory=False, drop_last=False)
        attr_encoding = []
        cntx_encoding = []
        for X in dl:
            X = X[0].to(device)
            ae, ce = encoder_fn(X)
            attr_encoding.append(ae.detach().cpu())
            cntx_encoding.append(ce.detach().cpu())
        attr_encoding = torch.cat(attr_encoding)
        cntx_encoding = torch.cat(cntx_encoding)
        attr_encoding = attr_encoding.view([attr_encoding.shape[0], nb_attributes, -1])

        # Find valid examples for each attribute.
        valid = []
        for att in range(nb_attributes):
            valid.append(np.where(train_attrs_bin[:, att] == 1)[0])

        nb_classes =  len(test_attrs_bin)
        frankenstein_attr_enc = np.zeros([per_class_samples*nb_classes, attr_encoding.shape[1], attr_encoding.shape[2]])
        y_trues = []
        for cls in range(nb_classes):
            attr = test_attrs_bin[cls]
            attr_indices, = np.where(attr)
            y_trues += [cls+new_class_offset]*per_class_samples
            for idx in attr_indices:
                try:
                    v = np.random.choice(valid[idx], per_class_samples)
                except ValueError as t:
                    continue# In this case there are no examples with this attribute
                frankenstein_attr_enc[cls*per_class_samples:(cls+1)*per_class_samples, idx, :] = attr_encoding[v, idx, :]

        frankenstein_attr_enc = frankenstein_attr_enc.reshape(frankenstein_attr_enc.shape[0], -1)
        y_trues =np.stack(y_trues)
        random_cntx_enc = cntx_encoding[np.random.choice(len(cntx_encoding), len(frankenstein_attr_enc))]
        return TensorDataset(torch.tensor(frankenstein_attr_enc).float(),
                             random_cntx_enc.float(),
                             torch.tensor(y_trues).long())

if __name__ == '__main__':
    net = torch.load('checkpoint.pt')
    train, val, test_unseen, test_seen = get_dataset('AWA2', use_valid=False, gzsl=False)
    ds = InfiniteDataset(100,
                         net,
                         train['feats'],
                         train['labels'],
                         train['attr'],
                         train['attr_bin'],
                         test_unseen['class_attr_bin'])


import pygame, sys
from pygame import *
from pygame import mixer
from player import Player
from score import show_score
from life import Life
from bullets import Bullets
from meteor import Meteor
from menu import Menu

pygame.init()
screen = pygame.display.set_mode((1080, 720))
font = pygame.font.SysFont('Cooper black', 30)
ck = pygame.time.Clock()
def draw_text(text, font, color, surface, x, y):
    textobj = font.render(text, 1, color)
    textrect = textobj.get_rect()
    textrect.topleft = (x, y)
    surface.blit(textobj, textrect)

def main_menu():

    click = False
    menu = True
    while menu:

        screen.fill((0,0,0))
        draw_text('Start Menu', font, (255, 255, 255), screen, 20, 20)

        mx, my = pygame.mouse.get_pos()

        button_1 = pygame.Rect(525, 250, 200, 50)
        text1 = font.render('Jouer', False, (255,255,255))

        if button_1.collidepoint ((mx, my)) and click == True :
            menu = False

        pygame.draw.rect(screen, (0, 0, 0), button_1)
        screen.blit(text1, (583, 255))

        click = False
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                menu = False
            if event.type == MOUSEBUTTONDOWN:
                if event.button == 1:
                    click = True

        pygame.display.update()
        ck.tick(60)

main_menu()

class Game:
    def __init__(self,screen):
        self.screen = screen
        self.background = pygame.image.load('.\Images\Background.jpg')
        self.running = True
        self.clock = pygame.time.Clock()
        px = 500
        py = 500
        self.player = Player(px, py)
        self.meteor = Meteor()
        self.score = show_score(10,10)
        self.life = Life(10, 50)
        self.menu = Menu()
        self.bullets = Bullets(2000, 2000)
        self.bullets.state = "ready"
        self.BACKGROUND_SOUND = pygame.mixer.Sound('./Sons/BackgroundMusic.mp3')
        self.BACKGROUND_SOUND.set_volume(0.3)
        self.BACKGROUND_SOUND.play(loops=0, maxtime=0, fade_ms=0)

    def handling_event(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    if self.bullets.state == "ready":
                        self.bullets.rect.x = self.player.rect.x
                        self.bullets.rect.y = self.player.rect.y + 15
                        self.bullets.state = "fire"
                        self.bullets.SHOOT_SOUND.play()
                        self.bullets.velocity[0] = -1

        key = pygame.key.get_pressed()
        if key[pygame.K_LEFT]:
            self.player.velocity[0] = -1
        elif key[pygame.K_RIGHT]:
            self.player.velocity[0] = 1
        else:
            self.player.velocity[0] = 0

        if key[pygame.K_UP]:
            self.player.velocity[1] = -1
        elif key[pygame.K_DOWN]:
            self.player.velocity[1] = 1
        else:
            self.player.velocity[1] = 0

        if self.player.rect.x <= 0:
            self.player.rect.x = 0
        if self.player.rect.x >= 1010:
            self.player.rect.x = 1010
        if self.player.rect.y <= 0:
            self.player.rect.y = 0
        if self.player.rect.y >= 650:
            self.player.rect.y = 650

    def update(self):
        self.player.move()
        if self.meteor.rect.colliderect(self.bullets.rect):
            self.meteor.move(True)
            self.score.score_value += 1
            self.bullets.velocity[0] = 0
            self.bullets.rect.x = 2000
            self.bullets.rect.y = 2000
            self.bullets.state = "ready"
            self.bullets.HIT_SOUND.play()
        if (self.meteor.rect.y > 610):
            self.meteor.rect.y = 2000
            self.life.life_value -= 1
            if self.life.life_value == 0:
                self.running = False
        self.score.update()
        self.life.update()
        self.meteor.move(False)
        self.bullets.move()
        if self.bullets.rect.y <= -10:
            self.bullets.state = "ready"

    def display(self):
        self.screen.blit(self.background, (0, 0))
        self.player.draw(self.screen)
        self.meteor.draw(self.screen)
        self.bullets.draw(self.screen)
        self.score.draw(self.screen)
        self.life.draw(self.screen)
        pygame.display.flip()

    def run(self):
        while self.running:
            self.handling_event()
            self.update()
            self.display()
            self.clock.tick(300)

pygame.init()
screen = pygame.display.set_mode((1080,720))
pygame.display.set_caption("Space Shooter")
game = Game(screen)
game.run()

pygame.quit()


import tensorflow as tf
import argparse
import xml.etree.ElementTree as ET
import numpy as np
import json
import collections
import random
import re
import os

# Note that the char mappings are just ASCII value of char minus the lowest value (space) = 2
# 0 is the padding value, 1 is the UNK token and 2 is newline

# FOR SCIENCE
RAND_SEED = int(0xCAFEBABE)
random.seed(RAND_SEED)
np.random.seed(RAND_SEED)

def str_to_int(utt, newline=True):
	arr = []

	for c in list(utt):
		if c == 'π':
			arr.append(1)
		else:
			arr.append(ord(c)-27)

	if newline:
		arr.append(2)
		return arr
	return arr

class SequenceBuff:

	def __init__(self, buffersize):
		self.buffersize = buffersize
		self.capacity = 0
		self.internalMem = []

	def poll(self):
		if self.capacity > 2:
			index = random.randint(0, self.capacity-1)
		else:
			index = 0
		# make sure to shuffle the buffer
		if self.capacity < self.buffersize:
			np.random.shuffle(self.internalMem)
		return str_to_int(self.internalMem[index])

	def update(self, utterance):
		# replace

		if self.capacity > self.buffersize:
			index = random.randint(0, self.capacity-1)
			self.internalMem[index] = utterance
		# add
		else:
			self.internalMem.append(utterance)
			self.capacity += 1

def main(args):
	tree = ET.parse(args.filename)
	json_file = './data/mini_train.json'
	valid_file = './data/mini_valid.json'
	xml_root = tree.getroot()
	# max = -1
	# utt_num = []
	# convo_len = []

	buff = SequenceBuff(args.buffersize)
	json_objs = []
	convo_num = 0

	for conversation in xml_root:
		utt_num = 0

		convo = []
		for utterance in conversation:
			if utterance.text == None:
				buff.update('π')
				convo.append('π')
			else:
				buff.update(utterance.text)
				convo.append(utterance.text)
			utt_num += 1

		obj_real = {}
		obj_fake = {}
		context = []

		if utt_num < 2:
			continue
		elif utt_num-1 < args.context:
			obj_real['context_size'] = utt_num-1
			obj_fake['context_size'] = utt_num-1
			for i in range(0, utt_num-1):
				context += str_to_int(convo[i])

			next_utt = str_to_int(convo[utt_num-1])
		else:
			obj_real['context_size'] = args.context
			obj_fake['context_size'] = args.context
			for i in range(0, args.context):
				context += str_to_int(convo[i])
			next_utt = str_to_int(convo[args.context])
		fake_utt = buff.poll()

		obj_real['next_utt'] = next_utt
		obj_real['context'] = context
		obj_real['label'] = 0

		obj_fake['context'] = context
		obj_fake['next_utt'] = fake_utt
		obj_fake['label'] = 1

		json_objs.append(obj_real)
		json_objs.append(obj_fake)

		convo_num += 1

		if convo_num % 10000 == 0:
			print(convo_num)
			if convo_num < 450000:
				with open(json_file, 'a', encoding='utf-8') as f:
					for obj in json_objs:
						f.write(json.dumps(obj))
						f.write('\n')
					del json_objs[:]
			else:
				with open(valid_file, 'a', encoding='utf-8') as f2:
					for obj in json_objs:
						f2.write(json.dumps(obj))
						f2.write('\n')
					del json_objs[:]

if __name__ == '__main__':
	parser = argparse.ArgumentParser()
	parser.add_argument('filename')
	parser.add_argument('buffersize', type=int)
	parser.add_argument('context', type=int)
	args = parser.parse_args()
	main(args)


import random, os, json, datetime, time ,string
import docker
import random
import json
from flask import *
client = docker.from_env()
import requests
app = Flask(__name__)
c=0
gc = 0

@app.route("/<path:subreddits>", methods=['GET', 'POST', 'DELETE'])
def recv_req(subreddits):
	a = len(client.containers.list()) - 1
	global c
	global gc
	c+=1
	gc = gc + 1
	j=gc%(a)
	print("Request",gc)
	print(a,"containers running")
	pos = -1
	new_url = request.url
	#print(new_url)
	col = new_url.rfind(':')
	#print(col)
	for i in range(col,len(new_url)-1):
		if(new_url[i].isdigit() and new_url[i+1]=="/"):
			pos = i+1
			break
	#print(pos)
	ur = new_url[:col+1]+str(int(8000+j))+new_url[pos:]
	print("Request sent to:",ur)
	print("\n")
	print("\n")
	new_url = ur
	resp = requests.request(method=request.method,url= new_url,headers={key: value for (key, value) in request.headers if key != 'Host'}, data=request.get_data())
	headers = [(name, value) for (name, value) in resp.raw.headers.items()]
	response = Response(resp.content, resp.status_code, headers)

	return (response)

@app.route("/api/count",methods=['GET'])
def count():
	global c
	k = c
	c = 0
	return jsonify({"val":k})

@app.route("/api/global",methods=['GET'])
def count1():
	global gc
	return gc

if __name__ == "__main__":
	port = int(os.environ.get('PORT', 5000))
	app.run(debug=True, host='0.0.0.0', port=port)


import numpy as np
import pandas as pd
import os
import cv2
import matplotlib.pyplot as plt
from sklearn.utils import class_weight, shuffle
from tensorflow.keras import applications
from tensorflow.keras import optimizers
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.models import Sequential, Model, load_model
from tensorflow.keras.layers import Dropout, Flatten, Dense
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import ModelCheckpoint

foldernames = os.listdir('C:/Users/Ryu/Desktop/pythonEx/animal/raw-img')
categories = []
files = []
i = 0
for k, folder in enumerate(foldernames):
    filenames = os.listdir('C:/Users/Ryu/Desktop/pythonEx/animal/raw-img/'+ folder);
    for file in filenames:
        files.append('C:/Users/Ryu/Desktop/pythonEx/animal/raw-img/' + folder + "/" + file)
        categories.append(k)

df = pd.DataFrame({
    'filename': files,
    'category': categories
})
train_df = pd.DataFrame(columns=['filename', 'category'])
for i in range(10):
    train_df = train_df.append(df[df.category == i].iloc[:500,:])

train_df.head()
train_df = train_df.reset_index(drop=True)
print(train_df)

y = train_df['category']
x = train_df['filename']
y = train_df['category']

x, y = shuffle(x, y, random_state=8)

def centering_image(img):
    size = [256,256]

    img_size = img.shape[:2]

    # centering
    row = (size[1] - img_size[0]) // 2
    col = (size[0] - img_size[1]) // 2
    resized = np.zeros(list(size) + [img.shape[2]], dtype=np.uint8)
    resized[row:(row + img.shape[0]), col:(col + img.shape[1])] = img

    return resized

images = []
for i, file_path in enumerate(train_df.filename.values):
    #read image
    img = cv2.imread(file_path)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

    #resize
    if(img.shape[0] > img.shape[1]):
        tile_size = (int(img.shape[1]*256/img.shape[0]),256)
    else:
        tile_size = (256, int(img.shape[0]*256/img.shape[1]))

    #centering
    img = centering_image(cv2.resize(img, dsize=tile_size))

    #out put 224*224px
    img = img[16:240, 16:240]
    images.append(img)

images = np.array(images)

rows,cols = 2,5
fig, axes = plt.subplots(nrows=rows, ncols=cols, figsize=(50,50))
for i in range(10):
    path = train_df[train_df.category == i].values[2]
#     image = cv2.imread(path[0])/
    axes[i//cols, i%cols].set_title(path[0].split('/')[-2] + str(path[1]))
    axes[i//cols, i%cols].imshow(images[train_df[train_df.filename == path[0]].index[0]])

#plt.show()
data_num = len(y)
random_index = np.random.permutation(data_num)

x_shuffle = []
y_shuffle = []
for i in range(data_num):
    x_shuffle.append(images[random_index[i]])
    y_shuffle.append(y[random_index[i]])

x = np.array(x_shuffle)
y = np.array(y_shuffle)
val_split_num = int(round(0.2*len(y)))
x_train = x[val_split_num:]
y_train = y[val_split_num:]
x_test = x[:val_split_num]
y_test = y[:val_split_num]

print('x_train', x_train.shape)
print('y_train', y_train.shape)
print('x_test', x_test.shape)
print('y_test', y_test.shape)

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255

img_rows, img_cols, img_channel = 224, 224, 3
name_animal = []
for i in range(10):
    path = train_df[train_df.category == i].values[2]
    if path[0].split('/')[-2] == 'scoiattolo':
        name_animal.append('squirrel')
    elif path[0].split('/')[-2] == 'cavallo':
        name_animal.append('horse')
    elif path[0].split('/')[-2] == 'farfalla':
        name_animal.append('butterfly')
    elif path[0].split('/')[-2] == 'mucca':
        name_animal.append('cow')
    elif path[0].split('/')[-2] == 'gatto':
        name_animal.append('cat')
    elif path[0].split('/')[-2] == 'pecora':
        name_animal.append('sheep')
    elif path[0].split('/')[-2] == 'gallina':
        name_animal.append('chicken')
    elif path[0].split('/')[-2] == 'elefante':
        name_animal.append('elephant')
    elif path[0].split('/')[-2] == 'ragno':
        name_animal.append('spider')
    elif path[0].split('/')[-2] == 'cane':
        name_animal.append('dog')

base_model = applications.VGG16(weights='imagenet', include_top=False, input_shape=(img_rows, img_cols, img_channel))

add_model = Sequential()
add_model.add(Flatten(input_shape=base_model.output_shape[1:]))
add_model.add(Dense(256, activation='relu'))
add_model.add(Dense(10, activation='softmax'))

model = Model(inputs=base_model.input, outputs=add_model(base_model.output))
model.compile(loss='binary_crossentropy', optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
              metrics=['accuracy'])

model.summary()

batch_size = 50
epochs = 15

train_datagen = ImageDataGenerator(
        rotation_range=30,
        width_shift_range=0.1,
        height_shift_range=0.1,
        horizontal_flip=True)

train_datagen.fit(x_train)

history = model.fit_generator(
    train_datagen.flow(x_train, y_train, batch_size=batch_size),
    steps_per_epoch=x_train.shape[0] // batch_size,
    epochs=epochs,
    validation_data=(x_test, y_test),
    callbacks=[ModelCheckpoint('VGG16-transferlearning.model', monitor='val_acc')]
)


# encoding: utf-8
"""
@author: julse@qq.com
@time: 2020/11/15 20:20
@desc:
"""
from FastaDealer import FastaDealer
from FeatureDealer import BaseFeature, Feature_type
from common import check_path
from mySupport import savepredict

if __name__ == '__main__':
    ############# predict #######################################
    ## set file path: protein pair without label
    # in_pair = 'file/source/test1.txt'
    # in_fasta = 'file/source/test1.fasta'

    ############# evaluate #######################################
    # set file path: protein pair with label
    in_pair = 'file/source/test2.txt'
    in_fasta = 'file/source/test2.fasta'

    #######################################################

    fin_model = 'file/source/_my_model.h5'
    out_feature_dir = 'file/feature'
    out_feature_db_dir = 'file/featuredb'
    out_result_dir = 'file/result'

    # check path
    check_path(out_feature_dir)
    check_path(out_result_dir)
    # encoding seq
    FastaDealer().getNpy(in_fasta,out_feature_db_dir)
    # generate feature
    BaseFeature().base_compose(out_feature_dir, in_pair, out_feature_db_dir, feature_type=Feature_type.SEQ_1D)
    # predict and save
    savepredict(in_pair, out_feature_dir, fin_model, out_result_dir)