241 lines
7.9 KiB
Python
241 lines
7.9 KiB
Python
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() |