diff options
Diffstat (limited to 'examples/async/eratosthenes/eratosthenes_asyncio.py')
-rw-r--r-- | examples/async/eratosthenes/eratosthenes_asyncio.py | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/examples/async/eratosthenes/eratosthenes_asyncio.py b/examples/async/eratosthenes/eratosthenes_asyncio.py new file mode 100644 index 000000000..c5d7fc2fe --- /dev/null +++ b/examples/async/eratosthenes/eratosthenes_asyncio.py @@ -0,0 +1,134 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +from PySide6.QtCore import (Qt, QObject, Signal, Slot) +from PySide6.QtGui import (QColor, QFont, QPalette) +from PySide6.QtWidgets import (QApplication, QGridLayout, QLabel, QMainWindow, QVBoxLayout, QWidget) + +import PySide6.QtAsyncio as QtAsyncio + +import asyncio +import sys +from random import randint + + +class MainWindow(QMainWindow): + + set_num = Signal(int, QColor) + + def __init__(self, rows, cols): + super().__init__() + + self.rows = rows + self.cols = cols + + widget_central = QWidget() + self.setCentralWidget(widget_central) + + layout_outer = QVBoxLayout(widget_central) + + self.widget_outer_text = QLabel() + font = QFont() + font.setPointSize(14) + self.widget_outer_text.setFont(font) + layout_outer.addWidget(self.widget_outer_text, alignment=Qt.AlignmentFlag.AlignCenter) + + widget_inner_grid = QWidget() + layout_outer.addWidget(widget_inner_grid, alignment=Qt.AlignmentFlag.AlignCenter) + + self.layout_inner_grid = QGridLayout(widget_inner_grid) + k = 1 + for i in range(self.rows): + for j in range(self.cols): + box = QLabel(f"{k}") + self.layout_inner_grid.addWidget(box, i, j, Qt.AlignmentFlag.AlignCenter) + k += 1 + + self.set_num.connect(self.set_num_handler) + + @Slot(int, QColor) + def set_num_handler(self, i, color): + row = int((i - 1) / self.cols) + col = (i - 1) - (row * self.cols) + widget = self.layout_inner_grid.itemAtPosition(row, col).widget() + + font = QFont() + font.setWeight(QFont.Bold) + palette = QPalette() + palette.setColor(QPalette.WindowText, color) + widget.setFont(font) + widget.setPalette(palette) + + +class Eratosthenes(QObject): + + """ This Sieve of Eratosthenes runs on a configurable tick (default + 0.1 seconds). At each tick, a new subroutine will be created + that will check multiples of the next prime number. Each of + these subroutines also operates on the same tick. """ + + def __init__(self, num, window, tick=0.1): + super().__init__() + self.num = num + self.sieve = [True] * self.num + self.base = 0 + self.window = window + self.tick = tick + self.coroutines = [] + self.done = False + self.loop = None + + def get_tick(self): + return self.loop.time() + self.tick + + async def start(self): + self.loop = asyncio.get_event_loop() + asyncio.create_task(self.update_text()) + while self.base <= self.num / 2: + await asyncio.sleep(self.tick) + for i in range(self.base + 1, self.num): + if self.sieve[i]: + self.base = i + break + asyncio.create_task(self.mark_number(self.base + 1)) + while sum(self.coroutines) > 0: + await asyncio.sleep(self.tick) + self.done = True + + async def mark_number(self, base): + id = len(self.coroutines) + self.coroutines.append(1) + color = QColor(randint(64, 192), randint(64, 192), randint(64, 192)) + for i in range(2 * base, self.num + 1, base): + if self.sieve[i - 1]: + self.sieve[i - 1] = False + self.window.set_num.emit(i, color) + await asyncio.sleep(self.tick) + self.coroutines[id] = 0 + + async def update_text(self): + while not self.done: + await asyncio.sleep(self.tick) + if int(self.loop.time() + self.tick) % 2: + text = "⚙️ ...Calculating prime numbers... ⚙️" + else: + text = "👩💻 ...Hacking the universe... 👩💻" + self.window.widget_outer_text.setText(text) + + self.window.widget_outer_text.setText( + "🥳 Congratulations! You found all the prime numbers and solved mathematics. 🥳" + ) + + +if __name__ == "__main__": + rows = 40 + cols = 40 + num = rows * cols + + app = QApplication(sys.argv) + main_window = MainWindow(rows, cols) + eratosthenes = Eratosthenes(num, main_window) + + main_window.show() + + QtAsyncio.run(eratosthenes.start(), handle_sigint=True) |