mirror of
https://github.com/Yonokid/PyTaiko.git
synced 2026-02-04 11:40:13 +01:00
upgrade to uv, many fxes
This commit is contained in:
1
.python-version
Normal file
1
.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.13
|
||||
@@ -7,13 +7,13 @@ tja_path = 'Songs'
|
||||
video_path = 'Videos'
|
||||
|
||||
[keybinds]
|
||||
left_kat = ['D']
|
||||
left_kat = ['E']
|
||||
left_don = ['F']
|
||||
right_don = ['J']
|
||||
right_kat = ['K']
|
||||
right_kat = ['I']
|
||||
|
||||
[audio]
|
||||
device_type = 'WASAPI'
|
||||
device_type = 'ASIO'
|
||||
asio_buffer = 6
|
||||
|
||||
[video]
|
||||
|
||||
@@ -29,7 +29,9 @@ class Animation:
|
||||
self.duration,
|
||||
self.params['total_distance'],
|
||||
self.params['start_position'],
|
||||
delay=self.params.get('delay', 0.0))
|
||||
delay=self.params.get('delay', 0.0),
|
||||
ease_in=self.params.get('ease_in', None),
|
||||
ease_out=self.params.get('ease_out', None))
|
||||
elif self.type == 'texture_change':
|
||||
self.texture_change(current_ms,
|
||||
self.duration,
|
||||
@@ -50,25 +52,26 @@ class Animation:
|
||||
initial_size=self.params.get('final_size', 1.0),
|
||||
delay=self.params.get('delay', 0.0) + self.duration)
|
||||
|
||||
def _ease_out_progress(self, progress: float, ease: str | None) -> float:
|
||||
if ease == 'quadratic':
|
||||
return progress * (2 - progress)
|
||||
elif ease == 'cubic':
|
||||
return 1 - pow(1 - progress, 3)
|
||||
elif ease == 'exponential':
|
||||
return 1 - pow(2, -10 * progress)
|
||||
else:
|
||||
return progress
|
||||
def _ease_in_progress(self, progress: float, ease: str | None) -> float:
|
||||
if ease == 'quadratic':
|
||||
return progress * progress
|
||||
elif ease == 'cubic':
|
||||
return progress * progress * progress
|
||||
elif ease == 'exponential':
|
||||
return pow(2, 10 * (progress - 1))
|
||||
else:
|
||||
return progress
|
||||
|
||||
def fade(self, current_ms: float, duration: float, initial_opacity: float, final_opacity: float, delay: float, ease_in: str | None, ease_out: str | None) -> None:
|
||||
def _ease_out_progress(progress: float, ease: str | None) -> float:
|
||||
if ease == 'quadratic':
|
||||
return progress * (2 - progress)
|
||||
elif ease == 'cubic':
|
||||
return 1 - pow(1 - progress, 3)
|
||||
elif ease == 'exponential':
|
||||
return 1 - pow(2, -10 * progress)
|
||||
else:
|
||||
return progress
|
||||
def _ease_in_progress(progress: float, ease: str | None) -> float:
|
||||
if ease == 'quadratic':
|
||||
return progress * progress
|
||||
elif ease == 'cubic':
|
||||
return progress * progress * progress
|
||||
elif ease == 'exponential':
|
||||
return pow(2, 10 * (progress - 1))
|
||||
else:
|
||||
return progress
|
||||
elapsed_time = current_ms - self.start_ms
|
||||
if elapsed_time < delay:
|
||||
self.attribute = initial_opacity
|
||||
@@ -79,27 +82,32 @@ class Animation:
|
||||
self.is_finished = True
|
||||
|
||||
if ease_in is not None:
|
||||
progress = _ease_in_progress(elapsed_time / duration, ease_in)
|
||||
progress = self._ease_in_progress(elapsed_time / duration, ease_in)
|
||||
elif ease_out is not None:
|
||||
progress = _ease_out_progress(elapsed_time / duration, ease_out)
|
||||
progress = self._ease_out_progress(elapsed_time / duration, ease_out)
|
||||
else:
|
||||
progress = elapsed_time / duration
|
||||
|
||||
current_opacity = initial_opacity + (final_opacity - initial_opacity) * progress
|
||||
self.attribute = current_opacity
|
||||
def move(self, current_ms: float, duration: float, total_distance: float, start_position: float, delay: float) -> None:
|
||||
def move(self, current_ms: float, duration: float, total_distance: float, start_position: float, delay: float, ease_in: str | None, ease_out: str | None) -> None:
|
||||
elapsed_time = current_ms - self.start_ms
|
||||
if elapsed_time < delay:
|
||||
self.attribute = start_position
|
||||
|
||||
elapsed_time -= delay
|
||||
if elapsed_time <= duration:
|
||||
progress = elapsed_time / duration
|
||||
if ease_in is not None:
|
||||
progress = self._ease_in_progress(elapsed_time / duration, ease_in)
|
||||
elif ease_out is not None:
|
||||
progress = self._ease_out_progress(elapsed_time / duration, ease_out)
|
||||
else:
|
||||
progress = elapsed_time / duration
|
||||
self.attribute = start_position + (total_distance * progress)
|
||||
else:
|
||||
self.attribute = start_position + total_distance
|
||||
self.is_finished = True
|
||||
def texture_change(self, current_ms: float, duration: float, textures: list[tuple[float, float, float]]) -> None:
|
||||
def texture_change(self, current_ms: float, duration: float, textures: list[tuple[float, float, int]]) -> None:
|
||||
elapsed_time = current_ms - self.start_ms
|
||||
if elapsed_time <= duration:
|
||||
for start, end, index in textures:
|
||||
|
||||
@@ -741,3 +741,5 @@ class AudioEngineWrapper:
|
||||
raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}' and '{type(self._module).__name__}' has no attribute '{name}'")
|
||||
|
||||
audio = AudioEngineWrapper(get_config()["audio"]["device_type"])
|
||||
if get_config()["audio"]["device_type"] == 'ASIO':
|
||||
audio.set_master_volume(0.75)
|
||||
|
||||
@@ -371,6 +371,7 @@ class TJAParser:
|
||||
raise Exception("Balloon note found, but no count was specified")
|
||||
note = Balloon(note)
|
||||
note.count = int(balloon[balloon_index])
|
||||
balloon_index += 1
|
||||
self.current_ms += increment
|
||||
play_note_list.append(note)
|
||||
self.get_moji(play_note_list, ms_per_measure)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import os
|
||||
import tempfile
|
||||
import time
|
||||
import tomllib
|
||||
import zipfile
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import pyray as ray
|
||||
import tomllib
|
||||
|
||||
#TJA Format creator is unknown. I did not create the format, but I did write the parser though.
|
||||
|
||||
@@ -95,16 +95,33 @@ def get_config() -> dict[str, Any]:
|
||||
config_file = tomllib.load(f)
|
||||
return config_file
|
||||
|
||||
def draw_scaled_texture(texture, x: int, y: int, scale: float, color: ray.Color) -> None:
|
||||
width = texture.width
|
||||
height = texture.height
|
||||
src_rect = ray.Rectangle(0, 0, width, height)
|
||||
dst_rect = ray.Rectangle(x, y, width*scale, height*scale)
|
||||
ray.draw_texture_pro(texture, src_rect, dst_rect, ray.Vector2(0, 0), 0, color)
|
||||
|
||||
@dataclass
|
||||
class SessionData:
|
||||
selected_song: str = '' #Path
|
||||
selected_difficulty: int = 0
|
||||
song_title: str = ''
|
||||
result_score: int = 0
|
||||
result_good: int = 0
|
||||
result_ok: int = 0
|
||||
result_bad: int = 0
|
||||
result_max_combo: int = 0
|
||||
result_total_drumroll: int = 0
|
||||
result_gauge_length: int = 0
|
||||
|
||||
session_data = SessionData()
|
||||
|
||||
def reset_session():
|
||||
return SessionData()
|
||||
|
||||
@dataclass
|
||||
class GlobalData:
|
||||
videos_cleared = False
|
||||
selected_song: str = '' #Path
|
||||
selected_difficulty: int = -1
|
||||
song_title: str = ''
|
||||
result_good: int = -1
|
||||
result_ok: int = -1
|
||||
result_bad: int = -1
|
||||
result_score: int = -1
|
||||
songs_played: int = 0
|
||||
|
||||
global_data = GlobalData()
|
||||
@@ -168,3 +185,49 @@ class OutlinedText:
|
||||
|
||||
def unload(self):
|
||||
ray.unload_texture(self.texture)
|
||||
|
||||
'''
|
||||
class RenderTextureStack:
|
||||
def __init__(self):
|
||||
"""Initialize an empty stack for render textures."""
|
||||
self.texture_stack = []
|
||||
|
||||
def load_render_texture(self, width, height):
|
||||
"""Create and return a render texture with the specified dimensions."""
|
||||
return ray.load_render_texture(width, height)
|
||||
|
||||
def begin_texture_mode(self, target):
|
||||
"""Begin drawing to the render texture and add it to the stack."""
|
||||
ray.begin_texture_mode(target)
|
||||
self.texture_stack.append(target)
|
||||
return target
|
||||
|
||||
def end_texture_mode(self, pop_count=1):
|
||||
"""End the texture mode for the specified number of textures in the stack."""
|
||||
if not self.texture_stack:
|
||||
raise IndexError("Cannot end texture mode: texture stack is empty")
|
||||
|
||||
# Ensure pop_count is within valid range
|
||||
pop_count = min(pop_count, len(self.texture_stack))
|
||||
|
||||
# End the texture modes and pop from stack
|
||||
for _ in range(pop_count):
|
||||
ray.end_texture_mode()
|
||||
self.texture_stack.pop()
|
||||
|
||||
def get_texture(self, target):
|
||||
"""Get the texture from the render texture."""
|
||||
return ray.get_texture_default(target)
|
||||
|
||||
def draw_texture(self, texture, pos_x, pos_y, tint=ray.WHITE):
|
||||
"""Draw a texture at the specified position with the given tint."""
|
||||
ray.draw_texture(texture, pos_x, pos_y, tint)
|
||||
|
||||
def get_current_target(self):
|
||||
"""Get the current active render target from the stack."""
|
||||
if not self.texture_stack:
|
||||
return None
|
||||
return self.texture_stack[-1]
|
||||
|
||||
render_stack = RenderTextureStack()
|
||||
'''
|
||||
|
||||
@@ -9,63 +9,68 @@ class VideoPlayer:
|
||||
def __init__(self, path: str):
|
||||
self.video_path = path
|
||||
self.start_ms = None
|
||||
|
||||
self.current_frame = None
|
||||
self.last_frame = self.current_frame
|
||||
self.frame_index = 0
|
||||
self.frames = []
|
||||
self.cap = cv2.VideoCapture(self.video_path)
|
||||
self.fps = self.cap.get(cv2.CAP_PROP_FPS)
|
||||
|
||||
self.is_finished = [False, False]
|
||||
self.is_finished_list = [False, False, False] # Added third flag for frame conversion
|
||||
self.all_frames_converted = False
|
||||
audio_path = path[:-4] + '.ogg'
|
||||
self.audio = audio.load_music_stream(audio_path)
|
||||
|
||||
def _convert_frames_background(self):
|
||||
if not self.cap.isOpened():
|
||||
raise ValueError("Error: Could not open video file.")
|
||||
|
||||
total_frames = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
||||
if len(self.frames) == total_frames:
|
||||
return 0
|
||||
self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_index)
|
||||
|
||||
success, frame = self.cap.read()
|
||||
|
||||
timestamp = (self.frame_index / self.fps * 1000)
|
||||
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
|
||||
new_frame = ray.Image(frame_rgb.tobytes(), frame_rgb.shape[1], frame_rgb.shape[0], 1, ray.PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8)
|
||||
|
||||
self.frames.append((timestamp, new_frame))
|
||||
self.frame_index += 1
|
||||
def is_finished(self) -> bool:
|
||||
return all(self.is_finished_list)
|
||||
|
||||
def _convert_frames(self):
|
||||
"""Legacy method that converts all frames at once"""
|
||||
if not self.cap.isOpened():
|
||||
raise ValueError("Error: Could not open video file.")
|
||||
|
||||
frame_count = 0
|
||||
success, frame = self.cap.read()
|
||||
|
||||
while success:
|
||||
timestamp = (frame_count / self.fps * 1000)
|
||||
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
|
||||
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
new_frame = ray.Image(frame_rgb.tobytes(), frame_rgb.shape[1], frame_rgb.shape[0], 1, ray.PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8)
|
||||
|
||||
self.frames.append((timestamp, new_frame))
|
||||
|
||||
success, frame = self.cap.read()
|
||||
frame_count += 1
|
||||
|
||||
self.cap.release()
|
||||
print(f"Extracted {len(self.frames)} frames.")
|
||||
self.start_ms = get_current_ms()
|
||||
self.all_frames_converted = True
|
||||
self.is_finished_list[2] = True
|
||||
|
||||
def convert_frames_background(self):
|
||||
"""Converts a single frame each time it's called"""
|
||||
if self.all_frames_converted:
|
||||
return
|
||||
|
||||
if not self.cap.isOpened():
|
||||
self.cap = cv2.VideoCapture(self.video_path)
|
||||
if not self.cap.isOpened():
|
||||
raise ValueError("Error: Could not open video file.")
|
||||
|
||||
# Process one frame
|
||||
success, frame = self.cap.read()
|
||||
if success:
|
||||
timestamp = (len(self.frames) / self.fps * 1000)
|
||||
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
new_frame = ray.Image(frame_rgb.tobytes(), frame_rgb.shape[1], frame_rgb.shape[0], 1, ray.PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8)
|
||||
self.frames.append((timestamp, new_frame))
|
||||
else:
|
||||
# No more frames to convert
|
||||
self.cap.release()
|
||||
print(f"Extracted {len(self.frames)} frames.")
|
||||
self.all_frames_converted = True
|
||||
self.is_finished_list[2] = True
|
||||
|
||||
def _check_for_start(self):
|
||||
if self.frames == []:
|
||||
self._convert_frames()
|
||||
if not audio.is_music_stream_playing(self.audio):
|
||||
# Start audio once we have at least one frame
|
||||
if len(self.frames) > 0 and not audio.is_music_stream_playing(self.audio):
|
||||
audio.play_music_stream(self.audio)
|
||||
|
||||
def _audio_manager(self):
|
||||
@@ -73,36 +78,42 @@ class VideoPlayer:
|
||||
time_played = audio.get_music_time_played(self.audio) / audio.get_music_time_length(self.audio)
|
||||
ending_lenience = 0.95
|
||||
if time_played > ending_lenience:
|
||||
self.is_finished[1] = True
|
||||
self.is_finished_list[1] = True
|
||||
|
||||
def update(self):
|
||||
self._check_for_start()
|
||||
self._audio_manager()
|
||||
|
||||
if self.frame_index == len(self.frames)-1:
|
||||
self.is_finished[0] = True
|
||||
# Check if we've reached the end of available frames
|
||||
if self.frame_index == len(self.frames) - 1 and self.all_frames_converted:
|
||||
self.is_finished_list[0] = True
|
||||
return
|
||||
|
||||
if self.start_ms is None:
|
||||
return
|
||||
|
||||
timestamp, frame = self.frames[self.frame_index][0], self.frames[self.frame_index][1]
|
||||
elapsed_time = get_current_ms() - self.start_ms
|
||||
if elapsed_time >= timestamp:
|
||||
self.current_frame = ray.load_texture_from_image(frame)
|
||||
if self.last_frame != self.current_frame and self.last_frame is not None:
|
||||
ray.unload_texture(self.last_frame)
|
||||
self.frame_index += 1
|
||||
self.last_frame = self.current_frame
|
||||
# Only proceed if we have frames to display
|
||||
if self.frame_index < len(self.frames):
|
||||
timestamp, frame = self.frames[self.frame_index][0], self.frames[self.frame_index][1]
|
||||
elapsed_time = get_current_ms() - self.start_ms
|
||||
|
||||
if elapsed_time >= timestamp:
|
||||
self.current_frame = ray.load_texture_from_image(frame)
|
||||
if self.last_frame != self.current_frame and self.last_frame is not None:
|
||||
ray.unload_texture(self.last_frame)
|
||||
self.frame_index += 1
|
||||
self.last_frame = self.current_frame
|
||||
|
||||
def draw(self):
|
||||
if self.current_frame is not None:
|
||||
ray.draw_texture(self.current_frame, 0, 0, ray.WHITE)
|
||||
|
||||
def __del__(self):
|
||||
def stop(self):
|
||||
if hasattr(self, 'current_frame') and self.current_frame:
|
||||
ray.unload_texture(self.current_frame)
|
||||
if hasattr(self, 'last_frame') and self.last_frame:
|
||||
ray.unload_texture(self.last_frame)
|
||||
if audio.is_music_stream_playing(self.audio):
|
||||
audio.stop_music_stream(self.audio)
|
||||
if hasattr(self, 'cap') and self.cap.isOpened():
|
||||
self.cap.release()
|
||||
|
||||
6
main.py
6
main.py
@@ -1,7 +1,7 @@
|
||||
import pyray as ray
|
||||
|
||||
from libs.audio import audio
|
||||
from libs.utils import get_config, global_data
|
||||
from libs.utils import get_config
|
||||
from scenes.entry import EntryScreen
|
||||
from scenes.game import GameScreen
|
||||
from scenes.result import ResultScreen
|
||||
@@ -78,10 +78,6 @@ def main():
|
||||
if screen == title_screen:
|
||||
ray.clear_background(ray.BLACK)
|
||||
else:
|
||||
if not global_data.videos_cleared:
|
||||
del title_screen.op_video
|
||||
del title_screen.attract_video
|
||||
global_data.videos_cleared = True
|
||||
ray.clear_background(ray.WHITE)
|
||||
|
||||
if next_screen is not None:
|
||||
|
||||
17
pyproject.toml
Normal file
17
pyproject.toml
Normal file
@@ -0,0 +1,17 @@
|
||||
[project]
|
||||
name = "pytaiko"
|
||||
version = "0.1.0"
|
||||
description = "Taiko no Tatsujin simulator written in python and raylib"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"numpy>=2.2.5",
|
||||
"opencv-python>=4.11.0.86",
|
||||
"pydub>=0.25.1",
|
||||
"raylib>=5.5.0.2",
|
||||
"raylib-dynamic>=5.5.0.2",
|
||||
"ruff>=0.11.7",
|
||||
"scipy>=1.15.2",
|
||||
"sounddevice>=0.5.1",
|
||||
"audioop-lts; python_version >= '3.13'",
|
||||
]
|
||||
264
scenes/game.py
264
scenes/game.py
@@ -16,6 +16,7 @@ from libs.utils import (
|
||||
load_all_textures_from_zip,
|
||||
load_image_from_zip,
|
||||
load_texture_from_zip,
|
||||
session_data,
|
||||
)
|
||||
|
||||
|
||||
@@ -25,11 +26,8 @@ class GameScreen:
|
||||
self.height = height
|
||||
self.judge_x = 414
|
||||
self.current_ms = 0
|
||||
|
||||
self.result_transition = None
|
||||
|
||||
self.song_info = None
|
||||
|
||||
self.screen_init = False
|
||||
|
||||
def load_textures(self):
|
||||
@@ -99,12 +97,12 @@ class GameScreen:
|
||||
self.textures['onp_fusen'][0]]
|
||||
|
||||
self.tja = TJAParser(song)
|
||||
self.tja.get_metadata()
|
||||
metadata = self.tja.get_metadata()
|
||||
self.tja.distance = self.width - self.judge_x
|
||||
self.start_delay = 0
|
||||
global_data.song_title = self.tja.title
|
||||
session_data.song_title = self.tja.title
|
||||
|
||||
self.player_1 = Player(self, 1, difficulty, get_config()["general"]["judge_offset"])
|
||||
self.player_1 = Player(self, 1, difficulty, metadata, get_config()["general"]["judge_offset"])
|
||||
self.song_music = audio.load_sound(str(Path(self.tja.wave)))
|
||||
self.start_ms = (get_current_ms() - self.tja.offset*1000) + self.start_delay
|
||||
|
||||
@@ -113,7 +111,7 @@ class GameScreen:
|
||||
def on_screen_start(self):
|
||||
if not self.screen_init:
|
||||
self.screen_init = True
|
||||
self.init_tja(global_data.selected_song, global_data.selected_difficulty)
|
||||
self.init_tja(session_data.selected_song, session_data.selected_difficulty)
|
||||
self.current_ms = get_current_ms() - self.start_ms
|
||||
self.song_info = SongInfo(self.current_ms, self.tja.title, 'TEST')
|
||||
self.result_transition = None
|
||||
@@ -139,7 +137,8 @@ class GameScreen:
|
||||
if self.result_transition.is_finished:
|
||||
return self.on_screen_end()
|
||||
elif len(self.player_1.play_note_list) == 0 and (len(self.player_1.current_notes) == 0) and not audio.is_sound_playing(self.song_music):
|
||||
global_data.result_good, global_data.result_ok, global_data.result_bad, global_data.result_score = self.player_1.get_result_score()
|
||||
session_data.result_score, session_data.result_good, session_data.result_ok, session_data.result_bad, session_data.result_max_combo, session_data.result_total_drumroll = self.player_1.get_result_score()
|
||||
session_data.result_gauge_length = self.player_1.gauge.gauge_length
|
||||
self.result_transition = ResultTransition(self.current_ms, self.height)
|
||||
audio.play_sound(self.sound_result_transition)
|
||||
|
||||
@@ -152,7 +151,7 @@ class GameScreen:
|
||||
|
||||
|
||||
class Player:
|
||||
def __init__(self, game_screen: GameScreen, player_number: int, difficulty: int, judge_offset: int):
|
||||
def __init__(self, game_screen: GameScreen, player_number: int, difficulty: int, metadata, judge_offset: int):
|
||||
self.timing_good = 25.0250015258789
|
||||
self.timing_ok = 75.0750045776367
|
||||
self.timing_bad = 108.441665649414
|
||||
@@ -161,6 +160,8 @@ class Player:
|
||||
self.difficulty = difficulty
|
||||
|
||||
self.play_note_list, self.draw_note_list, self.draw_bar_list = game_screen.tja.notes_to_position(self.difficulty)
|
||||
self.total_notes = len([note for note in self.play_note_list if 0 < note.type < 5])
|
||||
print(self.total_notes)
|
||||
self.base_score = calculate_base_score(self.play_note_list)
|
||||
|
||||
self.judge_offset = judge_offset
|
||||
@@ -201,8 +202,10 @@ class Player:
|
||||
|
||||
self.input_log: dict[float, str] = dict()
|
||||
|
||||
self.gauge = Gauge(game_screen.current_ms, self.difficulty, metadata[-1][self.difficulty][0])
|
||||
|
||||
def get_result_score(self):
|
||||
return self.good_count, self.ok_count, self.bad_count, self.score
|
||||
return self.score, self.good_count, self.ok_count, self.bad_count, self.total_drumroll, self.max_combo
|
||||
|
||||
def get_position(self, game_screen: GameScreen, ms: float, pixels_per_frame: float) -> int:
|
||||
return int(game_screen.width + pixels_per_frame * 60 / 1000 * (ms - game_screen.current_ms + self.judge_offset) - 64)
|
||||
@@ -398,7 +401,6 @@ class Player:
|
||||
|
||||
def balloon_manager(self, game_screen: GameScreen):
|
||||
if self.balloon_anim is not None:
|
||||
print(self.is_balloon)
|
||||
self.balloon_anim.update(game_screen, game_screen.current_ms, self.curr_balloon_count, not self.is_balloon)
|
||||
if self.balloon_anim.is_finished:
|
||||
self.balloon_anim = None
|
||||
@@ -451,6 +453,8 @@ class Player:
|
||||
self.score_counter.update(game_screen.current_ms, self.score)
|
||||
self.key_manager(game_screen)
|
||||
|
||||
self.gauge.update(game_screen.current_ms, self.good_count, self.ok_count, self.bad_count, self.total_notes)
|
||||
|
||||
def draw_drumroll(self, game_screen: GameScreen, head: Drumroll, current_eighth: int):
|
||||
start_position = self.get_position(game_screen, head.load_ms, head.pixels_per_frame)
|
||||
tail = next((note for note in self.current_notes_draw[1:] if note.type == 8 and note.index > head.index), None)
|
||||
@@ -459,6 +463,8 @@ class Player:
|
||||
is_big = int(head.type == 6) * 2
|
||||
end_position = self.get_position(game_screen, tail.load_ms, tail.pixels_per_frame)
|
||||
length = (end_position - start_position - 50)
|
||||
if length <= 0:
|
||||
end_position += 50
|
||||
source_rect = ray.Rectangle(0,0,game_screen.note_type_list[8].width, game_screen.note_type_list[8].height)
|
||||
dest_rect = ray.Rectangle(start_position+64, 192, length, game_screen.note_type_list[1][0].height)
|
||||
color = ray.Color(255, head.color, head.color, 255)
|
||||
@@ -472,7 +478,7 @@ class Player:
|
||||
moji_texture = game_screen.texture_se_moji[head.moji]
|
||||
ray.draw_texture(moji_texture, start_position - (moji_texture.width//2) + 64, 323, ray.WHITE)
|
||||
moji_texture = game_screen.texture_se_moji[tail.moji]
|
||||
ray.draw_texture(moji_texture, end_position - (moji_texture.width//2) + 64, 323, ray.WHITE)
|
||||
ray.draw_texture(moji_texture, (end_position - (moji_texture.width//2)) + 32, 323, ray.WHITE)
|
||||
|
||||
def draw_balloon(self, game_screen: GameScreen, head: Balloon, current_eighth: int):
|
||||
offset = 12
|
||||
@@ -526,21 +532,19 @@ class Player:
|
||||
ray.draw_texture(moji_texture, position - (moji_texture.width//2) + 64, 323, ray.WHITE)
|
||||
#ray.draw_text(str(i), position+64, 192, 25, ray.GREEN)
|
||||
|
||||
def draw_gauge(self, textures: list[ray.Texture]):
|
||||
ray.draw_texture(textures[0], 327, 128, ray.WHITE)
|
||||
ray.draw_texture(textures[1], 483, 124, ray.WHITE)
|
||||
ray.draw_texture(textures[10], 483, 124, ray.fade(ray.WHITE, 0.15))
|
||||
ray.draw_texture(textures[11], 1038, 141, ray.WHITE)
|
||||
ray.draw_texture(textures[12], 1187, 130, ray.WHITE)
|
||||
|
||||
def draw(self, game_screen: GameScreen):
|
||||
ray.draw_texture(game_screen.textures['lane'][0], 332, 184, ray.WHITE)
|
||||
self.draw_gauge(game_screen.textures['gage_don_1p_hard'])
|
||||
self.gauge.draw(game_screen.textures['gage_don_1p_hard'])
|
||||
if self.lane_hit_effect is not None:
|
||||
self.lane_hit_effect.draw(game_screen.textures['lane_hit'])
|
||||
ray.draw_texture(game_screen.textures['lane_hit'][17], 342, 184, ray.WHITE)
|
||||
for anim in self.draw_judge_list:
|
||||
anim.draw(game_screen.textures['lane_hit'], game_screen.textures['lane_hit_effect'])
|
||||
|
||||
#ray.draw_texture(game_screen.textures['onp_kiseki_don_1p'][0], 350, 192, ray.WHITE)
|
||||
#ray.draw_texture(game_screen.textures['onp_kiseki_don_1p'][22], 332, -84, ray.WHITE)
|
||||
#ray.draw_texture(game_screen.textures['onp_kiseki_don_1p'][6], 1187 - 29, 130 - 29, ray.WHITE)
|
||||
|
||||
self.draw_bars(game_screen)
|
||||
self.draw_notes(game_screen)
|
||||
ray.draw_texture(game_screen.textures['lane_obi'][0], 0, 184, ray.WHITE)
|
||||
@@ -670,36 +674,87 @@ class DrumHitEffect:
|
||||
class NoteArc:
|
||||
def __init__(self, note_texture: ray.Texture, current_ms: float, player_number: int):
|
||||
self.texture = note_texture
|
||||
self.arc_points = 25
|
||||
self.arc_points = 22
|
||||
self.create_ms = current_ms
|
||||
self.player_number = player_number
|
||||
self.x_i = 414 - 64
|
||||
self.y_i = 168
|
||||
curve_height = 425
|
||||
|
||||
self.start_x, self.start_y = 350, 192
|
||||
self.end_x, self.end_y = 1158, 101
|
||||
|
||||
if self.player_number == 1:
|
||||
# Control point influences the curve shape
|
||||
self.control_x = (self.start_x + self.end_x) // 2
|
||||
self.control_y = min(self.start_y, self.end_y) - curve_height # Arc upward
|
||||
else:
|
||||
# For player 2 (assumed to be a downward arc)
|
||||
self.control_x = (self.start_x + self.end_x) // 2
|
||||
self.control_y = max(self.start_y, self.end_y) + curve_height # Arc downward
|
||||
|
||||
self.x_i = self.start_x
|
||||
self.y_i = self.start_y
|
||||
self.is_finished = False
|
||||
|
||||
num_precalc_points = 100 # More points for better approximation
|
||||
self.path_points = []
|
||||
self.path_distances = [0.0] # Cumulative distance at each point
|
||||
|
||||
prev_x, prev_y = self.start_x, self.start_y
|
||||
total_distance = 0.0
|
||||
|
||||
for i in range(1, num_precalc_points + 1):
|
||||
t = i / num_precalc_points
|
||||
x = int((1-t)**2 * self.start_x + 2*(1-t)*t * self.control_x + t**2 * self.end_x)
|
||||
y = int((1-t)**2 * self.start_y + 2*(1-t)*t * self.control_y + t**2 * self.end_y)
|
||||
|
||||
# Calculate distance from previous point
|
||||
dx = x - prev_x
|
||||
dy = y - prev_y
|
||||
distance = math.sqrt(dx*dx + dy*dy)
|
||||
total_distance += distance
|
||||
|
||||
self.path_points.append((x, y))
|
||||
self.path_distances.append(total_distance)
|
||||
|
||||
prev_x, prev_y = x, y
|
||||
|
||||
self.total_path_length = total_distance
|
||||
self.x_i = self.start_x
|
||||
self.y_i = self.start_y
|
||||
self.is_finished = False
|
||||
|
||||
def update(self, current_ms: float):
|
||||
if self.x_i >= 1150:
|
||||
if self.x_i >= self.end_x:
|
||||
self.is_finished = True
|
||||
radius = 414
|
||||
#Start at 180 degrees, end at 0
|
||||
theta_start = 3.14
|
||||
if self.player_number == 1:
|
||||
theta_end = 2 * 3.14
|
||||
#center of circle that does not exist
|
||||
center_x, center_y = 785, 168
|
||||
else:
|
||||
theta_end = 0
|
||||
center_x, center_y = 785, 468
|
||||
self.x_i = self.end_x
|
||||
self.y_i = self.end_y
|
||||
return
|
||||
|
||||
ms_since_call = (current_ms - self.create_ms) / 16.67
|
||||
if ms_since_call < 0:
|
||||
ms_since_call = 0
|
||||
if ms_since_call > self.arc_points:
|
||||
ms_since_call = self.arc_points
|
||||
angle_change = (theta_end - theta_start) / self.arc_points
|
||||
theta_i = theta_start + ms_since_call * angle_change
|
||||
self.x_i = int(center_x + radius * math.cos(theta_i))
|
||||
self.y_i = int(center_y + radius * 0.5 * math.sin(theta_i))
|
||||
ms_since_call = max(0, min(ms_since_call, self.arc_points))
|
||||
|
||||
# Calculate desired distance along the path (constant speed)
|
||||
target_distance = (ms_since_call / self.arc_points) * self.total_path_length
|
||||
|
||||
# Find the closest pre-calculated points
|
||||
index = 0
|
||||
while index < len(self.path_distances) - 1 and self.path_distances[index + 1] < target_distance:
|
||||
index += 1
|
||||
|
||||
# Interpolate between the points
|
||||
if index < len(self.path_distances) - 1:
|
||||
d1 = self.path_distances[index]
|
||||
d2 = self.path_distances[index + 1]
|
||||
if d2 > d1: # Avoid division by zero
|
||||
fraction = (target_distance - d1) / (d2 - d1)
|
||||
x1, y1 = self.path_points[index - 1] if index > 0 else (self.start_x, self.start_y)
|
||||
x2, y2 = self.path_points[index]
|
||||
self.x_i = int(x1 + fraction * (x2 - x1))
|
||||
self.y_i = int(y1 + fraction * (y2 - y1))
|
||||
else:
|
||||
# At the end of the path
|
||||
self.x_i = self.end_x
|
||||
self.y_i = self.end_y
|
||||
|
||||
def draw(self, game_screen):
|
||||
ray.draw_texture(self.texture, self.x_i, self.y_i, ray.WHITE)
|
||||
@@ -1028,6 +1083,7 @@ class ResultTransition:
|
||||
self.move = Animation(current_ms, 983.33, 'move')
|
||||
self.move.params['start_position'] = 0.0
|
||||
self.move.params['total_distance'] = screen_height//2
|
||||
self.move.params['ease_out'] = 'quadratic'
|
||||
|
||||
self.is_finished = False
|
||||
|
||||
@@ -1048,3 +1104,127 @@ class ResultTransition:
|
||||
ray.draw_texture(texture_2, x, (0 - texture_2.height//2) - (texture_1.height//2) + int(self.move.attribute), ray.WHITE)
|
||||
ray.draw_texture(texture_2, x, (screen_height) + (texture_1.height//2) - (texture_2.height//2) - int(self.move.attribute), ray.WHITE)
|
||||
x += texture_2.width
|
||||
|
||||
class Gauge:
|
||||
def __init__(self, current_ms: float, difficulty: int, level: int):
|
||||
self.gauge_length = 0
|
||||
self.difficulty = min(3, difficulty)
|
||||
self.clear_start = [0, 0, 68, 68]
|
||||
self.level = min(10, level)
|
||||
self.table = [
|
||||
[
|
||||
None,
|
||||
{"clear_rate": 36.0, "ok_multiplier": 0.75, "bad_multiplier": -0.5},
|
||||
{"clear_rate": 38.0, "ok_multiplier": 0.75, "bad_multiplier": -0.5},
|
||||
{"clear_rate": 38.0, "ok_multiplier": 0.75, "bad_multiplier": -0.5},
|
||||
{"clear_rate": 44.0, "ok_multiplier": 0.75, "bad_multiplier": -0.5},
|
||||
{"clear_rate": 44.0, "ok_multiplier": 0.75, "bad_multiplier": -0.5},
|
||||
],
|
||||
[
|
||||
None,
|
||||
{"clear_rate": 45.939, "ok_multiplier": 0.75, "bad_multiplier": -0.5},
|
||||
{"clear_rate": 45.939, "ok_multiplier": 0.75, "bad_multiplier": -0.5},
|
||||
{"clear_rate": 48.676, "ok_multiplier": 0.75, "bad_multiplier": -0.5},
|
||||
{"clear_rate": 49.232, "ok_multiplier": 0.75, "bad_multiplier": -0.75},
|
||||
{"clear_rate": 52.5, "ok_multiplier": 0.75, "bad_multiplier": -1.0},
|
||||
{"clear_rate": 52.5, "ok_multiplier": 0.75, "bad_multiplier": -1.0},
|
||||
{"clear_rate": 52.5, "ok_multiplier": 0.75, "bad_multiplier": -1.0},
|
||||
],
|
||||
[
|
||||
None,
|
||||
{"clear_rate": 54.325, "ok_multiplier": 0.75, "bad_multiplier": -0.75},
|
||||
{"clear_rate": 54.325, "ok_multiplier": 0.75, "bad_multiplier": -0.75},
|
||||
{"clear_rate": 50.774, "ok_multiplier": 0.75, "bad_multiplier": -1.0},
|
||||
{"clear_rate": 48.410, "ok_multiplier": 0.75, "bad_multiplier": -1.17},
|
||||
{"clear_rate": 47.246, "ok_multiplier": 0.75, "bad_multiplier": -1.25},
|
||||
{"clear_rate": 48.120, "ok_multiplier": 0.75, "bad_multiplier": -1.25},
|
||||
{"clear_rate": 48.120, "ok_multiplier": 0.75, "bad_multiplier": -1.25},
|
||||
{"clear_rate": 48.120, "ok_multiplier": 0.75, "bad_multiplier": -1.25},
|
||||
],
|
||||
[
|
||||
None,
|
||||
{"clear_rate": 56.603, "ok_multiplier": 0.5, "bad_multiplier": -1.6},
|
||||
{"clear_rate": 56.603, "ok_multiplier": 0.5, "bad_multiplier": -1.6},
|
||||
{"clear_rate": 56.603, "ok_multiplier": 0.5, "bad_multiplier": -1.6},
|
||||
{"clear_rate": 56.603, "ok_multiplier": 0.5, "bad_multiplier": -1.6},
|
||||
{"clear_rate": 56.603, "ok_multiplier": 0.5, "bad_multiplier": -1.6},
|
||||
{"clear_rate": 56.603, "ok_multiplier": 0.5, "bad_multiplier": -1.6},
|
||||
{"clear_rate": 56.603, "ok_multiplier": 0.5, "bad_multiplier": -1.6},
|
||||
{"clear_rate": 56.0, "ok_multiplier": 0.5, "bad_multiplier": -2.0},
|
||||
{"clear_rate": 61.428, "ok_multiplier": 0.5, "bad_multiplier": -2.0},
|
||||
{"clear_rate": 61.428, "ok_multiplier": 0.5, "bad_multiplier": -2.0},
|
||||
]
|
||||
]
|
||||
self.gauge_update_anim = None
|
||||
self.rainbow_fade_in = None
|
||||
self.rainbow_animation = None
|
||||
|
||||
def _create_rainbow_anim(self, current_ms):
|
||||
anim = Animation(current_ms, (16.67*8) * 3, 'texture_change')
|
||||
anim.params['textures'] = []
|
||||
for i in range(8):
|
||||
anim.params['textures'].append(((16.67* 3)*i, (16.67 * 3)*(i+1), i))
|
||||
return anim
|
||||
|
||||
def _create_anim(self, current_ms: float, init: float, final: float):
|
||||
anim = Animation(current_ms, 450, 'fade')
|
||||
anim.params['initial_opacity'] = init
|
||||
anim.params['final_opacity'] = final
|
||||
return anim
|
||||
|
||||
def update(self, current_ms: float, good_count: int, ok_count: int, bad_count: int, total_notes: int):
|
||||
gauge_length = int(((good_count +
|
||||
(ok_count * self.table[self.difficulty][self.level]["ok_multiplier"] +
|
||||
bad_count * self.table[self.difficulty][self.level]["bad_multiplier"])) / total_notes) * (100 * (self.clear_start[self.difficulty] / self.table[self.difficulty][self.level]["clear_rate"])))
|
||||
previous_length = self.gauge_length
|
||||
self.gauge_length = min(87, gauge_length)
|
||||
if self.gauge_length == 87 and self.rainbow_fade_in is None:
|
||||
self.rainbow_fade_in = self._create_anim(current_ms, 0.0, 1.0)
|
||||
if self.gauge_length > previous_length:
|
||||
self.gauge_update_anim = self._create_anim(current_ms, 1.0, 0.0)
|
||||
|
||||
if self.gauge_update_anim is not None:
|
||||
self.gauge_update_anim.update(current_ms)
|
||||
if self.gauge_update_anim.is_finished:
|
||||
self.gauge_update_anim = None
|
||||
|
||||
if self.rainbow_fade_in is not None:
|
||||
self.rainbow_fade_in.update(current_ms)
|
||||
|
||||
if self.rainbow_animation is None:
|
||||
self.rainbow_animation = self._create_rainbow_anim(current_ms)
|
||||
else:
|
||||
self.rainbow_animation.update(current_ms)
|
||||
if self.rainbow_animation.is_finished or self.gauge_length < 87:
|
||||
self.rainbow_animation = None
|
||||
|
||||
def draw(self, textures: list[ray.Texture]):
|
||||
ray.draw_texture(textures[0], 327, 132, ray.WHITE)
|
||||
ray.draw_texture(textures[1], 483, 124, ray.WHITE)
|
||||
if self.gauge_length == 87 and self.rainbow_fade_in is not None and self.rainbow_animation is not None:
|
||||
if 0 < self.rainbow_animation.attribute < 8:
|
||||
ray.draw_texture(textures[1 + int(self.rainbow_animation.attribute)], 483, 124, ray.fade(ray.WHITE, self.rainbow_fade_in.attribute))
|
||||
ray.draw_texture(textures[2 + int(self.rainbow_animation.attribute)], 483, 124, ray.fade(ray.WHITE, self.rainbow_fade_in.attribute))
|
||||
if self.rainbow_fade_in is None or not self.rainbow_fade_in.is_finished:
|
||||
for i in range(self.gauge_length):
|
||||
if i == 68:
|
||||
ray.draw_texture(textures[16], 491 + (i*textures[13].width), 160 - 24, ray.WHITE)
|
||||
elif i > 68:
|
||||
ray.draw_texture(textures[15], 491 + (i*textures[13].width) + 2, 160 - 22, ray.WHITE)
|
||||
ray.draw_texture(textures[20], 491 + (i*textures[13].width) + 2, 160, ray.WHITE)
|
||||
else:
|
||||
ray.draw_texture(textures[13], 491 + (i*textures[13].width), 160, ray.WHITE)
|
||||
if self.gauge_update_anim is not None and self.gauge_length < 88:
|
||||
if self.gauge_length == 69:
|
||||
ray.draw_texture(textures[17], 491 + (self.gauge_length*textures[13].width) - 13, 160 - 8 - 24, ray.fade(ray.WHITE, self.gauge_update_anim.attribute))
|
||||
elif self.gauge_length > 69:
|
||||
ray.draw_texture(textures[21], 491 + (self.gauge_length*textures[13].width) - 13, 160 - 8 - 22, ray.fade(ray.WHITE, self.gauge_update_anim.attribute))
|
||||
else:
|
||||
ray.draw_texture(textures[14], 491 + (self.gauge_length*textures[13].width) - 13, 160 - 8, ray.fade(ray.WHITE, self.gauge_update_anim.attribute))
|
||||
ray.draw_texture(textures[10], 483, 124, ray.fade(ray.WHITE, 0.15))
|
||||
if self.gauge_length >= 69:
|
||||
ray.draw_texture(textures[18], 1038, 141, ray.WHITE)
|
||||
ray.draw_texture(textures[19], 1187, 130, ray.WHITE)
|
||||
else:
|
||||
ray.draw_texture(textures[11], 1038, 141, ray.WHITE)
|
||||
ray.draw_texture(textures[12], 1187, 130, ray.WHITE)
|
||||
|
||||
220
scenes/result.py
220
scenes/result.py
@@ -2,50 +2,62 @@ from pathlib import Path
|
||||
|
||||
import pyray as ray
|
||||
|
||||
from libs import utils
|
||||
from libs.animation import Animation
|
||||
from libs.audio import audio
|
||||
from libs.utils import (
|
||||
OutlinedText,
|
||||
draw_scaled_texture,
|
||||
get_config,
|
||||
get_current_ms,
|
||||
global_data,
|
||||
load_all_textures_from_zip,
|
||||
session_data,
|
||||
)
|
||||
|
||||
|
||||
def draw_scaled_texture(texture, x: int, y: int, scale: float, color: ray.Color) -> None:
|
||||
width = texture.width
|
||||
height = texture.height
|
||||
src_rect = ray.Rectangle(0, 0, width, height)
|
||||
dst_rect = ray.Rectangle(x, y, width*scale, height*scale)
|
||||
ray.draw_texture_pro(texture, src_rect, dst_rect, ray.Vector2(0, 0), 0, color)
|
||||
|
||||
class ResultScreen:
|
||||
def __init__(self, width: int, height: int):
|
||||
self.width = width
|
||||
self.height = height
|
||||
sounds_dir = Path("Sounds")
|
||||
self.sound_don = audio.load_sound(str(sounds_dir / "inst_00_don.wav"))
|
||||
self.sound_kat = audio.load_sound(str(sounds_dir / "inst_00_katsu.wav"))
|
||||
self.bgm = audio.load_sound(str(sounds_dir / "result" / "JINGLE_SEISEKI [1].ogg"))
|
||||
self.screen_init = False
|
||||
self.load_sounds()
|
||||
|
||||
def load_textures(self):
|
||||
zip_file = Path('Graphics/lumendata/enso_result.zip')
|
||||
self.textures = load_all_textures_from_zip(zip_file)
|
||||
|
||||
self.song_info = FontText(global_data.song_title, 40).texture
|
||||
self.screen_init = False
|
||||
|
||||
self.fade_in = None
|
||||
|
||||
self.bgm_volume = 1.0
|
||||
def load_sounds(self):
|
||||
sounds_dir = Path("Sounds")
|
||||
self.sound_don = audio.load_sound(str(sounds_dir / "inst_00_don.wav"))
|
||||
self.sound_kat = audio.load_sound(str(sounds_dir / "inst_00_katsu.wav"))
|
||||
self.sound_num_up = audio.load_sound(str(sounds_dir / "result" / "SE_RESULT [4].ogg"))
|
||||
self.bgm = audio.load_sound(str(sounds_dir / "result" / "JINGLE_SEISEKI [1].ogg"))
|
||||
|
||||
def on_screen_start(self):
|
||||
if not self.screen_init:
|
||||
self.textures = load_all_textures_from_zip(Path('Graphics/lumendata/enso_result.zip'))
|
||||
self.load_textures()
|
||||
self.screen_init = True
|
||||
self.song_info = FontText(global_data.song_title, 40).texture
|
||||
self.bgm_volume = 1.0
|
||||
self.song_info = FontText(session_data.song_title, 40).texture
|
||||
audio.play_sound(self.bgm)
|
||||
self.fade_in = FadeIn(get_current_ms())
|
||||
self.gauge = None
|
||||
self.score_delay = None
|
||||
self.score_animator = ScoreAnimator(session_data.result_score)
|
||||
self.score = -1
|
||||
self.good = -1
|
||||
self.ok = -1
|
||||
self.bad = -1
|
||||
self.max_combo = -1
|
||||
self.total_drumroll = -1
|
||||
self.update_list = [['score', session_data.result_score],
|
||||
['good', session_data.result_good],
|
||||
['ok', session_data.result_ok],
|
||||
['bad', session_data.result_bad],
|
||||
['total_drumroll', session_data.result_total_drumroll],
|
||||
['max_combo', session_data.result_max_combo]]
|
||||
self.update_index = 0
|
||||
self.is_skipped = False
|
||||
|
||||
def on_screen_end(self):
|
||||
self.screen_init = False
|
||||
@@ -55,28 +67,80 @@ class ResultScreen:
|
||||
for texture in self.textures[zip]:
|
||||
ray.unload_texture(texture)
|
||||
audio.stop_sound(self.bgm)
|
||||
utils.session_data = utils.reset_session()
|
||||
return "SONG_SELECT"
|
||||
|
||||
def update_score_animation(self, is_skipped):
|
||||
if self.is_skipped:
|
||||
setattr(self, self.update_list[self.update_index][0], self.update_list[self.update_index][1])
|
||||
if self.update_index == len(self.update_list) - 1:
|
||||
return
|
||||
self.update_index += 1
|
||||
elif self.score_delay is not None:
|
||||
if get_current_ms() > self.score_delay:
|
||||
if self.score_animator is not None and not self.score_animator.is_finished:
|
||||
curr_num = self.update_list[self.update_index][0]
|
||||
setattr(self, self.update_list[self.update_index][0], self.score_animator.next_score())
|
||||
if self.update_list[self.update_index] != curr_num:
|
||||
audio.play_sound(self.sound_num_up)
|
||||
if self.score_animator.is_finished:
|
||||
audio.play_sound(self.sound_don)
|
||||
self.score_delay += 750
|
||||
if self.update_index == len(self.update_list) - 1:
|
||||
self.is_skipped = True
|
||||
return
|
||||
self.update_index += 1
|
||||
self.score_animator = ScoreAnimator(self.update_list[self.update_index][1])
|
||||
self.score_delay += 16.67 * 3
|
||||
|
||||
|
||||
def update(self):
|
||||
self.on_screen_start()
|
||||
if ray.is_key_pressed(ray.KeyboardKey.KEY_ENTER):
|
||||
return self.on_screen_end()
|
||||
|
||||
if self.fade_in is not None:
|
||||
self.fade_in.update(get_current_ms())
|
||||
if self.fade_in.is_finished and self.gauge is None:
|
||||
self.gauge = Gauge(get_current_ms(), session_data.result_gauge_length)
|
||||
|
||||
if self.gauge is not None:
|
||||
self.gauge.update(get_current_ms())
|
||||
if self.gauge.is_finished and self.score_delay is None:
|
||||
self.score_delay = get_current_ms() + 1883
|
||||
|
||||
left_dons = get_config()["keybinds"]["left_don"]
|
||||
right_dons = get_config()["keybinds"]["right_don"]
|
||||
for don in left_dons + right_dons:
|
||||
if ray.is_key_pressed(ord(don)):
|
||||
if not self.is_skipped:
|
||||
self.is_skipped = True
|
||||
audio.play_sound(self.sound_don)
|
||||
else:
|
||||
return self.on_screen_end()
|
||||
self.update_score_animation(self.is_skipped)
|
||||
|
||||
|
||||
def draw_score_info(self):
|
||||
for i in range(len(str(global_data.result_good))):
|
||||
ray.draw_texture(self.textures['result'][int(str(global_data.result_good)[::-1][i]) + 136], 943-(i*24), 186, ray.WHITE)
|
||||
for i in range(len(str(global_data.result_ok))):
|
||||
ray.draw_texture(self.textures['result'][int(str(global_data.result_ok)[::-1][i]) + 136], 943-(i*24), 227, ray.WHITE)
|
||||
for i in range(len(str(global_data.result_bad))):
|
||||
ray.draw_texture(self.textures['result'][int(str(global_data.result_bad)[::-1][i]) + 136], 943-(i*24), 267, ray.WHITE)
|
||||
if self.good > -1:
|
||||
for i in range(len(str(self.good))):
|
||||
ray.draw_texture(self.textures['result'][int(str(self.good)[::-1][i]) + 136], 943-(i*24), 186, ray.WHITE)
|
||||
if self.ok > -1:
|
||||
for i in range(len(str(self.ok))):
|
||||
ray.draw_texture(self.textures['result'][int(str(self.ok)[::-1][i]) + 136], 943-(i*24), 227, ray.WHITE)
|
||||
if self.bad > -1:
|
||||
for i in range(len(str(self.bad))):
|
||||
ray.draw_texture(self.textures['result'][int(str(self.bad)[::-1][i]) + 136], 943-(i*24), 267, ray.WHITE)
|
||||
if self.max_combo > -1:
|
||||
for i in range(len(str(self.max_combo))):
|
||||
ray.draw_texture(self.textures['result'][int(str(self.max_combo)[::-1][i]) + 136], 1217-(i*24), 227, ray.WHITE)
|
||||
if self.total_drumroll > -1:
|
||||
for i in range(len(str(self.total_drumroll))):
|
||||
ray.draw_texture(self.textures['result'][int(str(self.total_drumroll)[::-1][i]) + 136], 1217-(i*24), 186, ray.WHITE)
|
||||
|
||||
def draw_total_score(self):
|
||||
ray.draw_texture(self.textures['result'][167], 554, 236, ray.WHITE)
|
||||
for i in range(len(str(global_data.result_score))):
|
||||
ray.draw_texture(self.textures['result'][int(str(global_data.result_score)[::-1][i]) + 156], 723-(i*21), 252, ray.WHITE)
|
||||
if self.score > -1:
|
||||
for i in range(len(str(self.score))):
|
||||
ray.draw_texture(self.textures['result'][int(str(self.score)[::-1][i]) + 156], 723-(i*21), 252, ray.WHITE)
|
||||
|
||||
def draw(self):
|
||||
x = 0
|
||||
@@ -96,11 +160,8 @@ class ResultScreen:
|
||||
|
||||
ray.draw_texture(self.textures['result'][175], 532, 98, ray.fade(ray.WHITE, 0.75))
|
||||
|
||||
draw_scaled_texture(self.textures['result'][217], 554, 109, (10/11), ray.WHITE)
|
||||
draw_scaled_texture(self.textures['result'][226], 554, 109, (10/11), ray.fade(ray.WHITE, 0.15))
|
||||
draw_scaled_texture(self.textures['result'][176], 1185, 116, (10/11), ray.WHITE)
|
||||
draw_scaled_texture(self.textures['result'][187], 1058, 124, (10/11), ray.WHITE)
|
||||
draw_scaled_texture(self.textures['result'][188], 1182, 115, (10/11), ray.WHITE)
|
||||
if self.gauge is not None:
|
||||
self.gauge.draw(self.textures['result'])
|
||||
|
||||
ray.draw_texture(self.textures['result'][170], 817, 186, ray.WHITE)
|
||||
ray.draw_texture(self.textures['result'][171], 817, 227, ray.WHITE)
|
||||
@@ -123,9 +184,12 @@ class FadeIn:
|
||||
self.fadein.params['delay'] = 100
|
||||
self.fade = ray.fade(ray.WHITE, self.fadein.attribute)
|
||||
|
||||
self.is_finished = False
|
||||
|
||||
def update(self, current_ms: float):
|
||||
self.fadein.update(current_ms)
|
||||
self.fade = ray.fade(ray.WHITE, self.fadein.attribute)
|
||||
self.is_finished = self.fadein.is_finished
|
||||
|
||||
def draw(self, screen_width: int, screen_height: int, texture_1: ray.Texture, texture_2: ray.Texture):
|
||||
x = 0
|
||||
@@ -143,9 +207,93 @@ class FontText:
|
||||
def __init__(self, text, font_size):
|
||||
codepoint_count = ray.ffi.new('int *', 0)
|
||||
codepoints_no_dup = set()
|
||||
codepoints_no_dup.update(global_data.song_title)
|
||||
codepoints_no_dup.update(session_data.song_title)
|
||||
codepoints = ray.load_codepoints(''.join(codepoints_no_dup), codepoint_count)
|
||||
self.font = ray.load_font_ex(str(Path('Graphics/Modified-DFPKanteiryu-XB.ttf')), 32, codepoints, 0)
|
||||
self.text = OutlinedText(self.font, str(text), font_size, ray.WHITE, ray.BLACK, outline_thickness=5)
|
||||
|
||||
self.texture = self.text.texture
|
||||
|
||||
class ScoreAnimator:
|
||||
def __init__(self, target_score):
|
||||
self.target_score = str(target_score)
|
||||
self.current_score_list = [[0,0] for i in range(len(self.target_score))]
|
||||
self.digit_index = len(self.target_score) - 1
|
||||
self.is_finished = False
|
||||
|
||||
def next_score(self):
|
||||
if self.digit_index == -1:
|
||||
self.is_finished = True
|
||||
return int(''.join([str(item[0]) for item in self.current_score_list]))
|
||||
curr_digit, counter = self.current_score_list[self.digit_index]
|
||||
if counter < 9:
|
||||
self.current_score_list[self.digit_index][1] += 1
|
||||
self.current_score_list[self.digit_index][0] = (curr_digit + 1) % 10
|
||||
else:
|
||||
self.current_score_list[self.digit_index][0] = int(self.target_score[self.digit_index])
|
||||
self.digit_index -= 1
|
||||
return int(''.join([str(item[0]) for item in self.current_score_list]))
|
||||
|
||||
class Gauge:
|
||||
def __init__(self, current_ms: float, gauge_length):
|
||||
self.gauge_length = gauge_length
|
||||
self.rainbow_animation = None
|
||||
self.gauge_fade_in = Animation(get_current_ms(), 366, 'fade')
|
||||
self.gauge_fade_in.params['initial_opacity'] = 0.0
|
||||
self.gauge_fade_in.params['final_opacity'] = 1.0
|
||||
self.is_finished = self.gauge_fade_in.is_finished
|
||||
|
||||
def _create_rainbow_anim(self, current_ms):
|
||||
anim = Animation(current_ms, (16.67*8) * 3, 'texture_change')
|
||||
anim.params['textures'] = []
|
||||
for i in range(8):
|
||||
anim.params['textures'].append(((16.67* 3)*i, (16.67 * 3)*(i+1), i))
|
||||
return anim
|
||||
|
||||
def _create_anim(self, current_ms: float, init: float, final: float):
|
||||
anim = Animation(current_ms, 450, 'fade')
|
||||
anim.params['initial_opacity'] = init
|
||||
anim.params['final_opacity'] = final
|
||||
return anim
|
||||
|
||||
def update(self, current_ms: float):
|
||||
if self.rainbow_animation is None:
|
||||
self.rainbow_animation = self._create_rainbow_anim(current_ms)
|
||||
else:
|
||||
self.rainbow_animation.update(current_ms)
|
||||
if self.rainbow_animation.is_finished:
|
||||
self.rainbow_animation = None
|
||||
self.gauge_fade_in.update(current_ms)
|
||||
self.is_finished = self.gauge_fade_in.is_finished
|
||||
|
||||
def draw(self, textures: list[ray.Texture]):
|
||||
color = ray.fade(ray.WHITE, self.gauge_fade_in.attribute)
|
||||
draw_scaled_texture(textures[217], 554, 109, (10/11), color)
|
||||
if self.gauge_length == 87 and self.rainbow_animation is not None:
|
||||
if 0 < self.rainbow_animation.attribute < 8:
|
||||
draw_scaled_texture(textures[217 + int(self.rainbow_animation.attribute)], 554, 109, (10/11), color)
|
||||
draw_scaled_texture(textures[218 + int(self.rainbow_animation.attribute)], 554, 109, (10/11), color)
|
||||
else:
|
||||
for i in range(self.gauge_length+1):
|
||||
width = int(i * 7.2)
|
||||
if i == 69:
|
||||
draw_scaled_texture(textures[192], 562 + width, 142 - 22, (10/11), color)
|
||||
elif i > 69:
|
||||
if i % 5 == 0:
|
||||
draw_scaled_texture(textures[191], 561 + width, 142 - 20, (10/11), color)
|
||||
draw_scaled_texture(textures[196], 561 + width, 142, (10/11), color)
|
||||
draw_scaled_texture(textures[191], 562 + width, 142 - 20, (10/11), color)
|
||||
draw_scaled_texture(textures[196], 562 + width, 142, (10/11), color)
|
||||
else:
|
||||
if i % 5 == 0:
|
||||
draw_scaled_texture(textures[189], 561 + width, 142, (10/11), color)
|
||||
draw_scaled_texture(textures[189], 562 + width, 142, (10/11), color)
|
||||
draw_scaled_texture(textures[226], 554, 109, (10/11), ray.fade(ray.WHITE, min(0.15, self.gauge_fade_in.attribute)))
|
||||
draw_scaled_texture(textures[176], 1185, 116, (10/11), color)
|
||||
|
||||
if self.gauge_length >= 69:
|
||||
draw_scaled_texture(textures[194], 1058, 124, (10/11), color)
|
||||
draw_scaled_texture(textures[195], 1182, 115, (10/11), color)
|
||||
else:
|
||||
draw_scaled_texture(textures[187], 1058, 124, (10/11), color)
|
||||
draw_scaled_texture(textures[188], 1182, 115, (10/11), color)
|
||||
|
||||
@@ -5,15 +5,13 @@ import pyray as ray
|
||||
|
||||
from libs.audio import audio
|
||||
from libs.tja import TJAParser
|
||||
from libs.utils import get_config, global_data
|
||||
from libs.utils import get_config, session_data
|
||||
|
||||
|
||||
class SongSelectScreen:
|
||||
def __init__(self, width: int, height: int):
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.is_song_select = True
|
||||
self.is_difficulty_select = False
|
||||
self.song_list: dict[str, list] = dict()
|
||||
self.selected_song = 0
|
||||
self.selected_difficulty = 0
|
||||
@@ -31,15 +29,14 @@ class SongSelectScreen:
|
||||
def on_screen_start(self):
|
||||
if not self.screen_init:
|
||||
self.screen_init = True
|
||||
|
||||
self.is_song_select = True
|
||||
self.is_difficulty_select = False
|
||||
|
||||
def on_screen_end(self):
|
||||
self.screen_init = False
|
||||
audio.play_sound(self.sound_don)
|
||||
global_data.selected_song = list(self.song_list.keys())[self.selected_song]
|
||||
global_data.selected_difficulty = self.selected_difficulty
|
||||
session_data.selected_song = list(self.song_list.keys())[self.selected_song]
|
||||
session_data.selected_difficulty = self.selected_difficulty
|
||||
return "GAME"
|
||||
|
||||
def update_song_select(self):
|
||||
|
||||
@@ -22,20 +22,13 @@ class TitleScreen:
|
||||
self.op_video_list = [str(file) for file in video_dir.glob("**/*.mp4")]
|
||||
video_dir = Path(get_config()["paths"]["video_path"]) / "attract_videos"
|
||||
self.attract_video_list = [str(file) for file in video_dir.glob("**/*.mp4")]
|
||||
self.attract_video = VideoPlayer(random.choice(self.attract_video_list))
|
||||
self.op_video = VideoPlayer(random.choice(self.op_video_list))
|
||||
self.scene = 'Opening Video'
|
||||
self.load_textures()
|
||||
self.warning_board = WarningScreen(get_current_ms(), self)
|
||||
|
||||
self.load_sounds()
|
||||
self.screen_init = False
|
||||
|
||||
def get_videos(self):
|
||||
return self.op_video, self.attract_video
|
||||
|
||||
def load_textures(self):
|
||||
self.textures = load_all_textures_from_zip(Path('Graphics/lumendata/attract/keikoku.zip'))
|
||||
|
||||
def load_sounds(self):
|
||||
sounds_dir = Path("Sounds")
|
||||
title_dir = sounds_dir / "title"
|
||||
|
||||
@@ -43,14 +36,28 @@ class TitleScreen:
|
||||
self.sound_bachi_hit = audio.load_sound(str(title_dir / "SE_ATTRACT_3.ogg"))
|
||||
self.sound_warning_message = audio.load_sound(str(title_dir / "VO_ATTRACT_3.ogg"))
|
||||
self.sound_warning_error = audio.load_sound(str(title_dir / "SE_ATTRACT_1.ogg"))
|
||||
self.sounds = [self.sound_bachi_swipe, self.sound_bachi_hit, self.sound_warning_message, self.sound_warning_error]
|
||||
|
||||
def load_textures(self):
|
||||
self.textures = load_all_textures_from_zip(Path('Graphics/lumendata/attract/keikoku.zip'))
|
||||
self.texture_black = load_texture_from_zip(Path('Graphics/lumendata/attract/movie.zip'), 'movie_img00000.png')
|
||||
|
||||
def on_screen_start(self):
|
||||
if not self.screen_init:
|
||||
self.screen_init = True
|
||||
self.load_textures()
|
||||
self.scene = 'Opening Video'
|
||||
self.op_video = VideoPlayer(random.choice(self.op_video_list))
|
||||
self.op_video._convert_frames()
|
||||
self.warning_board = WarningScreen(get_current_ms(), self)
|
||||
self.attract_video = VideoPlayer(random.choice(self.attract_video_list))
|
||||
|
||||
def on_screen_end(self) -> str:
|
||||
self.op_video.stop()
|
||||
self.attract_video.stop()
|
||||
for sound in self.sounds:
|
||||
if audio.is_sound_playing(sound):
|
||||
audio.stop_sound(sound)
|
||||
for zip in self.textures:
|
||||
for texture in self.textures[zip]:
|
||||
ray.unload_texture(texture)
|
||||
@@ -60,19 +67,32 @@ class TitleScreen:
|
||||
def scene_manager(self):
|
||||
if self.scene == 'Opening Video':
|
||||
self.op_video.update()
|
||||
if all(self.op_video.is_finished):
|
||||
self.attract_video.convert_frames_background()
|
||||
if self.op_video.is_finished():
|
||||
self.op_video = VideoPlayer(random.choice(self.op_video_list))
|
||||
|
||||
self.scene = 'Warning Board'
|
||||
self.warning_board = WarningScreen(get_current_ms(), self)
|
||||
elif self.scene == 'Warning Board':
|
||||
self.warning_board.update(get_current_ms(), self)
|
||||
self.op_video.convert_frames_background()
|
||||
self.attract_video.convert_frames_background()
|
||||
if self.warning_board.is_finished:
|
||||
self.scene = 'Attract Video'
|
||||
self.attract_video = VideoPlayer(random.choice(self.attract_video_list))
|
||||
self.attract_video.start_ms = get_current_ms()
|
||||
elif self.scene == 'Attract Video':
|
||||
while not self.attract_video.all_frames_converted:
|
||||
self.attract_video.convert_frames_background()
|
||||
if self.attract_video.all_frames_converted:
|
||||
self.attract_video.start_ms = get_current_ms()
|
||||
self.attract_video.update()
|
||||
if all(self.attract_video.is_finished):
|
||||
self.op_video.convert_frames_background()
|
||||
if self.attract_video.is_finished():
|
||||
self.attract_video = VideoPlayer(random.choice(self.attract_video_list))
|
||||
|
||||
self.scene = 'Opening Video'
|
||||
self.op_video = VideoPlayer(random.choice(self.op_video_list))
|
||||
self.op_video.start_ms = get_current_ms()
|
||||
|
||||
|
||||
def update(self):
|
||||
self.on_screen_start()
|
||||
|
||||
258
uv.lock
generated
Normal file
258
uv.lock
generated
Normal file
@@ -0,0 +1,258 @@
|
||||
version = 1
|
||||
revision = 2
|
||||
requires-python = ">=3.12"
|
||||
resolution-markers = [
|
||||
"sys_platform == 'darwin'",
|
||||
"platform_machine == 'aarch64' and sys_platform == 'linux'",
|
||||
"(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cffi"
|
||||
version = "1.17.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pycparser" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178, upload-time = "2024-09-04T20:44:12.232Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840, upload-time = "2024-09-04T20:44:13.739Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload-time = "2024-09-04T20:44:15.231Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload-time = "2024-09-04T20:44:28.956Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload-time = "2024-09-04T20:44:30.289Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload-time = "2024-09-04T20:44:33.606Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload-time = "2024-09-04T20:44:35.191Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload-time = "2024-09-04T20:44:36.743Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload-time = "2024-09-04T20:44:38.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload-time = "2024-09-04T20:44:40.046Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload-time = "2024-09-04T20:44:41.616Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload-time = "2024-09-04T20:44:43.733Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inflection"
|
||||
version = "0.5.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e1/7e/691d061b7329bc8d54edbf0ec22fbfb2afe61facb681f9aaa9bff7a27d04/inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417", size = 15091, upload-time = "2020-08-22T08:16:29.139Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/59/91/aa6bde563e0085a02a435aa99b49ef75b0a4b062635e606dab23ce18d720/inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2", size = 9454, upload-time = "2020-08-22T08:16:27.816Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.2.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/dc/b2/ce4b867d8cd9c0ee84938ae1e6a6f7926ebf928c9090d036fc3c6a04f946/numpy-2.2.5.tar.gz", hash = "sha256:a9c0d994680cd991b1cb772e8b297340085466a6fe964bc9d4e80f5e2f43c291", size = 20273920, upload-time = "2025-04-19T23:27:42.561Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/f7/1fd4ff108cd9d7ef929b8882692e23665dc9c23feecafbb9c6b80f4ec583/numpy-2.2.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ee461a4eaab4f165b68780a6a1af95fb23a29932be7569b9fab666c407969051", size = 20948633, upload-time = "2025-04-19T22:37:52.4Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/03/d443c278348371b20d830af155ff2079acad6a9e60279fac2b41dbbb73d8/numpy-2.2.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ec31367fd6a255dc8de4772bd1658c3e926d8e860a0b6e922b615e532d320ddc", size = 14176123, upload-time = "2025-04-19T22:38:15.058Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/0b/5ca264641d0e7b14393313304da48b225d15d471250376f3fbdb1a2be603/numpy-2.2.5-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:47834cde750d3c9f4e52c6ca28a7361859fcaf52695c7dc3cc1a720b8922683e", size = 5163817, upload-time = "2025-04-19T22:38:24.885Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/b3/d522672b9e3d28e26e1613de7675b441bbd1eaca75db95680635dd158c67/numpy-2.2.5-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:2c1a1c6ccce4022383583a6ded7bbcda22fc635eb4eb1e0a053336425ed36dfa", size = 6698066, upload-time = "2025-04-19T22:38:35.782Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/93/0f7a75c1ff02d4b76df35079676b3b2719fcdfb39abdf44c8b33f43ef37d/numpy-2.2.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d75f338f5f79ee23548b03d801d28a505198297534f62416391857ea0479571", size = 14087277, upload-time = "2025-04-19T22:38:57.697Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/d9/7c338b923c53d431bc837b5b787052fef9ae68a56fe91e325aac0d48226e/numpy-2.2.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a801fef99668f309b88640e28d261991bfad9617c27beda4a3aec4f217ea073", size = 16135742, upload-time = "2025-04-19T22:39:22.689Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/10/4dec9184a5d74ba9867c6f7d1e9f2e0fb5fe96ff2bf50bb6f342d64f2003/numpy-2.2.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:abe38cd8381245a7f49967a6010e77dbf3680bd3627c0fe4362dd693b404c7f8", size = 15581825, upload-time = "2025-04-19T22:39:45.794Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/1f/2b6fcd636e848053f5b57712a7d1880b1565eec35a637fdfd0a30d5e738d/numpy-2.2.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5a0ac90e46fdb5649ab6369d1ab6104bfe5854ab19b645bf5cda0127a13034ae", size = 17899600, upload-time = "2025-04-19T22:40:13.427Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/87/36801f4dc2623d76a0a3835975524a84bd2b18fe0f8835d45c8eae2f9ff2/numpy-2.2.5-cp312-cp312-win32.whl", hash = "sha256:0cd48122a6b7eab8f06404805b1bd5856200e3ed6f8a1b9a194f9d9054631beb", size = 6312626, upload-time = "2025-04-19T22:40:25.223Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/09/4ffb4d6cfe7ca6707336187951992bd8a8b9142cf345d87ab858d2d7636a/numpy-2.2.5-cp312-cp312-win_amd64.whl", hash = "sha256:ced69262a8278547e63409b2653b372bf4baff0870c57efa76c5703fd6543282", size = 12645715, upload-time = "2025-04-19T22:40:44.528Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/a0/0aa7f0f4509a2e07bd7a509042967c2fab635690d4f48c6c7b3afd4f448c/numpy-2.2.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:059b51b658f4414fff78c6d7b1b4e18283ab5fa56d270ff212d5ba0c561846f4", size = 20935102, upload-time = "2025-04-19T22:41:16.234Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/e4/a6a9f4537542912ec513185396fce52cdd45bdcf3e9d921ab02a93ca5aa9/numpy-2.2.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:47f9ed103af0bc63182609044b0490747e03bd20a67e391192dde119bf43d52f", size = 14191709, upload-time = "2025-04-19T22:41:38.472Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/65/72f3186b6050bbfe9c43cb81f9df59ae63603491d36179cf7a7c8d216758/numpy-2.2.5-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:261a1ef047751bb02f29dfe337230b5882b54521ca121fc7f62668133cb119c9", size = 5149173, upload-time = "2025-04-19T22:41:47.823Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/e9/83e7a9432378dde5802651307ae5e9ea07bb72b416728202218cd4da2801/numpy-2.2.5-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4520caa3807c1ceb005d125a75e715567806fed67e315cea619d5ec6e75a4191", size = 6684502, upload-time = "2025-04-19T22:41:58.689Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/27/b80da6c762394c8ee516b74c1f686fcd16c8f23b14de57ba0cad7349d1d2/numpy-2.2.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d14b17b9be5f9c9301f43d2e2a4886a33b53f4e6fdf9ca2f4cc60aeeee76372", size = 14084417, upload-time = "2025-04-19T22:42:19.897Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/fc/ebfd32c3e124e6a1043e19c0ab0769818aa69050ce5589b63d05ff185526/numpy-2.2.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ba321813a00e508d5421104464510cc962a6f791aa2fca1c97b1e65027da80d", size = 16133807, upload-time = "2025-04-19T22:42:44.433Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/9b/4cc171a0acbe4666f7775cfd21d4eb6bb1d36d3a0431f48a73e9212d2278/numpy-2.2.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4cbdef3ddf777423060c6f81b5694bad2dc9675f110c4b2a60dc0181543fac7", size = 15575611, upload-time = "2025-04-19T22:43:09.928Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/45/40f4135341850df48f8edcf949cf47b523c404b712774f8855a64c96ef29/numpy-2.2.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:54088a5a147ab71a8e7fdfd8c3601972751ded0739c6b696ad9cb0343e21ab73", size = 17895747, upload-time = "2025-04-19T22:43:36.983Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/4c/b32a17a46f0ffbde8cc82df6d3daeaf4f552e346df143e1b188a701a8f09/numpy-2.2.5-cp313-cp313-win32.whl", hash = "sha256:c8b82a55ef86a2d8e81b63da85e55f5537d2157165be1cb2ce7cfa57b6aef38b", size = 6309594, upload-time = "2025-04-19T22:47:10.523Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/ae/72e6276feb9ef06787365b05915bfdb057d01fceb4a43cb80978e518d79b/numpy-2.2.5-cp313-cp313-win_amd64.whl", hash = "sha256:d8882a829fd779f0f43998e931c466802a77ca1ee0fe25a3abe50278616b1471", size = 12638356, upload-time = "2025-04-19T22:47:30.253Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/56/be8b85a9f2adb688e7ded6324e20149a03541d2b3297c3ffc1a73f46dedb/numpy-2.2.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:e8b025c351b9f0e8b5436cf28a07fa4ac0204d67b38f01433ac7f9b870fa38c6", size = 20963778, upload-time = "2025-04-19T22:44:09.251Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/77/19c5e62d55bff507a18c3cdff82e94fe174957bad25860a991cac719d3ab/numpy-2.2.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dfa94b6a4374e7851bbb6f35e6ded2120b752b063e6acdd3157e4d2bb922eba", size = 14207279, upload-time = "2025-04-19T22:44:31.383Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/22/aa11f22dc11ff4ffe4e849d9b63bbe8d4ac6d5fae85ddaa67dfe43be3e76/numpy-2.2.5-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:97c8425d4e26437e65e1d189d22dff4a079b747ff9c2788057bfb8114ce1e133", size = 5199247, upload-time = "2025-04-19T22:44:40.361Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/6c/12d5e760fc62c08eded0394f62039f5a9857f758312bf01632a81d841459/numpy-2.2.5-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:352d330048c055ea6db701130abc48a21bec690a8d38f8284e00fab256dc1376", size = 6711087, upload-time = "2025-04-19T22:44:51.188Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/94/ece8280cf4218b2bee5cec9567629e61e51b4be501e5c6840ceb593db945/numpy-2.2.5-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b4c0773b6ada798f51f0f8e30c054d32304ccc6e9c5d93d46cb26f3d385ab19", size = 14059964, upload-time = "2025-04-19T22:45:12.451Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/41/c5377dac0514aaeec69115830a39d905b1882819c8e65d97fc60e177e19e/numpy-2.2.5-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55f09e00d4dccd76b179c0f18a44f041e5332fd0e022886ba1c0bbf3ea4a18d0", size = 16121214, upload-time = "2025-04-19T22:45:37.734Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/db/54/3b9f89a943257bc8e187145c6bc0eb8e3d615655f7b14e9b490b053e8149/numpy-2.2.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:02f226baeefa68f7d579e213d0f3493496397d8f1cff5e2b222af274c86a552a", size = 15575788, upload-time = "2025-04-19T22:46:01.908Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/c4/2e407e85df35b29f79945751b8f8e671057a13a376497d7fb2151ba0d290/numpy-2.2.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c26843fd58f65da9491165072da2cccc372530681de481ef670dcc8e27cfb066", size = 17893672, upload-time = "2025-04-19T22:46:28.585Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/7e/d0b44e129d038dba453f00d0e29ebd6eaf2f06055d72b95b9947998aca14/numpy-2.2.5-cp313-cp313t-win32.whl", hash = "sha256:1a161c2c79ab30fe4501d5a2bbfe8b162490757cf90b7f05be8b80bc02f7bb8e", size = 6377102, upload-time = "2025-04-19T22:46:39.949Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/be/b85e4aa4bf42c6502851b971f1c326d583fcc68227385f92089cf50a7b45/numpy-2.2.5-cp313-cp313t-win_amd64.whl", hash = "sha256:d403c84991b5ad291d3809bace5e85f4bbf44a04bdc9a88ed2bb1807b3360bb8", size = 12750096, upload-time = "2025-04-19T22:47:00.147Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opencv-python"
|
||||
version = "4.11.0.86"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/17/06/68c27a523103dad5837dc5b87e71285280c4f098c60e4fe8a8db6486ab09/opencv-python-4.11.0.86.tar.gz", hash = "sha256:03d60ccae62304860d232272e4a4fda93c39d595780cb40b161b310244b736a4", size = 95171956, upload-time = "2025-01-16T13:52:24.737Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/05/4d/53b30a2a3ac1f75f65a59eb29cf2ee7207ce64867db47036ad61743d5a23/opencv_python-4.11.0.86-cp37-abi3-macosx_13_0_arm64.whl", hash = "sha256:432f67c223f1dc2824f5e73cdfcd9db0efc8710647d4e813012195dc9122a52a", size = 37326322, upload-time = "2025-01-16T13:52:25.887Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/84/0a67490741867eacdfa37bc18df96e08a9d579583b419010d7f3da8ff503/opencv_python-4.11.0.86-cp37-abi3-macosx_13_0_x86_64.whl", hash = "sha256:9d05ef13d23fe97f575153558653e2d6e87103995d54e6a35db3f282fe1f9c66", size = 56723197, upload-time = "2025-01-16T13:55:21.222Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/bd/29c126788da65c1fb2b5fb621b7fed0ed5f9122aa22a0868c5e2c15c6d23/opencv_python-4.11.0.86-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b92ae2c8852208817e6776ba1ea0d6b1e0a1b5431e971a2a0ddd2a8cc398202", size = 42230439, upload-time = "2025-01-16T13:51:35.822Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/8b/90eb44a40476fa0e71e05a0283947cfd74a5d36121a11d926ad6f3193cc4/opencv_python-4.11.0.86-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b02611523803495003bd87362db3e1d2a0454a6a63025dc6658a9830570aa0d", size = 62986597, upload-time = "2025-01-16T13:52:08.836Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/d7/1d5941a9dde095468b288d989ff6539dd69cd429dbf1b9e839013d21b6f0/opencv_python-4.11.0.86-cp37-abi3-win32.whl", hash = "sha256:810549cb2a4aedaa84ad9a1c92fbfdfc14090e2749cedf2c1589ad8359aa169b", size = 29384337, upload-time = "2025-01-16T13:52:13.549Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/7d/f1c30a92854540bf789e9cd5dde7ef49bbe63f855b85a2e6b3db8135c591/opencv_python-4.11.0.86-cp37-abi3-win_amd64.whl", hash = "sha256:085ad9b77c18853ea66283e98affefe2de8cc4c1f43eda4c100cf9b2721142ec", size = 39488044, upload-time = "2025-01-16T13:52:21.928Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycparser"
|
||||
version = "2.22"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydub"
|
||||
version = "0.25.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fe/9a/e6bca0eed82db26562c73b5076539a4a08d3cffd19c3cc5913a3e61145fd/pydub-0.25.1.tar.gz", hash = "sha256:980a33ce9949cab2a569606b65674d748ecbca4f0796887fd6f46173a7b0d30f", size = 38326, upload-time = "2021-03-10T02:09:54.659Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/53/d78dc063216e62fc55f6b2eebb447f6a4b0a59f55c8406376f76bf959b08/pydub-0.25.1-py2.py3-none-any.whl", hash = "sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6", size = 32327, upload-time = "2021-03-10T02:09:53.503Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytaiko"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
{ name = "opencv-python" },
|
||||
{ name = "pydub" },
|
||||
{ name = "raylib" },
|
||||
{ name = "raylib-dynamic" },
|
||||
{ name = "ruff" },
|
||||
{ name = "scipy" },
|
||||
{ name = "sounddevice" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "numpy", specifier = ">=2.2.5" },
|
||||
{ name = "opencv-python", specifier = ">=4.11.0.86" },
|
||||
{ name = "pydub", specifier = ">=0.25.1" },
|
||||
{ name = "raylib", specifier = ">=5.5.0.2" },
|
||||
{ name = "raylib-dynamic", specifier = ">=5.5.0.2" },
|
||||
{ name = "ruff", specifier = ">=0.11.7" },
|
||||
{ name = "scipy", specifier = ">=1.15.2" },
|
||||
{ name = "sounddevice", specifier = ">=0.5.1" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raylib"
|
||||
version = "5.5.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cffi" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8c/35/9bf3a2af73c55fd4310dcaec4f997c739888e0db9b4dfac71b7680810852/raylib-5.5.0.2.tar.gz", hash = "sha256:83c108ae3b4af40b53c93d1de2afbe309e986dd5efeb280ebe2e61c79956edb0", size = 181172, upload-time = "2024-11-26T11:12:02.791Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/69/2b/49bfa6833ad74ddf318d54ecafe73d535f583531469ecbd5b009d79667d1/raylib-5.5.0.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5233c529d9a0cfd469d88239c2182e55c5215a7755d83cc3d611148d3b9c9e67", size = 1706157, upload-time = "2024-11-26T11:09:43.6Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/9c/8a3f4de0c81ad1228bf26410cfe3ecdc73011c59f18e542685ffc92c0120/raylib-5.5.0.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:1f76204ffbc492722b571b12dbdc0dca89b10da76ddf48c12a3968d2db061dff", size = 1248027, upload-time = "2025-01-04T20:21:46.269Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/16/63baf1aae94832b9f5d15cafcee67bb6dd07a20cf64d40bac09903b79274/raylib-5.5.0.2-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:f8cc2e39f1d6b29211a97ec0ac818a5b04c43a40e747e4b4622101d48c711f9e", size = 2195374, upload-time = "2024-11-26T11:09:46.114Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/bd/61a006b4e3ce4a6ca974cb0ceeb19f3816815ebabac650e9bf82767e65f6/raylib-5.5.0.2-cp312-cp312-manylinux2014_x86_64.whl", hash = "sha256:f12da578a28da7f48481f46323e5aab8dd25461982b0e80d045782d6e69649f5", size = 2299593, upload-time = "2024-11-26T11:09:48.963Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/4f/59d554cc495bea8235b17cebfc76ed57aaa602c613b870159e31282fd4c1/raylib-5.5.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:b40234bbad9523fd6a2049640c76a98b4d6f0b8f4bd19bd33eaee55faf5e050d", size = 1696780, upload-time = "2024-11-26T11:09:50.787Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/0a/78edc3ed1e2ca7e2ccea31ac5a8f4440a924662ee1042ecb76e08f465d8a/raylib-5.5.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2bfa9419a12eeb259f99c75c351db167968306295a5017cd4735241eaf2fa399", size = 1706104, upload-time = "2024-11-26T11:09:53.571Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/fb/8b79a03c0d63bd6613d3e25df26d6c42fe36689f052abefa00a311be53fc/raylib-5.5.0.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:216456d0fa8da85c253a8596ca4b35c995bbf8af0fb8fa5244a4c6f5debfe294", size = 1248018, upload-time = "2024-11-26T11:09:56.257Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/42/8ef2a8e21a2b4ba7ac4ea13b1dd9bc5d1084020ddca06ad0c6582c784a4e/raylib-5.5.0.2-cp313-cp313-manylinux2014_x86_64.whl", hash = "sha256:4f1c33b7d2404e70dbf3dd8d71701efb24902adfcb553122bf3d9441ea4fd6f0", size = 2299336, upload-time = "2024-11-26T11:09:59.307Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/67/4c25526fde4dabf5cc60093202f8d07a7dc4b1bd29d7b84db55b443a527c/raylib-5.5.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:6b60c97a9f6cfaeef4f59ff162ea29f02c18282d129edebb62f132b2ad6bb935", size = 1696790, upload-time = "2024-11-26T11:10:01.812Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raylib-dynamic"
|
||||
version = "5.5.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cffi" },
|
||||
{ name = "inflection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/43/74/ee15f73ad900bc0ea013852626998f78ba1eec020f470bf9a6873f3725b4/raylib_dynamic-5.5.0.2.tar.gz", hash = "sha256:125c95e51754c56fc045052b22642e2d53839cb1aac9db9df99355744daae868", size = 3172948, upload-time = "2024-11-26T11:12:04.91Z" }
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.11.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5b/89/6f9c9674818ac2e9cc2f2b35b704b7768656e6b7c139064fc7ba8fbc99f1/ruff-0.11.7.tar.gz", hash = "sha256:655089ad3224070736dc32844fde783454f8558e71f501cb207485fe4eee23d4", size = 4054861, upload-time = "2025-04-24T18:49:37.007Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/ec/21927cb906c5614b786d1621dba405e3d44f6e473872e6df5d1a6bca0455/ruff-0.11.7-py3-none-linux_armv6l.whl", hash = "sha256:d29e909d9a8d02f928d72ab7837b5cbc450a5bdf578ab9ebee3263d0a525091c", size = 10245403, upload-time = "2025-04-24T18:48:40.459Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/af/fec85b6c2c725bcb062a354dd7cbc1eed53c33ff3aa665165871c9c16ddf/ruff-0.11.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dd1fb86b168ae349fb01dd497d83537b2c5541fe0626e70c786427dd8363aaee", size = 11007166, upload-time = "2025-04-24T18:48:44.742Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/9a/2d0d260a58e81f388800343a45898fd8df73c608b8261c370058b675319a/ruff-0.11.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d3d7d2e140a6fbbc09033bce65bd7ea29d6a0adeb90b8430262fbacd58c38ada", size = 10378076, upload-time = "2025-04-24T18:48:47.918Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/c4/9b09b45051404d2e7dd6d9dbcbabaa5ab0093f9febcae664876a77b9ad53/ruff-0.11.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4809df77de390a1c2077d9b7945d82f44b95d19ceccf0c287c56e4dc9b91ca64", size = 10557138, upload-time = "2025-04-24T18:48:51.707Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/5e/f62a1b6669870a591ed7db771c332fabb30f83c967f376b05e7c91bccd14/ruff-0.11.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3a0c2e169e6b545f8e2dba185eabbd9db4f08880032e75aa0e285a6d3f48201", size = 10095726, upload-time = "2025-04-24T18:48:54.243Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/59/a7aa8e716f4cbe07c3500a391e58c52caf665bb242bf8be42c62adef649c/ruff-0.11.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49b888200a320dd96a68e86736cf531d6afba03e4f6cf098401406a257fcf3d6", size = 11672265, upload-time = "2025-04-24T18:48:57.639Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/e3/101a8b707481f37aca5f0fcc3e42932fa38b51add87bfbd8e41ab14adb24/ruff-0.11.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2b19cdb9cf7dae00d5ee2e7c013540cdc3b31c4f281f1dacb5a799d610e90db4", size = 12331418, upload-time = "2025-04-24T18:49:00.697Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/71/037f76cbe712f5cbc7b852e4916cd3cf32301a30351818d32ab71580d1c0/ruff-0.11.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64e0ee994c9e326b43539d133a36a455dbaab477bc84fe7bfbd528abe2f05c1e", size = 11794506, upload-time = "2025-04-24T18:49:03.545Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/de/e450b6bab1fc60ef263ef8fcda077fb4977601184877dce1c59109356084/ruff-0.11.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bad82052311479a5865f52c76ecee5d468a58ba44fb23ee15079f17dd4c8fd63", size = 13939084, upload-time = "2025-04-24T18:49:07.159Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/2c/1e364cc92970075d7d04c69c928430b23e43a433f044474f57e425cbed37/ruff-0.11.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7940665e74e7b65d427b82bffc1e46710ec7f30d58b4b2d5016e3f0321436502", size = 11450441, upload-time = "2025-04-24T18:49:11.41Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/7d/1b048eb460517ff9accd78bca0fa6ae61df2b276010538e586f834f5e402/ruff-0.11.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:169027e31c52c0e36c44ae9a9c7db35e505fee0b39f8d9fca7274a6305295a92", size = 10441060, upload-time = "2025-04-24T18:49:14.184Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/57/8dc6ccfd8380e5ca3d13ff7591e8ba46a3b330323515a4996b991b10bd5d/ruff-0.11.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:305b93f9798aee582e91e34437810439acb28b5fc1fee6b8205c78c806845a94", size = 10058689, upload-time = "2025-04-24T18:49:17.559Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/bf/20487561ed72654147817885559ba2aa705272d8b5dee7654d3ef2dbf912/ruff-0.11.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a681db041ef55550c371f9cd52a3cf17a0da4c75d6bd691092dfc38170ebc4b6", size = 11073703, upload-time = "2025-04-24T18:49:20.247Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/27/04f2db95f4ef73dccedd0c21daf9991cc3b7f29901a4362057b132075aa4/ruff-0.11.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:07f1496ad00a4a139f4de220b0c97da6d4c85e0e4aa9b2624167b7d4d44fd6b6", size = 11532822, upload-time = "2025-04-24T18:49:23.765Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/72/43b123e4db52144c8add336581de52185097545981ff6e9e58a21861c250/ruff-0.11.7-py3-none-win32.whl", hash = "sha256:f25dfb853ad217e6e5f1924ae8a5b3f6709051a13e9dad18690de6c8ff299e26", size = 10362436, upload-time = "2025-04-24T18:49:27.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/a0/3e58cd76fdee53d5c8ce7a56d84540833f924ccdf2c7d657cb009e604d82/ruff-0.11.7-py3-none-win_amd64.whl", hash = "sha256:0a931d85959ceb77e92aea4bbedfded0a31534ce191252721128f77e5ae1f98a", size = 11566676, upload-time = "2025-04-24T18:49:30.938Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/ca/69d7c7752bce162d1516e5592b1cc6b6668e9328c0d270609ddbeeadd7cf/ruff-0.11.7-py3-none-win_arm64.whl", hash = "sha256:778c1e5d6f9e91034142dfd06110534ca13220bfaad5c3735f6cb844654f6177", size = 10677936, upload-time = "2025-04-24T18:49:34.392Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scipy"
|
||||
version = "1.15.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b7/b9/31ba9cd990e626574baf93fbc1ac61cf9ed54faafd04c479117517661637/scipy-1.15.2.tar.gz", hash = "sha256:cd58a314d92838f7e6f755c8a2167ead4f27e1fd5c1251fd54289569ef3495ec", size = 59417316, upload-time = "2025-02-17T00:42:24.791Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/5d/3c78815cbab499610f26b5bae6aed33e227225a9fa5290008a733a64f6fc/scipy-1.15.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c4697a10da8f8765bb7c83e24a470da5797e37041edfd77fd95ba3811a47c4fd", size = 38756184, upload-time = "2025-02-17T00:31:50.623Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/20/3d04eb066b471b6e171827548b9ddb3c21c6bbea72a4d84fc5989933910b/scipy-1.15.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:869269b767d5ee7ea6991ed7e22b3ca1f22de73ab9a49c44bad338b725603301", size = 30163558, upload-time = "2025-02-17T00:31:56.721Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/98/e5c964526c929ef1f795d4c343b2ff98634ad2051bd2bbadfef9e772e413/scipy-1.15.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:bad78d580270a4d32470563ea86c6590b465cb98f83d760ff5b0990cb5518a93", size = 22437211, upload-time = "2025-02-17T00:32:03.042Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/cd/1dc7371e29195ecbf5222f9afeedb210e0a75057d8afbd942aa6cf8c8eca/scipy-1.15.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:b09ae80010f52efddb15551025f9016c910296cf70adbf03ce2a8704f3a5ad20", size = 25232260, upload-time = "2025-02-17T00:32:07.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/24/1a181a9e5050090e0b5138c5f496fee33293c342b788d02586bc410c6477/scipy-1.15.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a6fd6eac1ce74a9f77a7fc724080d507c5812d61e72bd5e4c489b042455865e", size = 35198095, upload-time = "2025-02-17T00:32:14.565Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/53/eaada1a414c026673eb983f8b4a55fe5eb172725d33d62c1b21f63ff6ca4/scipy-1.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b871df1fe1a3ba85d90e22742b93584f8d2b8e6124f8372ab15c71b73e428b8", size = 37297371, upload-time = "2025-02-17T00:32:21.411Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/06/0449b744892ed22b7e7b9a1994a866e64895363572677a316a9042af1fe5/scipy-1.15.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:03205d57a28e18dfd39f0377d5002725bf1f19a46f444108c29bdb246b6c8a11", size = 36872390, upload-time = "2025-02-17T00:32:29.421Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/6f/a8ac3cfd9505ec695c1bc35edc034d13afbd2fc1882a7c6b473e280397bb/scipy-1.15.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:601881dfb761311045b03114c5fe718a12634e5608c3b403737ae463c9885d53", size = 39700276, upload-time = "2025-02-17T00:32:37.431Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/6f/e6e5aff77ea2a48dd96808bb51d7450875af154ee7cbe72188afb0b37929/scipy-1.15.2-cp312-cp312-win_amd64.whl", hash = "sha256:e7c68b6a43259ba0aab737237876e5c2c549a031ddb7abc28c7b47f22e202ded", size = 40942317, upload-time = "2025-02-17T00:32:45.47Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/40/09319f6e0f276ea2754196185f95cd191cb852288440ce035d5c3a931ea2/scipy-1.15.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01edfac9f0798ad6b46d9c4c9ca0e0ad23dbf0b1eb70e96adb9fa7f525eff0bf", size = 38717587, upload-time = "2025-02-17T00:32:53.196Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/c3/2854f40ecd19585d65afaef601e5e1f8dbf6758b2f95b5ea93d38655a2c6/scipy-1.15.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:08b57a9336b8e79b305a143c3655cc5bdbe6d5ece3378578888d2afbb51c4e37", size = 30100266, upload-time = "2025-02-17T00:32:59.318Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/b1/f9fe6e3c828cb5930b5fe74cb479de5f3d66d682fa8adb77249acaf545b8/scipy-1.15.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:54c462098484e7466362a9f1672d20888f724911a74c22ae35b61f9c5919183d", size = 22373768, upload-time = "2025-02-17T00:33:04.091Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/9d/a60db8c795700414c3f681908a2b911e031e024d93214f2d23c6dae174ab/scipy-1.15.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:cf72ff559a53a6a6d77bd8eefd12a17995ffa44ad86c77a5df96f533d4e6c6bb", size = 25154719, upload-time = "2025-02-17T00:33:08.909Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/3b/9bda92a85cd93f19f9ed90ade84aa1e51657e29988317fabdd44544f1dd4/scipy-1.15.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9de9d1416b3d9e7df9923ab23cd2fe714244af10b763975bea9e4f2e81cebd27", size = 35163195, upload-time = "2025-02-17T00:33:15.352Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/5a/fc34bf1aa14dc7c0e701691fa8685f3faec80e57d816615e3625f28feb43/scipy-1.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb530e4794fc8ea76a4a21ccb67dea33e5e0e60f07fc38a49e821e1eae3b71a0", size = 37255404, upload-time = "2025-02-17T00:33:22.21Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/71/472eac45440cee134c8a180dbe4c01b3ec247e0338b7c759e6cd71f199a7/scipy-1.15.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5ea7ed46d437fc52350b028b1d44e002646e28f3e8ddc714011aaf87330f2f32", size = 36860011, upload-time = "2025-02-17T00:33:29.446Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/b3/21f890f4f42daf20e4d3aaa18182dddb9192771cd47445aaae2e318f6738/scipy-1.15.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11e7ad32cf184b74380f43d3c0a706f49358b904fa7d5345f16ddf993609184d", size = 39657406, upload-time = "2025-02-17T00:33:39.019Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/76/77cf2ac1f2a9cc00c073d49e1e16244e389dd88e2490c91d84e1e3e4d126/scipy-1.15.2-cp313-cp313-win_amd64.whl", hash = "sha256:a5080a79dfb9b78b768cebf3c9dcbc7b665c5875793569f48bf0e2b1d7f68f6f", size = 40961243, upload-time = "2025-02-17T00:34:51.024Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/4b/a57f8ddcf48e129e6054fa9899a2a86d1fc6b07a0e15c7eebff7ca94533f/scipy-1.15.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:447ce30cee6a9d5d1379087c9e474628dab3db4a67484be1b7dc3196bfb2fac9", size = 38870286, upload-time = "2025-02-17T00:33:47.62Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/43/c304d69a56c91ad5f188c0714f6a97b9c1fed93128c691148621274a3a68/scipy-1.15.2-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:c90ebe8aaa4397eaefa8455a8182b164a6cc1d59ad53f79943f266d99f68687f", size = 30141634, upload-time = "2025-02-17T00:33:54.131Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/1a/6c21b45d2548eb73be9b9bff421aaaa7e85e22c1f9b3bc44b23485dfce0a/scipy-1.15.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:def751dd08243934c884a3221156d63e15234a3155cf25978b0a668409d45eb6", size = 22415179, upload-time = "2025-02-17T00:33:59.948Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/4b/aefac4bba80ef815b64f55da06f62f92be5d03b467f2ce3668071799429a/scipy-1.15.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:302093e7dfb120e55515936cb55618ee0b895f8bcaf18ff81eca086c17bd80af", size = 25126412, upload-time = "2025-02-17T00:34:06.328Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/53/1cbb148e6e8f1660aacd9f0a9dfa2b05e9ff1cb54b4386fe868477972ac2/scipy-1.15.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cd5b77413e1855351cdde594eca99c1f4a588c2d63711388b6a1f1c01f62274", size = 34952867, upload-time = "2025-02-17T00:34:12.928Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/23/e0eb7f31a9c13cf2dca083828b97992dd22f8184c6ce4fec5deec0c81fcf/scipy-1.15.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d0194c37037707b2afa7a2f2a924cf7bac3dc292d51b6a925e5fcb89bc5c776", size = 36890009, upload-time = "2025-02-17T00:34:19.55Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/f3/e699e19cabe96bbac5189c04aaa970718f0105cff03d458dc5e2b6bd1e8c/scipy-1.15.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:bae43364d600fdc3ac327db99659dcb79e6e7ecd279a75fe1266669d9a652828", size = 36545159, upload-time = "2025-02-17T00:34:26.724Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/f5/ab3838e56fe5cc22383d6fcf2336e48c8fe33e944b9037fbf6cbdf5a11f8/scipy-1.15.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f031846580d9acccd0044efd1a90e6f4df3a6e12b4b6bd694a7bc03a89892b28", size = 39136566, upload-time = "2025-02-17T00:34:34.512Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/c8/b3f566db71461cabd4b2d5b39bcc24a7e1c119535c8361f81426be39bb47/scipy-1.15.2-cp313-cp313t-win_amd64.whl", hash = "sha256:fe8a9eb875d430d81755472c5ba75e84acc980e4a8f6204d402849234d3017db", size = 40477705, upload-time = "2025-02-17T00:34:43.619Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sounddevice"
|
||||
version = "0.5.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cffi" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/80/2d/b04ae180312b81dbb694504bee170eada5372242e186f6298139fd3a0513/sounddevice-0.5.1.tar.gz", hash = "sha256:09ca991daeda8ce4be9ac91e15a9a81c8f81efa6b695a348c9171ea0c16cb041", size = 52896, upload-time = "2024-10-12T09:40:12.24Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/06/d1/464b5fca3decdd0cfec8c47f7b4161a0b12972453201c1bf03811f367c5e/sounddevice-0.5.1-py3-none-any.whl", hash = "sha256:e2017f182888c3f3c280d9fbac92e5dbddac024a7e3442f6e6116bd79dab8a9c", size = 32276, upload-time = "2024-10-12T09:40:05.605Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/f6/6703fe7cf3d7b7279040c792aeec6334e7305956aba4a80f23e62c8fdc44/sounddevice-0.5.1-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl", hash = "sha256:d16cb23d92322526a86a9490c427bf8d49e273d9ccc0bd096feecd229cde6031", size = 107916, upload-time = "2024-10-12T09:40:07.436Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/a5/78a5e71f5ec0faedc54f4053775d61407bfbd7d0c18228c7f3d4252fd276/sounddevice-0.5.1-py3-none-win32.whl", hash = "sha256:d84cc6231526e7a08e89beff229c37f762baefe5e0cc2747cbe8e3a565470055", size = 312494, upload-time = "2024-10-12T09:40:09.355Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/9b/15217b04f3b36d30de55fef542389d722de63f1ad81f9c72d8afc98cb6ab/sounddevice-0.5.1-py3-none-win_amd64.whl", hash = "sha256:4313b63f2076552b23ac3e0abd3bcfc0c1c6a696fc356759a13bd113c9df90f1", size = 363634, upload-time = "2024-10-12T09:40:11.065Z" },
|
||||
]
|
||||
Reference in New Issue
Block a user