Fix completion for video games
This commit is contained in:
@ -57,14 +57,7 @@ class ChartRecordAdmin(admin.ModelAdmin):
|
|||||||
ordering = ("-created",)
|
ordering = ("-created",)
|
||||||
|
|
||||||
def media_name(self, obj):
|
def media_name(self, obj):
|
||||||
if obj.video:
|
return obj.media_obj
|
||||||
return obj.video
|
|
||||||
if obj.track:
|
|
||||||
return obj.track
|
|
||||||
if obj.podcast_episode:
|
|
||||||
return obj.podcast_episode
|
|
||||||
if obj.sport_event:
|
|
||||||
return obj.sport_event
|
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Scrobble)
|
@admin.register(Scrobble)
|
||||||
@ -86,6 +79,7 @@ class ScrobbleAdmin(admin.ModelAdmin):
|
|||||||
"track",
|
"track",
|
||||||
"sport_event",
|
"sport_event",
|
||||||
"book",
|
"book",
|
||||||
|
"video_game",
|
||||||
)
|
)
|
||||||
list_filter = ("is_paused", "in_progress", "source", "track__artist")
|
list_filter = ("is_paused", "in_progress", "source", "track__artist")
|
||||||
ordering = ("-timestamp",)
|
ordering = ("-timestamp",)
|
||||||
@ -95,14 +89,6 @@ class ScrobbleAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
def media_type(self, obj):
|
def media_type(self, obj):
|
||||||
return obj.media_obj.__class__.__name__
|
return obj.media_obj.__class__.__name__
|
||||||
if obj.video:
|
|
||||||
return "Video"
|
|
||||||
if obj.track:
|
|
||||||
return "Track"
|
|
||||||
if obj.podcast_episode:
|
|
||||||
return "Podcast"
|
|
||||||
if obj.sport_event:
|
|
||||||
return "Sport Event"
|
|
||||||
|
|
||||||
def playback_percent(self, obj):
|
def playback_percent(self, obj):
|
||||||
return obj.percent_played
|
return obj.percent_played
|
||||||
|
|||||||
@ -417,7 +417,6 @@ class Scrobble(TimeStampedModel):
|
|||||||
|
|
||||||
# Fields for keeping track long content like books and games
|
# Fields for keeping track long content like books and games
|
||||||
book_pages_read = models.IntegerField(**BNULL)
|
book_pages_read = models.IntegerField(**BNULL)
|
||||||
videogame_minutes_played = models.IntegerField(**BNULL)
|
|
||||||
long_play_complete = models.BooleanField(**BNULL)
|
long_play_complete = models.BooleanField(**BNULL)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
@ -490,6 +489,8 @@ class Scrobble(TimeStampedModel):
|
|||||||
media_obj = self.sport_event
|
media_obj = self.sport_event
|
||||||
if self.book:
|
if self.book:
|
||||||
media_obj = self.book
|
media_obj = self.book
|
||||||
|
if self.video_game:
|
||||||
|
media_obj = self.video_game
|
||||||
return media_obj
|
return media_obj
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -501,21 +502,26 @@ class Scrobble(TimeStampedModel):
|
|||||||
cls, media, user_id: int, scrobble_data: dict
|
cls, media, user_id: int, scrobble_data: dict
|
||||||
) -> "Scrobble":
|
) -> "Scrobble":
|
||||||
|
|
||||||
if media.__class__.__name__ == "Track":
|
media_class = media.__class__.__name__
|
||||||
|
|
||||||
|
if media_class == "Track":
|
||||||
media_query = models.Q(track=media)
|
media_query = models.Q(track=media)
|
||||||
scrobble_data["track_id"] = media.id
|
scrobble_data["track_id"] = media.id
|
||||||
if media.__class__.__name__ == "Video":
|
if media_class == "Video":
|
||||||
media_query = models.Q(video=media)
|
media_query = models.Q(video=media)
|
||||||
scrobble_data["video_id"] = media.id
|
scrobble_data["video_id"] = media.id
|
||||||
if media.__class__.__name__ == "Episode":
|
if media_class == "Episode":
|
||||||
media_query = models.Q(podcast_episode=media)
|
media_query = models.Q(podcast_episode=media)
|
||||||
scrobble_data["podcast_episode_id"] = media.id
|
scrobble_data["podcast_episode_id"] = media.id
|
||||||
if media.__class__.__name__ == "SportEvent":
|
if media_class == "SportEvent":
|
||||||
media_query = models.Q(sport_event=media)
|
media_query = models.Q(sport_event=media)
|
||||||
scrobble_data["sport_event_id"] = media.id
|
scrobble_data["sport_event_id"] = media.id
|
||||||
if media.__class__.__name__ == "Book":
|
if media_class == "Book":
|
||||||
media_query = models.Q(book=media)
|
media_query = models.Q(book=media)
|
||||||
scrobble_data["book_id"] = media.id
|
scrobble_data["book_id"] = media.id
|
||||||
|
if media_class == "VideoGame":
|
||||||
|
media_query = models.Q(video_game=media)
|
||||||
|
scrobble_data["video_game_id"] = media.id
|
||||||
|
|
||||||
scrobble = (
|
scrobble = (
|
||||||
cls.objects.filter(
|
cls.objects.filter(
|
||||||
|
|||||||
@ -112,6 +112,14 @@ def check_scrobble_for_finish(
|
|||||||
def get_scrobbles_for_media(media_obj, user: User) -> models.QuerySet:
|
def get_scrobbles_for_media(media_obj, user: User) -> models.QuerySet:
|
||||||
Scrobble = apps.get_model(app_label="scrobbles", model_name="Scrobble")
|
Scrobble = apps.get_model(app_label="scrobbles", model_name="Scrobble")
|
||||||
|
|
||||||
if media_obj.__class__.__name__ == "Book":
|
media_query = None
|
||||||
|
media_class = media_obj.__class__.__name__
|
||||||
|
if media_class == "Book":
|
||||||
media_query = models.Q(book=media_obj)
|
media_query = models.Q(book=media_obj)
|
||||||
|
if media_class == "VideoGame":
|
||||||
|
media_query = models.Q(video_game=media_obj)
|
||||||
|
|
||||||
|
if not media_query:
|
||||||
|
logger.warn("Do not know about media {media_class} 🙍")
|
||||||
|
return []
|
||||||
return Scrobble.objects.filter(media_query, user=user)
|
return Scrobble.objects.filter(media_query, user=user)
|
||||||
|
|||||||
@ -6,6 +6,10 @@ from howlongtobeatpy import HowLongToBeat
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def hrs_to_secs(hrs: float) -> int:
|
||||||
|
return int(hrs * 60 * 60)
|
||||||
|
|
||||||
|
|
||||||
def lookup_game_from_hltb(name_or_id: str) -> Optional[dict]:
|
def lookup_game_from_hltb(name_or_id: str) -> Optional[dict]:
|
||||||
"""Lookup game on HowLongToBeat.com via HLtB ID or a name string and return
|
"""Lookup game on HowLongToBeat.com via HLtB ID or a name string and return
|
||||||
the data in a dictonary mapped to our internal game fields
|
the data in a dictonary mapped to our internal game fields
|
||||||
|
|||||||
@ -1,16 +1,18 @@
|
|||||||
import logging
|
import logging
|
||||||
from typing import Optional
|
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django_extensions.db.models import TimeStampedModel
|
from django_extensions.db.models import TimeStampedModel
|
||||||
from scrobbles.mixins import ScrobblableMixin
|
from scrobbles.mixins import ScrobblableMixin
|
||||||
|
|
||||||
|
from vrobbler.apps.scrobbles.utils import get_scrobbles_for_media
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
BNULL = {"blank": True, "null": True}
|
BNULL = {"blank": True, "null": True}
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class VideoGamePlatform(TimeStampedModel):
|
class VideoGamePlatform(TimeStampedModel):
|
||||||
@ -93,6 +95,24 @@ class VideoGame(ScrobblableMixin):
|
|||||||
def hltb_link(self):
|
def hltb_link(self):
|
||||||
return f"https://howlongtobeat.com/game/{self.hltb_id}"
|
return f"https://howlongtobeat.com/game/{self.hltb_id}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def seconds_for_completion(self) -> int:
|
||||||
|
completion_time = self.run_time_ticks
|
||||||
|
if not completion_time:
|
||||||
|
# Default to 10 hours, why not
|
||||||
|
completion_time = 10 * 60 * 60
|
||||||
|
return int(completion_time * (self.COMPLETION_PERCENT / 100))
|
||||||
|
|
||||||
|
def progress_for_user(self, user_id: int) -> int:
|
||||||
|
"""Used to keep track of whether the game is complete or not"""
|
||||||
|
user = User.objects.get(id=user_id)
|
||||||
|
last_scrobble = get_scrobbles_for_media(self, user).last()
|
||||||
|
if not last_scrobble or not last_scrobble.playback_position:
|
||||||
|
logger.warn("No total minutes in last scrobble, no progress")
|
||||||
|
return 0
|
||||||
|
sec_played = last_scrobble.playback_position * 60
|
||||||
|
return int(sec_played / self.run_time) * 100
|
||||||
|
|
||||||
def fix_metadata(
|
def fix_metadata(
|
||||||
self,
|
self,
|
||||||
force_update: bool = False,
|
force_update: bool = False,
|
||||||
@ -107,3 +127,8 @@ class VideoGame(ScrobblableMixin):
|
|||||||
|
|
||||||
if self.igdb_id:
|
if self.igdb_id:
|
||||||
load_game_data_from_igdb(self.id)
|
load_game_data_from_igdb(self.id)
|
||||||
|
|
||||||
|
if (not self.run_time_ticks or force_update) and self.main_story_time:
|
||||||
|
self.run_time_ticks = self.main_story_time * 1000 # miliseconds
|
||||||
|
self.run_time = self.main_story_time
|
||||||
|
self.save(update_fields=["run_time_ticks", "run_time"])
|
||||||
|
|||||||
@ -11,10 +11,6 @@ from videogames.igdb import lookup_game_from_igdb
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def hrs_to_secs(hrs: float) -> int:
|
|
||||||
return int(hrs * 60 * 60)
|
|
||||||
|
|
||||||
|
|
||||||
def get_or_create_videogame(
|
def get_or_create_videogame(
|
||||||
name_or_id: str, force_update=False
|
name_or_id: str, force_update=False
|
||||||
) -> Optional[VideoGame]:
|
) -> Optional[VideoGame]:
|
||||||
|
|||||||
Reference in New Issue
Block a user