Added stats
This commit is contained in:
@@ -1,11 +1,7 @@
|
|||||||
{% if session == None %}
|
{% set dn = date_names(session.date) %}
|
||||||
L'últim Dimecres de cada mes
|
{{ dn.day_name }} {{ dn.day }} {{ dn.month_name }}
|
||||||
{% else %}
|
|
||||||
{% set dn = date_names(session.date) %}
|
|
||||||
{{ dn.day_name }} {{ dn.day }} {{ dn.month_name }}
|
|
||||||
de {{ session.start_time.strftime("%H:%M") }}
|
de {{ session.start_time.strftime("%H:%M") }}
|
||||||
a {{ session.end_time.strftime("%H:%M") }}
|
a {{ session.end_time.strftime("%H:%M") }}
|
||||||
{% if session.venue.name %}
|
{% if session.venue.name %}
|
||||||
a {{ session.venue.name }}
|
a {{ session.venue.name }}
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -13,5 +13,6 @@
|
|||||||
{% include "fragments/tema/lyrics.html" %}
|
{% include "fragments/tema/lyrics.html" %}
|
||||||
{% include "fragments/tema/links.html" %}
|
{% include "fragments/tema/links.html" %}
|
||||||
{% include "fragments/tema/properties.html" %}
|
{% include "fragments/tema/properties.html" %}
|
||||||
|
{% include "fragments/tema/stats.html" %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
42
folkugat_web/assets/templates/fragments/tema/stats.html
Normal file
42
folkugat_web/assets/templates/fragments/tema/stats.html
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{% if tema.stats %}
|
||||||
|
<h4 class="pt-4 text-xl mt-3 text-beige">Estadístiques</h4>
|
||||||
|
<hr class="h-px mt-1 mb-3 bg-beige border-0">
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
Aquest tema ha sigut tocat en
|
||||||
|
{% if tema.stats.times_played == 1%}
|
||||||
|
una sessió.
|
||||||
|
{% else %}
|
||||||
|
{{ tema.stats.times_played }} sessions.
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
<p class="py-2">
|
||||||
|
S'ha tocat a les sessions següents:
|
||||||
|
<ol class="flex flex-col items-center justify-center">
|
||||||
|
{% for session in tema.stats.sessions_played %}
|
||||||
|
<li class="border rounded border-beige
|
||||||
|
flex flex-row grow
|
||||||
|
p-2 m-2 w-full max-w-xl
|
||||||
|
relative">
|
||||||
|
<a href="/session/{{session.id}}">
|
||||||
|
<div class="flex flex-row grow items-center">
|
||||||
|
<div class="flex-1">
|
||||||
|
<a href="/sessio/{{session.id}}/">
|
||||||
|
{% set dn = date_names(session.date) %}
|
||||||
|
{{ dn.day_name }} {{ dn.day }} {{ dn.month_name }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="ml-auto">
|
||||||
|
<a title="Més informació"
|
||||||
|
class="text-beige mx-1"
|
||||||
|
href="/sessio/{{session.id}}/">
|
||||||
|
<i class="fa fa-chevron-right" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ol>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
<tr class="border-b border-beige">
|
<tr class="border-b border-beige">
|
||||||
<td class="font-bold py-2 px-4">Nom</td>
|
<td class="font-bold py-2 px-4">Nom</td>
|
||||||
<td class="font-bold py-2 px-4">Enllaços</td>
|
<td class="font-bold py-2 px-4">Enllaços</td>
|
||||||
|
<td class="font-bold py-2 px-4">Cops tocat</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% for tema in temes %}
|
{% for tema in temes %}
|
||||||
<tr class="border-b border-beige">
|
<tr class="border-b border-beige">
|
||||||
@@ -15,6 +16,13 @@
|
|||||||
<td class="py-2 px-4">
|
<td class="py-2 px-4">
|
||||||
{% include "fragments/temes/result_links.html" %}
|
{% include "fragments/temes/result_links.html" %}
|
||||||
</td>
|
</td>
|
||||||
|
<td class="py-2 px-4">
|
||||||
|
{% if tema.stats is none %}
|
||||||
|
-
|
||||||
|
{% else %}
|
||||||
|
{{ tema.stats.times_played }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
from collections.abc import Iterator
|
from collections.abc import Iterable, Iterator
|
||||||
from typing import TypedDict
|
from typing import TypedDict
|
||||||
|
|
||||||
from folkugat_web.dal.sql import Connection, get_connection
|
from folkugat_web.dal.sql import Connection, get_connection
|
||||||
from folkugat_web.dal.sql.sessions import conversion as sessions_conversion
|
from folkugat_web.dal.sql.sessions import conversion as sessions_conversion
|
||||||
from folkugat_web.model import playlists as model
|
from folkugat_web.model import playlists as model
|
||||||
from folkugat_web.model.sessions import Session
|
from folkugat_web.model.sessions import Session
|
||||||
|
from folkugat_web.utils import groupby
|
||||||
|
|
||||||
from . import conversion
|
from . import conversion
|
||||||
|
|
||||||
@@ -55,14 +56,22 @@ def get_playlist_entries(
|
|||||||
return map(conversion.row_to_playlist_entry, cur.fetchall())
|
return map(conversion.row_to_playlist_entry, cur.fetchall())
|
||||||
|
|
||||||
|
|
||||||
def get_tune_sessions(tema_ids: list[int], con: Connection | None = None) -> Iterator[Session]:
|
GetTuneSessionsRow = tuple[int, int, str, str, str, str | None, str | None, bool]
|
||||||
query = """
|
|
||||||
|
|
||||||
|
def get_tune_sessions(tema_ids: list[int], con: Connection | None = None) -> dict[int, list[Session]]:
|
||||||
|
placeholders = ", ".join(["?" for _ in tema_ids])
|
||||||
|
query = f"""
|
||||||
SELECT p.tema_id, s.id, s.date, s.start_time, s.end_time, s.venue_name, s.venue_url, s.is_live
|
SELECT p.tema_id, s.id, s.date, s.start_time, s.end_time, s.venue_name, s.venue_url, s.is_live
|
||||||
FROM playlists p JOIN sessions s ON p.session_id = s.id
|
FROM playlists p JOIN sessions s ON p.session_id = s.id
|
||||||
WHERE p.tema_id IN :tema_ids
|
WHERE p.tema_id IN ({placeholders})
|
||||||
"""
|
"""
|
||||||
data = dict(tema_ids=tuple(tema_ids))
|
|
||||||
with get_connection(con) as con:
|
with get_connection(con) as con:
|
||||||
cur = con.cursor()
|
cur = con.cursor()
|
||||||
_ = cur.execute(query, data)
|
_ = cur.execute(query, tema_ids)
|
||||||
return map(sessions_conversion.row_to_session, cur.fetchall())
|
result_rows: Iterable[GetTuneSessionsRow] = cur.fetchall()
|
||||||
|
return dict(groupby(
|
||||||
|
result_rows,
|
||||||
|
key_fn=lambda row: row[0],
|
||||||
|
group_fn=lambda rows: list(sessions_conversion.row_to_session(row[1:]) for row in rows)
|
||||||
|
))
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
from typing import Optional
|
from fastapi import HTTPException, Request
|
||||||
|
|
||||||
from fastapi import Request
|
|
||||||
from folkugat_web.model import temes as model
|
from folkugat_web.model import temes as model
|
||||||
from folkugat_web.services.temes import query as temes_q
|
from folkugat_web.services.temes import query as temes_q
|
||||||
from folkugat_web.services.temes.links import guess_link_type
|
from folkugat_web.services.temes.links import guess_link_type
|
||||||
@@ -12,6 +10,8 @@ def title(request: Request, logged_in: bool, tema: model.Tema | None = None, tem
|
|||||||
if tema_id is None:
|
if tema_id is None:
|
||||||
raise ValueError("Either 'tema' or 'tema_id' must be given!")
|
raise ValueError("Either 'tema' or 'tema_id' must be given!")
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
|
if not tema:
|
||||||
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
"fragments/tema/title.html",
|
"fragments/tema/title.html",
|
||||||
{
|
{
|
||||||
@@ -24,6 +24,8 @@ def title(request: Request, logged_in: bool, tema: model.Tema | None = None, tem
|
|||||||
|
|
||||||
def title_editor(request: Request, logged_in: bool, tema_id: int):
|
def title_editor(request: Request, logged_in: bool, tema_id: int):
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
|
if not tema:
|
||||||
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
"fragments/tema/editor/title.html",
|
"fragments/tema/editor/title.html",
|
||||||
{
|
{
|
||||||
@@ -36,8 +38,8 @@ def title_editor(request: Request, logged_in: bool, tema_id: int):
|
|||||||
|
|
||||||
def lyric(request: Request, logged_in: bool, tema_id: int, lyric_id: int):
|
def lyric(request: Request, logged_in: bool, tema_id: int, lyric_id: int):
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
if tema is None:
|
if not tema:
|
||||||
raise ValueError(f"No tune exists for tema_id: {tema_id}")
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
lyric = tema.lyrics.get(lyric_id)
|
lyric = tema.lyrics.get(lyric_id)
|
||||||
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
@@ -54,8 +56,8 @@ def lyric(request: Request, logged_in: bool, tema_id: int, lyric_id: int):
|
|||||||
|
|
||||||
def lyric_editor(request: Request, logged_in: bool, tema_id: int, lyric_id: int):
|
def lyric_editor(request: Request, logged_in: bool, tema_id: int, lyric_id: int):
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
if tema is None:
|
if not tema:
|
||||||
raise ValueError(f"No tune exists for tema_id: {tema_id}")
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
lyric = tema.lyrics.get(lyric_id)
|
lyric = tema.lyrics.get(lyric_id)
|
||||||
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
@@ -72,8 +74,8 @@ def lyric_editor(request: Request, logged_in: bool, tema_id: int, lyric_id: int)
|
|||||||
|
|
||||||
def link(request: Request, logged_in: bool, tema_id: int, link_id: int):
|
def link(request: Request, logged_in: bool, tema_id: int, link_id: int):
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
if tema is None:
|
if not tema:
|
||||||
raise ValueError(f"No tune exists for tema_id: {tema_id}")
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
link = tema.links.get(link_id)
|
link = tema.links.get(link_id)
|
||||||
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
@@ -95,8 +97,8 @@ def link(request: Request, logged_in: bool, tema_id: int, link_id: int):
|
|||||||
|
|
||||||
def link_editor(request: Request, logged_in: bool, tema_id: int, link_id: int):
|
def link_editor(request: Request, logged_in: bool, tema_id: int, link_id: int):
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
if tema is None:
|
if not tema:
|
||||||
raise ValueError(f"No tune exists for tema_id: {tema_id}")
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
link = tema.links.get(link_id)
|
link = tema.links.get(link_id)
|
||||||
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
@@ -115,8 +117,8 @@ def link_editor(request: Request, logged_in: bool, tema_id: int, link_id: int):
|
|||||||
|
|
||||||
def link_editor_url(request: Request, logged_in: bool, tema_id: int, link_id: int):
|
def link_editor_url(request: Request, logged_in: bool, tema_id: int, link_id: int):
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
if tema is None:
|
if not tema:
|
||||||
raise ValueError(f"No tune exists for tema_id: {tema_id}")
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
link = tema.links.get(link_id)
|
link = tema.links.get(link_id)
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
"fragments/tema/editor/link_url.html",
|
"fragments/tema/editor/link_url.html",
|
||||||
@@ -134,8 +136,8 @@ def link_editor_url(request: Request, logged_in: bool, tema_id: int, link_id: in
|
|||||||
|
|
||||||
def link_editor_file(request: Request, logged_in: bool, tema_id: int, link_id: int):
|
def link_editor_file(request: Request, logged_in: bool, tema_id: int, link_id: int):
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
if tema is None:
|
if not tema:
|
||||||
raise ValueError(f"No tune exists for tema_id: {tema_id}")
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
link = tema.links.get(link_id)
|
link = tema.links.get(link_id)
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
"fragments/tema/editor/link_file.html",
|
"fragments/tema/editor/link_file.html",
|
||||||
@@ -175,8 +177,8 @@ def link_icon(request: Request, logged_in: bool, tema_id: int, link_id: int, url
|
|||||||
|
|
||||||
def score(request: Request, logged_in: bool, tema_id: int):
|
def score(request: Request, logged_in: bool, tema_id: int):
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
if tema is None:
|
if not tema:
|
||||||
raise ValueError(f"No tune exists for tema_id: {tema_id}")
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
"fragments/tema/score.html",
|
"fragments/tema/score.html",
|
||||||
{
|
{
|
||||||
@@ -190,8 +192,8 @@ def score(request: Request, logged_in: bool, tema_id: int):
|
|||||||
|
|
||||||
def property_(request: Request, logged_in: bool, tema_id: int, property_id: int):
|
def property_(request: Request, logged_in: bool, tema_id: int, property_id: int):
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
if tema is None:
|
if not tema:
|
||||||
raise ValueError(f"No tune exists for tema_id: {tema_id}")
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
prop = tema.properties.get(property_id)
|
prop = tema.properties.get(property_id)
|
||||||
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
@@ -209,8 +211,8 @@ def property_(request: Request, logged_in: bool, tema_id: int, property_id: int)
|
|||||||
|
|
||||||
def property_editor(request: Request, logged_in: bool, tema_id: int, property_id: int):
|
def property_editor(request: Request, logged_in: bool, tema_id: int, property_id: int):
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
if tema is None:
|
if not tema:
|
||||||
raise ValueError(f"No tune exists for tema_id: {tema_id}")
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
prop = tema.properties.get(property_id)
|
prop = tema.properties.get(property_id)
|
||||||
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from fastapi import Request
|
from fastapi import HTTPException, Request
|
||||||
from folkugat_web.model import temes as model
|
from folkugat_web.model import temes as model
|
||||||
from folkugat_web.model.pagines import Pages
|
from folkugat_web.model.pagines import Pages
|
||||||
|
from folkugat_web.services import sessions as sessions_service
|
||||||
from folkugat_web.services.temes import query as temes_q
|
from folkugat_web.services.temes import query as temes_q
|
||||||
from folkugat_web.services.temes import search as temes_s
|
from folkugat_web.services.temes import search as temes_s
|
||||||
from folkugat_web.templates import templates
|
from folkugat_web.templates import templates
|
||||||
@@ -34,6 +35,8 @@ def temes_busca(request: Request, logged_in: bool, query: str, offset: int = 0,
|
|||||||
if offset > 0:
|
if offset > 0:
|
||||||
prev_offset = max(offset - limit, 0)
|
prev_offset = max(offset - limit, 0)
|
||||||
|
|
||||||
|
temes = temes_q.temes_compute_stats(temes)
|
||||||
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
"fragments/temes/results.html",
|
"fragments/temes/results.html",
|
||||||
{
|
{
|
||||||
@@ -51,6 +54,9 @@ def temes_busca(request: Request, logged_in: bool, query: str, offset: int = 0,
|
|||||||
|
|
||||||
def tema(request: Request, tema_id: int, logged_in: bool):
|
def tema(request: Request, tema_id: int, logged_in: bool):
|
||||||
tema = temes_q.get_tema_by_id(tema_id)
|
tema = temes_q.get_tema_by_id(tema_id)
|
||||||
|
if not tema:
|
||||||
|
raise HTTPException(status_code=404, detail="Could not find tune")
|
||||||
|
tema = temes_q.tema_compute_stats(tema)
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
"fragments/tema/pagina.html",
|
"fragments/tema/pagina.html",
|
||||||
{
|
{
|
||||||
@@ -60,5 +66,6 @@ def tema(request: Request, tema_id: int, logged_in: bool):
|
|||||||
"LinkType": model.LinkType,
|
"LinkType": model.LinkType,
|
||||||
"ContentType": model.ContentType,
|
"ContentType": model.ContentType,
|
||||||
"tema": tema,
|
"tema": tema,
|
||||||
|
"date_names": sessions_service.get_date_names,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -101,6 +101,12 @@ class Lyrics(WithId):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
|
class Stats:
|
||||||
|
times_played: int
|
||||||
|
sessions_played: list[Session]
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class Tema:
|
class Tema:
|
||||||
id: int | None = None
|
id: int | None = None
|
||||||
@@ -117,7 +123,7 @@ class Tema:
|
|||||||
modification_date: datetime.datetime = dataclasses.field(default_factory=datetime.datetime.now)
|
modification_date: datetime.datetime = dataclasses.field(default_factory=datetime.datetime.now)
|
||||||
creation_date: datetime.datetime = dataclasses.field(default_factory=datetime.datetime.now)
|
creation_date: datetime.datetime = dataclasses.field(default_factory=datetime.datetime.now)
|
||||||
# Stats
|
# Stats
|
||||||
played: list[Session] = dataclasses.field(default_factory=list)
|
stats: Stats | None = None
|
||||||
|
|
||||||
def compute_ngrams(self):
|
def compute_ngrams(self):
|
||||||
self.ngrams = ngrams.get_text_ngrams(self.title, *self.alternatives)
|
self.ngrams = ngrams.get_text_ngrams(self.title, *self.alternatives)
|
||||||
@@ -126,5 +132,13 @@ class Tema:
|
|||||||
self.compute_ngrams()
|
self.compute_ngrams()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _is_score(link: Link) -> bool:
|
||||||
|
if link.content_type is not ContentType.PARTITURA:
|
||||||
|
return False
|
||||||
|
if link.link_type is LinkType.PDF:
|
||||||
|
return link.url.startswith("/")
|
||||||
|
return link.link_type is LinkType.IMAGE
|
||||||
|
|
||||||
def score(self) -> Link | None:
|
def score(self) -> Link | None:
|
||||||
return next(filter(lambda l: l.content_type is ContentType.PARTITURA and l.url.startswith('/'), self.links), None)
|
return next(filter(self._is_score, self.links), None)
|
||||||
|
|||||||
@@ -1,8 +1,29 @@
|
|||||||
from typing import Optional
|
from folkugat_web.dal.sql.playlists import query as playlists_q
|
||||||
|
|
||||||
from folkugat_web.dal.sql.temes import query as temes_q
|
from folkugat_web.dal.sql.temes import query as temes_q
|
||||||
|
from folkugat_web.model import sessions as sessions_model
|
||||||
from folkugat_web.model import temes as model
|
from folkugat_web.model import temes as model
|
||||||
|
|
||||||
|
|
||||||
def get_tema_by_id(tema_id: int) -> model.Tema | None:
|
def get_tema_by_id(tema_id: int) -> model.Tema | None:
|
||||||
return temes_q.get_tema_by_id(tema_id)
|
return temes_q.get_tema_by_id(tema_id)
|
||||||
|
|
||||||
|
|
||||||
|
def tema_compute_stats(
|
||||||
|
tema: model.Tema,
|
||||||
|
tune_sessions_dict: dict[int, list[sessions_model.Session]] | None = None,
|
||||||
|
) -> model.Tema:
|
||||||
|
if tema.id:
|
||||||
|
if tune_sessions_dict is None:
|
||||||
|
tune_sessions_dict = playlists_q.get_tune_sessions(tema_ids=[tema.id])
|
||||||
|
if tema.id and (tune_sessions := tune_sessions_dict.get(tema.id)):
|
||||||
|
tema.stats = model.Stats(
|
||||||
|
times_played=len(tune_sessions),
|
||||||
|
sessions_played=list(reversed(sorted(tune_sessions, key=lambda s: s.date))),
|
||||||
|
)
|
||||||
|
return tema
|
||||||
|
|
||||||
|
|
||||||
|
def temes_compute_stats(temes: list[model.Tema]) -> list[model.Tema]:
|
||||||
|
tema_ids = [tema.id for tema in temes if tema.id is not None]
|
||||||
|
tune_sessions_dict = playlists_q.get_tune_sessions(tema_ids=tema_ids)
|
||||||
|
return [tema_compute_stats(tema=tema, tune_sessions_dict=tune_sessions_dict) for tema in temes]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from typing import Protocol, Self, TypeVar
|
|||||||
|
|
||||||
|
|
||||||
class SupportsLessThan(Protocol):
|
class SupportsLessThan(Protocol):
|
||||||
def __lt__(self, other: Self) -> bool:
|
def __lt__(self, other: Self, /) -> bool:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user