diff --git a/pictures/non-reflection.gif b/pictures/non-reflection.gif new file mode 100644 index 0000000..24585b2 Binary files /dev/null and b/pictures/non-reflection.gif differ diff --git a/swarm/manager.py b/swarm/manager.py index e0f994f..2263bcd 100644 --- a/swarm/manager.py +++ b/swarm/manager.py @@ -24,6 +24,7 @@ class Animation(NamedTuple): y: int frames: list[Image.Image] spf: float + offset: int = 0 OFFSET_STATE = 0 @@ -156,6 +157,7 @@ class Manager: for frame in ImageSequence.Iterator(anim) ], elem.get("spf", 10), + elem.get("offset", 0) ) elif elem["type"] == "image": with Image.open(elem["path"]).convert("LA") as im: @@ -330,7 +332,7 @@ class Manager: im.save("avoid.png") print(f"# Animations {len(self.animations)}") for anim in self.animations: - frame = int(time.time() / anim.spf) % len(anim.frames) + frame = int(time.time() / anim.spf + anim.offset) % len(anim.frames) print( str.format( "X: {:4d} Y: {:4d} Frames: {:3d} S/F: {:4.1f} Frame: {:d}", @@ -468,9 +470,9 @@ class Manager: return im.convert("LA") def put_animation( - self, x: int, y: int, frames: list[Image.Image], spf: float = 10 + self, x: int, y: int, frames: list[Image.Image], spf: float = 10, offset: int = 0 ): - self.animations.append(Animation(x, y, frames, spf)) + self.animations.append(Animation(x, y, frames, spf, offset)) def get_font( self, font_name: str, font_size: int diff --git a/swarm/settings.json b/swarm/settings.json index 5d0dd90..75ba9f6 100644 --- a/swarm/settings.json +++ b/swarm/settings.json @@ -47,25 +47,11 @@ }, { "type": "animation", - "path": "../pictures/hat_kid.gif", - "spf": 30, - "x": 470, - "y": 300, - "w": 56, - "h": 130 - }, - { - "type": "image", - "x": 190, - "y": 30, - "path": "../pictures/af.png" - }, - { - "type": "animation", - "x": 70, - "y": 50, - "path": "../pictures/lagtrain.gif", - "spf": 30 + "path": "../pictures/non-reflection.gif", + "x": 300, + "y": 40, + "spf": 15, + "offset": -822 } ] } diff --git a/swarm/worker.py b/swarm/worker.py index 8bb94b1..fc33f2a 100644 --- a/swarm/worker.py +++ b/swarm/worker.py @@ -26,6 +26,7 @@ class WorkerManager: self.shmem_name = shmem_name self.base = "https://onemillioncheckboxes.com" self.delay = 0.25 + self.batch_size = 7 self.queue: asyncio.Queue[int] = asyncio.Queue(128) self.n_toggles = 0 @@ -37,10 +38,12 @@ class WorkerManager: async def queue_manager(self): offset = random.randint(0, 1000000) + matrixX = [ 0, 2, 2, 0, 1, 3, 3, 1, 1, 3, 3, 1, 0, 2, 2, 0 ] + matrixY = [ 0, 2, 0, 2, 1, 3, 1, 3, 0, 2, 0, 2, 1, 3, 1, 3 ] while True: - for oy in [0, 2, 1, 3]: + for ox, oy in zip(matrixX, matrixY): for y in range(oy, 1000, 4): - for x in range(1000): + for x in range(ox, 1000, 4): index = (x + y * 1000 + offset) % 1000000 byte, bit = index >> 3, index & 7 mask = 0x80 >> bit @@ -55,7 +58,7 @@ class WorkerManager: self.shmem.buf[OFFSET_STATE + byte] & mask ): await self.queue.put(index) - await asyncio.sleep(0.01) + await asyncio.sleep(0.001) async def writer(self, bot_index: int, proxy: Optional[str] = None): connector = ProxyConnector.from_url(proxy) if proxy else None @@ -69,7 +72,9 @@ class WorkerManager: self._restarts[bot_index] += 1 cookie = bot_index, self._restarts[bot_index] self.workers.add(cookie) + try: + batch = 0 while sio.connected: index = await self.queue.get() byte, bit = index >> 3, index & 7 @@ -86,12 +91,13 @@ class WorkerManager: if (self.shmem.buf[OFFSET_CANVAS + byte] & mask) != ( self.shmem.buf[OFFSET_STATE + byte] & mask ): - byte, bit = divmod(index, 8) - self.n_toggles += 1 - self.shmem.buf[OFFSET_STATE + byte] ^= 0x80 >> bit await sio.emit("toggle_bit", {"index": index}) + self.n_toggles += 1 self.queue.task_done() - await asyncio.sleep(self.delay) + batch += 1 + if batch >= self.batch_size: + await asyncio.sleep(self.delay) + batch = 0 else: self.miss_state += 1 finally: @@ -111,7 +117,7 @@ class WorkerManager: print() print(f"Workers: {len(self.workers)} {self.workers}") print(f"Queue size: {self.queue.qsize()}/{self.queue.maxsize}") - print(f"Toggles: {self.n_toggles / diff:.2f}/s") + print(f"Toggles: {self.n_toggles / diff:.2f}/s EST: {len(self.workers) / self.delay}") print(f"Misses: A:{self.miss_avoid} M:{self.miss_mask} S:{self.miss_state}") print(f"Q: {self.queue}") @@ -124,8 +130,7 @@ class WorkerManager: return self async def __aexit__(self, a, b, c): - print("Closing shmem") - self.shmem.close() + pass async def main(config_path: str = "worker.json", *_): @@ -137,6 +142,7 @@ async def main(config_path: str = "worker.json", *_): async with WorkerManager(config.get("shmem", "omcb-bot")) as mgr: mgr.delay = config.get("delay", mgr.delay) + mgr.batch_size = config.get("batch", mgr.batch_size) workers = [] if proxies := config.get("proxy", []):