import PySimpleGUI as sg import json as js import ui class Helper: def __init__(self): self.song_file = "G:\\Working\\MDB\\song.txt" self.dance_file = "G:\\Working\\MDB\\dance.txt" self.song_file_json = "G:\\Working\\MDB\\songs.json" def get_songs_dict(self, *args): ''' Retrieves all Songs Containing the Input as a dictionary. Parameters: *args (str): Parameters to search for. Returns: list: List of song dicts containing all specified substrings. ''' result_list = [] try: with open(self.song_file_json, 'r') as file: for line in file: try: song = js.loads(line) except ValueError: print(f"skipping{line}") # Convert values to strings for substring search if all(any(arg in str(value) for value in song.values()) for arg in args): song["dance"] = song["dance"][0].split(":") result_list.append(song) except FileNotFoundError: sg.popup_error('Datei wurde nicht gefunden.') return 0 except IsADirectoryError: sg.popup_error('The given Filepath is a directory') return 0 except PermissionError: sg.popup_error('The program has no permission to acces file') return 0 return result_list def get_songs_dict_beautified(self, dance_length, format, *args): ugly_songs = self.get_songs_dict(*args) beautiful_songs = [] beautiful_lists = [] if not ugly_songs: return [] for song in ugly_songs: dance_list = song["dance"] match dance_length: case "long": song["dance"] = str(dance_list[1]) # Keep the second element for "long" beautiful_songs.append(song) case "short": song["dance"] = str(dance_list[0]) # Keep the first element for "short" beautiful_songs.append(song) match format: case "list": for song in beautiful_songs: beautiful_lists.append(list(song.values())) print(beautiful_lists) return beautiful_lists def write_song_json(self, song, artist, album, duration, dance, comment): """ Writes multiple values as a single line to the song file: "{Song}{Artist}{Album}{Duration}{Dance}{comment}" """ #sets default duration to "00:00:00" if duration == "": duration = "00:00:00" #validate the data validation_result = self.validate_song(song, artist, album, duration, dance) match validation_result: case 0: return validation_result case 1: return validation_result case 2: return validation_result case 3: return validation_result #convert the data to a json object dance_tuple = self.get_dance(dance) song_dict = {"song":song,"artist":artist,"album":album,"duration":duration,"dance":dance_tuple,"comment":comment} try: with open(self.song_file_json, "a") as f: f.write(f"{js.dumps(song_dict)}\n") return None except FileNotFoundError: sg.popup_error('Datei wurde nicht gefunden.') return 0 except IsADirectoryError: sg.popup_error('The given Filepath is a directory') return 0 except PermissionError: sg.popup_error('The program has no permission to acces file') return 0 def get_dance(self, input): """ Retrieves All Dances containing the Input Parameters: input (str): Substring to search for in the dance file. Returns: list: List of tuples containing matching short and long dances. Empty list if no matches found. """ result_list = [] try: with open(self.dance_file, 'r') as f: for line in f: short, long = line.strip().split(':') if input == short or input == long: result_list.append(f"{short}:{long}") # Append "short:long" return result_list except FileNotFoundError: sg.popup_error('Datei wurde nicht gefunden.') return 0 except IsADirectoryError: sg.popup_error('The given Filepath is a directory') return 0 except PermissionError: sg.popup_error('The program has no permission to acces file') return 0 def add_dance(self, short, long): """ Appends a new line to the dance file in the following format: "short:long" Parameters: short (str): Short name of the dance. long (str): Full name of the dance. """ try: with open(self.dance_file, "a") as f: f.write(f"{short}:{long}\n") except FileNotFoundError: sg.popup_error('Datei wurde nicht gefunden.') return 0 except IsADirectoryError: sg.popup_error('The given Filepath is a directory') return 0 except PermissionError: sg.popup_error('The program has no permission to acces file') return 0 def validate_time_format(self, string, delimiter=":"): """ Checks if string is in "hh:mm:ss" Format or in "mm:ss" format Parameters: string (str): the string to be checked. delimiter (str): the delimiter between the numbers. Returns: bool: True, wenn der String gültig ist, False sonst. """ parts = string.split(delimiter) if len(parts) == 2: minute, second = parts hour = "00" elif len(parts) == 3: hour, minute, second = parts else: return False if not hour.isdigit() and minute.isdigit() and second.isdigit(): return False hour = int(hour) minute = int(minute) second = int(second) if not (0 <= hour < 24) or not (0 <= minute < 60) or not (0 <= second < 60): return False return True def validate_song(self, song, artist, album, duration, dance): """ Validates a song based on its attributes. Parameters: song (str): The title of the song. artist (str): The artist of the song. album (str): The album of the song. duration (int): The duration of the song. dance (str): The dance style of the song. Returns: 1: if song already is in the database 2: if the duration is invalid 3: if the dance is invalid """ # Check if the song already exists in the database exists = self.get_songs_dict(song, artist, album, duration, dance) dance_entry = self.get_dance(dance) if exists and exists != 0: sg.popup_error('This Song already exists') return 1 if not self.validate_time_format(duration): sg.popup_error('The Time Format is not Valid. Please use "00:00:00"') return 2 # Check if the dance style is invalid if dance_entry == 0: return if not dance_entry: sg.popup_error('The Dance is not valid') return 3 # Otherwise, return the dance style found in the database return dance_entry class Settings: def __init__(self) -> None: pass if __name__ == "__main__": app = ui.Main() app.run()