Пример #1
0
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Thread Example")
        form_layout = QVBoxLayout()
        self.setLayout(form_layout)
        self.resize(400, 800)

        self.button_start_threads = QPushButton()
        self.button_start_threads.clicked.connect(self.start_threads)
        self.button_start_threads.setText("Start {} threads".format(self.NUM_THREADS))
        form_layout.addWidget(self.button_start_threads)

        self.button_stop_threads = QPushButton()
        self.button_stop_threads.clicked.connect(self.abort_workers)
        self.button_stop_threads.setText("Stop threads")
        self.button_stop_threads.setDisabled(True)
        form_layout.addWidget(self.button_stop_threads)

        self.log = QTextEdit()
        form_layout.addWidget(self.log)

        self.progress = QTextEdit()
        form_layout.addWidget(self.progress)

        QThread.currentThread().setObjectName('main')  # threads can be named, useful for log output
        self.__workers_done = None
        self.__threads = None
Пример #2
0
def main_gui():
    main_app = QApplication(sys.argv)
    QThread.currentThread().setPriority(QThread.HighPriority)

    main_app.setStyle('fusion')
    main_app.main_window = MainWindow()
    main_app.main_window.show()
    # main_app.controller = MainController(main_app)

    sys.exit(main_app.exec_())
Пример #3
0
    def service_party_time_left(self):
        """ Update time left """
        _service_name = 'Service::Timeleft'
        print('> {} is running...'.format(_service_name))
        while self.services_are_running:
            try:
                for _name, _party in self.hosted_parties.items():
                    _state = _party[PartyKey.KEY_STATE]
                    if _state == PartyState.STATE_WAITING_FOR_PLAYERS:
                        if _party[PartyKey.KEY_TIME_LEFT] > 0:
                            _party[PartyKey.KEY_TIME_LEFT] -= 1
                        else:
                            print('> Party [{}] change state to [{}]'.format(
                                _name, PartyState.STATE_PARTY_ENDED))
                            _party[PartyKey.
                                   KEY_STATE] = PartyState.STATE_PARTY_ENDED
                            _party[PartyKey.KEY_TIME_LEFT] = 10
                    elif _state == PartyState.STATE_READY_TO_FIGHT:
                        if _party[PartyKey.KEY_TIME_LEFT] > 0:
                            _party[PartyKey.KEY_TIME_LEFT] -= 1
                        else:
                            print('> Party [{}] change state to [{}]'.format(
                                _name, PartyState.STATE_IN_PROGRESS))
                            _party[PartyKey.
                                   KEY_STATE] = PartyState.STATE_IN_PROGRESS
                            _party[PartyKey.KEY_TIME_LEFT] = 0

                    elif _state == PartyState.STATE_IN_PROGRESS:
                        if _party[PartyKey.KEY_TIME_LEFT] > 0:
                            _party[PartyKey.KEY_TIME_LEFT] -= 1
                        else:
                            print('> Party [{}] change state to [{}]'.format(
                                _name, PartyState.STATE_PARTY_ENDED))
                            _party[PartyKey.
                                   KEY_STATE] = PartyState.STATE_PARTY_ENDED
                            _party[PartyKey.KEY_TIME_LEFT] = 0

                    elif _state == PartyState.STATE_WINNER:
                        if _party[PartyKey.KEY_TIME_LEFT] > 0:
                            _party[PartyKey.KEY_TIME_LEFT] -= 1
                        else:
                            print('> Party [{}] change state to [{}]'.format(
                                _name, PartyState.STATE_PARTY_ENDED))
                            _party[PartyKey.
                                   KEY_STATE] = PartyState.STATE_PARTY_ENDED
                            _party[PartyKey.KEY_TIME_LEFT] = 10

                QThread.currentThread().msleep(SERVICE_TIME_LEFT_PERIOD_S *
                                               1000)
            except Exception as e:
                pass
        print('> {} ended'.format(_service_name))
Пример #4
0
    def service_debug(self):
        """ Debug display """
        if not DEBUG_MODE: return

        _service_name = 'Service::Debug'
        print('> {} is running...'.format(_service_name))
        while self.services_are_running:
            try:
                QThread.currentThread().msleep(
                    int(DEBUG_DISPLAY_PERIOD_S * 1000))
            except Exception as e:
                pass
        print('> {} ended'.format(_service_name))
Пример #5
0
 def __init__(self, mainw):
     super().__init__()
     self.setupUi(mainw)
     self.CONFIG = ''
     self.template = ''
     self.xlsx_rows_list = ''
     self.parent = mainw
     self.pushButton_open_list_and_template.clicked.connect(
         self.open_xls_and_template)
     self.pushButton_ask_and_send.clicked.connect(self.send_msg)
     self.pushButton_cancel_send.clicked.connect(self.abort_workers)
     QThread.currentThread().setObjectName(
         'main')  # threads can be named, useful for log output
     self.__workers_done = None
     self.__threads = None
Пример #6
0
    def run(self):
        self.manager.connection.core.ChangeWindowAttributesChecked(
            self.manager.screen.root,
            xcffib.xproto.CW.EventMask,
            [
                xcffib.xproto.EventMask.PropertyChange
                | xcffib.xproto.EventMask.SubstructureNotify,
            ],
        ).check()
        current_thread = QThread.currentThread()

        while True:
            if current_thread.isInterruptionRequested():
                return

            evt = self.manager.connection.poll_for_event()
            if evt is None:
                QThread.msleep(10)
                continue

            for wanted_type, handler in self.handlers.items():
                if isinstance(evt, wanted_type):
                    try:
                        handler(evt)
                    except:
                        self.logger.error(
                            "Error handling event %s", repr(evt), exc_info=True
                        )
Пример #7
0
    def registerThread(self):
        """
        This slot shall be called from each activated nexxT thread with a direct connection.

        :return:
        """
        t = QThread.currentThread()
        logger.internal("registering thread %s", t.objectName())
        with self._lockThreadSpecific:
            if not t in self._threadSpecificProfiling:
                self._threadSpecificProfiling[t] = ThreadSpecificProfItem()
                self._threadSpecificProfiling[t].timer = QTimer(
                    parent=self.sender())
                self._threadSpecificProfiling[t].timer.timeout.connect(
                    self._generateRecord, Qt.DirectConnection)
                self._threadSpecificProfiling[t].timer.setInterval(
                    int(ThreadSpecificProfItem.THREAD_PROFILING_PERIOD_SEC *
                        1e3))
                self.stopTimers.connect(
                    self._threadSpecificProfiling[t].timer.stop)
                self.startTimers.connect(
                    self._threadSpecificProfiling[t].timer.start)
                if self._loadMonitoringEnabled:
                    self._threadSpecificProfiling[t].timer.start()

            tmain = QCoreApplication.instance().thread()
            if self._mi is None and not tmain in self._threadSpecificProfiling:
                self._mi = MethodInvoker(
                    dict(object=self, method="registerThread", thread=tmain),
                    Qt.QueuedConnection)
Пример #8
0
    def __init__(self):
        QObject.__init__(self, None)
        self._mainthread = QThread.currentThread()

        self._signalthread = SignalThread()
        QObject.connect(self._signalthread, SIGNAL("triggerSignal()"),
                        self.sensorQueueChanged)

        self._idletimer = QTimer()
        self._delaytimer = QTimer()
        self._timerqueuetimer = QTimer()

        self._idletimer.setSingleShot(True)
        self._delaytimer.setSingleShot(True)
        self._timerqueuetimer.setSingleShot(True)

        self.connect(self._idletimer, SIGNAL("timeout()"), self.idleTimeout)
        self.connect(self._delaytimer, SIGNAL("timeout()"), self.delayTimeout)
        self.connect(self._timerqueuetimer, SIGNAL("timeout()"),
                     self.timerQueueTimeout)

        SoDB.getSensorManager().setChangedCallback(self.sensorQueueChangedCB,
                                                   self)
        SoDB.setRealTimeInterval(1.0 / 25.0)
        SoRenderManager.enableRealTimeUpdate(False)
Пример #9
0
 def get_db():
     name = "db-{0}".format(str(QThread.currentThread()))
     if QSqlDatabase.contains(name):
         return QSqlDatabase.database(name)
     else:
         db = QSqlDatabase.addDatabase("QSQLITE", name)
         db.setDatabaseName("video.db")
         return db
Пример #10
0
    def _generateRecord(self):
        """
        This slot is automaticall called periodically

        :return:
        """
        t = QThread.currentThread()
        with self._lockThreadSpecific:
            self._threadSpecificProfiling[t].update()
            self._emitData()
Пример #11
0
 def sensorQueueChangedCB(self, closure):
     # if we get a callback from another thread, route the callback
     # through SignalThread so that we receive the callback in the
     # QApplication thread (needed since QTimer isn't thread safe)
     if QThread.currentThread() != closure._mainthread:
         if not closure._signalthread.isRunning():
             closure._signalthread.start()
         self._signalthread.trigger()
     else:
         self.sensorQueueChanged()
Пример #12
0
 def transmit(self, dataSample):
     """
     transmit a data sample over this port
     :param dataSample: sample to transmit
     """
     if not QThread.currentThread() is self.thread():
         raise NexTRuntimeError(
             "OutputPort.transmit has been called from an unexpected thread."
         )
     self.transmitSample.emit(dataSample)
Пример #13
0
 def _receiveSample(self, dataSample):
     assert QThread.currentThread() is self.thread()
     while True:
         if self._stopped:
             logger.info(
                 "The inter-thread connection is set to stopped mode; data sample discarded."
             )
             break
         if self.semaphore.tryAcquire(1, 500):
             self.transmitInterThread.emit(dataSample, self.semaphore)
             break
Пример #14
0
 def _receiveSync(self, dataSample):
     """
     Called from framework only and implements the synchronous receive mechanism.
     :param dataSample: the transmitted DataSample instance
     :return: None
     """
     if not QThread.currentThread() is self.thread():
         raise NexTInternalError(
             "InputPort.receiveSync has been called from an unexpected thread."
         )
     self._addToQueue(dataSample)
     self._transmit()
Пример #15
0
    def deregisterThread(self):
        """
        This slot shall be called from each deactivated nexxT thread with a direct connection

        :return:
        """
        self._mi = None
        t = QThread.currentThread()
        logger.debug("deregistering thread %s", t.objectName())
        with self._lockThreadSpecific:
            if t in self._threadSpecificProfiling:
                self._threadSpecificProfiling[t].timer.stop()
                del self._threadSpecificProfiling[t]
        self.threadDeregistered.emit(t.objectName())
    def test(self):
        worker_thread_receiver = Receiver()
        worker_thread_receiver.moveToThread(self._worker_thread)
        self._worker_thread.started.connect(
            worker_thread_receiver.slot_function)

        main_thread = QThread.currentThread()
        main_thread_receiver = Receiver()
        self._worker_thread.started.connect(main_thread_receiver.slot_function)

        self._timer.start()
        self.app.exec_()

        self.assertEqual(worker_thread_receiver.senderThread,
                         self._worker_thread)
        self.assertEqual(main_thread_receiver.senderThread, main_thread)
Пример #17
0
    def afterPortDataChanged(self, portname):
        """
        This slot is called after calling onPortDataChanged.

        :param portname: the fully qualified name of the port
        :param timeNs: the timestamp
        :return:
        """
        if not self._portProfilingEnabled:
            return
        t = QThread.currentThread()
        timeNs = time.perf_counter_ns()
        with self._lockThreadSpecific:
            if t in self._threadSpecificProfiling:
                self._threadSpecificProfiling[t].registerPortChangeFinished(
                    portname, timeNs)
Пример #18
0
 def __init__(self):
     """
     Intended to be called by `initialise` only. Instantiates the singleton, and checks if we're on the main thread.
     If not, raises a RuntimeError.
     """
     super().__init__()
     app = QtWidgets.QApplication.instance()
     if app is None:
         print(
             'Running without QT event queue. Callbacks will occur on the caller\'s thread, and UI bindings will '
             'be ignored.')
     elif app.thread() != QThread.currentThread():
         raise RuntimeError(
             'QWidgetUpdaterFactory must be created on the main thread')
     else:
         self._sig_make_object.connect(self._create_QWidgetUpdater_slot)
         self._sig_execute_function.connect(self._execute_slot)
Пример #19
0
 def _getDB(self):
     if self.threadSafety == self.SINGLE_CONNECTION:
         return self.dbConn
     # create a new connection for each thread
     with QMutexLocker(self.mutex):
         tid = QThread.currentThread()
         if not tid in self.dbs:
             # Our custom argument
             db = sqlite3.connect(self.filename)  # might need to use self.filename
             if len(self.dbs) == 0:
                 db.execute(
                     "CREATE TABLE IF NOT EXISTS "
                     "debug(date datetime, loggername text, filename, srclineno integer, "
                     "func text, level text, msg text)")
                 db.commit()
             self.dbs[tid] = db
         return self.dbs[tid]
Пример #20
0
    def execute(cls, fn: Callable[[], None], blocking: bool = False) -> None:
        app = QtWidgets.QApplication.instance()
        if app is None or app.thread() == QThread.currentThread():
            # If already on main thread then just execute directly. This check works even if standard python threads
            # (not QThreads) are used. Function called explicitly (instead of relying on direct QT signal) as the QT
            # event queue may not be available.
            fn()
            return

        # On non-main thread
        cls._executor_mutex.acquire(
        )  # Will be released when object is created (on main thread)
        cls._in_function = fn
        cls._instance._sig_execute_function.emit()  # releases lock

        if blocking:
            cls._executor_mutex.acquire()
            cls._executor_mutex.release()
Пример #21
0
def test_abstract_build_runner(qtbot):
    main_thread = QThread.currentThread()

    class Worker(QObject):
        call_started = Signal()

        def __init__(self, *args):
            QObject.__init__(self)

        @Slot()
        def my_slot(self):
            assert main_thread != self.thread()
            self.call_started.emit()

    class BuildRunner(build_runner.AbstractBuildRunner):
        call_started = Signal()
        thread_finished = Signal()
        worker_class = Worker

        def init_worker(self, fetch_config, options):
            build_runner.AbstractBuildRunner.init_worker(self, fetch_config,
                                                         options)
            self.thread.finished.connect(self.thread_finished)
            self.worker.call_started.connect(self.call_started)
            return self.worker.my_slot

    # instantiate the runner
    runner = BuildRunner(Mock(persist='.'))

    assert not runner.thread

    with qtbot.waitSignal(runner.thread_finished, raising=True):
        with qtbot.waitSignal(runner.call_started, raising=True):
            runner.start(
                create_config('firefox', 'linux', 64, 'x86_64'),
                {'addons': (), 'profile': '/path/to/profile',
                    'profile_persistence': 'clone'},
            )

        runner.stop(True)

    assert not runner.pending_threads
Пример #22
0
    def create_QWidgetUpdater(
            cls, widget: QWidget, widget_setter: Callable[[T], None],
            model_getter: Callable[[], T]) -> Callable[[], None]:
        """
        Creates a new QWidgetUpdater. If this is called from a secondary thread, the QWidgetUpdater is created on the
         main thread via signal.
        Parameters
        ----------
        widget The widget to be updated, required so signals can be blocked during update
        widget_setter Function to be called on the widget with input from model_getter()
        model_getter Retrieves the value to be provided to widget_setter

        Returns QWidgetUpdater constructed on the main thread
        -------

        """
        app = QtWidgets.QApplication.instance()
        if app is None:
            # Headless mode; updater doesn't need to do anything.
            return lambda: None
        if app.thread() == QThread.currentThread():
            # If already on main thread then just make function directly. This check works even if standard python
            # threads (not QThreads) are used. Function called explicitly (instead of relying on direct QT signal) as
            # the QT event queue may not be available.
            return QWidgetUpdater(widget, widget_setter, model_getter)
        # On non-main thread
        # Acquire lock and set input variables. Lock will be released & inputs will be cleared on main thread.
        cls._updater_mutex.acquire()
        cls._in_widget = widget
        cls._in_widget_setter = widget_setter
        cls._in_model_getter = model_getter
        cls._instance._sig_make_object.emit()

        # Block until main thread does it's job, and get output & rest output variable.
        cls._updater_mutex.acquire()
        out = cls._updater_out
        cls._updater_out = None
        cls._updater_mutex.release()
        return out
Пример #23
0
    def work(self):
        """
        Pretend this worker method does work that takes a long time. During this time, the thread's
        event loop is blocked, except if the application's processEvents() is called: this gives every
        thread (incl. main) a chance to process events, which in this sample means processing signals
        received from GUI (such as abort).
        """
        thread_name = QThread.currentThread().objectName()
        self.sig_step.emit(
            self.__id, 'Running worker #{} from thread "{}"'.format(
                self.__id, thread_name))

        while True:
            batch_sender_app.processEvents(
            )  # this could cause change to self.__abort
            if self.__abort:
                self.sig_step.emit(
                    self.__id, 'Worker #{} aborting work'.format(self.__id))
                break
            try:
                mail = self.envelope.take_next_mail()
                qt_mail_id, xls_mail_id, sent_to = mail['qt_id'], mail[
                    'xls_id'], mail['to_addrs']
            except StopIteration:
                break  # Это — победа
            # Теперь пытаемся отправить полученное письмо
            try:
                self.envelope.send_next(mail)
            except Exception as e:
                self.sig_step.emit(self.__id,
                                   'Worker #{} error: {}'.format(self.__id, e))
                self.sig_mail_error.emit(qt_mail_id, str(e))
            else:
                self.sig_step.emit(
                    self.__id,
                    'Worker #{} sent to {}'.format(self.__id, sent_to))
                self.sig_mail_sent.emit(qt_mail_id, xls_mail_id)

        self.sig_done.emit(self.__id)
Пример #24
0
 def _receiveAsync(self, dataSample, semaphore):
     """
     Called from framework only and implements the asynchronous receive mechanism using a semaphore.
     :param dataSample: the transmitted DataSample instance
     :param semaphore: a QSemaphore instance
     :return: None
     """
     if not QThread.currentThread() is self.thread():
         raise NexTInternalError(
             "InputPort.receiveAsync has been called from an unexpected thread."
         )
     self._addToQueue(dataSample)
     if not self._interthreadDynamicQueue:
         # usual behaviour
         semaphore.release(1)
         self._transmit()
     else:
         if semaphore not in self._semaphoreN:
             self._semaphoreN[semaphore] = 1
         delta = self._semaphoreN[semaphore] - len(self.queue)
         if delta <= 0:
             # the semaphore's N is too small
             semaphore.release(1 - delta)
             self._semaphoreN[semaphore] += -delta
             logger.internal("delta = %d: semaphoreN = %d", delta,
                             self._semaphoreN[semaphore])
             self._transmit()
         elif delta > 0:
             # first acquire is done by caller
             self._semaphoreN[semaphore] -= 1
             # the semaphore's N is too large, try acquires to reduce the size
             for i in range(1, delta):
                 if semaphore.tryAcquire(1):
                     self._semaphoreN[semaphore] -= 1
                 else:
                     break
             logger.internal("delta = %d: semaphoreN = %d", delta,
                             self._semaphoreN[semaphore])
             self._transmit()
Пример #25
0
    def work(self):
        """
        Pretend this worker method does work that takes a long time. During this time, the thread's
        event loop is blocked, except if the application's processEvents() is called: this gives every
        thread (incl. main) a chance to process events, which in this sample means processing signals
        received from GUI (such as abort).
        """
        thread_name = QThread.currentThread().objectName()
        thread_id = int(QThread.currentThreadId())  # cast to int() is necessary
        self.sig_msg.emit('Running worker #{} from thread "{}" (#{})'.format(self.__id, thread_name, thread_id))

        for step in range(100):
            time.sleep(0.1)
            self.sig_step.emit(self.__id, 'step ' + str(step))

            # check if we need to abort the loop; need to process events to receive signals;
            app.processEvents()  # this could cause change to self.__abort
            if self.__abort:
                # note that "step" value will not necessarily be same for every thread
                self.sig_msg.emit('Worker #{} aborting work at step {}'.format(self.__id, step))
                break

        self.sig_done.emit(self.__id)
Пример #26
0
 def getData(self, delaySamples=0, delaySeconds=None):
     """
     Return a data sample stored in the queue (called by the filter).
     :param delaySamples: 0 related the most actual sample, numbers > 0 relates to historic samples (None can be
                          given if delaySeconds is not None)
     :param delaySeconds: if not None, a delay of 0.0 is related to the current sample, positive numbers are related
                          to historic samples (TODO specify the exact semantics of delaySeconds)
     :return: DataSample instance
     """
     if not QThread.currentThread() is self.thread():
         raise NexTRuntimeError(
             "InputPort.getData has been called from an unexpected thread.")
     if delaySamples is not None:
         assert delaySeconds is None
         return self.queue[delaySamples]
     if delaySeconds is not None:
         assert delaySamples is None
         delayTime = delaySeconds / DataSample.TIMESTAMP_RES
         i = 0
         while i < len(self.queue) and self.queue[0].getTimestamp(
         ) - self.queue[i].getTimestamp() < delayTime:
             i += 1
         return self.queue[i]
     raise RuntimeError("delaySamples and delaySeconds are both None.")
Пример #27
0
    def service_party_states(self):
        """ Solve party states """
        _service_name = 'Service::States'
        print('> {} is running...'.format(_service_name))
        while self.services_are_running:
            try:
                for _name, _model in self.hosted_parties.items():
                    _state = _model[PartyKey.KEY_STATE]
                    if _state == PartyState.STATE_WAITING_FOR_PLAYERS:
                        if len(_model[PartyKey.KEY_PLAYERS]) >= _model[
                                PartyKey.KEY_LIMIT]:
                            print('> Party [{}] change state to [{}]'.format(
                                _name, PartyState.STATE_READY_TO_FIGHT))
                            self.startup_party_elements(_name)
                            _model[PartyKey.
                                   KEY_STATE] = PartyState.STATE_READY_TO_FIGHT
                            _model[PartyKey.
                                   KEY_TIME_LEFT] = PartyConst.TIME_MAX_READY
                    elif _state == PartyState.STATE_READY_TO_FIGHT:
                        if _model[PartyKey.KEY_TIME_LEFT] <= 0:
                            print('> Party [{}] change state to [{}]'.format(
                                _name, PartyState.STATE_IN_PROGRESS))
                            _model[PartyKey.
                                   KEY_STATE] = PartyState.STATE_IN_PROGRESS
                            _model[PartyKey.
                                   KEY_TIME_LEFT] = PartyConst.TIME_MAX_GAME
                    elif _state == PartyState.STATE_IN_PROGRESS:
                        if sum([
                                int(_mob.is_alive)
                                for _mob in _model[PartyKey.KEY_MOBS][
                                    PartyKey.KEY_MOB_PLAYERS]
                        ]) <= 1:
                            print('> Party [{}] change state to [{}]'.format(
                                _name, PartyState.STATE_WINNER))
                            for _mob in _model[PartyKey.KEY_MOBS][
                                    PartyKey.KEY_MOB_PLAYERS]:
                                if _mob.is_alive:
                                    _model[PartyKey.KEY_DEAD_POOL].append(
                                        _mob.name)
                                    break
                            _model[
                                PartyKey.KEY_STATE] = PartyState.STATE_WINNER
                            _model[PartyKey.
                                   KEY_TIME_LEFT] = PartyConst.TIME_MAX_WIN
                            _has_winner = False
                            for _mob in _model[PartyKey.KEY_MOBS][
                                    PartyKey.KEY_MOB_PLAYERS]:
                                if _mob.is_alive:
                                    _has_winner = True
                                    print(
                                        '> Party [{}] Winner is: [{}]'.format(
                                            _name, _mob.name))
                                    break
                            if not _has_winner:
                                print('> Party [{}] NO WINNER !')
                    _model[PartyKey.KEY_PREV_STATE] = _state

                    # ***** Delete dead mobs
                    _bolt_temp = list()
                    for _bolt in _model[PartyKey.KEY_MOBS][
                            PartyKey.KEY_MOB_BOLTS]:
                        if _bolt.is_alive:
                            _bolt_temp.append(_bolt)

                    _asteroid_temp = list()
                    for _asteroid in _model[PartyKey.KEY_MOBS][
                            PartyKey.KEY_MOB_ASTEROIDS]:
                        if not -PartyConst.WIDTH < _asteroid.x < PartyConst.WIDTH:
                            continue
                        if not -PartyConst.HEIGHT < _asteroid.y < PartyConst.HEIGHT:
                            continue
                        _asteroid_temp.append(_asteroid)

                    _model[PartyKey.KEY_MOBS][
                        PartyKey.KEY_MOB_ASTEROIDS] = _asteroid_temp
                    _model[PartyKey.KEY_MOBS][
                        PartyKey.KEY_MOB_BOLTS] = _bolt_temp

                    # ***** Delete party
                    if _state == PartyState.STATE_PARTY_ENDED:
                        self.delete_party(_name)
                QThread.currentThread().msleep(
                    int(SERVICE_STATE_PERIOD_S * 1000))

            except Exception as e:
                print('> [ERR] {} > {}: {}'.format(_service_name,
                                                   type(e).__name__, e))
        print('> {} ended'.format(_service_name))
Пример #28
0
    def service_party_collision(self):
        """ Solve collisions """
        _service_name = 'Service::Collision'
        print('> {} is running... '.format(_service_name))
        while self.services_are_running:
            _begin = time.time()
            try:
                for _name, _party in self.hosted_parties.items():

                    if _party[PartyKey.KEY_STATE] in [
                            PartyState.STATE_IN_PROGRESS,
                            PartyState.STATE_WINNER
                    ]:
                        _all_mobs = _party[PartyKey.KEY_MOBS][
                            PartyKey.
                            KEY_MOB_PLAYERS] + _party[PartyKey.KEY_MOBS][
                                PartyKey.KEY_MOB_ASTEROIDS] + _party[
                                    PartyKey.KEY_MOBS][PartyKey.KEY_MOB_BOLTS]
                        for _i, _mob in enumerate(_all_mobs):

                            # Dead zone damage
                            _dt_mob_from_dz_center = np.linalg.norm(
                                _mob.xy - _party[PartyKey.KEY_DEAD_ZONE][
                                    PartyKey.KEY_DEAD_ZONE_CENTER])
                            if _dt_mob_from_dz_center > _party[
                                    PartyKey.KEY_DEAD_ZONE][
                                        PartyKey.KEY_DEAD_ZONE_RADIUS]:
                                if _party[
                                        PartyKey.
                                        KEY_STATE] == PartyState.STATE_IN_PROGRESS:
                                    if _mob.is_alive:
                                        _mob.set_damage(
                                            PartyConst.DEAD_ZONE_DAMAGE_PER_S *
                                            SERVICE_REAL_TIME_PERIOD_S)
                                        if _mob.type == ModelType.SHIP_MODEL and not _mob.is_alive:
                                            _party[
                                                PartyKey.KEY_DEAD_POOL].append(
                                                    _mob.name)

                            # Detect collision
                            for _collider in _all_mobs[_i:]:
                                if not _collider.name == _mob.name:
                                    _dist = np.linalg.norm(_collider.xy -
                                                           _mob.xy)
                                    if _dist == 0:
                                        continue
                                    if _dist < (_collider.radius +
                                                _mob.radius) / 2:
                                        if ModelType.BOLT_MODEL not in [
                                                _mob.type, _collider.type
                                        ]:
                                            # print('COLLISION:', _mob.name, 'with', _collider.name)
                                            # Set position offset after collision
                                            _diff = (_collider.radius +
                                                     _mob.radius) / 2 - _dist
                                            # _diff += 5
                                            _diff_ratio1 = _mob.weight / (
                                                _mob.weight +
                                                _collider.weight) * _diff
                                            _diff_ratio2 = _collider.weight / (
                                                _mob.weight +
                                                _collider.weight) * _diff

                                            _mob.set_position(
                                                _mob.xy + _diff_ratio2 *
                                                (_mob.xy - _collider.xy) /
                                                _dist)
                                            _collider.set_position(
                                                _collider.xy + _diff_ratio1 *
                                                (_collider.xy - _mob.xy) /
                                                _dist)

                                            # Set orientation offset after collision
                                            # -- Normal
                                            _normal = (_collider.xy -
                                                       _mob.xy) / _dist

                                            # -- Tangente
                                            _tx = -_normal[1]
                                            _ty = _normal[0]

                                            # -- dot product tangent
                                            _dp_tan_1 = _mob.dir_x * _mob.get_propulsion_speed(
                                            ) * _tx + _mob.dir_y * _mob.get_propulsion_speed(
                                            ) * _ty
                                            _dp_tan_2 = _collider.dir_x * _collider.get_propulsion_speed(
                                            ) * _tx + _collider.dir_y * _collider.get_propulsion_speed(
                                            ) * _ty

                                            # -- dot product normal
                                            _dp_normal_mob = _mob.dir_x * _mob.get_propulsion_speed(
                                            ) * _normal[
                                                0] + _mob.dir_y * _mob.get_propulsion_speed(
                                                ) * _normal[1]
                                            _dp_normal_collider = _collider.dir_x * _collider.get_propulsion_speed(
                                            ) * _normal[
                                                0] + _collider.dir_y * _collider.get_propulsion_speed(
                                                ) * _normal[1]

                                            # -- conservation of momentum
                                            _m1 = (_dp_normal_mob *
                                                   (_mob.weight -
                                                    _collider.weight) +
                                                   2 * _collider.weight *
                                                   _dp_normal_collider) / (
                                                       _mob.weight +
                                                       _collider.weight)
                                            _m2 = (_dp_normal_collider *
                                                   (_collider.weight -
                                                    _mob.weight) + 2 *
                                                   _mob.weight * _dp_normal_mob
                                                   ) / (_mob.weight +
                                                        _collider.weight)

                                            _speed1 = np.array([
                                                _tx * _dp_tan_1 +
                                                _normal[0] * _m1,
                                                _ty * _dp_tan_1 +
                                                _normal[1] * _m1
                                            ])
                                            _speed2 = np.array([
                                                _tx * _dp_tan_2 +
                                                _normal[0] * _m2,
                                                _ty * _dp_tan_2 +
                                                _normal[1] * _m2
                                            ])

                                            _prop1 = np.linalg.norm(_speed1)
                                            _prop2 = np.linalg.norm(_speed2)

                                            _dir1 = _speed1 / _prop1
                                            _mob.set_dir(_dir1)
                                            _mob.set_speed(
                                                np.array(
                                                    [_prop1, _mob.speed[1]]))

                                            _dir2 = _speed2 / _prop2
                                            _collider.set_dir(_dir2)
                                            _collider.set_speed(
                                                np.array([
                                                    _prop2, _collider.speed[1]
                                                ]))

                                        # SET DAMAGE
                                        if _mob.is_alive:
                                            _mob.set_damage(_collider.damage)
                                            if _mob.type == ModelType.SHIP_MODEL and not _mob.is_alive:
                                                _party[PartyKey.
                                                       KEY_DEAD_POOL].append(
                                                           _mob.name)
                                        if _collider.is_alive:
                                            _collider.set_damage(_mob.damage)
                                            if _collider.type == ModelType.SHIP_MODEL and not _collider.is_alive:
                                                _party[PartyKey.
                                                       KEY_DEAD_POOL].append(
                                                           _collider.name)

            except Exception as e:
                print('> [ERR] {} | {}:{}'.format(_service_name,
                                                  type(e).__name__, e))
                traceback.print_exc()

            _end = time.time()
            _run_time = SERVICE_REAL_TIME_PERIOD_S - (_end - _begin)
            if _run_time > 0:
                QThread.currentThread().msleep(int(_run_time * 1000))
        print('> {} ended'.format(_service_name))