diff --git a/data/data.txt b/data/data.txt new file mode 100644 index 0000000..70f5f60 --- /dev/null +++ b/data/data.txt @@ -0,0 +1,20 @@ +1|Smells Like Teen Spirit|Nirvana|Nevermind|rock|301|980000|75000|1991-09-10|false +2|Blinding Lights|The Weeknd|After Hours|pop|200|1500000|120000|2019-11-29|false +3|Lose Yourself|Eminem|8 Mile|hip-hop|326|1200000|98000|2002-10-28|true +4|Levels|Avicii|True|electronic|193|870000|65000|2011-10-28|false +5|Come As You Are|Nirvana|Nevermind|rock|219|750000|58000|1992-03-02|false +6|Starboy|The Weeknd|Starboy|pop|230|1100000|88000|2016-09-22|true +7|Rap God|Eminem|The Marshall Mathers LP2|hip-hop|363|950000|82000|2013-10-14|true +8|Wake Me Up|Avicii|True|electronic|247|920000|71000|2013-06-17|false +9|In Bloom|Nirvana|Nevermind|rock|255|620000|47000|1992-11-30|false +10|Save Your Tears|The Weeknd|After Hours|pop|215|1050000|91000|2020-08-06|false +11|Without Me|Eminem|The Eminem Show|hip-hop|290|880000|69000|2002-05-14|true +12|Hey You|Pink Floyd|The Wall|rock|277|540000|49000|1979-11-30|false +13|Wish You Were Here|Pink Floyd|Wish You Were Here|rock|334|670000|61000|1975-09-12|false +14|Scared to Be Lonely|Avicii|Avicii 01|electronic|211|430000|38000|2017-02-03|false +15|Die For You|The Weeknd|Starboy|pop|260|990000|95000|2016-11-25|false +16|Godzilla|Eminem|Music to Be Murdered By|hip-hop|213|760000|55000|2020-01-17|true +17|Money|Pink Floyd|The Dark Side of the Moon|rock|382|590000|53000|1973-03-01|false +18|The Night|Avicii|Stories|electronic|198|380000|29000|2015-10-02|false +19|Lithium|Nirvana|Nevermind|rock|256|690000|52000|1992-07-21|false +20|Take My Breath|The Weeknd|Dawn FM|pop|223|820000|74000|2021-08-06|false \ No newline at end of file diff --git a/music_analyzer.py b/music_analyzer.py new file mode 100644 index 0000000..71e57c9 --- /dev/null +++ b/music_analyzer.py @@ -0,0 +1,241 @@ +import os + + +def load_tracks(filepath): + """Загружает треки из txt файла. При ошибке возвращает пустой список.""" + tracks = [] + + try: + with open(filepath, "r", encoding="utf-8") as f: + for line in f: + line = line.strip() + + # пропускаем пустые строки + if not line: + continue + + parts = line.split("|") + + # проверяем что полей ровно 10 + if len(parts) != 10: + print("Пропускаю некорректную строку:", line) + continue + + track = { + "track_id": int(parts[0]), + "title": parts[1], + "artist": parts[2], + "album": parts[3], + "genre": parts[4], + "duration_seconds": int(parts[5]), + "plays": int(parts[6]), + "likes": int(parts[7]), + "release_date": parts[8], + "explicit": parts[9] == "true" + } + tracks.append(track) + + except FileNotFoundError: + print("Файл не найден:", filepath) + return [] + + return tracks + + +def filter_by_genre(tracks, genre): + """Возвращает треки с указанным жанром.""" + result = [] + for track in tracks: + if track["genre"].lower() == genre.lower(): + result.append(track) + return result + + +def filter_by_duration(tracks, min_sec, max_sec): + """Возвращает треки с длительностью в диапазоне [min_sec, max_sec].""" + result = [] + for track in tracks: + if min_sec <= track["duration_seconds"] <= max_sec: + result.append(track) + return result + + +def get_top_tracks(tracks, n): + """Возвращает n треков с наибольшим числом прослушиваний.""" + sorted_tracks = sorted(tracks, key=lambda t: t["plays"], reverse=True) + return sorted_tracks[:n] + + +def calculate_artist_stats(tracks, artist): + """Возвращает статистику по исполнителю.""" + artist_tracks = [] + for track in tracks: + if track["artist"].lower() == artist.lower(): + artist_tracks.append(track) + + if len(artist_tracks) == 0: + return { + "total_tracks": 0, + "total_plays": 0, + "total_likes": 0, + "avg_duration_seconds": 0.0 + } + + total_plays = 0 + total_likes = 0 + total_duration = 0 + + for track in artist_tracks: + total_plays += track["plays"] + total_likes += track["likes"] + total_duration += track["duration_seconds"] + + avg_duration = total_duration / len(artist_tracks) + + return { + "total_tracks": len(artist_tracks), + "total_plays": total_plays, + "total_likes": total_likes, + "avg_duration_seconds": round(avg_duration, 2) + } + + +def get_unique_genres(tracks): + """Возвращает отсортированный список уникальных жанров.""" + genres = [] + for track in tracks: + if track["genre"] not in genres: + genres.append(track["genre"]) + return sorted(genres) + + +def calculate_like_rate(tracks): + """Считает коэффициент лайков для каждого трека.""" + result = [] + for track in tracks: + if track["plays"] == 0: + continue + rate = track["likes"] / track["plays"] * 100 + rate = round(rate, 2) + result.append((track["title"], rate)) + + result = sorted(result, key=lambda x: x[1], reverse=True) + return result + + +def group_by_artist(tracks): + """Группирует треки по исполнителю.""" + result = {} + for track in tracks: + artist = track["artist"] + if artist not in result: + result[artist] = [] + result[artist].append(track) + return result + + +def filter_by_date_range(tracks, date_from, date_to): + """Возвращает треки выпущенные в диапазоне дат.""" + result = [] + for track in tracks: + if date_from <= track["release_date"] <= date_to: + result.append(track) + return result + + +def save_report(data, filepath): + """Сохраняет список треков в txt файл.""" + try: + directory = os.path.dirname(filepath) + if directory and not os.path.exists(directory): + os.makedirs(directory) + + with open(filepath, "w", encoding="utf-8") as f: + for track in data: + line = "{title} | {artist} | {genre} | {plays} прослушиваний\n".format( + title=track["title"], + artist=track["artist"], + genre=track["genre"], + plays=track["plays"] + ) + f.write(line) + + return True + + except Exception as e: + print("Ошибка при сохранении файла:", e) + return False + + +def main(): + # 1. Загружаем треки + tracks = load_tracks("data/data.txt") + + if len(tracks) == 0: + print("Нет данных для обработки") + return + + # 2. Общее количество треков и жанры + print("=" * 40) + print("Всего треков:", len(tracks)) + genres = get_unique_genres(tracks) + print("Жанры:", ", ".join(genres)) + + # 3. Фильтрация по жанру + print("=" * 40) + rock_tracks = filter_by_genre(tracks, "rock") + print("Треков в жанре rock:", len(rock_tracks)) + + # 4. Топ-5 треков по прослушиваниям + print("=" * 40) + print("Топ-5 треков по прослушиваниям:") + top5 = get_top_tracks(tracks, 5) + for track in top5: + print(" -", track["title"], "—", track["plays"], "прослушиваний") + + # 5. Статистика исполнителя + print("=" * 40) + first_artist = tracks[0]["artist"] + stats = calculate_artist_stats(tracks, first_artist) + print("Статистика исполнителя:", first_artist) + print(" - Треков:", stats["total_tracks"]) + print(" - Прослушиваний:", stats["total_plays"]) + print(" - Лайков:", stats["total_likes"]) + print(" - Средняя длительность (сек):", stats["avg_duration_seconds"]) + + # 6. Фильтрация по длительности + print("=" * 40) + mid_tracks = filter_by_duration(tracks, 180, 240) + print("Треков длительностью 3-4 минуты:", len(mid_tracks)) + + # 7. Топ-5 по коэффициенту лайков + print("=" * 40) + print("Топ-5 треков по лайкам:") + like_rates = calculate_like_rate(tracks) + for title, rate in like_rates[:5]: + print(" -", title, "—", rate, "%") + + # 8. Фильтрация по дате + print("=" * 40) + date_filtered = filter_by_date_range(tracks, "2020-01-01", "2024-12-31") + print("Треков за период 2020-2024:", len(date_filtered)) + + # 9. Группировка по исполнителям + print("=" * 40) + print("Треков по исполнителям:") + grouped = group_by_artist(tracks) + for artist, artist_tracks in grouped.items(): + print(" -", artist, ":", len(artist_tracks), "треков") + + # 10. Сохраняем топ-10 в файл + print("=" * 40) + top10 = get_top_tracks(tracks, 10) + success = save_report(top10, "results/top_tracks.txt") + if success: + print("Топ-10 треков сохранён в results/top_tracks.txt") + else: + print("Не удалось сохранить файл") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/results/top_tracks.txt b/results/top_tracks.txt new file mode 100644 index 0000000..60999b2 --- /dev/null +++ b/results/top_tracks.txt @@ -0,0 +1,10 @@ +Blinding Lights | The Weeknd | pop | 1500000 прослушиваний +Lose Yourself | Eminem | hip-hop | 1200000 прослушиваний +Starboy | The Weeknd | pop | 1100000 прослушиваний +Save Your Tears | The Weeknd | pop | 1050000 прослушиваний +Die For You | The Weeknd | pop | 990000 прослушиваний +Smells Like Teen Spirit | Nirvana | rock | 980000 прослушиваний +Rap God | Eminem | hip-hop | 950000 прослушиваний +Wake Me Up | Avicii | electronic | 920000 прослушиваний +Without Me | Eminem | hip-hop | 880000 прослушиваний +Levels | Avicii | electronic | 870000 прослушиваний