summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinteck <contact@minteck.org>2022-11-28 17:30:40 +0100
committerMinteck <contact@minteck.org>2022-11-28 17:30:40 +0100
commit0beaa17c10bd8fea776adaa08e41c1d543058c03 (patch)
treeef554bc27470ac257a554d228cfdd656ffb96e18
downloadmaneplace-timelapse-0beaa17c10bd8fea776adaa08e41c1d543058c03.tar.gz
maneplace-timelapse-0beaa17c10bd8fea776adaa08e41c1d543058c03.tar.bz2
maneplace-timelapse-0beaa17c10bd8fea776adaa08e41c1d543058c03.zip
Initial commit
-rw-r--r--.gitignore6
-rw-r--r--.idea/.gitignore8
-rw-r--r--.idea/deployment.xml21
-rw-r--r--.idea/discord.xml7
-rw-r--r--.idea/inspectionProfiles/profiles_settings.xml6
-rw-r--r--.idea/maneplace-timelapse.iml8
-rw-r--r--.idea/misc.xml4
-rw-r--r--.idea/modules.xml8
-rw-r--r--.idea/sshConfigs.xml8
-rw-r--r--.idea/webServers.xml14
-rw-r--r--initial.pngbin0 -> 21716 bytes
-rw-r--r--main.py186
-rw-r--r--main2.py159
-rw-r--r--user.py43
14 files changed, 478 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..50ed299
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+frame.png
+data.json
+frames
+users
+out.mp4
+out.webm
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/deployment.xml b/.idea/deployment.xml
new file mode 100644
index 0000000..a3f0ef4
--- /dev/null
+++ b/.idea/deployment.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="PublishConfigData" autoUpload="Always" serverName="zephyrheights" remoteFilesAllowedToDisappearOnAutoupload="false">
+ <serverData>
+ <paths name="zephyrheights">
+ <serverdata>
+ <mappings>
+ <mapping deploy="/mnt/maneplace-timelapse" local="$PROJECT_DIR$" web="/" />
+ </mappings>
+ <excludedPaths>
+ <excludedPath local="true" path="$PROJECT_DIR$/frames" />
+ <excludedPath local="true" path="$PROJECT_DIR$/data.json" />
+ <excludedPath local="true" path="$PROJECT_DIR$/out.webm" />
+ <excludedPath local="true" path="$PROJECT_DIR$/out.mp4" />
+ </excludedPaths>
+ </serverdata>
+ </paths>
+ </serverData>
+ <option name="myAutoUpload" value="ALWAYS" />
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/discord.xml b/.idea/discord.xml
new file mode 100644
index 0000000..d8e9561
--- /dev/null
+++ b/.idea/discord.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="DiscordProjectSettings">
+ <option name="show" value="PROJECT_FILES" />
+ <option name="description" value="" />
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+ <settings>
+ <option name="USE_PROJECT_PROFILE" value="false" />
+ <version value="1.0" />
+ </settings>
+</component> \ No newline at end of file
diff --git a/.idea/maneplace-timelapse.iml b/.idea/maneplace-timelapse.iml
new file mode 100644
index 0000000..d0876a7
--- /dev/null
+++ b/.idea/maneplace-timelapse.iml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+ <component name="NewModuleRootManager">
+ <content url="file://$MODULE_DIR$" />
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module> \ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..dc9ea49
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" />
+</project> \ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..d0ee548
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/.idea/maneplace-timelapse.iml" filepath="$PROJECT_DIR$/.idea/maneplace-timelapse.iml" />
+ </modules>
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/sshConfigs.xml b/.idea/sshConfigs.xml
new file mode 100644
index 0000000..ebf677e
--- /dev/null
+++ b/.idea/sshConfigs.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="SshConfigs">
+ <configs>
+ <sshConfig host="zephyrheights.equestria.dev" id="20eb5082-bb4d-4ccb-80b9-d1f885ee9ac8" keyPath="$USER_HOME$/.ssh/id_rsa" port="2222" nameFormat="DESCRIPTIVE" username="root" useOpenSSHConfig="true" />
+ </configs>
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/webServers.xml b/.idea/webServers.xml
new file mode 100644
index 0000000..3b5af2a
--- /dev/null
+++ b/.idea/webServers.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="WebServers">
+ <option name="servers">
+ <webServer id="b1a8137c-ae95-45e8-9689-f27e4b37f34b" name="zephyrheights">
+ <fileTransfer accessType="SFTP" host="zephyrheights.equestria.dev" port="2222" sshConfigId="20eb5082-bb4d-4ccb-80b9-d1f885ee9ac8" sshConfig="root@zephyrheights.equestria.dev:2222 key" keyPair="true">
+ <advancedOptions>
+ <advancedOptions dataProtectionLevel="Private" keepAliveTimeout="0" passiveMode="true" shareSSLContext="true" />
+ </advancedOptions>
+ </fileTransfer>
+ </webServer>
+ </option>
+ </component>
+</project> \ No newline at end of file
diff --git a/initial.png b/initial.png
new file mode 100644
index 0000000..5a7ef95
--- /dev/null
+++ b/initial.png
Binary files differ
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..44647e0
--- /dev/null
+++ b/main.py
@@ -0,0 +1,186 @@
+import json
+import time
+import shutil
+import os
+import datetime
+from PIL import Image
+
+divider = 60
+dates = {}
+
+try:
+ shutil.rmtree("./frames")
+except FileNotFoundError:
+ pass
+
+os.mkdir("./frames")
+
+data = json.load(open('data.json'))
+image = Image.open('initial.png')
+initial = Image.open('initial.png')
+image.save('frames/0000000000000000.png')
+
+total = len(data)
+
+
+def hex_to_rgb(value):
+ value = value.lstrip('#')
+ lv = len(value)
+ return tuple(int(value[i:i + lv // 3], 16) for i in range(0, lv, lv // 3))
+
+
+colors = [
+ "#6D001A",
+ "#BE0039",
+ "#FF4500",
+ "#FFA800",
+ "#FFD635",
+ "#FFF8B8",
+ "#00A368",
+ "#00CC78",
+ "#7EED56",
+ "#00756F",
+ "#009EAA",
+ "#00CCC0",
+ "#2450A4",
+ "#3690EA",
+ "#51E9F4",
+ "#493AC1",
+ "#6A5CFF",
+ "#94B3FF",
+ "#811E9F",
+ "#B44AC0",
+ "#E4ABFF",
+ "#DE107F",
+ "#FF3881",
+ "#FF99AA",
+ "#6D482F",
+ "#9C6926",
+ "#FFB470",
+ "#000000",
+ "#515252",
+ "#898D90",
+ "#D4D7D9",
+ "#FFFFFF",
+ "#ffff5c",
+ "#d9d94a",
+ "#ff7313",
+ "#fce07c",
+ "#bdbd3e",
+ "#c0aa19",
+ "#8f8fe0",
+ "#6b6bd1",
+ "#9efe90",
+ "#360082",
+ "#00ccff",
+ "#44b1ce",
+ "#4a2157",
+ "#d676e3",
+ "#abfbff",
+ "#a11461",
+ "#592d1b",
+ "#914724",
+ "#cc6d42",
+ "#ff8559",
+ "#ffd5ad",
+ "#d39748",
+ "#fa74a4",
+ "#ffd1dc",
+ "#679112",
+ "#d39648",
+ "#9fc455",
+ "#d5ebad",
+ "#adafb0",
+ "#793ccf",
+ "#a771f7",
+ "#d3bff5",
+]
+
+frame = 1
+frameFile = 1
+times = []
+
+for event in data:
+ percentage = "%.2f" % ((frame / total) * 100)
+ remaining = total - frame
+
+ if len(times) > 0:
+ avg = sum(times) / len(times)
+ else:
+ avg = 0
+
+ eta = None
+
+ if frame > 1000:
+ eta = avg * remaining
+
+ if eta is not None:
+ eta_seconds = round(eta / 1000000000)
+ eta_string = str(eta_seconds) + " seconds remaining"
+ done_by = datetime.datetime.fromtimestamp(round(time.time() + eta_seconds)).isoformat().split("T")[1]
+
+ if eta_seconds > 60:
+ if eta_seconds > 3600:
+ if round(eta_seconds / 3600) > 1:
+ eta_string = str(round(eta_seconds / 3600)) + " hours remaining"
+ else:
+ eta_string = str(round(eta_seconds / 3600)) + " hour remaining"
+ else:
+ if round(eta_seconds / 60) > 1:
+ eta_string = str(round(eta_seconds / 60)) + " minutes remaining"
+ else:
+ eta_string = str(round(eta_seconds / 60)) + " minute remaining"
+
+ print(f"\r{frame}/{total} ({percentage}% complete, {eta_string}, done at {done_by})", end="", flush=True)
+ else:
+ print(f"\r{frame}/{total} ({percentage}% complete, calculating...)", end="", flush=True)
+
+ start = time.time_ns()
+ if 'x' in event and 'y' in event:
+ # Normal pixel placement
+ if colors[event['color']] is not None and event['userId'] != "591555636505083905":
+ image.putpixel((event['x'], event['y']), hex_to_rgb(colors[event['color']]))
+ else:
+ # Mod tool
+ if 0 <= event['x1'] <= 1000 and 0 <= event['x2'] <= 1000 \
+ and 0 <= event['y1'] <= 1000 and 0 <= event['y2'] <= 1000:
+ for x in range(event['x1'], event['x2']):
+ for y in range(event['y1'], event['y2']):
+ if colors[event['color']] is not None:
+ image.putpixel((x, y), hex_to_rgb(colors[event['color']]))
+ else:
+ print(event)
+
+ if frame % divider == 0:
+ image.save(f'frames/{str(frameFile).rjust(16, "0")}.png')
+ dates[str(frameFile / 60)] = event['timestamp']
+ frameFile += 1
+
+ frame += 1
+
+ end = time.time_ns()
+ duration = end - start
+ times.append(duration)
+
+print("\r\nSaving video...")
+os.system("ffmpeg -y -framerate 60 -pattern_type glob -i 'frames/*.png' -c:v libx264 out.pre.mp4")
+os.system("ffmpeg -y -i out.pre.mp4 out.pre.webm")
+
+print("\r\nSaving metadata...")
+with open('metadata.json', 'w') as f:
+ json.dump(dates, f)
+
+print("\r\nSwitching slots...")
+try:
+ os.remove("out.old.mp4")
+except FileNotFoundError:
+ pass
+os.rename("out.mp4", "out.old.mp4")
+os.rename("out.pre.mp4", "out.mp4")
+
+try:
+ os.remove("out.old.webm")
+except FileNotFoundError:
+ pass
+os.rename("out.webm", "out.old.webm")
+os.rename("out.pre.webm", "out.webm")
diff --git a/main2.py b/main2.py
new file mode 100644
index 0000000..9730ba9
--- /dev/null
+++ b/main2.py
@@ -0,0 +1,159 @@
+import json
+import time
+import shutil
+import os
+import datetime
+from PIL import Image
+
+divider = 10
+dates = {}
+
+data = json.load(open('data.json'))
+image = Image.open('initial.png')
+initial = Image.open('initial.png')
+image.save('frame.png')
+
+total = len(data)
+
+
+def hex_to_rgb(value):
+ value = value.lstrip('#')
+ return int(value[0:2], 16), int(value[2:4], 16), int(value[4:6], 16)
+
+
+"""
+def hex_to_rgb(value):
+ value = value.lstrip('#')
+ lv = len(value)
+ return tuple(int(value[i:i + lv // 3], 16) for i in range(0, lv, lv // 3))
+"""
+
+
+colors = [
+ "#6D001A",
+ "#BE0039",
+ "#FF4500",
+ "#FFA800",
+ "#FFD635",
+ "#FFF8B8",
+ "#00A368",
+ "#00CC78",
+ "#7EED56",
+ "#00756F",
+ "#009EAA",
+ "#00CCC0",
+ "#2450A4",
+ "#3690EA",
+ "#51E9F4",
+ "#493AC1",
+ "#6A5CFF",
+ "#94B3FF",
+ "#811E9F",
+ "#B44AC0",
+ "#E4ABFF",
+ "#DE107F",
+ "#FF3881",
+ "#FF99AA",
+ "#6D482F",
+ "#9C6926",
+ "#FFB470",
+ "#000000",
+ "#515252",
+ "#898D90",
+ "#D4D7D9",
+ "#FFFFFF",
+ "#ffff5c",
+ "#d9d94a",
+ "#ff7313",
+ "#fce07c",
+ "#bdbd3e",
+ "#c0aa19",
+ "#8f8fe0",
+ "#6b6bd1",
+ "#9efe90",
+ "#360082",
+ "#00ccff",
+ "#44b1ce",
+ "#4a2157",
+ "#d676e3",
+ "#abfbff",
+ "#a11461",
+ "#592d1b",
+ "#914724",
+ "#cc6d42",
+ "#ff8559",
+ "#ffd5ad",
+ "#d39748",
+ "#fa74a4",
+ "#ffd1dc",
+ "#679112",
+ "#d39648",
+ "#9fc455",
+ "#d5ebad",
+ "#adafb0",
+ "#793ccf",
+ "#a771f7",
+ "#d3bff5",
+]
+
+frame = 1
+frameFile = 1
+times = []
+
+for event in data:
+ percentage = "%.2f" % ((frame / total) * 100)
+ remaining = total - frame
+
+ if len(times) > 0:
+ avg = sum(times) / len(times)
+ else:
+ avg = 0
+
+ eta = None
+
+ if frame > 1000:
+ eta = avg * remaining
+
+ if eta is not None:
+ eta_seconds = round(eta / 1000000000)
+ eta_string = str(eta_seconds) + " seconds remaining"
+ done_by = datetime.datetime.fromtimestamp(round(time.time() + eta_seconds)).isoformat().split("T")[1]
+
+ if eta_seconds > 60:
+ if eta_seconds > 3600:
+ if round(eta_seconds / 3600) > 1:
+ eta_string = str(round(eta_seconds / 3600)) + " hours remaining"
+ else:
+ eta_string = str(round(eta_seconds / 3600)) + " hour remaining"
+ else:
+ if round(eta_seconds / 60) > 1:
+ eta_string = str(round(eta_seconds / 60)) + " minutes remaining"
+ else:
+ eta_string = str(round(eta_seconds / 60)) + " minute remaining"
+
+ print(f"\r{frame}/{total} ({percentage}% complete, {eta_string}, done at {done_by})", end="", flush=True)
+ else:
+ print(f"\r{frame}/{total} ({percentage}% complete, calculating...)", end="", flush=True)
+
+ start = time.time_ns()
+ if 'x' in event and 'y' in event:
+ # Normal pixel placement
+ if colors[event['color']] is not None:
+ image.putpixel((event['x'], event['y']), hex_to_rgb(colors[event['color']]))
+ else:
+ # Mod tool
+ if 0 <= event['x1'] <= 1000 and 0 <= event['x2'] <= 1000 \
+ and 0 <= event['y1'] <= 1000 and 0 <= event['y2'] <= 1000:
+ for x in range(event['x1'], event['x2']):
+ for y in range(event['y1'], event['y2']):
+ if colors[event['color']] is not None:
+ image.putpixel((x, y), hex_to_rgb(colors[event['color']]))
+
+ frame += 1
+
+ end = time.time_ns()
+ duration = end - start
+ times.append(duration)
+
+print("\r\nSaving frame to 'frame.png'...")
+image.save(f'frame.png')
diff --git a/user.py b/user.py
new file mode 100644
index 0000000..1a4b785
--- /dev/null
+++ b/user.py
@@ -0,0 +1,43 @@
+import sys
+
+import json
+import time
+import os
+from PIL import Image
+
+try:
+ os.mkdir("./users")
+except FileExistsError:
+ pass
+
+data = json.load(open('data.json'))
+users = []
+
+for item in data:
+ if item['userId'] not in users:
+ users.append(item['userId'])
+
+
+def hex_to_rgb(value):
+ value = value.lstrip('#')
+ lv = len(value)
+ return tuple(int(value[i:i + lv // 3], 16) for i in range(0, lv, lv // 3))
+
+
+length = len(users)
+index = 1
+
+for user in users:
+ image = Image.new(mode="RGB", size=(1000, 1000))
+
+ frame = 1
+ times = []
+
+ for event in data:
+ start = time.time_ns()
+ if 'x' in event and 'y' in event and event['userId'] == user:
+ image.putpixel((event['x'], event['y']), (255, 255, 255))
+
+ print(f"Saving frame for {user} [{index}/{length}, {round((index / length) * 100, 2)}%]...")
+ image.save(f'users/{user}.png')
+ index += 1