mirror of
				https://github.com/osmarks/random-stuff
				synced 2025-10-31 13:53:01 +00:00 
			
		
		
		
	declassify some projects
This commit is contained in:
		
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +1,3 @@ | |||||||
| out.wav | out.wav | ||||||
|  | */target/* | ||||||
|  | code-guessing/analytics/people | ||||||
							
								
								
									
										12
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
									
									
									
									
								
							| @@ -39,4 +39,14 @@ This comes with absolutely no guarantee of support or correct function, although | |||||||
| * `length_terminated_strings.c` - a revolution in computer science, combining the efficient `strlen` of null-terminated strings with the... inclusion of length? of length-prefixed/fat-pointer strings. A length-terminated string has its length at the *end*, occupying 1 to 8 bytes. To find its length, simply traverse the string until the data at the end matches the length traversed so far. Yes, this implementation might slightly have a bit of undefined behaviour. | * `length_terminated_strings.c` - a revolution in computer science, combining the efficient `strlen` of null-terminated strings with the... inclusion of length? of length-prefixed/fat-pointer strings. A length-terminated string has its length at the *end*, occupying 1 to 8 bytes. To find its length, simply traverse the string until the data at the end matches the length traversed so far. Yes, this implementation might slightly have a bit of undefined behaviour. | ||||||
| * `discord-message-dump.py`, which reads a GDPR data dump from Discord and copies all the messages in public channels to a CSV file. I used this for training of a GPT-2 instance on my messages (available on request). | * `discord-message-dump.py`, which reads a GDPR data dump from Discord and copies all the messages in public channels to a CSV file. I used this for training of a GPT-2 instance on my messages (available on request). | ||||||
| * `spudnet-http.py` - connect to the SPUDNET backend underlying [PotatOS](https://git.osmarks.net/osmarks/potatOS/)'s ~~backdoors~~ remote debugging system via the convenient new HTTP long-polling-based API. | * `spudnet-http.py` - connect to the SPUDNET backend underlying [PotatOS](https://git.osmarks.net/osmarks/potatOS/)'s ~~backdoors~~ remote debugging system via the convenient new HTTP long-polling-based API. | ||||||
| * `fractalart-rs` - [this](https://github.com/TomSmeets/FractalArt/) in Rust and faster, see its own README for more details. | * `fractalart-rs` - [this](https://github.com/TomSmeets/FractalArt/) in Rust and faster, see its own README for more details. | ||||||
|  | * `arbtt_wayland_toplevel.py` - interfaces [arbtt](https://arbtt.nomeata.de/) with Wayland foreign toplevel protocol and idle notifications. | ||||||
|  | * `fractalize_image.py` - used for making a profile picture for someone once. | ||||||
|  | * `goose2function.py` - converts goose neck profiles extracted from images of geese into activation functions for machine learning. | ||||||
|  | * `histretention.py` - dump Firefox `places.sqlite3` into a separate database (Firefox clears out old history internally for performance reasons or something like that) for later search. | ||||||
|  | * `memeticize.py` - the script I use to process memes from a large directory of heterogenous files. | ||||||
|  | * `rng_trainer.html` - a very unfinished attempt to implement a paper I found on training high-quality random number generation. | ||||||
|  | * `smtp2rss.py` - bridge SMTP (inbound emails) to RSS. | ||||||
|  | * `yearbox.html` - DokuWiki-type yearbox prototype for Minoteaur (I think this actually contains an off-by-one error somewhere; it isn't what's actually in use). | ||||||
|  | * `arbitrary-politics-graphs` - all you need to run your own election campaign. | ||||||
|  | * `heavbiome` - some work on biome generation with Perlin noise. | ||||||
							
								
								
									
										
											BIN
										
									
								
								arbitrary-politics-graphs/g1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								arbitrary-politics-graphs/g1.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 24 KiB | 
							
								
								
									
										
											BIN
										
									
								
								arbitrary-politics-graphs/g2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								arbitrary-politics-graphs/g2.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 14 KiB | 
							
								
								
									
										
											BIN
										
									
								
								arbitrary-politics-graphs/g3.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								arbitrary-politics-graphs/g3.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 26 KiB | 
							
								
								
									
										
											BIN
										
									
								
								arbitrary-politics-graphs/g4.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								arbitrary-politics-graphs/g4.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 21 KiB | 
							
								
								
									
										40
									
								
								arbitrary-politics-graphs/test.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								arbitrary-politics-graphs/test.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <style> | ||||||
|  |     .outer { | ||||||
|  |         display: flex; | ||||||
|  |     } | ||||||
|  |     .inner { | ||||||
|  |         width: 50%; | ||||||
|  |     } | ||||||
|  |     img { | ||||||
|  |         width: 30em; | ||||||
|  |     } | ||||||
|  |     h1 { | ||||||
|  |         font-style: italic; | ||||||
|  |         font-size: 4em; | ||||||
|  |         font-weight: 400; | ||||||
|  |         margin-top: 0; | ||||||
|  |     } | ||||||
|  |     h2 { | ||||||
|  |         font-style: italic; | ||||||
|  |         margin-top: 0; | ||||||
|  |         font-size: 3em; | ||||||
|  |         font-weight: 400; | ||||||
|  |     } | ||||||
|  | </style> | ||||||
|  | <div class="outer"> | ||||||
|  |     <div class="inner"> | ||||||
|  |         <h1>if I am elected</h1> | ||||||
|  |         <h2>good things</h2> | ||||||
|  |         <img src="g1.png"> | ||||||
|  |         <h2>bad things</h2> | ||||||
|  |         <img src="g2.png"> | ||||||
|  |     </div> | ||||||
|  |     <div class="inner"> | ||||||
|  |         <h1>otherwise</h1> | ||||||
|  |         <h2>good things</h2> | ||||||
|  |         <img src="g4.png"> | ||||||
|  |         <h2>bad things</h2> | ||||||
|  |         <img src="g3.png"> | ||||||
|  |     </div> | ||||||
|  | </div> | ||||||
							
								
								
									
										128
									
								
								arbtt_wayland_toplevel.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										128
									
								
								arbtt_wayland_toplevel.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,128 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | from functools import partial | ||||||
|  | from datetime import datetime, timezone | ||||||
|  | from wl_framework.network.connection import WaylandConnection | ||||||
|  | from wl_framework.protocols.base import UnsupportedProtocolError | ||||||
|  | from wl_framework.protocols.foreign_toplevel import ForeignTopLevel | ||||||
|  | from wl_framework.protocols.data_control import DataControl | ||||||
|  | from wl_framework.protocols.idle_notify import ( IdleNotifyManager, IdleNotifier as _IdleNotifier ) | ||||||
|  | import asyncio.subprocess as subprocess | ||||||
|  | import orjson | ||||||
|  |  | ||||||
|  | class ForeignTopLevelMonitor(ForeignTopLevel): | ||||||
|  | 	def __init__(self, *args, **kwargs): | ||||||
|  | 		self.tlwindows = {} | ||||||
|  | 		super().__init__(*args, **kwargs) | ||||||
|  |  | ||||||
|  | 	def on_toplevel_created(self, toplevel): | ||||||
|  | 		self.tlwindows[toplevel.obj_id] = {} | ||||||
|  |  | ||||||
|  | 	def on_toplevel_synced(self, toplevel): | ||||||
|  | 		self.tlwindows[toplevel.obj_id]["app_id"] = toplevel.app_id | ||||||
|  | 		self.tlwindows[toplevel.obj_id]["title"] = toplevel.title | ||||||
|  | 		self.tlwindows[toplevel.obj_id]["states"] = toplevel.states | ||||||
|  | 		self.tlwindows[toplevel.obj_id]["outputs"] = { x.name for x in toplevel.outputs } | ||||||
|  |  | ||||||
|  | 	def on_toplevel_closed(self, toplevel): | ||||||
|  | 		del self.tlwindows[toplevel.obj_id] | ||||||
|  |  | ||||||
|  | # not actually using this | ||||||
|  | class ClipboardMonitor(DataControl): | ||||||
|  |  | ||||||
|  | 	def on_new_selection(self, offer): | ||||||
|  | 		self._print_selection(offer) | ||||||
|  | 		self._receive(offer) | ||||||
|  |  | ||||||
|  | 	def on_new_primary_selection(self, offer): | ||||||
|  | 		self._print_selection(offer, is_primary=True) | ||||||
|  | 		self._receive(offer, is_primary=True) | ||||||
|  |  | ||||||
|  | 	# Internal | ||||||
|  | 	def _receive(self, offer, is_primary=False): | ||||||
|  | 		if offer is None: | ||||||
|  | 			return | ||||||
|  | 		for mime in ( | ||||||
|  | 			'text/plain;charset=utf-8', | ||||||
|  | 			'UTF8_STRING', | ||||||
|  | 		): | ||||||
|  | 			if mime in offer.get_mime_types(): | ||||||
|  | 				offer.receive(mime, partial(self._on_received, is_primary=is_primary)) | ||||||
|  | 				break | ||||||
|  |  | ||||||
|  | 	def _print_selection(self, offer, is_primary=False): | ||||||
|  | 		_selection = 'primary' if is_primary else 'main' | ||||||
|  | 		if offer is None: | ||||||
|  | 			self.log(f"{_selection.capitalize()} selection cleared") | ||||||
|  | 			return | ||||||
|  | 		self.log(f"New {_selection} selection offers:") | ||||||
|  | 		for mime_type in offer.get_mime_types(): | ||||||
|  | 			self.log(f"  {mime_type}") | ||||||
|  |  | ||||||
|  | 	def _on_received(self, mime_type, data, is_primary=False): | ||||||
|  | 		if data: | ||||||
|  | 			data = data.decode('utf-8') | ||||||
|  | 		self.log(f"Received {' primary' if is_primary else 'main'} selection: '{data}'") | ||||||
|  |  | ||||||
|  | class IdleNotifier(_IdleNotifier): | ||||||
|  | 	def __init__(self, *args, **kwargs): | ||||||
|  | 		super().__init__(*args, **kwargs) | ||||||
|  | 		self.idle_start = None | ||||||
|  |  | ||||||
|  | 	def on_idle(self): | ||||||
|  | 		self.idle_start = datetime.now(tz=timezone.utc) | ||||||
|  |  | ||||||
|  | 	def on_resume(self): | ||||||
|  | 		self.idle_start = None | ||||||
|  |  | ||||||
|  | class WlMonitor(WaylandConnection): | ||||||
|  | 	def on_initial_sync(self, data): | ||||||
|  | 		super().on_initial_sync(data) | ||||||
|  | 		self.toplevels = ForeignTopLevelMonitor(self) | ||||||
|  | 		#self.clipboard = ClipboardMonitor(self) | ||||||
|  | 		self.idle = IdleNotifyManager(self, IdleNotifier) | ||||||
|  | 		self.idle_notifier = self.idle.get_idle_notifier(0, self.display.seat) | ||||||
|  |  | ||||||
|  | INTERVAL_MS = 60_000 | ||||||
|  |  | ||||||
|  | def generate_log_entry(wl: WlMonitor()): | ||||||
|  | 	entry = {"desktop": ""} | ||||||
|  | 	now = datetime.now(timezone.utc) | ||||||
|  | 	entry["date"] = now.isoformat() | ||||||
|  | 	entry["rate"] = INTERVAL_MS | ||||||
|  | 	if wl.idle_notifier.idle_start: | ||||||
|  | 		entry["inactive"] = int((now.timestamp() - wl.idle_notifier.idle_start.timestamp()) * 1000) | ||||||
|  | 	else: | ||||||
|  | 		entry["inactive"] = 0 | ||||||
|  | 	def arbitrary_output(window): | ||||||
|  | 		s = window["outputs"] | ||||||
|  | 		try: | ||||||
|  | 			return s.pop() | ||||||
|  | 		except KeyError: | ||||||
|  | 			return "" | ||||||
|  | 	entry["windows"] = [ { "title": x["title"], "program": x["app_id"], "active": "activated" in x["states"], "hidden": "minimized" in x["states"] } for x in wl.toplevels.tlwindows.values() ] | ||||||
|  | 	return entry | ||||||
|  |  | ||||||
|  | if __name__ == '__main__': | ||||||
|  | 	import sys | ||||||
|  |  | ||||||
|  | 	import asyncio | ||||||
|  | 	from wl_framework.loop_integrations import AsyncIOIntegration | ||||||
|  |  | ||||||
|  | 	async def init(): | ||||||
|  | 		arbtt_importer = await subprocess.create_subprocess_exec("arbtt-import", "-a", "-t", "JSON", stdin=subprocess.PIPE) | ||||||
|  | 		loop = AsyncIOIntegration() | ||||||
|  | 		try: | ||||||
|  | 			app = WlMonitor(eventloop_integration=loop) | ||||||
|  | 			await asyncio.sleep(1) | ||||||
|  | 			while True: | ||||||
|  | 				entry = generate_log_entry(app) | ||||||
|  | 				arbtt_importer.stdin.write(orjson.dumps(entry)) | ||||||
|  | 				arbtt_importer.stdin.write(b"\n") | ||||||
|  | 				await asyncio.sleep(INTERVAL_MS / 1000) | ||||||
|  | 		except RuntimeError as e: | ||||||
|  | 			print(e) | ||||||
|  | 			sys.exit(1) | ||||||
|  | 	try: | ||||||
|  | 		asyncio.run(init()) | ||||||
|  | 	except KeyboardInterrupt: | ||||||
|  | 		print() | ||||||
							
								
								
									
										27
									
								
								beep.py
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								beep.py
									
									
									
									
									
								
							| @@ -56,10 +56,27 @@ def save_wav(file_name): | |||||||
|     wav_file.close() |     wav_file.close() | ||||||
|     return |     return | ||||||
|  |  | ||||||
|  | BAD_INTERVALS = [6, 8, 10, 11, 13] | ||||||
|  | NOTE_FACTOR = pow(2, 1/12) | ||||||
|  | LOG_NOTE_FACTOR = math.log(NOTE_FACTOR) | ||||||
|  | BASE = 440 | ||||||
|  | MIN = math.ceil(math.log(200/440) / LOG_NOTE_FACTOR) | ||||||
|  | MAX = math.floor(math.log(2000/440) / LOG_NOTE_FACTOR) | ||||||
|  |  | ||||||
| import random | import random | ||||||
| freq = 6 | for i in range(10): | ||||||
| for i in range(160): |     """ | ||||||
|     append_sinewave(volume=1.0, freq=math.exp(freq), duration_milliseconds=50) |     for i in range(3): | ||||||
|     freq += random.uniform(-0.2, 0.2) |         append_sinewave(800, 100) | ||||||
|     freq = max(4.5, min(freq, 9)) |         append_silence(100) | ||||||
|  |     append_sinewave(600, 500) | ||||||
|  |     append_silence() | ||||||
|  |     """ | ||||||
|  |     note = random.randint(MIN, MAX) | ||||||
|  |     while MIN <= note <= MAX: | ||||||
|  |         interval = random.choice(BAD_INTERVALS) | ||||||
|  |         time = random.randint(50, 1000) | ||||||
|  |         append_sinewave(BASE * pow(NOTE_FACTOR, note), time) | ||||||
|  |         note += interval if random.choice((True, False)) else -interval | ||||||
|  |      | ||||||
| save_wav("output.wav") | save_wav("output.wav") | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								code-guessing/analytics/download_6_to_13.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								code-guessing/analytics/download_6_to_13.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | from bs4 import BeautifulSoup | ||||||
|  | import requests | ||||||
|  | import os | ||||||
|  | import os.path | ||||||
|  |  | ||||||
|  | people = { | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | for round_id in range(6, 13): | ||||||
|  |     print("round", round_id) | ||||||
|  |     m = BeautifulSoup(requests.get(f"https://cg.esolangs.gay/{round_id}/").text, features="lxml") | ||||||
|  |     for file_link in m.select("details > summary > a"): | ||||||
|  |         name = file_link.parent.parent.previous_sibling.previous_sibling.previous_sibling.previous_sibling | ||||||
|  |         if "impersonating" in name.text: | ||||||
|  |             name = name.previous_sibling.previous_sibling | ||||||
|  |         assert "written by" in name.text, f"oh no {name.text}" | ||||||
|  |         name = name.text.split("written by ")[-1] | ||||||
|  |         name = people.get(name, name).lower() | ||||||
|  |         href = file_link.attrs["href"] | ||||||
|  |         filename = str(round_id) + "-" + href.split(f"/{round_id}/")[-1] | ||||||
|  |         full_href = f"https://cg.esolangs.gay{href}" | ||||||
|  |         os.makedirs(os.path.join("people", name), exist_ok=True) | ||||||
|  |         with open(os.path.join("people", name, filename), "wb") as f: | ||||||
|  |             with requests.get(full_href, stream=True) as r: | ||||||
|  |                 r.raise_for_status() | ||||||
|  |                 for chunk in r.iter_content(chunk_size=(2<<18)): | ||||||
|  |                     f.write(chunk) | ||||||
							
								
								
									
										6
									
								
								code-guessing/analytics/run.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								code-guessing/analytics/run.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | import os | ||||||
|  | import os.path | ||||||
|  |  | ||||||
|  | for person in os.listdir("people"): | ||||||
|  |     for submission in os.listdir(os.path.join("people", person)): | ||||||
|  |         print(person, submission) | ||||||
							
								
								
									
										257
									
								
								code-guessing/entry-rs/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								code-guessing/entry-rs/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,257 @@ | |||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "bitflags" | ||||||
|  | version = "1.3.2" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "cfg-if" | ||||||
|  | version = "1.0.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "entry-rs" | ||||||
|  | version = "0.1.0" | ||||||
|  | dependencies = [ | ||||||
|  |  "pyo3", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "indoc" | ||||||
|  | version = "0.3.6" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" | ||||||
|  | dependencies = [ | ||||||
|  |  "indoc-impl", | ||||||
|  |  "proc-macro-hack", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "indoc-impl" | ||||||
|  | version = "0.3.6" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" | ||||||
|  | dependencies = [ | ||||||
|  |  "proc-macro-hack", | ||||||
|  |  "proc-macro2", | ||||||
|  |  "quote", | ||||||
|  |  "syn", | ||||||
|  |  "unindent", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "instant" | ||||||
|  | version = "0.1.12" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" | ||||||
|  | dependencies = [ | ||||||
|  |  "cfg-if", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "libc" | ||||||
|  | version = "0.2.117" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "lock_api" | ||||||
|  | version = "0.4.6" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" | ||||||
|  | dependencies = [ | ||||||
|  |  "scopeguard", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "once_cell" | ||||||
|  | version = "1.9.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "parking_lot" | ||||||
|  | version = "0.11.2" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" | ||||||
|  | dependencies = [ | ||||||
|  |  "instant", | ||||||
|  |  "lock_api", | ||||||
|  |  "parking_lot_core", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "parking_lot_core" | ||||||
|  | version = "0.8.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" | ||||||
|  | dependencies = [ | ||||||
|  |  "cfg-if", | ||||||
|  |  "instant", | ||||||
|  |  "libc", | ||||||
|  |  "redox_syscall", | ||||||
|  |  "smallvec", | ||||||
|  |  "winapi", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "paste" | ||||||
|  | version = "0.1.18" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" | ||||||
|  | dependencies = [ | ||||||
|  |  "paste-impl", | ||||||
|  |  "proc-macro-hack", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "paste-impl" | ||||||
|  | version = "0.1.18" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" | ||||||
|  | dependencies = [ | ||||||
|  |  "proc-macro-hack", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "proc-macro-hack" | ||||||
|  | version = "0.5.19" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "proc-macro2" | ||||||
|  | version = "1.0.36" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" | ||||||
|  | dependencies = [ | ||||||
|  |  "unicode-xid", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "pyo3" | ||||||
|  | version = "0.14.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "35100f9347670a566a67aa623369293703322bb9db77d99d7df7313b575ae0c8" | ||||||
|  | dependencies = [ | ||||||
|  |  "cfg-if", | ||||||
|  |  "indoc", | ||||||
|  |  "libc", | ||||||
|  |  "parking_lot", | ||||||
|  |  "paste", | ||||||
|  |  "pyo3-build-config", | ||||||
|  |  "pyo3-macros", | ||||||
|  |  "unindent", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "pyo3-build-config" | ||||||
|  | version = "0.14.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "d12961738cacbd7f91b7c43bc25cfeeaa2698ad07a04b3be0aa88b950865738f" | ||||||
|  | dependencies = [ | ||||||
|  |  "once_cell", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "pyo3-macros" | ||||||
|  | version = "0.14.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "fc0bc5215d704824dfddddc03f93cb572e1155c68b6761c37005e1c288808ea8" | ||||||
|  | dependencies = [ | ||||||
|  |  "pyo3-macros-backend", | ||||||
|  |  "quote", | ||||||
|  |  "syn", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "pyo3-macros-backend" | ||||||
|  | version = "0.14.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "71623fc593224afaab918aa3afcaf86ed2f43d34f6afde7f3922608f253240df" | ||||||
|  | dependencies = [ | ||||||
|  |  "proc-macro2", | ||||||
|  |  "pyo3-build-config", | ||||||
|  |  "quote", | ||||||
|  |  "syn", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "quote" | ||||||
|  | version = "1.0.15" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" | ||||||
|  | dependencies = [ | ||||||
|  |  "proc-macro2", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "redox_syscall" | ||||||
|  | version = "0.2.10" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" | ||||||
|  | dependencies = [ | ||||||
|  |  "bitflags", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "scopeguard" | ||||||
|  | version = "1.1.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "smallvec" | ||||||
|  | version = "1.8.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "syn" | ||||||
|  | version = "1.0.86" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" | ||||||
|  | dependencies = [ | ||||||
|  |  "proc-macro2", | ||||||
|  |  "quote", | ||||||
|  |  "unicode-xid", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "unicode-xid" | ||||||
|  | version = "0.2.2" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "unindent" | ||||||
|  | version = "0.1.7" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "winapi" | ||||||
|  | version = "0.3.9" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" | ||||||
|  | dependencies = [ | ||||||
|  |  "winapi-i686-pc-windows-gnu", | ||||||
|  |  "winapi-x86_64-pc-windows-gnu", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "winapi-i686-pc-windows-gnu" | ||||||
|  | version = "0.4.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "winapi-x86_64-pc-windows-gnu" | ||||||
|  | version = "0.4.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | ||||||
							
								
								
									
										13
									
								
								code-guessing/entry-rs/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								code-guessing/entry-rs/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  |  | ||||||
|  | [package] | ||||||
|  | name = "entry-rs" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  |  | ||||||
|  | [lib] | ||||||
|  | name = "entry_rs" | ||||||
|  | crate-type = ["cdylib"] | ||||||
|  |  | ||||||
|  | [dependencies.pyo3] | ||||||
|  | version = "0.14.5" | ||||||
|  | features = ["extension-module"] | ||||||
							
								
								
									
										85
									
								
								code-guessing/entry-rs/src/entry_impl.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								code-guessing/entry-rs/src/entry_impl.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | |||||||
|  | pub fn entry(s: &str) -> i32 { | ||||||
|  |     let digit = |c: u8| (c as i32) - 48; | ||||||
|  |     let mut acc = 0; | ||||||
|  |     let mut pos = 0; | ||||||
|  |     let b = s.as_bytes(); | ||||||
|  |     loop { | ||||||
|  |         match b[pos] { | ||||||
|  |             b'+' => { | ||||||
|  |                 acc += { | ||||||
|  |                     pos += 1; | ||||||
|  |                     let mut acc = 0; | ||||||
|  |                     while (pos + 1) < b.len() && (b[pos + 1] == b'/' || b[pos + 1] == b'*') { | ||||||
|  |                         println!("DIV or MUL {} {} {}", b[pos], b[pos + 1], b[pos + 2]); | ||||||
|  |                         if acc == 0 { | ||||||
|  |                             acc = digit(b[pos]) | ||||||
|  |                         } | ||||||
|  |                         if b[pos + 1] == b'/' { | ||||||
|  |                             acc /= digit(b[pos + 2]) | ||||||
|  |                         } else { | ||||||
|  |                             acc *= digit(b[pos + 2]) | ||||||
|  |                         } | ||||||
|  |                         pos += 2; | ||||||
|  |                     } | ||||||
|  |                     if acc == 0 { | ||||||
|  |                         digit(b[pos]) | ||||||
|  |                     } else { | ||||||
|  |                         acc | ||||||
|  |                     } | ||||||
|  |                 }; | ||||||
|  |                 pos += 1; | ||||||
|  |             }, | ||||||
|  |             b'-' => { | ||||||
|  |                 acc -= { | ||||||
|  |                     pos += 1; | ||||||
|  |                     let mut acc = -1; | ||||||
|  |                     while (pos + 1) < b.len() && (b[pos + 1] == b'/' || b[pos + 1] == b'*') { | ||||||
|  |                         println!("DIV or MUL {} {} {}", b[pos], b[pos + 1], b[pos + 2]); | ||||||
|  |                         if acc == -1 { | ||||||
|  |                             acc = digit(b[pos]) | ||||||
|  |                         } | ||||||
|  |                         if b[pos + 1] == b'/' { | ||||||
|  |                             acc /= digit(b[pos + 2]) | ||||||
|  |                         } else { | ||||||
|  |                             acc *= digit(b[pos + 2]) | ||||||
|  |                         } | ||||||
|  |                         pos += 2; | ||||||
|  |                     } | ||||||
|  |                     if acc == -1 { | ||||||
|  |                         digit(b[pos]) | ||||||
|  |                     } else { | ||||||
|  |                         acc | ||||||
|  |                     } | ||||||
|  |                 }; | ||||||
|  |                 pos += 1; | ||||||
|  |             }, | ||||||
|  |             x => { | ||||||
|  |                 acc += { | ||||||
|  |                     let mut acc = 0; | ||||||
|  |                     while (pos + 1) < b.len() && (b[pos + 1] == b'/' || b[pos + 1] == b'*') { | ||||||
|  |                         println!("DIV or MUL {} {} {}", b[pos], b[pos + 1], b[pos + 2]); | ||||||
|  |                         if acc == 0 { | ||||||
|  |                             acc = digit(b[pos]) | ||||||
|  |                         } | ||||||
|  |                         if b[pos + 1] == b'/' { | ||||||
|  |                             acc /= digit(b[pos + 2]) | ||||||
|  |                         } else { | ||||||
|  |                             acc *= digit(b[pos + 2]) | ||||||
|  |                         } | ||||||
|  |                         pos += 2; | ||||||
|  |                     } | ||||||
|  |                     if acc == 0 { | ||||||
|  |                         digit(b[pos]) | ||||||
|  |                     } else { | ||||||
|  |                         acc | ||||||
|  |                     } | ||||||
|  |                 }; | ||||||
|  |                 pos += 1 | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if pos >= b.len() { | ||||||
|  |             break | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     acc | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								code-guessing/entry-rs/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								code-guessing/entry-rs/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  |  | ||||||
|  | use pyo3::prelude::*; | ||||||
|  |  | ||||||
|  | mod entry_impl; | ||||||
|  | use entry_impl::entry; | ||||||
|  |  | ||||||
|  | #[pyfunction] | ||||||
|  | fn wrapped_entry(s: &str) -> PyResult<i32> { | ||||||
|  |     Ok(entry(s)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[pymodule] | ||||||
|  | fn entry_rs(_py: Python, m: &PyModule) -> PyResult<()> { | ||||||
|  |     m.add_function(wrap_pyfunction!(wrapped_entry, m)?)?; | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
							
								
								
									
										53
									
								
								code-guessing/gif.s
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								code-guessing/gif.s
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | ; a hand-made GIF containing valid JavaScript code | ||||||
|  | ; abusing header to start a JavaScript comment | ||||||
|  |  | ||||||
|  | ; inspired by Saumil Shah's Deadly Pixels presentation | ||||||
|  |  | ||||||
|  | ; Ange Albertini, BSD Licence 2013 | ||||||
|  |  | ||||||
|  | ; yamal gifjs.asm -o img.gif | ||||||
|  |  | ||||||
|  | WIDTH equ 10799 ; equivalent to 2f2a, which is '/*' in ASCII, thus starting an opening comment | ||||||
|  |  | ||||||
|  | HEIGHT equ 10799 ; just to make it easier to spot | ||||||
|  |  | ||||||
|  | db 'GIF89a' | ||||||
|  |     dw WIDTH, HEIGHT | ||||||
|  |  | ||||||
|  | db 0 ; GCT | ||||||
|  |     db -1 ;  background color | ||||||
|  |     db 0 ; default aspect ratio | ||||||
|  |     ;db 0fch, 0feh, 0fch | ||||||
|  |     ;times COLORS db 0, 0, 0 | ||||||
|  |  | ||||||
|  | ; no need of Graphic Control Extension | ||||||
|  |  ; db 21h, 0f9h | ||||||
|  |  ; db GCESIZE ; size | ||||||
|  |  ; gce_start: | ||||||
|  |  ;     db 0 ; transparent background | ||||||
|  |  ;     dw 0 ; delay for anim | ||||||
|  |  ;     db 0 ; other transparent | ||||||
|  |  ; GCESIZE equ $ - gce_start | ||||||
|  |  ;     db 0 ; end of GCE | ||||||
|  |  | ||||||
|  | db 02ch ; Image descriptor | ||||||
|  |     dw 0, 0 ; NW corner | ||||||
|  |     dw WIDTH, HEIGHT ; w/h of image | ||||||
|  |     db 0    ; color table | ||||||
|  |  | ||||||
|  | db 2 ; lzw size | ||||||
|  |  | ||||||
|  | ;db DATASIZE | ||||||
|  | ;data_start: | ||||||
|  | ;    db 00, 01, 04, 04 | ||||||
|  | ;    DATASIZE equ $ - data_start | ||||||
|  |  | ||||||
|  | db 0 | ||||||
|  | db 3bh ; GIF terminator | ||||||
|  |  | ||||||
|  | ; end of the GIF | ||||||
|  |  | ||||||
|  | db '*/'  ; closing the comment | ||||||
|  | db '=1;' ; creating a fake use of that GIF89a string | ||||||
|  |  | ||||||
|  | db 'alert("haxx");' | ||||||
							
								
								
									
										2
									
								
								code-guessing/giftest.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								code-guessing/giftest.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | <img src="./img.gif"> | ||||||
|  | <script src="./img.js"></script> | ||||||
							
								
								
									
										
											BIN
										
									
								
								code-guessing/img.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								code-guessing/img.gif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 45 B | 
							
								
								
									
										1
									
								
								code-guessing/img.js
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								code-guessing/img.js
									
									
									
									
									
										Symbolic link
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | img.gif | ||||||
							
								
								
									
										185
									
								
								code-guessing/test12.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								code-guessing/test12.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,185 @@ | |||||||
|  | import sys | ||||||
|  | import importlib | ||||||
|  | import subprocess | ||||||
|  | import ctypes | ||||||
|  | import random | ||||||
|  | import traceback | ||||||
|  | import textwrap | ||||||
|  | import json | ||||||
|  | import os | ||||||
|  | import shutil | ||||||
|  | try: | ||||||
|  |     from tqdm import tqdm, trange | ||||||
|  | except ImportError: | ||||||
|  |     print("`tqdm` not found. there will be no progress bars") | ||||||
|  |     def tqdm(x): | ||||||
|  |         return x | ||||||
|  |     trange = range | ||||||
|  |  | ||||||
|  |  | ||||||
|  | filename = sys.argv[1] | ||||||
|  |  | ||||||
|  | if filename.endswith(".py"): | ||||||
|  |     print("importing as Python...") | ||||||
|  |     module = importlib.import_module(filename.removesuffix(".py")) | ||||||
|  |     print("done.") | ||||||
|  |     try: | ||||||
|  |         entry = module.entry | ||||||
|  |     except AttributeError: | ||||||
|  |         print("module is missing entrypoint `entry`. aborting.") | ||||||
|  |         sys.exit(1) | ||||||
|  | elif filename.endswith(".c"): | ||||||
|  |     print("compiling as C with `gcc`...") | ||||||
|  |     obj = "./" + filename.removesuffix(".c") + ".so" | ||||||
|  |     rc = subprocess.call(["gcc", "-shared", "-fPIC", *sys.argv[2:], filename, "-o", obj]) | ||||||
|  |     if rc != 0: | ||||||
|  |         print("compilation failed. aborting.") | ||||||
|  |         sys.exit(rc) | ||||||
|  |     lib = ctypes.CDLL(obj) | ||||||
|  |     try: | ||||||
|  |         entry = lib.entry | ||||||
|  |     except AttributeError: | ||||||
|  |         print("library is missing entrypoint `entry`. aborting.") | ||||||
|  |         sys.exit(1) | ||||||
|  | elif filename.endswith(".rs"): | ||||||
|  |     print("compiling as Rust...") | ||||||
|  |     os.makedirs("./entry-rs/src", exist_ok=True) | ||||||
|  |     with open("./entry-rs/Cargo.toml", "w") as f: | ||||||
|  |         f.write(""" | ||||||
|  | [package] | ||||||
|  | name = "entry-rs" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  |  | ||||||
|  | [lib] | ||||||
|  | name = "entry_rs" | ||||||
|  | crate-type = ["cdylib"] | ||||||
|  |  | ||||||
|  | [dependencies.pyo3] | ||||||
|  | version = "0.14.5" | ||||||
|  | features = ["extension-module"] | ||||||
|  | """) | ||||||
|  |     with open("./entry-rs/src/lib.rs", "w") as f: | ||||||
|  |         f.write(""" | ||||||
|  | use pyo3::prelude::*; | ||||||
|  |  | ||||||
|  | mod entry_impl; | ||||||
|  | use entry_impl::entry; | ||||||
|  |  | ||||||
|  | #[pyfunction] | ||||||
|  | fn wrapped_entry(s: &str) -> PyResult<i32> { | ||||||
|  |     Ok(entry(s)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[pymodule] | ||||||
|  | fn entry_rs(_py: Python, m: &PyModule) -> PyResult<()> { | ||||||
|  |     m.add_function(wrap_pyfunction!(wrapped_entry, m)?)?; | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | """) | ||||||
|  |     shutil.copyfile(filename, "./entry-rs/src/entry_impl.rs") | ||||||
|  |     os.chdir("entry-rs") | ||||||
|  |     rc = subprocess.call(["cargo", "build", "--release"]) | ||||||
|  |     os.chdir("..") | ||||||
|  |     if rc != 0: | ||||||
|  |         print("compilation failed. aborting.") | ||||||
|  |         sys.exit(1) | ||||||
|  |     sys.path.append("./entry-rs/target/release") | ||||||
|  |     os.rename("./entry-rs/target/release/libentry_rs.so", "./entry-rs/target/release/entry_rs.so") | ||||||
|  |     module = importlib.import_module("entry_rs") | ||||||
|  |     entry = module.wrapped_entry | ||||||
|  | else: | ||||||
|  |     print("unrecognized file extension") | ||||||
|  |     sys.exit(1) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | tests = [ | ||||||
|  |     ("zero", "0", 0), | ||||||
|  |     ("add", "1+2", 3), | ||||||
|  |     ("sub", "2-1", 1), | ||||||
|  |     ("mul", "2*3", 6), | ||||||
|  |     ("div", "4/2", 2), | ||||||
|  |     ("floor", "4/3", 1), | ||||||
|  |     ("neg", "0-4", -4), | ||||||
|  |     ("chain", "4/2/2", 1), | ||||||
|  |     ("olivia", "1+7/4-0*4", 2), | ||||||
|  |     ("gollario", "4-4-4-4+8", 0) | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | print("beginning testing suite") | ||||||
|  | failures = 0 | ||||||
|  |  | ||||||
|  | for test_name, value, result in tqdm(tests): | ||||||
|  |     print(f"`{test_name}`... ", end="") | ||||||
|  |     try: | ||||||
|  |         r = entry(value) | ||||||
|  |     except BaseException: | ||||||
|  |         print("error") | ||||||
|  |         traceback.print_exc() | ||||||
|  |         print(f"in test `{test_name}`:") | ||||||
|  |         print(textwrap.indent(value, " "*2)) | ||||||
|  |         failures += 1 | ||||||
|  |         continue | ||||||
|  |     if r == result: | ||||||
|  |         print("ok") | ||||||
|  |     else: | ||||||
|  |         failures += 1 | ||||||
|  |         print("failed") | ||||||
|  |         print(f"for test `{test_name}`:") | ||||||
|  |         print(textwrap.indent(value, " "*2)) | ||||||
|  |         print(f"entry returned {r} when {result} was expected\n") | ||||||
|  | if not failures: | ||||||
|  |     print("test suite finished, all ok") | ||||||
|  | else: | ||||||
|  |     print(f"test suite finished. {failures} tests failed\n\n") | ||||||
|  |     print("skipping randomized testing because your program is clearly broken and the output from those isn't very helpful for finding bugs") | ||||||
|  |     sys.exit(2) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def gen_random_json(): | ||||||
|  |     s = random.choice("0123456789") | ||||||
|  |     for _ in range(random.randint(0, 10)): | ||||||
|  |         s += random.choice("+-*/") | ||||||
|  |         s += random.choice("0123456789") | ||||||
|  |     return s | ||||||
|  |  | ||||||
|  |  | ||||||
|  | print("beginning randomized testing.") | ||||||
|  | random_failures = 0 | ||||||
|  | for _ in trange(100): | ||||||
|  |     while True: | ||||||
|  |         j = gen_random_json() | ||||||
|  |         try: | ||||||
|  |             tr = eval(j.replace("/", "//")) | ||||||
|  |         except ZeroDivisionError: | ||||||
|  |             continue | ||||||
|  |         else: | ||||||
|  |             break | ||||||
|  |     try: | ||||||
|  |         r = entry(j) | ||||||
|  |     except BaseException: | ||||||
|  |         print("error") | ||||||
|  |         traceback.print_exc() | ||||||
|  |         print("in randomized test case:") | ||||||
|  |         print(textwrap.indent(j, " "*2)) | ||||||
|  |         random_failures += 1 | ||||||
|  |         continue | ||||||
|  |     if r != tr: | ||||||
|  |         print("randomized test case failed:") | ||||||
|  |         print(textwrap.indent(j, " "*2)) | ||||||
|  |         print(f"entry returned {r} when {tr} was expected\n") | ||||||
|  |         random_failures += 1 | ||||||
|  |  | ||||||
|  | if not random_failures: | ||||||
|  |     print("randomized testing finished. all ok\n\n") | ||||||
|  | else: | ||||||
|  |     print(f"randomized testing finished with {random_failures} failures\n\n") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | print("overall report:") | ||||||
|  | overall = failures + random_failures | ||||||
|  | if not overall: | ||||||
|  |     print("no failures detected. all seems well!") | ||||||
|  | else: | ||||||
|  |     print(f"{overall} failures detected overall. you have some bugs to fix") | ||||||
|  |     sys.exit(2) | ||||||
							
								
								
									
										14
									
								
								count_words_in_directory.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								count_words_in_directory.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | import os, sys, string | ||||||
|  |  | ||||||
|  | count = 0 | ||||||
|  | words = 0 | ||||||
|  | characters = 0 | ||||||
|  | for dirpath, dirnames, filenames in os.walk(sys.argv[1]): | ||||||
|  |     for filename in filenames: | ||||||
|  |         with open(os.path.join(dirpath, filename)) as f: | ||||||
|  |             content = f.read() | ||||||
|  |             characters += len([c for c in content if c in string.ascii_letters]) | ||||||
|  |             words += len([thing for thing in content.split() if thing.strip()]) | ||||||
|  |             count += 1 | ||||||
|  |  | ||||||
|  | print(words / count, characters / count) | ||||||
							
								
								
									
										19
									
								
								cycdec.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								cycdec.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | perm = [ | ||||||
|  |     [1, 2, 3, 4, 5, 6, 7, 8], | ||||||
|  |     [5, 7, 8, 2, 3, 6, 4, 1] | ||||||
|  | ] | ||||||
|  | perm = dict(zip(*perm)) | ||||||
|  | vals = set(perm) | ||||||
|  |  | ||||||
|  | print(perm) | ||||||
|  | cycs = [] | ||||||
|  | while vals: | ||||||
|  |     nxt = vals.pop() | ||||||
|  |     seen = [] | ||||||
|  |     while nxt not in seen: | ||||||
|  |         lnxt = nxt | ||||||
|  |         nxt = perm[nxt] | ||||||
|  |         seen.append(lnxt) | ||||||
|  |     cycs.append(seen) | ||||||
|  |     vals -= set(seen) | ||||||
|  | print(cycs) | ||||||
							
								
								
									
										25
									
								
								cyclcm.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								cyclcm.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | import math, itertools | ||||||
|  |  | ||||||
|  | count = 0 | ||||||
|  | for permutation in itertools.permutations(range(7)): | ||||||
|  |     perm = [ | ||||||
|  |         list(range(7)), | ||||||
|  |         list(permutation) | ||||||
|  |     ] | ||||||
|  |     perm = dict(zip(*perm)) | ||||||
|  |     vals = set(perm) | ||||||
|  |  | ||||||
|  |     print(perm) | ||||||
|  |     cycs = [] | ||||||
|  |     while vals: | ||||||
|  |         nxt = vals.pop() | ||||||
|  |         seen = [] | ||||||
|  |         while nxt not in seen: | ||||||
|  |             lnxt = nxt | ||||||
|  |             nxt = perm[nxt] | ||||||
|  |             seen.append(lnxt) | ||||||
|  |         cycs.append(seen) | ||||||
|  |         vals -= set(seen) | ||||||
|  |     if math.lcm(*map(len, cycs)) == 4: | ||||||
|  |         count += 1 | ||||||
|  | print(count) | ||||||
| @@ -148,6 +148,7 @@ li, h2 { | |||||||
| <li>heavpoot is osmarks</li> | <li>heavpoot is osmarks</li> | ||||||
| <li>second #staff-only channel</li> | <li>second #staff-only channel</li> | ||||||
| <li>colin</li> | <li>colin</li> | ||||||
|  | <li>hactar secretly planning takeover</li> | ||||||
| <li>less than 10% of users are frequently active</li> | <li>less than 10% of users are frequently active</li> | ||||||
| <li>cyber PC diagram</li> | <li>cyber PC diagram</li> | ||||||
| </ul> | </ul> | ||||||
| @@ -175,4 +176,4 @@ li, h2 { | |||||||
| </ul> | </ul> | ||||||
| </div> | </div> | ||||||
| </div> | </div> | ||||||
| </body></html> | </body></html> | ||||||
|   | |||||||
							
								
								
									
										41
									
								
								fractalize_image.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								fractalize_image.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | from PIL import Image | ||||||
|  | from functools import cache | ||||||
|  | from collections import namedtuple | ||||||
|  | Region = namedtuple("Region", ["left", "upper", "right", "lower"]) | ||||||
|  | glasses = Image.open("./pv.webp") | ||||||
|  | glasses = glasses.crop(glasses.getbbox()) | ||||||
|  | def scale(i, x): | ||||||
|  |     if i.size[0] // x == 0 or i.size[1] // x == 0: | ||||||
|  |         return False | ||||||
|  |     return i.resize((int(i.size[0] // x), int(i.size[1] // x))) | ||||||
|  | output = Image.new("RGBA", (256, 256)) | ||||||
|  | def paste_at_centre(src: Image, x, y): | ||||||
|  |     #dc = Region(*dc) | ||||||
|  |     left = x - src.size[0] // 2 | ||||||
|  |     upper = y - src.size[1] // 2 | ||||||
|  |     output.alpha_composite(src, (left, upper)) | ||||||
|  |  | ||||||
|  | paste_at_centre(glasses, output.size[0] // 2, output.size[1] // 2) | ||||||
|  | def do_transpositions(im, parity, count): | ||||||
|  |     if count == 0: return im | ||||||
|  |     if parity:  | ||||||
|  |         return do_transpositions(im.transpose(Image.Transpose.ROTATE_90), parity, count - 1) | ||||||
|  |     else: | ||||||
|  |         return do_transpositions(im.transpose(Image.Transpose.ROTATE_270), parity, count - 1) | ||||||
|  | k = 1 | ||||||
|  | while True: | ||||||
|  |     #output.show() | ||||||
|  |     s = 2**k | ||||||
|  |     bounds = Region(*output.getbbox()) | ||||||
|  |     print(bounds) | ||||||
|  |     if not scale(output, s): | ||||||
|  |         break | ||||||
|  |     g = do_transpositions(scale(output, s), True, k) | ||||||
|  |     h = do_transpositions(scale(output, s), False, k) | ||||||
|  |     paste_at_centre(g, bounds.left, bounds.upper) | ||||||
|  |     paste_at_centre(h, bounds.right, bounds.upper) | ||||||
|  |     paste_at_centre(g, bounds.left, bounds.lower) | ||||||
|  |     paste_at_centre(h, bounds.right, bounds.lower) | ||||||
|  |     k += 1 | ||||||
|  | output.show() | ||||||
|  | output.save("./pvf.webp") | ||||||
							
								
								
									
										31
									
								
								goose2function.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								goose2function.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | import cv2, numpy, matplotlib.pyplot as plt, scipy.interpolate, sys | ||||||
|  | from collections import defaultdict | ||||||
|  |  | ||||||
|  | img = cv2.imread(sys.argv[1])  | ||||||
|  | H, S, L = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV)) | ||||||
|  | img_blur = cv2.GaussianBlur(H, (15,15), 0)  | ||||||
|  | thresh = cv2.threshold(img_blur, 55, 255, cv2.THRESH_BINARY)[1] | ||||||
|  | edges = cv2.Canny(image=thresh, threshold1=100, threshold2=200) | ||||||
|  | c, hier = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) | ||||||
|  | best = max(c, key=lambda x: x.shape[0])[:, 0, :] | ||||||
|  | min_x, max_x = min(best[:, 0]), max(best[:, 0]) | ||||||
|  | min_y, max_y = min(best[:, 1]), max(best[:, 1]) | ||||||
|  | xrange = max_x - min_x | ||||||
|  | yrange = max_y - min_y | ||||||
|  | coords = [[((x - min_x) / xrange) * 2 - 1, ((y - min_y) / yrange) * 2 - 1] for x, y in best ] | ||||||
|  | coords.sort(key=lambda x: x[0]) | ||||||
|  | coords2 = defaultdict(list) | ||||||
|  | for x, y in coords: | ||||||
|  |     coords2[x].append(y) | ||||||
|  | coords3x = [] | ||||||
|  | coords3y = [] | ||||||
|  | last = -1 | ||||||
|  | for x, ys in coords2.items(): | ||||||
|  |     coords3y.append(min(ys, key=lambda x: abs(x - last))) | ||||||
|  |     coords3x.append(x) | ||||||
|  |     last = coords3y[-1] | ||||||
|  | i = scipy.interpolate.CubicSpline(coords3x, coords3y, extrapolate=True) | ||||||
|  | xs = numpy.arange(-1.0, 1.0, 0.02) | ||||||
|  | plt.plot(coords3x, coords3y, label='data') | ||||||
|  | plt.plot(xs, i(xs)) | ||||||
|  | plt.show() | ||||||
							
								
								
									
										93
									
								
								heavbiome/main.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								heavbiome/main.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | |||||||
|  | local map = {} | ||||||
|  | local w = 300 | ||||||
|  | local h = 300 | ||||||
|  | local seed = 349259 | ||||||
|  | require("perlin") -- not mine. | ||||||
|  | -- it uses globals. spiteful, but i do not care enough about code quality for this. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | local biomecols = { | ||||||
|  |     empty      = {0.5, 0.5, 0.5}, | ||||||
|  |     forest     = {  0, 0.5,   0}, | ||||||
|  |     rainforest = {  0, 0.5, 0.5}, | ||||||
|  |     ocean      = {  0,   0,   1}, | ||||||
|  |     plains     = {  0,   1,   0}, | ||||||
|  |     desert     = {  1,   1,   0}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | local PERSISTENCE = 0.3 | ||||||
|  | local ITERS = 4 | ||||||
|  | local function oct_noise(x, y, seed, gen) | ||||||
|  |     local total = 0 | ||||||
|  |     local frequency = 1 | ||||||
|  |     local amplitude = 1 | ||||||
|  |     local norm = 0 | ||||||
|  |     for i = 1, ITERS do | ||||||
|  |         total = total + gen:noise(x * frequency, y * frequency, seed + i) * amplitude | ||||||
|  |         norm = norm + amplitude | ||||||
|  |         frequency = frequency * 2 | ||||||
|  |         amplitude = amplitude * PERSISTENCE | ||||||
|  |     end | ||||||
|  |     return total | ||||||
|  | end | ||||||
|  |  | ||||||
|  | local sf = 1/20 -- scaling factor. | ||||||
|  | local function pick_biome(x, y, gen) | ||||||
|  |     local islandicity = gen:noise(x*sf/10, y*sf/10, 302382359)/2+1/2 | ||||||
|  |     islandicity = math.min(math.max(0,islandicity*3),1) | ||||||
|  |     local mainland_modifier = gen:noise(x*sf/20, y*sf/20, 302382359)/2 | ||||||
|  |     local is_ocean = gen:noise(x*sf/4, y*sf/4, 555575)/2+1/2 + gen:noise(x*sf, y*sf, 555575)/(25-islandicity*10) + mainland_modifier | ||||||
|  |     local humidity = oct_noise(x*sf/2, y*sf/2, 10000, gen)/2+1/2 | ||||||
|  |     local temp = oct_noise(x*sf/6, y*sf/6, 20000, gen)/2+1/2 | ||||||
|  |     --return { is_ocean, humidity, temp } | ||||||
|  |     -- | ||||||
|  |     if is_ocean > 0.45 then return "ocean" end | ||||||
|  |     if is_ocean > 0.43 and humidity < 0.6 then return "desert" end -- coast? | ||||||
|  |     if temp > 0.75 then return "desert" end | ||||||
|  |     if humidity < 0.5 then | ||||||
|  |         if temp > 0.5 then | ||||||
|  |             return "desert" | ||||||
|  |         else | ||||||
|  |             return "plains" | ||||||
|  |         end | ||||||
|  |     else | ||||||
|  |         if humidity > 0.75 then | ||||||
|  |             return "rainforest" | ||||||
|  |         else | ||||||
|  |             if temp < 0.6 then | ||||||
|  |                 return "forest" | ||||||
|  |             else | ||||||
|  |                 return "plains" | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     return "empty" | ||||||
|  |     --]] | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function love.load() | ||||||
|  |     local noise = perlin(seed) | ||||||
|  |     local gen = noise | ||||||
|  |     for x=1, w do | ||||||
|  |         map[x] = {} | ||||||
|  |         for y=1, h do | ||||||
|  |             map[x][y] = 0 | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  |     for x=1, w do | ||||||
|  |         for y=1, h do | ||||||
|  |             local biome = pick_biome(x, y, noise) | ||||||
|  |             --map[x][y] = biome | ||||||
|  |             map[x][y] = biomecols[biome] | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function love.draw() | ||||||
|  |     for x=1, w do | ||||||
|  |         for y=1, h do | ||||||
|  |             love.graphics.setColor(unpack(map[x][y])) | ||||||
|  |             love.graphics.rectangle("fill",x*2, y*2, 2, 2) | ||||||
|  |         end | ||||||
|  |     end | ||||||
|  | end | ||||||
							
								
								
									
										134
									
								
								heavbiome/perlin.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								heavbiome/perlin.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | |||||||
|  | local defaultSeed = 1337 | ||||||
|  |  | ||||||
|  | local dot_product = { | ||||||
|  |   [0x0]=function(x,y,z) return  x + y end, | ||||||
|  |   [0x1]=function(x,y,z) return -x + y end, | ||||||
|  |   [0x2]=function(x,y,z) return  x - y end, | ||||||
|  |   [0x3]=function(x,y,z) return -x - y end, | ||||||
|  |   [0x4]=function(x,y,z) return  x + z end, | ||||||
|  |   [0x5]=function(x,y,z) return -x + z end, | ||||||
|  |   [0x6]=function(x,y,z) return  x - z end, | ||||||
|  |   [0x7]=function(x,y,z) return -x - z end, | ||||||
|  |   [0x8]=function(x,y,z) return  y + z end, | ||||||
|  |   [0x9]=function(x,y,z) return -y + z end, | ||||||
|  |   [0xA]=function(x,y,z) return  y - z end, | ||||||
|  |   [0xB]=function(x,y,z) return -y - z end, | ||||||
|  |   [0xC]=function(x,y,z) return  y + x end, | ||||||
|  |   [0xD]=function(x,y,z) return -y + z end, | ||||||
|  |   [0xE]=function(x,y,z) return  y - x end, | ||||||
|  |   [0xF]=function(x,y,z) return -y - z end | ||||||
|  | } | ||||||
|  |  | ||||||
|  | local grad = function(hash, x,y,z) | ||||||
|  |   return dot_product[hash % 0x10](x,y,z) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | local fade = function(t) | ||||||
|  |   return t * t * t * (t * (t * 6 - 15) + 10) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | local lerp = function(t,a,b) | ||||||
|  |   return a + t * (b - a) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | local generatePermutation = function(seed) | ||||||
|  |   math.randomseed(seed) | ||||||
|  |  | ||||||
|  |   local permutation = {0} | ||||||
|  |  | ||||||
|  |   for i=1,255 do | ||||||
|  |     table.insert(permutation,math.random(1,#permutation+1),i) | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   local p = {} | ||||||
|  |  | ||||||
|  |   for i=0,255 do | ||||||
|  |     p[i] = permutation[i+1] | ||||||
|  |     p[i+256] = permutation[i+1] | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   return p | ||||||
|  | end | ||||||
|  |  | ||||||
|  | perlin = {} | ||||||
|  | perlin.__index = perlin | ||||||
|  |  | ||||||
|  | perlin.noise = function(self,x,y,z) | ||||||
|  |   y = y or 0 | ||||||
|  |   z = z or 0 | ||||||
|  |  | ||||||
|  |   local xi = math.floor(x) % 0x100 | ||||||
|  |   local yi = math.floor(y) % 0x100 | ||||||
|  |   local zi = math.floor(z) % 0x100 | ||||||
|  |  | ||||||
|  |   x = x - math.floor(x) | ||||||
|  |   y = y - math.floor(y) | ||||||
|  |   z = z - math.floor(z) | ||||||
|  |  | ||||||
|  |   local u = fade(x) | ||||||
|  |   local v = fade(y) | ||||||
|  |   local w = fade(z) | ||||||
|  |  | ||||||
|  |   local A, AA, AB, AAA, ABA, AAB, ABB, B, BA, BB, BAA, BBA, BAB, BBB | ||||||
|  |   A   = self.p[xi  ] + yi | ||||||
|  |   AA  = self.p[A   ] + zi | ||||||
|  |   AB  = self.p[A+1 ] + zi | ||||||
|  |   AAA = self.p[ AA ] | ||||||
|  |   ABA = self.p[ AB ] | ||||||
|  |   AAB = self.p[ AA+1 ] | ||||||
|  |   ABB = self.p[ AB+1 ] | ||||||
|  |  | ||||||
|  |   B   = self.p[xi+1] + yi | ||||||
|  |   BA  = self.p[B   ] + zi | ||||||
|  |   BB  = self.p[B+1 ] + zi | ||||||
|  |   BAA = self.p[ BA ] | ||||||
|  |   BBA = self.p[ BB ] | ||||||
|  |   BAB = self.p[ BA+1 ] | ||||||
|  |   BBB = self.p[ BB+1 ] | ||||||
|  |  | ||||||
|  |   return lerp(w, | ||||||
|  |     lerp(v, | ||||||
|  |       lerp(u, | ||||||
|  |         grad(AAA,x,y,z), | ||||||
|  |         grad(BAA,x-1,y,z) | ||||||
|  |       ), | ||||||
|  |       lerp(u, | ||||||
|  |         grad(ABA,x,y-1,z), | ||||||
|  |         grad(BBA,x-1,y-1,z) | ||||||
|  |       ) | ||||||
|  |     ), | ||||||
|  |     lerp(v, | ||||||
|  |       lerp(u, | ||||||
|  |         grad(AAB,x,y,z-1), grad(BAB,x-1,y,z-1) | ||||||
|  |       ), | ||||||
|  |       lerp(u, | ||||||
|  |         grad(ABB,x,y-1,z-1), grad(BBB,x-1,y-1,z-1) | ||||||
|  |       ) | ||||||
|  |     ) | ||||||
|  |   ) | ||||||
|  | end | ||||||
|  |  | ||||||
|  | setmetatable(perlin,{ | ||||||
|  |   __call = function(self,seed) | ||||||
|  |     seed = seed or defaultSeed | ||||||
|  |  | ||||||
|  |     return setmetatable({ | ||||||
|  |       seed = seed, | ||||||
|  |       p = generatePermutation(seed), | ||||||
|  |     },self) | ||||||
|  |   end | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | --[[ | ||||||
|  | EXAMPLE | ||||||
|  |   local p1 = perlin(1338) | ||||||
|  |   local p2 = perlin(1337) | ||||||
|  |  | ||||||
|  |   local x,y,z = 1.0,2.0,3.0 | ||||||
|  |  | ||||||
|  |   print(p1:noise(x,y,z)) | ||||||
|  |   print(p2:noise(x,y,z)) | ||||||
|  |    | ||||||
|  |   >> 0.23456 | ||||||
|  |   >> 0.47598 | ||||||
|  | --]] | ||||||
							
								
								
									
										36
									
								
								histretention.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								histretention.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | import sqlite3 | ||||||
|  |  | ||||||
|  | longterm = sqlite3.connect("/data/archive/lthist.sqlite3") | ||||||
|  | longterm.executescript(f""" | ||||||
|  | CREATE TABLE IF NOT EXISTS places ( | ||||||
|  |     guid TEXT PRIMARY KEY, | ||||||
|  |     url TEXT, | ||||||
|  |     title TEXT, | ||||||
|  |     visit_count INTEGER DEFAULT 0, | ||||||
|  |     last_visit_date INTEGER, | ||||||
|  |     description TEXT, | ||||||
|  |     preview_image_url TEXT | ||||||
|  | ); | ||||||
|  | CREATE TABLE IF NOT EXISTS bookmarks ( | ||||||
|  |     guid TEXT PRIMARY KEY, | ||||||
|  |     bookmark TEXT NOT NULL REFERENCES places(guid), | ||||||
|  |     title TEXT, | ||||||
|  |     dateAdded INTEGER, | ||||||
|  |     lastModified INTEGER | ||||||
|  | ); | ||||||
|  | CREATE TABLE IF NOT EXISTS historyvisits ( | ||||||
|  |     id TEXT PRIMARY KEY, | ||||||
|  |     place TEXT NOT NULL REFERENCES places(guid), | ||||||
|  |     date INTEGER NOT NULL, | ||||||
|  |     type INTEGER NOT NULL | ||||||
|  | ); | ||||||
|  | """) | ||||||
|  | longterm.execute("ATTACH DATABASE '/tmp/places.sqlite' AS transient;") | ||||||
|  | longterm.execute("""INSERT INTO places SELECT guid, url, title, visit_count, last_visit_date, description, preview_image_url FROM moz_places WHERE true | ||||||
|  | ON CONFLICT DO UPDATE SET visit_count = excluded.visit_count, last_visit_date = excluded.last_visit_date, title = excluded.title, description = excluded.description, preview_image_url = excluded.preview_image_url;""") | ||||||
|  | longterm.execute("""INSERT INTO bookmarks SELECT moz_bookmarks.guid, moz_places.guid, moz_bookmarks.title, dateAdded, lastModified FROM moz_bookmarks JOIN moz_places ON moz_places.id = moz_bookmarks.fk WHERE true | ||||||
|  | ON CONFLICT DO UPDATE SET lastModified = excluded.lastModified, title = excluded.title;""") | ||||||
|  | # TODO: possibly wrong with new profile, might need to increment historyvisits or something | ||||||
|  | longterm.execute("INSERT INTO historyvisits SELECT (moz_historyvisits.id || '/' || visit_date), moz_places.guid, visit_date, visit_type FROM moz_historyvisits JOIN moz_places ON moz_places.id = moz_historyvisits.place_id ON CONFLICT DO NOTHING;") | ||||||
|  |  | ||||||
|  | longterm.commit() | ||||||
							
								
								
									
										25
									
								
								hyperplane.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								hyperplane.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | def step(x): | ||||||
|  |     return ((x * 1039) + (x * 6177) + 1605 + (x * 4253)) % 8041 | ||||||
|  |  | ||||||
|  | points = set() | ||||||
|  | a, b, c = None, None, 417 | ||||||
|  | for n in range(100000): | ||||||
|  |     a, b, c = b, c, step(c) | ||||||
|  |     if a is not None and b is not None: | ||||||
|  |         points.add((a, b, c)) | ||||||
|  |  | ||||||
|  | import numpy as np | ||||||
|  | import matplotlib.pyplot as plt | ||||||
|  |   | ||||||
|  | fig = plt.figure() | ||||||
|  | ax = plt.axes(projection="3d") | ||||||
|  | def unzip(l): | ||||||
|  |     ls = [] | ||||||
|  |     for x in l: | ||||||
|  |         for i, v in enumerate(x): | ||||||
|  |             if len(ls) <= i: | ||||||
|  |                 ls.append([]) | ||||||
|  |             ls[i].append(v) | ||||||
|  |     return ls | ||||||
|  | ax.scatter(*unzip(points)) | ||||||
|  | plt.show() | ||||||
							
								
								
									
										22
									
								
								memeticize.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								memeticize.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | import os, sys, subprocess, datetime | ||||||
|  |  | ||||||
|  | dt_threshold = datetime.datetime(2022, 11, 27).timestamp() | ||||||
|  |  | ||||||
|  | _, indir, outdir = sys.argv | ||||||
|  | for x in os.listdir(indir): | ||||||
|  |     inpath = os.path.join(indir, x) | ||||||
|  |     if os.stat(inpath).st_mtime > dt_threshold: | ||||||
|  |         if subprocess.run(("feh", inpath)).returncode == 0: | ||||||
|  |             newname = input(x + ": ") | ||||||
|  |             if newname: | ||||||
|  |                 ctr = 1 | ||||||
|  |                 while True: | ||||||
|  |                     newpath = os.path.join(outdir, newname + (f"-{ctr}" if ctr > 1 else "") + os.path.splitext(x)[1]) | ||||||
|  |                     if os.path.exists(newpath): | ||||||
|  |                         print("already in use") | ||||||
|  |                         ctr += 1 | ||||||
|  |                     else: | ||||||
|  |                         os.rename(inpath, newpath) | ||||||
|  |                         break | ||||||
|  |             else: | ||||||
|  |                 print("keeping") | ||||||
							
								
								
									
										
											BIN
										
									
								
								output.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								output.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										61
									
								
								randomlookingthing.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								randomlookingthing.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <h1>changed version</h1> | ||||||
|  | <input type="number" id="w" min="0" value="8" placeholder="width"> | ||||||
|  | <input type="number" id="h" min="0" value="8" placeholder="height"> | ||||||
|  | <input type="range" id="d" min="0" max="1" step="0.0001" value="0.1" placeholder="density"> | ||||||
|  | <button id="run">run</button> | ||||||
|  | <br> | ||||||
|  | <canvas id="out"></canvas> | ||||||
|  | <script> | ||||||
|  |     const pixels = 32 | ||||||
|  |     const zipWith = (f, xs, ys) => xs.map((x, i) => f(x, ys[i])) | ||||||
|  |     const sum = xs => xs.reduce((a, y) => a + y, 0) | ||||||
|  |     const vecAdd = (a, b) => zipWith((x, y) => x + y, a, b) | ||||||
|  |     const hadamardProduct = (a, b) => zipWith((x, y) => x * y, a, b) | ||||||
|  |     const scalarMult = (a, n) => a.map(x => x * n) | ||||||
|  |     const dotProduct = (a, b) => sum(hadamardProduct(a, b)) | ||||||
|  |     const vecLength = a => Math.sqrt(sum(a.map(x => x ** 2))) | ||||||
|  |     const normalize = a => scalarMult(a, 1/vecLength(a)) | ||||||
|  |     const vsub = (x, y) => vecAdd(x, scalarMult(y, -1)) | ||||||
|  |     const clampDim = (a, i, min, max) => { | ||||||
|  |         if (a[i] >= max) { | ||||||
|  |             a[i] = min + a[i] - max | ||||||
|  |         } | ||||||
|  |         if (a[i] <= min) { | ||||||
|  |             a[i] = max - (min - a[i]) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     run.onclick = () => { | ||||||
|  |         const width = parseInt(w.value) | ||||||
|  |         const height = parseInt(h.value) | ||||||
|  |         const geomean = Math.sqrt(width * height) | ||||||
|  |         const rdist = 1 / geomean | ||||||
|  |         const density = parseFloat(d.value) | ||||||
|  |         out.width = width * pixels | ||||||
|  |         out.height = height * pixels | ||||||
|  |         const ctx = out.getContext("2d") | ||||||
|  |         /* | ||||||
|  |         let points = Array(Math.floor(width * height * density)).fill(null).map(x => [Math.random(), Math.random()]) | ||||||
|  |         for (let i = 0; i < 100; i++) { | ||||||
|  |             for (let j = 0; j < points.length; j++) { | ||||||
|  |                 const p = points[j] | ||||||
|  |                 const v = points.filter((_, k) => k !== j).map(q => {  | ||||||
|  |                     const direction = normalize(vsub(p, q)) | ||||||
|  |                     const distance = vecLength(vsub(p, q)) | ||||||
|  |                     const magnitude = distance < rdist ? -5 : distance ** -3 | ||||||
|  |                     return scalarMult(direction, magnitude) | ||||||
|  |                 }).reduce(vecAdd, [0, 0]) | ||||||
|  |                 clampDim(p, 0, 0, 1) | ||||||
|  |                 clampDim(p, 1, 0, 1) | ||||||
|  |                 points[j] = vecAdd(p, scalarMult(v, 0.025)) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         console.log(points)*/ | ||||||
|  |         for (let x = 0; x < width; x++) { | ||||||
|  |             for (let y = 0; y < width; y++) { | ||||||
|  |                 ctx.fillStyle = /*points.filter(([p, q]) => p >= (x / width) && p <= ((x + 1) / width) && q >= (y / height) && q <= ((y + 1) / height)).length > 0*/ Math.random() < density ? "green" : "black" | ||||||
|  |                 ctx.fillRect(x * pixels, y * pixels, pixels, pixels) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | </script> | ||||||
							
								
								
									
										116
									
								
								rank_ordering_assignment_system.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								rank_ordering_assignment_system.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | |||||||
|  | <body> | ||||||
|  |     <script src="https://unpkg.com/mithril/mithril.js"></script> | ||||||
|  |     <script> | ||||||
|  |         let people = 3 | ||||||
|  |         let info = [] | ||||||
|  |         let pointsForRank = "" | ||||||
|  |  | ||||||
|  |         const regenerateInfo = () => { | ||||||
|  |             if (info.length > people) { | ||||||
|  |                 info = info.slice(0, people) | ||||||
|  |             } | ||||||
|  |             if (info.length < people) { | ||||||
|  |                 info = JSON.parse(JSON.stringify(info.concat(new Array(people - info.length).fill({ rank: "", weighting: 1 })))) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         regenerateInfo() | ||||||
|  |  | ||||||
|  |         const changeCount = ev => { | ||||||
|  |             people = parseInt(ev.target.value) | ||||||
|  |             regenerateInfo() | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const permutations = xs => { | ||||||
|  |             if (xs.length === 0) { return [[]] } | ||||||
|  |             const result = [] | ||||||
|  |             for (let i = 0; i < xs.length; i++) { | ||||||
|  |                 const listWithoutIth = xs.slice(0, i).concat(xs.slice(i + 1)) | ||||||
|  |                 for (const perm of permutations(listWithoutIth)) { | ||||||
|  |                     result.push([xs[i]].concat(perm)) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return result | ||||||
|  |         } | ||||||
|  |         const range = n => new Array(n).fill(null).map((x, i) => i) | ||||||
|  |  | ||||||
|  |         let result = "" | ||||||
|  |  | ||||||
|  |         const targetPerms = 5 | ||||||
|  |         const solve = () => { | ||||||
|  |             const points = pointsForRank.split(",").map(parseFloat) | ||||||
|  |             if (points.length !== people) { | ||||||
|  |                 throw "There must be as many points defined as ranks." | ||||||
|  |             } else if (!points.every(x => !isNaN(x))) { | ||||||
|  |                 throw "Invalid number" | ||||||
|  |             } | ||||||
|  |             const pointsForPerson = [] | ||||||
|  |             for (let i = 0; i < info.length; i++) { | ||||||
|  |                 const inf = info[i] | ||||||
|  |                 const rankOrder = inf.rank.split(",").map(parseFloat) | ||||||
|  |                 const sortedCopy = Array.from(rankOrder) | ||||||
|  |                 sortedCopy.sort((a, b) => a - b) | ||||||
|  |                 console.log(JSON.stringify(sortedCopy), JSON.stringify(range(people).map(x => x + 1))) | ||||||
|  |                 if (rankOrder.length !== people) { | ||||||
|  |                     throw `Person ${i + 1}'s ranking is too short/long.` | ||||||
|  |                 } else if (!rankOrder.every(x => !isNaN(x))) { | ||||||
|  |                     throw `Person ${i + 1}'s ranking contains an invalid number.` | ||||||
|  |                 } else if (JSON.stringify(sortedCopy) !== JSON.stringify(range(people).map(x => x + 1))) { | ||||||
|  |                     throw `Person ${i + 1}'s ranking is not a valid permutation.` | ||||||
|  |                 } | ||||||
|  |                 const newx = new Array(people).fill(null) | ||||||
|  |                 for (let j = 0; j < people; j++) { | ||||||
|  |                     const thingWithJthRank = rankOrder[j] - 1 | ||||||
|  |                     newx[thingWithJthRank] = inf.weighting * points[j] | ||||||
|  |                 } | ||||||
|  |                 pointsForPerson.push(newx) | ||||||
|  |             } | ||||||
|  |             console.log("got", points, pointsForPerson) | ||||||
|  |             let bestPerms = [] | ||||||
|  |             for (const perm of permutations(range(people))) { // ith person gets perm[i]th thing person | ||||||
|  |                 const score = perm.map((person, thingIndex) => pointsForPerson[person][thingIndex]).reduce((a, b) => a + b, 0) | ||||||
|  |                 for (let i = 0; i < bestPerms.length; i++) { | ||||||
|  |                     const [otherPerm, otherScore] = bestPerms[i] | ||||||
|  |                     if (otherScore < score) { | ||||||
|  |                         bestPerms.splice(i, 1) | ||||||
|  |                         break | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 if (bestPerms.length < targetPerms) { | ||||||
|  |                     bestPerms.push(([perm, score])) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             bestPerms.sort((a, b) => b[1] - a[1]) | ||||||
|  |             return m("", [ | ||||||
|  |                 "Solutions found:", | ||||||
|  |                 m("ul", bestPerms.map(([bestPerm, bestScore]) => m("li", bestPerm.map((person, thingIndex) => `Person ${person + 1} gets ${thingIndex + 1}`).join("; ") + ` (${bestScore} points).`))) | ||||||
|  |             ]) | ||||||
|  |         } | ||||||
|  |         const solveWrapper = () => { | ||||||
|  |             try { | ||||||
|  |                 result = solve() | ||||||
|  |             } catch(e) { | ||||||
|  |                 console.warn(e) | ||||||
|  |                 result = e.toString() | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         m.mount(document.body, { | ||||||
|  |             view: function() { | ||||||
|  |                 return [ | ||||||
|  |                     m("p", "Rank orders must be given as comma-separated one-indexed integers. The points for each rank must be given as comma-separated real numbers."), | ||||||
|  |                     m("input", { value: pointsForRank, placeholder: "Points for ranks", oninput: ev => { pointsForRank = ev.target.value } }), | ||||||
|  |                     m("", [ m("label", "People: "), m("input[type=number]", { value: people, oninput: changeCount }) ]), | ||||||
|  |                     m("", info.map((i, index) => m("", [  | ||||||
|  |                         m("label", `Person ${index + 1}: `), | ||||||
|  |                         m("input", { value: i.rank, placeholder: "Ranking", oninput: ev => { i.rank = ev.target.value } }), | ||||||
|  |                         m("label", " Weighting: "), m("input[type=number]", { value: i.weighting, oninput: ev => { i.weighting = parseFloat(ev.target.value) }, step: 0.1 }) | ||||||
|  |                     ]))), | ||||||
|  |                     m("button", { onclick: solveWrapper }, "Solve"), | ||||||
|  |                     m("", result) | ||||||
|  |                 ] | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |     </script> | ||||||
|  | </body> | ||||||
							
								
								
									
										61
									
								
								rng_trainer.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								rng_trainer.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <!-- https://www.researchgate.net/publication/232494603_Can_People_Behave_Randomly_The_Role_of_Feedback --> | ||||||
|  | <meta charset="utf8"> | ||||||
|  | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|  | <style> | ||||||
|  |     #buttons { | ||||||
|  |         width: 100%; | ||||||
|  |         display: flex; | ||||||
|  |     } | ||||||
|  |     #buttons button { | ||||||
|  |         height: 20rem; | ||||||
|  |         width: 100%; | ||||||
|  |         margin: 2rem; | ||||||
|  |         font-size: 3em; | ||||||
|  |     } | ||||||
|  |     button { | ||||||
|  |         border-radius: 0; | ||||||
|  |         border: 1px solid blue; | ||||||
|  |         padding: 0.5rem; | ||||||
|  |     } | ||||||
|  | </style> | ||||||
|  | <div id="buttons"> | ||||||
|  |     <button id="l">L</button> | ||||||
|  |     <button id="r">R</button> | ||||||
|  | </div> | ||||||
|  | <div id="other-controls"> | ||||||
|  |     <div id="qty"></div> | ||||||
|  |     <button id="restart">Restart</button> | ||||||
|  | </div> | ||||||
|  | <div id="seq"></div> | ||||||
|  | <script> | ||||||
|  |     var working = true | ||||||
|  |     const FINALSEQLEN = 100 | ||||||
|  |     const tests = { | ||||||
|  |         "RNG1": [] | ||||||
|  |     } | ||||||
|  |     var seq = [] | ||||||
|  |     const push = val => { | ||||||
|  |         if (working) { | ||||||
|  |             seq.push(val) | ||||||
|  |             qty.innerText = `${seq.length}/${FINALSEQLEN}` | ||||||
|  |             if (seq.length === FINALSEQLEN) { | ||||||
|  |                 working = false | ||||||
|  |                 qty.innerText = "Done" | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     restart.onclick = () => { | ||||||
|  |         working = true | ||||||
|  |         seq = [] | ||||||
|  |     } | ||||||
|  |     l.onclick = () => push("L") | ||||||
|  |     r.onclick = () => push("R") | ||||||
|  |     window.onkeypress = ev => { | ||||||
|  |         if (ev.key.toLowerCase() == "l" || ev.key == "1") { | ||||||
|  |             push("L") | ||||||
|  |         } else if (ev.key.toLowerCase() == "r" || ev.key == "2") { | ||||||
|  |             push("R") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | </script> | ||||||
							
								
								
									
										175
									
								
								smtp2rss.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								smtp2rss.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | |||||||
|  | import asyncio | ||||||
|  | from aiosmtpd.controller import UnthreadedController | ||||||
|  | from aiosmtpd.smtp import SMTP, syntax | ||||||
|  | from email.message import Message, EmailMessage | ||||||
|  | from email import message_from_bytes | ||||||
|  | from email.header import Header, decode_header, make_header | ||||||
|  | import aiosqlite | ||||||
|  | from datetime import datetime, timezone | ||||||
|  | from aiohttp import web | ||||||
|  | import re | ||||||
|  | import json | ||||||
|  | import feedparser.sanitizer | ||||||
|  | import rfeed | ||||||
|  | import base64 | ||||||
|  |  | ||||||
|  | def now(): return datetime.now(tz=timezone.utc) | ||||||
|  | def decode_mime(subject): return str(make_header(decode_header(subject))) | ||||||
|  |  | ||||||
|  | def handle_addr(a): | ||||||
|  |     if a: | ||||||
|  |         if x := re.search("<(.*)>$", a.strip()): | ||||||
|  |             return x.group(1) | ||||||
|  |         else: | ||||||
|  |             return a.strip() | ||||||
|  |  | ||||||
|  | async def open_connection(): | ||||||
|  |     conn = await aiosqlite.connect("./smtp2rss.sqlite3") | ||||||
|  |     conn.row_factory = aiosqlite.Row | ||||||
|  |     await conn.execute("PRAGMA journal_mode = WAL") | ||||||
|  |     await conn.executescript(""" | ||||||
|  | CREATE TABLE IF NOT EXISTS mails ( | ||||||
|  |     id INTEGER PRIMARY KEY, | ||||||
|  |     timestamp REAL NOT NULL, | ||||||
|  |     full_mail BLOB NOT NULL, | ||||||
|  |     from_addr TEXT, | ||||||
|  |     to_addr TEXT, | ||||||
|  |     subject TEXT | ||||||
|  | ); | ||||||
|  |     """) | ||||||
|  |     await conn.commit() | ||||||
|  |     return conn | ||||||
|  |  | ||||||
|  | routes = web.RouteTableDef() | ||||||
|  |  | ||||||
|  | import dominate | ||||||
|  | from dominate.tags import * | ||||||
|  |  | ||||||
|  | def base_template(title, content, err=None): | ||||||
|  |     doc = dominate.document(title=title) | ||||||
|  |  | ||||||
|  |     with doc.head: | ||||||
|  |         meta(name="viewport", content="width=device-width, initial-scale=1.0") | ||||||
|  |         style(""" | ||||||
|  | * { | ||||||
|  |     box-sizing: border-box; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | h1, h2, h3 { | ||||||
|  |     margin-top: 0; | ||||||
|  |     border-bottom: 1px solid gray; | ||||||
|  |     font-weight: normal; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .mails .entry { | ||||||
|  |     border: 1px solid gray; | ||||||
|  |     margin: 0.5em; | ||||||
|  |     padding: 0.5em; | ||||||
|  | } | ||||||
|  | """) | ||||||
|  |     with doc: | ||||||
|  |         if err: div(err, cls="error") | ||||||
|  |         h1(title, cls="title") | ||||||
|  |         m = main() | ||||||
|  |         m += content | ||||||
|  |  | ||||||
|  |     return web.Response(text=doc.render(), content_type="text/html") | ||||||
|  |  | ||||||
|  | preference = { | ||||||
|  |     "text/html": 2, | ||||||
|  |     "text/plain": 1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | def email_to_html(emsg, debug_info=False): | ||||||
|  |     if isinstance(emsg, Message): | ||||||
|  |         payload = emsg.get_payload() | ||||||
|  |         if isinstance(payload, list): | ||||||
|  |             if not debug_info and emsg.get_content_type() == "multipart/alternative": | ||||||
|  |                 payload.sort(key=lambda x: preference.get(x.get_content_type(), 0)) | ||||||
|  |                 return email_to_html(payload[-1], debug_info) | ||||||
|  |             else: | ||||||
|  |                 html = [ email_to_html(thing, debug_info) for thing in payload ] | ||||||
|  |         else: | ||||||
|  |             try: | ||||||
|  |                 payload = emsg.get_payload(decode=True).decode("utf-8") | ||||||
|  |             except: | ||||||
|  |                 payload = emsg.get_payload(decode=True).decode("latin1") | ||||||
|  |             if emsg.get_content_subtype() == "html": | ||||||
|  |                 html = div(dominate.util.raw(feedparser.sanitizer._sanitize_html(payload.replace("<!doctype html>", ""), "utf-8", "text/html"))) | ||||||
|  |             else: | ||||||
|  |                 html = pre(payload) | ||||||
|  |     else: | ||||||
|  |         html = [ email_to_html(thing, debug_info) for thing in emsg.get_body(list(preference.keys())) ] | ||||||
|  |     return div([ | ||||||
|  |         pre([ f"{header}: {value}\n" for header, value in emsg.items() ]) if debug_info else "", | ||||||
|  |         html | ||||||
|  |     ], cls="entry") | ||||||
|  |  | ||||||
|  | async def run(): | ||||||
|  |     accessed_feeds = {} | ||||||
|  |  | ||||||
|  |     loop = asyncio.get_event_loop() | ||||||
|  |     db = await open_connection() | ||||||
|  |  | ||||||
|  |     class Handler: | ||||||
|  |         async def handle_DATA(handler, server, session, envelope): | ||||||
|  |             mail = message_from_bytes(envelope.content) | ||||||
|  |             print("got mail", handle_addr(mail["From"]), handle_addr(mail["To"]), mail["Subject"]) | ||||||
|  |             await db.execute_insert("INSERT INTO mails (timestamp, full_mail, from_addr, to_addr, subject) VALUES (?, ?, ?, ?, ?)",  | ||||||
|  |                 (now().timestamp(), envelope.content, handle_addr(mail["From"]), handle_addr(mail["To"]), decode_mime(mail["Subject"]))) | ||||||
|  |             await db.commit() | ||||||
|  |             return "250 OK" | ||||||
|  |  | ||||||
|  |     controller = UnthreadedController(Handler(), loop=loop, hostname="127.0.0.1") | ||||||
|  |     srv = await controller._create_server() | ||||||
|  |     controller.server = srv | ||||||
|  |     print(controller.hostname, controller.port) | ||||||
|  |  | ||||||
|  |     @routes.get("/") | ||||||
|  |     async def index(req): | ||||||
|  |         page = int(req.query.get("page", 0)) | ||||||
|  |         exclude = [ feed for feed, time in accessed_feeds.items() if (time.timestamp() > (now().timestamp() - 3600)) ] | ||||||
|  |         items = await db.execute_fetchall("SELECT * FROM mails WHERE from_addr NOT IN (SELECT value FROM json_each(?)) ORDER BY timestamp DESC LIMIT 25 OFFSET ?", (json.dumps(exclude), page * 25)) | ||||||
|  |         def display_mail(row): | ||||||
|  |             data = message_from_bytes(row["full_mail"]) | ||||||
|  |             return div([ | ||||||
|  |                 div([ datetime.fromtimestamp(row["timestamp"], tz=timezone.utc).strftime("%Y-%m-%d %H:%M:%S"), " / ", f"{row['from_addr'] or '[from addr missing]'}→{row['to_addr'] or '[to addr missing]'}", " / ", row["subject"] or "[no subject]" ]), | ||||||
|  |                 email_to_html(data, True) | ||||||
|  |             ], cls="entry") | ||||||
|  |         return base_template("Unused Mails", div([ | ||||||
|  |             display_mail(mail) for mail in items | ||||||
|  |         ], cls="mails")) | ||||||
|  |  | ||||||
|  |     @routes.get("/feed/{from}") | ||||||
|  |     async def feed(req): | ||||||
|  |         accessed_feeds[req.match_info["from"]] = now() | ||||||
|  |         items = [] | ||||||
|  |         for mail in await db.execute_fetchall("SELECT * FROM mails WHERE from_addr = ? ORDER BY timestamp DESC LIMIT 20", (req.match_info["from"],)): | ||||||
|  |             data = message_from_bytes(mail["full_mail"]) | ||||||
|  |             content = email_to_html(data, debug_info=False).render() | ||||||
|  |             items.append(rfeed.Item( | ||||||
|  |                 title=mail["subject"], | ||||||
|  |                 guid=rfeed.Guid(f"smtp2rss-{mail['id']}"), | ||||||
|  |                 pubDate=datetime.fromtimestamp(mail["timestamp"], tz=timezone.utc), | ||||||
|  |                 author=req.match_info["from"], | ||||||
|  |                 description=content.strip() | ||||||
|  |             )) | ||||||
|  |         return web.Response(text=rfeed.Feed( | ||||||
|  |             title=f"{req.match_info['from']} via SMTP2RSS", | ||||||
|  |             lastBuildDate=now(), | ||||||
|  |             link="http://localhost:3394", | ||||||
|  |             description="", | ||||||
|  |             items=items | ||||||
|  |         ).rss()) | ||||||
|  |  | ||||||
|  |     app = web.Application() | ||||||
|  |     app.router.add_routes(routes) | ||||||
|  |  | ||||||
|  |     runner = web.AppRunner(app) | ||||||
|  |     await runner.setup() | ||||||
|  |     site = web.TCPSite(runner, "100.64.0.2", 3394) | ||||||
|  |     await site.start() | ||||||
|  |  | ||||||
|  | loop = asyncio.get_event_loop_policy().get_event_loop() | ||||||
|  | loop.run_until_complete(run()) | ||||||
|  | loop.run_forever() | ||||||
							
								
								
									
										
											BIN
										
									
								
								spectro/1200.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								spectro/1200.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 670 KiB | 
							
								
								
									
										777
									
								
								spectro/AColorResources.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										777
									
								
								spectro/AColorResources.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,777 @@ | |||||||
|  | const unsigned char specColormap[256][3] = [ | ||||||
|  |    [  0,   0,   0], | ||||||
|  |    [  0,   0,   0], | ||||||
|  |    [  0,   0,   0], | ||||||
|  |    [  0,   1,   0], | ||||||
|  |    [  0,   1,   1], | ||||||
|  |    [  1,   1,   1], | ||||||
|  |    [  1,   2,   2], | ||||||
|  |    [  1,   2,   2], | ||||||
|  |    [  1,   3,   3], | ||||||
|  |    [  1,   4,   4], | ||||||
|  |    [  2,   5,   4], | ||||||
|  |    [  2,   6,   5], | ||||||
|  |    [  2,   7,   6], | ||||||
|  |    [  2,   8,   8], | ||||||
|  |    [  2,   9,   9], | ||||||
|  |    [  2,  10,  10], | ||||||
|  |    [  2,  11,  12], | ||||||
|  |    [  2,  13,  13], | ||||||
|  |    [  2,  14,  15], | ||||||
|  |    [  2,  15,  16], | ||||||
|  |    [  2,  16,  18], | ||||||
|  |    [  2,  18,  19], | ||||||
|  |    [  2,  19,  21], | ||||||
|  |    [  2,  20,  22], | ||||||
|  |    [  1,  21,  24], | ||||||
|  |    [  1,  22,  26], | ||||||
|  |    [  1,  23,  27], | ||||||
|  |    [  1,  25,  29], | ||||||
|  |    [  0,  26,  31], | ||||||
|  |    [  0,  27,  33], | ||||||
|  |    [  0,  28,  34], | ||||||
|  |    [  0,  29,  36], | ||||||
|  |    [  0,  30,  38], | ||||||
|  |    [  0,  31,  40], | ||||||
|  |    [  0,  32,  42], | ||||||
|  |    [  0,  33,  44], | ||||||
|  |    [  0,  34,  46], | ||||||
|  |    [  0,  35,  48], | ||||||
|  |    [  0,  36,  50], | ||||||
|  |    [  0,  37,  52], | ||||||
|  |    [  0,  38,  55], | ||||||
|  |    [  0,  39,  57], | ||||||
|  |    [  0,  40,  59], | ||||||
|  |    [  0,  41,  61], | ||||||
|  |    [  0,  42,  64], | ||||||
|  |    [  0,  42,  66], | ||||||
|  |    [  0,  43,  69], | ||||||
|  |    [  0,  44,  71], | ||||||
|  |    [  0,  45,  73], | ||||||
|  |    [  0,  46,  76], | ||||||
|  |    [  0,  46,  79], | ||||||
|  |    [  0,  47,  81], | ||||||
|  |    [  0,  48,  84], | ||||||
|  |    [  0,  48,  86], | ||||||
|  |    [  1,  49,  89], | ||||||
|  |    [  3,  49,  92], | ||||||
|  |    [  5,  50,  94], | ||||||
|  |    [  7,  50,  97], | ||||||
|  |    [ 10,  51, 100], | ||||||
|  |    [ 13,  51, 102], | ||||||
|  |    [ 16,  51, 105], | ||||||
|  |    [ 19,  52, 108], | ||||||
|  |    [ 22,  52, 111], | ||||||
|  |    [ 25,  52, 113], | ||||||
|  |    [ 27,  53, 116], | ||||||
|  |    [ 30,  53, 119], | ||||||
|  |    [ 33,  53, 121], | ||||||
|  |    [ 35,  53, 124], | ||||||
|  |    [ 38,  53, 127], | ||||||
|  |    [ 41,  53, 129], | ||||||
|  |    [ 43,  53, 132], | ||||||
|  |    [ 46,  53, 134], | ||||||
|  |    [ 49,  53, 137], | ||||||
|  |    [ 52,  53, 139], | ||||||
|  |    [ 54,  52, 142], | ||||||
|  |    [ 57,  52, 144], | ||||||
|  |    [ 60,  52, 146], | ||||||
|  |    [ 62,  52, 148], | ||||||
|  |    [ 65,  51, 151], | ||||||
|  |    [ 68,  51, 153], | ||||||
|  |    [ 70,  51, 155], | ||||||
|  |    [ 73,  50, 157], | ||||||
|  |    [ 76,  50, 159], | ||||||
|  |    [ 78,  49, 161], | ||||||
|  |    [ 81,  49, 162], | ||||||
|  |    [ 84,  48, 164], | ||||||
|  |    [ 86,  48, 166], | ||||||
|  |    [ 89,  47, 167], | ||||||
|  |    [ 92,  46, 169], | ||||||
|  |    [ 94,  46, 170], | ||||||
|  |    [ 97,  45, 171], | ||||||
|  |    [ 99,  45, 172], | ||||||
|  |    [102,  44, 173], | ||||||
|  |    [105,  44, 174], | ||||||
|  |    [107,  43, 175], | ||||||
|  |    [110,  42, 176], | ||||||
|  |    [112,  42, 177], | ||||||
|  |    [115,  41, 178], | ||||||
|  |    [117,  41, 178], | ||||||
|  |    [120,  40, 179], | ||||||
|  |    [122,  40, 179], | ||||||
|  |    [124,  39, 179], | ||||||
|  |    [127,  39, 180], | ||||||
|  |    [129,  38, 180], | ||||||
|  |    [132,  38, 180], | ||||||
|  |    [134,  37, 180], | ||||||
|  |    [136,  37, 180], | ||||||
|  |    [139,  37, 179], | ||||||
|  |    [141,  37, 179], | ||||||
|  |    [143,  36, 179], | ||||||
|  |    [146,  36, 178], | ||||||
|  |    [148,  36, 178], | ||||||
|  |    [150,  36, 177], | ||||||
|  |    [152,  36, 176], | ||||||
|  |    [155,  36, 176], | ||||||
|  |    [157,  36, 175], | ||||||
|  |    [159,  36, 174], | ||||||
|  |    [161,  36, 173], | ||||||
|  |    [163,  37, 172], | ||||||
|  |    [165,  37, 171], | ||||||
|  |    [167,  37, 170], | ||||||
|  |    [170,  38, 169], | ||||||
|  |    [172,  38, 167], | ||||||
|  |    [174,  39, 166], | ||||||
|  |    [176,  39, 165], | ||||||
|  |    [178,  40, 163], | ||||||
|  |    [180,  41, 162], | ||||||
|  |    [182,  41, 160], | ||||||
|  |    [183,  42, 159], | ||||||
|  |    [185,  43, 157], | ||||||
|  |    [187,  44, 155], | ||||||
|  |    [189,  45, 154], | ||||||
|  |    [191,  45, 152], | ||||||
|  |    [193,  46, 150], | ||||||
|  |    [195,  47, 149], | ||||||
|  |    [196,  48, 147], | ||||||
|  |    [198,  49, 145], | ||||||
|  |    [200,  50, 143], | ||||||
|  |    [202,  51, 141], | ||||||
|  |    [203,  53, 139], | ||||||
|  |    [205,  54, 138], | ||||||
|  |    [207,  55, 136], | ||||||
|  |    [208,  56, 134], | ||||||
|  |    [210,  57, 132], | ||||||
|  |    [211,  59, 130], | ||||||
|  |    [213,  60, 128], | ||||||
|  |    [214,  61, 126], | ||||||
|  |    [216,  63, 124], | ||||||
|  |    [217,  64, 122], | ||||||
|  |    [219,  65, 120], | ||||||
|  |    [220,  67, 118], | ||||||
|  |    [222,  68, 116], | ||||||
|  |    [223,  70, 114], | ||||||
|  |    [224,  71, 112], | ||||||
|  |    [226,  72, 110], | ||||||
|  |    [227,  74, 108], | ||||||
|  |    [228,  75, 106], | ||||||
|  |    [230,  77, 104], | ||||||
|  |    [231,  78, 102], | ||||||
|  |    [232,  80, 100], | ||||||
|  |    [233,  81,  98], | ||||||
|  |    [234,  83,  96], | ||||||
|  |    [236,  84,  94], | ||||||
|  |    [237,  86,  92], | ||||||
|  |    [238,  87,  91], | ||||||
|  |    [239,  89,  89], | ||||||
|  |    [240,  91,  87], | ||||||
|  |    [241,  92,  85], | ||||||
|  |    [242,  94,  83], | ||||||
|  |    [243,  96,  81], | ||||||
|  |    [244,  97,  79], | ||||||
|  |    [245,  99,  77], | ||||||
|  |    [246, 101,  75], | ||||||
|  |    [247, 102,  73], | ||||||
|  |    [248, 104,  71], | ||||||
|  |    [249, 106,  69], | ||||||
|  |    [249, 108,  67], | ||||||
|  |    [250, 110,  65], | ||||||
|  |    [251, 111,  63], | ||||||
|  |    [251, 113,  61], | ||||||
|  |    [252, 115,  59], | ||||||
|  |    [253, 117,  57], | ||||||
|  |    [253, 119,  55], | ||||||
|  |    [254, 121,  53], | ||||||
|  |    [254, 123,  51], | ||||||
|  |    [254, 125,  49], | ||||||
|  |    [255, 127,  48], | ||||||
|  |    [255, 129,  46], | ||||||
|  |    [255, 131,  44], | ||||||
|  |    [255, 134,  43], | ||||||
|  |    [255, 136,  41], | ||||||
|  |    [255, 138,  40], | ||||||
|  |    [255, 140,  39], | ||||||
|  |    [255, 142,  38], | ||||||
|  |    [255, 145,  37], | ||||||
|  |    [255, 147,  36], | ||||||
|  |    [255, 149,  35], | ||||||
|  |    [255, 151,  35], | ||||||
|  |    [254, 154,  35], | ||||||
|  |    [254, 156,  36], | ||||||
|  |    [253, 158,  36], | ||||||
|  |    [253, 161,  37], | ||||||
|  |    [252, 163,  38], | ||||||
|  |    [252, 166,  40], | ||||||
|  |    [251, 168,  41], | ||||||
|  |    [250, 170,  43], | ||||||
|  |    [249, 173,  45], | ||||||
|  |    [248, 175,  48], | ||||||
|  |    [248, 177,  50], | ||||||
|  |    [247, 180,  53], | ||||||
|  |    [246, 182,  56], | ||||||
|  |    [245, 185,  59], | ||||||
|  |    [244, 187,  63], | ||||||
|  |    [242, 189,  66], | ||||||
|  |    [241, 192,  70], | ||||||
|  |    [240, 194,  73], | ||||||
|  |    [239, 196,  77], | ||||||
|  |    [238, 198,  81], | ||||||
|  |    [237, 200,  85], | ||||||
|  |    [236, 203,  90], | ||||||
|  |    [234, 205,  94], | ||||||
|  |    [233, 207,  99], | ||||||
|  |    [232, 209, 103], | ||||||
|  |    [231, 211, 108], | ||||||
|  |    [230, 213, 112], | ||||||
|  |    [229, 215, 117], | ||||||
|  |    [228, 217, 122], | ||||||
|  |    [227, 219, 127], | ||||||
|  |    [227, 220, 132], | ||||||
|  |    [226, 222, 137], | ||||||
|  |    [226, 224, 142], | ||||||
|  |    [225, 225, 147], | ||||||
|  |    [225, 227, 152], | ||||||
|  |    [225, 228, 157], | ||||||
|  |    [225, 230, 163], | ||||||
|  |    [225, 231, 168], | ||||||
|  |    [225, 233, 173], | ||||||
|  |    [226, 234, 178], | ||||||
|  |    [226, 235, 183], | ||||||
|  |    [227, 236, 188], | ||||||
|  |    [228, 237, 192], | ||||||
|  |    [229, 238, 197], | ||||||
|  |    [230, 239, 202], | ||||||
|  |    [232, 240, 206], | ||||||
|  |    [233, 241, 211], | ||||||
|  |    [235, 242, 215], | ||||||
|  |    [236, 243, 219], | ||||||
|  |    [238, 244, 223], | ||||||
|  |    [240, 245, 227], | ||||||
|  |    [242, 245, 231], | ||||||
|  |    [244, 246, 235], | ||||||
|  |    [247, 247, 238], | ||||||
|  |    [249, 248, 241], | ||||||
|  |    [251, 248, 245], | ||||||
|  |    [253, 249, 247], | ||||||
|  |    [255, 250, 250], | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | const unsigned char selColormap[256][3] = [ | ||||||
|  |    [ 77,  77,  77], | ||||||
|  |    [ 77,  77,  77], | ||||||
|  |    [ 77,  77,  77], | ||||||
|  |    [ 77,  77,  77], | ||||||
|  |    [ 77,  77,  77], | ||||||
|  |    [ 77,  78,  77], | ||||||
|  |    [ 77,  78,  78], | ||||||
|  |    [ 77,  78,  78], | ||||||
|  |    [ 77,  79,  79], | ||||||
|  |    [ 78,  80,  79], | ||||||
|  |    [ 78,  80,  80], | ||||||
|  |    [ 78,  81,  81], | ||||||
|  |    [ 78,  82,  82], | ||||||
|  |    [ 78,  83,  83], | ||||||
|  |    [ 78,  84,  84], | ||||||
|  |    [ 78,  85,  85], | ||||||
|  |    [ 78,  86,  86], | ||||||
|  |    [ 78,  87,  87], | ||||||
|  |    [ 78,  88,  88], | ||||||
|  |    [ 78,  89,  89], | ||||||
|  |    [ 78,  90,  91], | ||||||
|  |    [ 78,  91,  92], | ||||||
|  |    [ 78,  91,  93], | ||||||
|  |    [ 78,  92,  94], | ||||||
|  |    [ 78,  93,  96], | ||||||
|  |    [ 77,  94,  97], | ||||||
|  |    [ 77,  95,  98], | ||||||
|  |    [ 77,  96, 100], | ||||||
|  |    [ 77,  97, 101], | ||||||
|  |    [ 76,  98, 103], | ||||||
|  |    [ 76,  99, 104], | ||||||
|  |    [ 76, 100, 105], | ||||||
|  |    [ 75, 100, 107], | ||||||
|  |    [ 75, 101, 109], | ||||||
|  |    [ 75, 102, 110], | ||||||
|  |    [ 74, 103, 112], | ||||||
|  |    [ 74, 104, 113], | ||||||
|  |    [ 74, 105, 115], | ||||||
|  |    [ 73, 105, 117], | ||||||
|  |    [ 73, 106, 118], | ||||||
|  |    [ 72, 107, 120], | ||||||
|  |    [ 72, 108, 122], | ||||||
|  |    [ 72, 108, 124], | ||||||
|  |    [ 72, 109, 126], | ||||||
|  |    [ 72, 110, 127], | ||||||
|  |    [ 72, 110, 129], | ||||||
|  |    [ 72, 111, 131], | ||||||
|  |    [ 72, 112, 133], | ||||||
|  |    [ 72, 112, 135], | ||||||
|  |    [ 72, 113, 137], | ||||||
|  |    [ 73, 113, 139], | ||||||
|  |    [ 74, 114, 141], | ||||||
|  |    [ 75, 115, 143], | ||||||
|  |    [ 76, 115, 146], | ||||||
|  |    [ 77, 116, 148], | ||||||
|  |    [ 79, 116, 150], | ||||||
|  |    [ 80, 116, 152], | ||||||
|  |    [ 82, 117, 154], | ||||||
|  |    [ 85, 117, 156], | ||||||
|  |    [ 87, 117, 158], | ||||||
|  |    [ 90, 118, 161], | ||||||
|  |    [ 92, 118, 163], | ||||||
|  |    [ 94, 118, 165], | ||||||
|  |    [ 96, 118, 167], | ||||||
|  |    [ 98, 119, 169], | ||||||
|  |    [101, 119, 171], | ||||||
|  |    [103, 119, 173], | ||||||
|  |    [105, 119, 176], | ||||||
|  |    [107, 119, 178], | ||||||
|  |    [109, 119, 180], | ||||||
|  |    [111, 119, 182], | ||||||
|  |    [113, 119, 184], | ||||||
|  |    [116, 119, 186], | ||||||
|  |    [118, 119, 188], | ||||||
|  |    [120, 118, 190], | ||||||
|  |    [122, 118, 192], | ||||||
|  |    [124, 118, 193], | ||||||
|  |    [126, 118, 195], | ||||||
|  |    [128, 118, 197], | ||||||
|  |    [131, 117, 199], | ||||||
|  |    [133, 117, 200], | ||||||
|  |    [135, 117, 202], | ||||||
|  |    [137, 116, 203], | ||||||
|  |    [139, 116, 205], | ||||||
|  |    [141, 115, 206], | ||||||
|  |    [143, 115, 208], | ||||||
|  |    [146, 115, 209], | ||||||
|  |    [148, 114, 210], | ||||||
|  |    [150, 114, 211], | ||||||
|  |    [152, 113, 212], | ||||||
|  |    [154, 113, 213], | ||||||
|  |    [156, 112, 214], | ||||||
|  |    [158, 112, 215], | ||||||
|  |    [160, 111, 216], | ||||||
|  |    [162, 111, 217], | ||||||
|  |    [164, 110, 217], | ||||||
|  |    [166, 110, 218], | ||||||
|  |    [168, 110, 219], | ||||||
|  |    [170, 109, 219], | ||||||
|  |    [172, 109, 219], | ||||||
|  |    [174, 108, 220], | ||||||
|  |    [176, 108, 220], | ||||||
|  |    [178, 107, 220], | ||||||
|  |    [180, 107, 220], | ||||||
|  |    [182, 107, 220], | ||||||
|  |    [184, 106, 220], | ||||||
|  |    [186, 106, 220], | ||||||
|  |    [187, 106, 220], | ||||||
|  |    [189, 106, 220], | ||||||
|  |    [191, 106, 219], | ||||||
|  |    [193, 105, 219], | ||||||
|  |    [195, 105, 219], | ||||||
|  |    [197, 105, 218], | ||||||
|  |    [198, 105, 218], | ||||||
|  |    [200, 105, 217], | ||||||
|  |    [202, 105, 216], | ||||||
|  |    [204, 105, 216], | ||||||
|  |    [205, 106, 215], | ||||||
|  |    [207, 106, 214], | ||||||
|  |    [209, 106, 213], | ||||||
|  |    [210, 106, 212], | ||||||
|  |    [212, 107, 211], | ||||||
|  |    [214, 107, 210], | ||||||
|  |    [215, 108, 209], | ||||||
|  |    [217, 108, 208], | ||||||
|  |    [219, 108, 207], | ||||||
|  |    [220, 109, 206], | ||||||
|  |    [222, 110, 205], | ||||||
|  |    [223, 110, 203], | ||||||
|  |    [225, 111, 202], | ||||||
|  |    [226, 111, 201], | ||||||
|  |    [228, 112, 200], | ||||||
|  |    [229, 113, 198], | ||||||
|  |    [231, 114, 197], | ||||||
|  |    [232, 114, 195], | ||||||
|  |    [234, 115, 194], | ||||||
|  |    [235, 116, 193], | ||||||
|  |    [236, 117, 191], | ||||||
|  |    [238, 118, 190], | ||||||
|  |    [239, 119, 188], | ||||||
|  |    [240, 120, 187], | ||||||
|  |    [242, 120, 185], | ||||||
|  |    [243, 121, 183], | ||||||
|  |    [244, 122, 182], | ||||||
|  |    [246, 123, 180], | ||||||
|  |    [247, 124, 179], | ||||||
|  |    [248, 126, 177], | ||||||
|  |    [249, 127, 176], | ||||||
|  |    [250, 128, 174], | ||||||
|  |    [252, 129, 173], | ||||||
|  |    [253, 130, 171], | ||||||
|  |    [254, 131, 169], | ||||||
|  |    [255, 132, 168], | ||||||
|  |    [255, 133, 166], | ||||||
|  |    [255, 134, 165], | ||||||
|  |    [255, 136, 163], | ||||||
|  |    [255, 137, 162], | ||||||
|  |    [255, 138, 160], | ||||||
|  |    [255, 139, 158], | ||||||
|  |    [255, 140, 157], | ||||||
|  |    [255, 142, 155], | ||||||
|  |    [255, 143, 154], | ||||||
|  |    [255, 144, 152], | ||||||
|  |    [255, 145, 150], | ||||||
|  |    [255, 146, 149], | ||||||
|  |    [255, 148, 147], | ||||||
|  |    [255, 149, 146], | ||||||
|  |    [255, 150, 144], | ||||||
|  |    [255, 152, 143], | ||||||
|  |    [255, 153, 141], | ||||||
|  |    [255, 154, 139], | ||||||
|  |    [255, 156, 138], | ||||||
|  |    [255, 157, 136], | ||||||
|  |    [255, 158, 135], | ||||||
|  |    [255, 160, 133], | ||||||
|  |    [255, 161, 131], | ||||||
|  |    [255, 163, 130], | ||||||
|  |    [255, 164, 128], | ||||||
|  |    [255, 166, 127], | ||||||
|  |    [255, 167, 125], | ||||||
|  |    [255, 169, 124], | ||||||
|  |    [255, 170, 122], | ||||||
|  |    [255, 172, 120], | ||||||
|  |    [255, 173, 119], | ||||||
|  |    [255, 175, 117], | ||||||
|  |    [255, 177, 116], | ||||||
|  |    [255, 178, 115], | ||||||
|  |    [255, 180, 113], | ||||||
|  |    [255, 182, 112], | ||||||
|  |    [255, 183, 111], | ||||||
|  |    [255, 185, 109], | ||||||
|  |    [255, 187, 108], | ||||||
|  |    [255, 189, 107], | ||||||
|  |    [255, 190, 107], | ||||||
|  |    [255, 192, 106], | ||||||
|  |    [255, 194, 105], | ||||||
|  |    [255, 196, 105], | ||||||
|  |    [255, 198, 105], | ||||||
|  |    [255, 200, 105], | ||||||
|  |    [255, 201, 105], | ||||||
|  |    [255, 203, 105], | ||||||
|  |    [255, 205, 106], | ||||||
|  |    [255, 207, 107], | ||||||
|  |    [255, 209, 108], | ||||||
|  |    [255, 211, 109], | ||||||
|  |    [255, 213, 111], | ||||||
|  |    [255, 215, 113], | ||||||
|  |    [255, 217, 115], | ||||||
|  |    [255, 218, 117], | ||||||
|  |    [255, 220, 119], | ||||||
|  |    [255, 222, 121], | ||||||
|  |    [255, 224, 124], | ||||||
|  |    [255, 226, 127], | ||||||
|  |    [255, 228, 129], | ||||||
|  |    [255, 230, 132], | ||||||
|  |    [255, 232, 135], | ||||||
|  |    [255, 233, 138], | ||||||
|  |    [255, 235, 142], | ||||||
|  |    [255, 237, 145], | ||||||
|  |    [255, 239, 148], | ||||||
|  |    [255, 240, 152], | ||||||
|  |    [255, 242, 155], | ||||||
|  |    [255, 244, 159], | ||||||
|  |    [255, 245, 163], | ||||||
|  |    [255, 247, 166], | ||||||
|  |    [255, 248, 170], | ||||||
|  |    [255, 250, 174], | ||||||
|  |    [255, 251, 178], | ||||||
|  |    [255, 253, 182], | ||||||
|  |    [255, 254, 186], | ||||||
|  |    [255, 255, 190], | ||||||
|  |    [255, 255, 194], | ||||||
|  |    [255, 255, 198], | ||||||
|  |    [255, 255, 202], | ||||||
|  |    [255, 255, 207], | ||||||
|  |    [255, 255, 211], | ||||||
|  |    [255, 255, 215], | ||||||
|  |    [255, 255, 219], | ||||||
|  |    [255, 255, 223], | ||||||
|  |    [255, 255, 227], | ||||||
|  |    [255, 255, 230], | ||||||
|  |    [255, 255, 234], | ||||||
|  |    [255, 255, 238], | ||||||
|  |    [255, 255, 242], | ||||||
|  |    [255, 255, 245], | ||||||
|  |    [255, 255, 249], | ||||||
|  |    [255, 255, 252], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | const unsigned char freqSelColormap[256][3] = [ | ||||||
|  |    [ 62,  65,  89], | ||||||
|  |    [ 63,  65,  91], | ||||||
|  |    [ 64,  66,  92], | ||||||
|  |    [ 65,  66,  94], | ||||||
|  |    [ 66,  66,  95], | ||||||
|  |    [ 67,  67,  97], | ||||||
|  |    [ 68,  67,  98], | ||||||
|  |    [ 70,  67, 100], | ||||||
|  |    [ 71,  68, 101], | ||||||
|  |    [ 72,  68, 103], | ||||||
|  |    [ 74,  68, 104], | ||||||
|  |    [ 75,  69, 106], | ||||||
|  |    [ 76,  69, 107], | ||||||
|  |    [ 78,  69, 109], | ||||||
|  |    [ 79,  69, 110], | ||||||
|  |    [ 81,  69, 112], | ||||||
|  |    [ 82,  70, 113], | ||||||
|  |    [ 84,  70, 115], | ||||||
|  |    [ 86,  70, 116], | ||||||
|  |    [ 87,  70, 118], | ||||||
|  |    [ 89,  70, 119], | ||||||
|  |    [ 91,  70, 120], | ||||||
|  |    [ 92,  70, 122], | ||||||
|  |    [ 94,  70, 123], | ||||||
|  |    [ 96,  70, 124], | ||||||
|  |    [ 98,  70, 126], | ||||||
|  |    [100,  70, 127], | ||||||
|  |    [102,  70, 128], | ||||||
|  |    [104,  70, 129], | ||||||
|  |    [106,  69, 130], | ||||||
|  |    [108,  69, 132], | ||||||
|  |    [110,  69, 133], | ||||||
|  |    [112,  69, 134], | ||||||
|  |    [114,  69, 135], | ||||||
|  |    [116,  68, 136], | ||||||
|  |    [118,  68, 137], | ||||||
|  |    [120,  68, 138], | ||||||
|  |    [122,  67, 138], | ||||||
|  |    [124,  67, 139], | ||||||
|  |    [126,  66, 140], | ||||||
|  |    [129,  66, 141], | ||||||
|  |    [131,  65, 141], | ||||||
|  |    [133,  65, 142], | ||||||
|  |    [135,  64, 142], | ||||||
|  |    [138,  64, 142], | ||||||
|  |    [140,  63, 143], | ||||||
|  |    [142,  63, 143], | ||||||
|  |    [144,  62, 143], | ||||||
|  |    [147,  61, 143], | ||||||
|  |    [149,  61, 143], | ||||||
|  |    [151,  60, 143], | ||||||
|  |    [153,  59, 143], | ||||||
|  |    [156,  59, 142], | ||||||
|  |    [158,  58, 142], | ||||||
|  |    [160,  57, 141], | ||||||
|  |    [162,  57, 141], | ||||||
|  |    [165,  56, 140], | ||||||
|  |    [167,  55, 139], | ||||||
|  |    [169,  55, 138], | ||||||
|  |    [171,  54, 137], | ||||||
|  |    [173,  53, 136], | ||||||
|  |    [176,  53, 135], | ||||||
|  |    [178,  52, 134], | ||||||
|  |    [180,  51, 133], | ||||||
|  |    [182,  51, 131], | ||||||
|  |    [184,  50, 130], | ||||||
|  |    [186,  50, 128], | ||||||
|  |    [188,  49, 127], | ||||||
|  |    [190,  49, 125], | ||||||
|  |    [192,  49, 123], | ||||||
|  |    [194,  48, 121], | ||||||
|  |    [196,  48, 119], | ||||||
|  |    [198,  48, 117], | ||||||
|  |    [200,  48, 115], | ||||||
|  |    [202,  48, 113], | ||||||
|  |    [203,  47, 110], | ||||||
|  |    [205,  47, 108], | ||||||
|  |    [207,  48, 106], | ||||||
|  |    [209,  48, 103], | ||||||
|  |    [210,  48, 101], | ||||||
|  |    [212,  48,  98], | ||||||
|  |    [214,  48,  96], | ||||||
|  |    [215,  49,  93], | ||||||
|  |    [217,  49,  91], | ||||||
|  |    [218,  50,  88], | ||||||
|  |    [220,  50,  85], | ||||||
|  |    [221,  51,  83], | ||||||
|  |    [223,  52,  80], | ||||||
|  |    [224,  53,  77], | ||||||
|  |    [225,  54,  74], | ||||||
|  |    [226,  55,  71], | ||||||
|  |    [228,  56,  68], | ||||||
|  |    [229,  57,  65], | ||||||
|  |    [230,  58,  62], | ||||||
|  |    [231,  59,  59], | ||||||
|  |    [232,  60,  56], | ||||||
|  |    [233,  62,  53], | ||||||
|  |    [234,  63,  49], | ||||||
|  |    [235,  64,  46], | ||||||
|  |    [236,  66,  42], | ||||||
|  |    [237,  67,  38], | ||||||
|  |    [238,  69,  35], | ||||||
|  |    [239,  71,  30], | ||||||
|  |    [239,  72,  26], | ||||||
|  |    [240,  74,  20], | ||||||
|  |    [241,  76,  14], | ||||||
|  |    [241,  77,   5], | ||||||
|  |    [242,  79,   0], | ||||||
|  |    [243,  81,   0], | ||||||
|  |    [243,  83,   0], | ||||||
|  |    [244,  85,   0], | ||||||
|  |    [244,  87,   0], | ||||||
|  |    [244,  89,   0], | ||||||
|  |    [245,  91,   0], | ||||||
|  |    [245,  93,   0], | ||||||
|  |    [245,  95,   0], | ||||||
|  |    [245,  97,   0], | ||||||
|  |    [245,  99,   0], | ||||||
|  |    [245, 101,   0], | ||||||
|  |    [245, 103,   0], | ||||||
|  |    [245, 105,   0], | ||||||
|  |    [245, 108,   0], | ||||||
|  |    [245, 110,   0], | ||||||
|  |    [245, 112,   0], | ||||||
|  |    [245, 114,   0], | ||||||
|  |    [244, 116,   0], | ||||||
|  |    [244, 119,   0], | ||||||
|  |    [243, 121,   0], | ||||||
|  |    [243, 123,   0], | ||||||
|  |    [242, 126,   0], | ||||||
|  |    [242, 128,   0], | ||||||
|  |    [241, 130,   0], | ||||||
|  |    [241, 132,   0], | ||||||
|  |    [240, 135,   0], | ||||||
|  |    [239, 137,   0], | ||||||
|  |    [238, 139,   0], | ||||||
|  |    [237, 142,   0], | ||||||
|  |    [236, 144,   0], | ||||||
|  |    [235, 146,   0], | ||||||
|  |    [234, 149,   0], | ||||||
|  |    [233, 151,   0], | ||||||
|  |    [232, 154,   0], | ||||||
|  |    [230, 156,   0], | ||||||
|  |    [229, 158,   0], | ||||||
|  |    [227, 161,   0], | ||||||
|  |    [226, 163,   0], | ||||||
|  |    [224, 165,   0], | ||||||
|  |    [223, 168,   0], | ||||||
|  |    [221, 170,   0], | ||||||
|  |    [219, 173,   0], | ||||||
|  |    [217, 175,   0], | ||||||
|  |    [215, 177,   0], | ||||||
|  |    [213, 180,   0], | ||||||
|  |    [211, 182,   0], | ||||||
|  |    [209, 184,   0], | ||||||
|  |    [207, 187,   0], | ||||||
|  |    [205, 189,   0], | ||||||
|  |    [202, 191,   0], | ||||||
|  |    [200, 193,   0], | ||||||
|  |    [197, 196,   0], | ||||||
|  |    [195, 198,   0], | ||||||
|  |    [192, 200,   0], | ||||||
|  |    [189, 203,   0], | ||||||
|  |    [186, 205,   0], | ||||||
|  |    [183, 207,   0], | ||||||
|  |    [180, 209,   0], | ||||||
|  |    [177, 211,   0], | ||||||
|  |    [174, 214,   0], | ||||||
|  |    [170, 216,   0], | ||||||
|  |    [167, 218,   0], | ||||||
|  |    [163, 220,   0], | ||||||
|  |    [159, 222,   0], | ||||||
|  |    [155, 225,   0], | ||||||
|  |    [151, 227,   0], | ||||||
|  |    [147, 229,   0], | ||||||
|  |    [142, 231,   0], | ||||||
|  |    [137, 233,  10], | ||||||
|  |    [132, 235,  24], | ||||||
|  |    [127, 237,  34], | ||||||
|  |    [121, 239,  42], | ||||||
|  |    [116, 241,  50], | ||||||
|  |    [109, 243,  56], | ||||||
|  |    [103, 245,  63], | ||||||
|  |    [ 95, 247,  69], | ||||||
|  |    [ 88, 249,  75], | ||||||
|  |    [ 79, 251,  80], | ||||||
|  |    [ 69, 253,  86], | ||||||
|  |    [ 57, 255,  91], | ||||||
|  |    [ 42, 255,  97], | ||||||
|  |    [ 18, 255, 102], | ||||||
|  |    [  0, 255, 107], | ||||||
|  |    [  0, 255, 113], | ||||||
|  |    [  0, 255, 118], | ||||||
|  |    [  0, 255, 123], | ||||||
|  |    [  0, 255, 129], | ||||||
|  |    [  0, 255, 134], | ||||||
|  |    [  0, 255, 139], | ||||||
|  |    [  0, 255, 144], | ||||||
|  |    [  0, 255, 149], | ||||||
|  |    [  0, 255, 155], | ||||||
|  |    [  0, 255, 160], | ||||||
|  |    [  0, 255, 165], | ||||||
|  |    [  0, 255, 170], | ||||||
|  |    [  0, 255, 175], | ||||||
|  |    [  0, 255, 180], | ||||||
|  |    [  0, 255, 185], | ||||||
|  |    [  0, 255, 190], | ||||||
|  |    [  0, 255, 195], | ||||||
|  |    [  0, 255, 200], | ||||||
|  |    [  0, 255, 205], | ||||||
|  |    [  0, 255, 210], | ||||||
|  |    [  0, 255, 214], | ||||||
|  |    [  0, 255, 219], | ||||||
|  |    [  0, 255, 223], | ||||||
|  |    [  0, 255, 228], | ||||||
|  |    [  0, 255, 232], | ||||||
|  |    [  0, 255, 237], | ||||||
|  |    [  0, 255, 241], | ||||||
|  |    [  0, 255, 245], | ||||||
|  |    [  0, 255, 249], | ||||||
|  |    [  0, 255, 253], | ||||||
|  |    [  0, 255, 255], | ||||||
|  |    [  0, 255, 255], | ||||||
|  |    [ 21, 255, 255], | ||||||
|  |    [ 50, 255, 255], | ||||||
|  |    [ 68, 255, 255], | ||||||
|  |    [ 82, 255, 255], | ||||||
|  |    [ 95, 255, 255], | ||||||
|  |    [106, 255, 255], | ||||||
|  |    [116, 255, 255], | ||||||
|  |    [126, 255, 255], | ||||||
|  |    [135, 255, 255], | ||||||
|  |    [143, 255, 255], | ||||||
|  |    [151, 255, 255], | ||||||
|  |    [159, 255, 255], | ||||||
|  |    [166, 255, 255], | ||||||
|  |    [173, 255, 255], | ||||||
|  |    [180, 255, 255], | ||||||
|  |    [187, 255, 255], | ||||||
|  |    [193, 255, 255], | ||||||
|  |    [199, 255, 255], | ||||||
|  |    [205, 255, 255], | ||||||
|  |    [211, 255, 255], | ||||||
|  |    [216, 255, 255], | ||||||
|  |    [222, 255, 255], | ||||||
|  |    [227, 255, 255], | ||||||
|  |    [232, 255, 255], | ||||||
|  |    [237, 255, 255], | ||||||
|  |    [241, 255, 255], | ||||||
|  |    [246, 255, 255], | ||||||
|  |    [250, 255, 255], | ||||||
|  |    [254, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 253], | ||||||
|  | ]; | ||||||
|  |  | ||||||
							
								
								
									
										303
									
								
								spectro/run.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								spectro/run.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,303 @@ | |||||||
|  | colorscheme = [ | ||||||
|  |    [ 77,  77,  77], | ||||||
|  |    [ 77,  77,  77], | ||||||
|  |    [ 77,  77,  77], | ||||||
|  |    [ 77,  77,  77], | ||||||
|  |    [ 77,  77,  77], | ||||||
|  |    [ 77,  78,  77], | ||||||
|  |    [ 77,  78,  78], | ||||||
|  |    [ 77,  78,  78], | ||||||
|  |    [ 77,  79,  79], | ||||||
|  |    [ 78,  80,  79], | ||||||
|  |    [ 78,  80,  80], | ||||||
|  |    [ 78,  81,  81], | ||||||
|  |    [ 78,  82,  82], | ||||||
|  |    [ 78,  83,  83], | ||||||
|  |    [ 78,  84,  84], | ||||||
|  |    [ 78,  85,  85], | ||||||
|  |    [ 78,  86,  86], | ||||||
|  |    [ 78,  87,  87], | ||||||
|  |    [ 78,  88,  88], | ||||||
|  |    [ 78,  89,  89], | ||||||
|  |    [ 78,  90,  91], | ||||||
|  |    [ 78,  91,  92], | ||||||
|  |    [ 78,  91,  93], | ||||||
|  |    [ 78,  92,  94], | ||||||
|  |    [ 78,  93,  96], | ||||||
|  |    [ 77,  94,  97], | ||||||
|  |    [ 77,  95,  98], | ||||||
|  |    [ 77,  96, 100], | ||||||
|  |    [ 77,  97, 101], | ||||||
|  |    [ 76,  98, 103], | ||||||
|  |    [ 76,  99, 104], | ||||||
|  |    [ 76, 100, 105], | ||||||
|  |    [ 75, 100, 107], | ||||||
|  |    [ 75, 101, 109], | ||||||
|  |    [ 75, 102, 110], | ||||||
|  |    [ 74, 103, 112], | ||||||
|  |    [ 74, 104, 113], | ||||||
|  |    [ 74, 105, 115], | ||||||
|  |    [ 73, 105, 117], | ||||||
|  |    [ 73, 106, 118], | ||||||
|  |    [ 72, 107, 120], | ||||||
|  |    [ 72, 108, 122], | ||||||
|  |    [ 72, 108, 124], | ||||||
|  |    [ 72, 109, 126], | ||||||
|  |    [ 72, 110, 127], | ||||||
|  |    [ 72, 110, 129], | ||||||
|  |    [ 72, 111, 131], | ||||||
|  |    [ 72, 112, 133], | ||||||
|  |    [ 72, 112, 135], | ||||||
|  |    [ 72, 113, 137], | ||||||
|  |    [ 73, 113, 139], | ||||||
|  |    [ 74, 114, 141], | ||||||
|  |    [ 75, 115, 143], | ||||||
|  |    [ 76, 115, 146], | ||||||
|  |    [ 77, 116, 148], | ||||||
|  |    [ 79, 116, 150], | ||||||
|  |    [ 80, 116, 152], | ||||||
|  |    [ 82, 117, 154], | ||||||
|  |    [ 85, 117, 156], | ||||||
|  |    [ 87, 117, 158], | ||||||
|  |    [ 90, 118, 161], | ||||||
|  |    [ 92, 118, 163], | ||||||
|  |    [ 94, 118, 165], | ||||||
|  |    [ 96, 118, 167], | ||||||
|  |    [ 98, 119, 169], | ||||||
|  |    [101, 119, 171], | ||||||
|  |    [103, 119, 173], | ||||||
|  |    [105, 119, 176], | ||||||
|  |    [107, 119, 178], | ||||||
|  |    [109, 119, 180], | ||||||
|  |    [111, 119, 182], | ||||||
|  |    [113, 119, 184], | ||||||
|  |    [116, 119, 186], | ||||||
|  |    [118, 119, 188], | ||||||
|  |    [120, 118, 190], | ||||||
|  |    [122, 118, 192], | ||||||
|  |    [124, 118, 193], | ||||||
|  |    [126, 118, 195], | ||||||
|  |    [128, 118, 197], | ||||||
|  |    [131, 117, 199], | ||||||
|  |    [133, 117, 200], | ||||||
|  |    [135, 117, 202], | ||||||
|  |    [137, 116, 203], | ||||||
|  |    [139, 116, 205], | ||||||
|  |    [141, 115, 206], | ||||||
|  |    [143, 115, 208], | ||||||
|  |    [146, 115, 209], | ||||||
|  |    [148, 114, 210], | ||||||
|  |    [150, 114, 211], | ||||||
|  |    [152, 113, 212], | ||||||
|  |    [154, 113, 213], | ||||||
|  |    [156, 112, 214], | ||||||
|  |    [158, 112, 215], | ||||||
|  |    [160, 111, 216], | ||||||
|  |    [162, 111, 217], | ||||||
|  |    [164, 110, 217], | ||||||
|  |    [166, 110, 218], | ||||||
|  |    [168, 110, 219], | ||||||
|  |    [170, 109, 219], | ||||||
|  |    [172, 109, 219], | ||||||
|  |    [174, 108, 220], | ||||||
|  |    [176, 108, 220], | ||||||
|  |    [178, 107, 220], | ||||||
|  |    [180, 107, 220], | ||||||
|  |    [182, 107, 220], | ||||||
|  |    [184, 106, 220], | ||||||
|  |    [186, 106, 220], | ||||||
|  |    [187, 106, 220], | ||||||
|  |    [189, 106, 220], | ||||||
|  |    [191, 106, 219], | ||||||
|  |    [193, 105, 219], | ||||||
|  |    [195, 105, 219], | ||||||
|  |    [197, 105, 218], | ||||||
|  |    [198, 105, 218], | ||||||
|  |    [200, 105, 217], | ||||||
|  |    [202, 105, 216], | ||||||
|  |    [204, 105, 216], | ||||||
|  |    [205, 106, 215], | ||||||
|  |    [207, 106, 214], | ||||||
|  |    [209, 106, 213], | ||||||
|  |    [210, 106, 212], | ||||||
|  |    [212, 107, 211], | ||||||
|  |    [214, 107, 210], | ||||||
|  |    [215, 108, 209], | ||||||
|  |    [217, 108, 208], | ||||||
|  |    [219, 108, 207], | ||||||
|  |    [220, 109, 206], | ||||||
|  |    [222, 110, 205], | ||||||
|  |    [223, 110, 203], | ||||||
|  |    [225, 111, 202], | ||||||
|  |    [226, 111, 201], | ||||||
|  |    [228, 112, 200], | ||||||
|  |    [229, 113, 198], | ||||||
|  |    [231, 114, 197], | ||||||
|  |    [232, 114, 195], | ||||||
|  |    [234, 115, 194], | ||||||
|  |    [235, 116, 193], | ||||||
|  |    [236, 117, 191], | ||||||
|  |    [238, 118, 190], | ||||||
|  |    [239, 119, 188], | ||||||
|  |    [240, 120, 187], | ||||||
|  |    [242, 120, 185], | ||||||
|  |    [243, 121, 183], | ||||||
|  |    [244, 122, 182], | ||||||
|  |    [246, 123, 180], | ||||||
|  |    [247, 124, 179], | ||||||
|  |    [248, 126, 177], | ||||||
|  |    [249, 127, 176], | ||||||
|  |    [250, 128, 174], | ||||||
|  |    [252, 129, 173], | ||||||
|  |    [253, 130, 171], | ||||||
|  |    [254, 131, 169], | ||||||
|  |    [255, 132, 168], | ||||||
|  |    [255, 133, 166], | ||||||
|  |    [255, 134, 165], | ||||||
|  |    [255, 136, 163], | ||||||
|  |    [255, 137, 162], | ||||||
|  |    [255, 138, 160], | ||||||
|  |    [255, 139, 158], | ||||||
|  |    [255, 140, 157], | ||||||
|  |    [255, 142, 155], | ||||||
|  |    [255, 143, 154], | ||||||
|  |    [255, 144, 152], | ||||||
|  |    [255, 145, 150], | ||||||
|  |    [255, 146, 149], | ||||||
|  |    [255, 148, 147], | ||||||
|  |    [255, 149, 146], | ||||||
|  |    [255, 150, 144], | ||||||
|  |    [255, 152, 143], | ||||||
|  |    [255, 153, 141], | ||||||
|  |    [255, 154, 139], | ||||||
|  |    [255, 156, 138], | ||||||
|  |    [255, 157, 136], | ||||||
|  |    [255, 158, 135], | ||||||
|  |    [255, 160, 133], | ||||||
|  |    [255, 161, 131], | ||||||
|  |    [255, 163, 130], | ||||||
|  |    [255, 164, 128], | ||||||
|  |    [255, 166, 127], | ||||||
|  |    [255, 167, 125], | ||||||
|  |    [255, 169, 124], | ||||||
|  |    [255, 170, 122], | ||||||
|  |    [255, 172, 120], | ||||||
|  |    [255, 173, 119], | ||||||
|  |    [255, 175, 117], | ||||||
|  |    [255, 177, 116], | ||||||
|  |    [255, 178, 115], | ||||||
|  |    [255, 180, 113], | ||||||
|  |    [255, 182, 112], | ||||||
|  |    [255, 183, 111], | ||||||
|  |    [255, 185, 109], | ||||||
|  |    [255, 187, 108], | ||||||
|  |    [255, 189, 107], | ||||||
|  |    [255, 190, 107], | ||||||
|  |    [255, 192, 106], | ||||||
|  |    [255, 194, 105], | ||||||
|  |    [255, 196, 105], | ||||||
|  |    [255, 198, 105], | ||||||
|  |    [255, 200, 105], | ||||||
|  |    [255, 201, 105], | ||||||
|  |    [255, 203, 105], | ||||||
|  |    [255, 205, 106], | ||||||
|  |    [255, 207, 107], | ||||||
|  |    [255, 209, 108], | ||||||
|  |    [255, 211, 109], | ||||||
|  |    [255, 213, 111], | ||||||
|  |    [255, 215, 113], | ||||||
|  |    [255, 217, 115], | ||||||
|  |    [255, 218, 117], | ||||||
|  |    [255, 220, 119], | ||||||
|  |    [255, 222, 121], | ||||||
|  |    [255, 224, 124], | ||||||
|  |    [255, 226, 127], | ||||||
|  |    [255, 228, 129], | ||||||
|  |    [255, 230, 132], | ||||||
|  |    [255, 232, 135], | ||||||
|  |    [255, 233, 138], | ||||||
|  |    [255, 235, 142], | ||||||
|  |    [255, 237, 145], | ||||||
|  |    [255, 239, 148], | ||||||
|  |    [255, 240, 152], | ||||||
|  |    [255, 242, 155], | ||||||
|  |    [255, 244, 159], | ||||||
|  |    [255, 245, 163], | ||||||
|  |    [255, 247, 166], | ||||||
|  |    [255, 248, 170], | ||||||
|  |    [255, 250, 174], | ||||||
|  |    [255, 251, 178], | ||||||
|  |    [255, 253, 182], | ||||||
|  |    [255, 254, 186], | ||||||
|  |    [255, 255, 190], | ||||||
|  |    [255, 255, 194], | ||||||
|  |    [255, 255, 198], | ||||||
|  |    [255, 255, 202], | ||||||
|  |    [255, 255, 207], | ||||||
|  |    [255, 255, 211], | ||||||
|  |    [255, 255, 215], | ||||||
|  |    [255, 255, 219], | ||||||
|  |    [255, 255, 223], | ||||||
|  |    [255, 255, 227], | ||||||
|  |    [255, 255, 230], | ||||||
|  |    [255, 255, 234], | ||||||
|  |    [255, 255, 238], | ||||||
|  |    [255, 255, 242], | ||||||
|  |    [255, 255, 245], | ||||||
|  |    [255, 255, 249], | ||||||
|  |    [255, 255, 252], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  |    [255, 255, 255], | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | from PIL import Image | ||||||
|  | import numpy as np | ||||||
|  | import wave, math | ||||||
|  | import os, pickle | ||||||
|  |  | ||||||
|  | cols = np.array(colorscheme) | ||||||
|  |  | ||||||
|  | def nearest_color(x): | ||||||
|  |     return np.argmin(np.linalg.norm(x - cols, axis=1)) | ||||||
|  |  | ||||||
|  | im = np.array(Image.open("1200.png"))[:-1, ..., :3] | ||||||
|  | if not os.path.exists("save.pkl"): | ||||||
|  |     spectro = np.apply_along_axis(nearest_color, -1, im) | ||||||
|  |     pickle.dump(spectro, open("save.pkl", "wb")) | ||||||
|  | else: | ||||||
|  |     spectro = pickle.load(open("save.pkl", "rb")) | ||||||
|  | print(spectro) | ||||||
|  | samples = 48000 | ||||||
|  | actual_samples = samples * 4 # 4 seconds of audio time | ||||||
|  | print(im.shape) | ||||||
|  | spectro = spectro.transpose() # axis 0 is horizontal in image and axis 1 is vertical, probably | ||||||
|  | spectro = spectro.astype(np.float) | ||||||
|  | spectro -= spectro.min() | ||||||
|  | out = np.zeros(actual_samples) | ||||||
|  | ω = np.linspace(0, 10_000, num=im.shape[0]) * 2 * math.pi | ||||||
|  | for i in range(actual_samples): | ||||||
|  |     index = i / actual_samples * (im.shape[1] - 1) | ||||||
|  |     p, n = math.floor(index), math.ceil(index) | ||||||
|  |     d = index - p | ||||||
|  |     spec = spectro[p] * (1-d) + spectro[n] * d | ||||||
|  |     θ = ω * (i / samples) | ||||||
|  |     a = np.sin(θ * spec) | ||||||
|  |     out[i] = sum(a) | ||||||
|  |     if i % 1000 == 0: print(i) | ||||||
|  | print(out) | ||||||
|  | out /= max(out) | ||||||
|  | out *= 16384 | ||||||
|  | print(out) | ||||||
|  | data = out.astype("<i2") | ||||||
|  | with wave.open("out.wav", "wb") as w: | ||||||
|  |     w.setsampwidth(2) | ||||||
|  |     w.setnchannels(1) | ||||||
|  |     w.setframerate(samples) | ||||||
|  |     w.writeframes(data.tobytes()) | ||||||
							
								
								
									
										43
									
								
								yearbox.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								yearbox.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | <div id="table"></div> | ||||||
|  | <script> | ||||||
|  |     const year = 2023 | ||||||
|  |     const months = [31, 28 + (year % 4 === 0 ? (year % 100 === 0 ? (year % 400 === 0 ? 1 : 0) : 1) : 0), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] | ||||||
|  |     const weekdays = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"] | ||||||
|  |     const monthShortnames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nev", "Dec"] | ||||||
|  |     const shiftWeekday = x => { | ||||||
|  |         if (x === 0) x = 7 | ||||||
|  |         x -= 1 | ||||||
|  |         return x | ||||||
|  |     } | ||||||
|  |     const getWeekday = (y, m, d) => shiftWeekday(new Date(Date.parse(`${y}-${m}-${d}`)).getUTCDay()) | ||||||
|  |     let cols = 0 | ||||||
|  |     for (let month = 1; month <= 12; month++) { | ||||||
|  |         const len = months[month - 1] | ||||||
|  |         const start = getWeekday(year, month, 1) | ||||||
|  |         cols = Math.max(cols, len + start) | ||||||
|  |     } | ||||||
|  |     let html = `<table>` | ||||||
|  |     html += `<tr><th>${year}</th>` | ||||||
|  |     for (let i = 0; i < cols; i++) { | ||||||
|  |         html += `<th>${weekdays[i % 7]}</th>` | ||||||
|  |     } | ||||||
|  |     html += `</tr>` | ||||||
|  |     for (let month = 1; month <= 12; month++) { | ||||||
|  |         html += `<tr><th>${monthShortnames[month - 1]}</th>` | ||||||
|  |         let start = getWeekday(year, month, 1) | ||||||
|  |         for (let i = 0; i < start; i++) { | ||||||
|  |             html += `<td></td>` | ||||||
|  |         } | ||||||
|  |         let mlen = months[month - 1] | ||||||
|  |         for (let i = 0; i < mlen; i++) { | ||||||
|  |             html += `<td>${(i + 1).toString().padStart(2, "0")}</td>` | ||||||
|  |         } | ||||||
|  |         for (let i = 0; i < cols - mlen - start; i++) { | ||||||
|  |             html += `<td></td>` | ||||||
|  |         } | ||||||
|  |         html += `</tr>` | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     html += `</table>` | ||||||
|  |     window.table.innerHTML = html | ||||||
|  | </script> | ||||||
		Reference in New Issue
	
	Block a user