diff --git a/.gitignore b/.gitignore index aab52d9..85c17cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -*.png \ No newline at end of file +*.png +.env +__pycache__ \ No newline at end of file diff --git a/add.py b/add.py index 38f0c62..27bc990 100644 --- a/add.py +++ b/add.py @@ -1,54 +1,84 @@ # Blender import import math +import os import random import sys import bmesh import bpy +import mathutils +sys.path.append(os.path.dirname(__file__)) +from fetch import fetch_github_contributions + +GRID_SIZE = 0.5 GRASS_FILE = "./grass.blend" + +# 環境変数の読み込み +github_username = os.getenv("GITHUB_USERNAME") +github_token = os.getenv("GITHUB_TOKEN") + # すべてのオブジェクト削除 bpy.ops.object.select_all(action="SELECT") bpy.ops.object.delete() -# 0: 無し, 1: grass_low, 2: grass_mid, 3: grass_high -field = [[random.randint(0, 3) for i in range(10)] for j in range(7)] - # grass object の読み込み -bpy.ops.wm.append( - filename="grass_low", - directory=GRASS_FILE + "/Object", -) -bpy.ops.wm.append( - filename="grass_mid", - directory=GRASS_FILE + "/Object", -) -bpy.ops.wm.append( - filename="grass_high", - directory=GRASS_FILE + "/Object", -) +filenames = ["grass_none", "grass_first", "grass_second", "grass_third", "grass_fourth"] +for filename in filenames: + bpy.ops.wm.append( + filename=filename, + directory=GRASS_FILE + "/Object", + ) + +# GitHub contributions を取得 +data = fetch_github_contributions(github_username, github_token).get("data") +calender = data.get("user").get("contributionsCollection").get("contributionCalendar") # 位置 -for i in range(7): - for j in range(10): - if field[i][j] == 1: - obj = bpy.data.objects["grass_low"] - elif field[i][j] == 2: - obj = bpy.data.objects["grass_mid"] - elif field[i][j] == 3: - obj = bpy.data.objects["grass_high"] +for i, week in enumerate(calender.get("weeks")): + for j, day in enumerate(week.get("contributionDays")): + level = day.get("contributionLevel") + if level == "NONE": + obj = bpy.data.objects[filenames[0]] + elif level == "FIRST_QUARTILE": + obj = bpy.data.objects[filenames[1]] + elif level == "SECOND_QUARTILE": + obj = bpy.data.objects[filenames[2]] + elif level == "THIRD_QUARTILE": + obj = bpy.data.objects[filenames[3]] + elif level == "FOURTH_QUARTILE": + obj = bpy.data.objects[filenames[4]] else: continue obj = obj.copy() obj.data = obj.data.copy() - - obj.location = (j * 2, i * 2, 0) + obj.dimensions = ( + GRID_SIZE, + GRID_SIZE, + obj.dimensions.z, + ) + obj.location = ( + (i + 1 / 2) * GRID_SIZE, + -(j + 1 / 2) * GRID_SIZE, + obj.dimensions.z / 2, + ) bpy.context.collection.objects.link(obj) +# Original grass object の削除 +for obj in bpy.data.objects: + if obj.name in filenames: + bpy.data.objects.remove(obj) + # カメラ -bpy.ops.object.camera_add(location=(10, -25, 30), rotation=(math.pi / 4, 0, 0)) +look_at = (53 * GRID_SIZE / 2, -7 * GRID_SIZE / 2, 0) +camera_location = (53 * GRID_SIZE / 2, -40 * GRID_SIZE / 2, 40) +direction = mathutils.Vector(camera_location) - mathutils.Vector(look_at) +quaternion = direction.to_track_quat("Z", "Y") +bpy.ops.object.camera_add(location=camera_location) +bpy.context.object.rotation_euler = quaternion.to_euler() + bpy.context.object.data.ortho_scale = 20 bpy.context.scene.camera = bpy.context.object @@ -59,9 +89,9 @@ # レンダリング bpy.context.scene.render.image_settings.file_format = "PNG" bpy.context.scene.render.filepath = "./output.png" -bpy.context.scene.render.resolution_x = 256 * 4 -bpy.context.scene.render.resolution_y = 128 * 4 -bpy.context.scene.cycles.samples = 1024 +bpy.context.scene.render.resolution_x = 1024 +bpy.context.scene.render.resolution_y = 256 +bpy.context.scene.cycles.samples = 256 bpy.context.scene.render.engine = "CYCLES" bpy.context.scene.cycles.device = "CPU" bpy.ops.render.render(write_still=True) diff --git a/fetch.py b/fetch.py new file mode 100644 index 0000000..65d5ede --- /dev/null +++ b/fetch.py @@ -0,0 +1,81 @@ +import json + +import requests + + +def fetch_github_contributions(username: str, token: str): + url = "https://api.github.com/graphql" + query = f""" + query {{ + user(login: "{username}") {{ + contributionsCollection {{ + contributionCalendar {{ + totalContributions + weeks {{ + contributionDays {{ + contributionCount + contributionLevel + date + }} + }} + }} + }} + }} + }} + """ + headers = { + "Authorization": f"Bearer {token}", + "Content-Type": "application/json", + } + + response = requests.post(url, headers=headers, json={"query": query}) + + if response.status_code != 200: + raise Exception(f"Failed to fetch data from GitHub: {response.text}") + + return json.loads(response.text) + + +if __name__ == "__main__": + import os + + import dotenv + + username = os.getenv("GITHUB_USERNAME") + token = os.getenv("GITHUB_TOKEN") + + data = fetch_github_contributions(username, token).get("data") + + total_contributions = ( + data.get("user") + .get("contributionsCollection") + .get("contributionCalendar") + .get("totalContributions") + ) + + total_weeks = len( + data.get("user") + .get("contributionsCollection") + .get("contributionCalendar") + .get("weeks") + ) + + first = ( + data.get("user") + .get("contributionsCollection") + .get("contributionCalendar") + .get("weeks")[0] + ) + + matrix = [ + [day.get("contributionLevel") for day in week.get("contributionDays")] + for week in data.get("user") + .get("contributionsCollection") + .get("contributionCalendar") + .get("weeks") + ] + + print(f"Total contributions: {total_contributions}") + print(f"Total weeks: {total_weeks}") + print(f"First week: {first}") + print(f"Matrix Size: {len(matrix)}x{len(matrix[0])}") diff --git a/grass.blend b/grass.blend index a2907ec..3212e6d 100644 Binary files a/grass.blend and b/grass.blend differ diff --git a/grass.blend1 b/grass.blend1 index e957f71..ca90187 100644 Binary files a/grass.blend1 and b/grass.blend1 differ