Implement Veto Mode
This commit is contained in:
42
app/crud.py
42
app/crud.py
@@ -10,9 +10,7 @@ def get_songs_and_vote_for_session(db, session_name) -> list[models.Song]:
|
||||
models.Vote.session_id == session_entry.id).subquery()
|
||||
|
||||
songs_and_votes = db.query(
|
||||
models.Song, votes.c.vote
|
||||
).filter(
|
||||
models.Song.singable == True
|
||||
models.Song, votes.c.vote, votes.c.comment
|
||||
).join(votes, isouter=True).filter().all()
|
||||
|
||||
return songs_and_votes
|
||||
@@ -46,7 +44,8 @@ def create_song(db,
|
||||
arng_url,
|
||||
categories,
|
||||
main_category,
|
||||
singable
|
||||
singable,
|
||||
comment
|
||||
):
|
||||
s = models.Song(og_artist=og_artist,
|
||||
aca_artist=aca_artist,
|
||||
@@ -61,7 +60,8 @@ def create_song(db,
|
||||
arng_url=arng_url,
|
||||
categories=categories,
|
||||
main_category=main_category,
|
||||
singable=singable)
|
||||
singable=singable,
|
||||
comment=comment)
|
||||
|
||||
db.add(s)
|
||||
db.commit()
|
||||
@@ -80,6 +80,21 @@ def create_or_update_vote(db, song_id, session_name, vote):
|
||||
db.add(vote_entry)
|
||||
db.commit()
|
||||
|
||||
def create_or_update_comment(db, song_id, session_name, comment):
|
||||
session_entry = activate_session(db, session_name)
|
||||
|
||||
if comment == "":
|
||||
comment = None
|
||||
|
||||
vote_entry = db.query(models.Vote).filter(
|
||||
(models.Vote.session_id == session_entry.id) & (models.Vote.song_id == song_id)).first()
|
||||
if vote_entry:
|
||||
vote_entry.comment = comment # type: ignore
|
||||
else:
|
||||
vote_entry = models.Vote(
|
||||
song_id=song_id, session_id=session_entry.id, comment=comment)
|
||||
db.add(vote_entry)
|
||||
db.commit()
|
||||
|
||||
def activate_session(db, session_name):
|
||||
session_entry = db.query(models.Session).filter(
|
||||
@@ -104,3 +119,20 @@ def deactivate_session(db, session_name):
|
||||
session_entry = models.Session(session_name=session_name, active=False)
|
||||
db.add(session_entry)
|
||||
db.commit()
|
||||
|
||||
|
||||
def get_setting(db, key):
|
||||
entry = db.query(models.Config.value).filter(models.Config.key == key).first()
|
||||
if entry:
|
||||
return entry[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def set_setting(db, key, value):
|
||||
setting_entry = db.query(models.Config).filter(models.Config.key == key).first()
|
||||
if setting_entry:
|
||||
setting_entry.value = value
|
||||
else:
|
||||
setting_entry = models.Config(key=key, value=value)
|
||||
db.add(setting_entry)
|
||||
db.commit()
|
||||
@@ -21,5 +21,6 @@ async def get_db():
|
||||
|
||||
class Base(DeclarativeBase):
|
||||
type_annotation_map = {
|
||||
dict[str, bool]: PickleType
|
||||
dict[str, bool]: PickleType,
|
||||
object: PickleType
|
||||
}
|
||||
28
app/main.py
28
app/main.py
@@ -4,10 +4,11 @@ from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from app.database import engine, Base, get_db
|
||||
from app.crud import get_songs_and_vote_for_session
|
||||
from app.crud import get_songs_and_vote_for_session, get_setting
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import Annotated
|
||||
from app.schemas import Song
|
||||
import json
|
||||
|
||||
Base.metadata.create_all(engine)
|
||||
|
||||
@@ -31,17 +32,23 @@ async def root(request: Request) -> HTMLResponse:
|
||||
|
||||
|
||||
@app.get("/vote")
|
||||
async def vote(request: Request, session_id: str, db: Annotated[Session, Depends(get_db)]) -> HTMLResponse:
|
||||
songs = [Song(**s.__dict__, vote=v)
|
||||
for s, v in get_songs_and_vote_for_session(db, session_id)]
|
||||
async def vote(request: Request, session_id: str, db: Session = Depends(get_db)) -> HTMLResponse:
|
||||
veto_mode = get_setting(db, "veto_mode")
|
||||
|
||||
songs = [Song(**s.__dict__, vote=v, vote_comment=c)
|
||||
for s, v, c in get_songs_and_vote_for_session(db, session_id)]
|
||||
|
||||
songs_by_category = {}
|
||||
all_categories = set()
|
||||
|
||||
wildcard_songs = []
|
||||
current_songs = []
|
||||
other_songs = []
|
||||
|
||||
for song in songs:
|
||||
if (not song.singable) and (not veto_mode):
|
||||
continue
|
||||
|
||||
if song.is_current:
|
||||
current_songs.append(song)
|
||||
continue
|
||||
@@ -50,26 +57,35 @@ async def vote(request: Request, session_id: str, db: Annotated[Session, Depends
|
||||
wildcard_songs.append(song)
|
||||
continue
|
||||
|
||||
if not song.main_category:
|
||||
other_songs.append(song)
|
||||
continue
|
||||
|
||||
if song.main_category not in songs_by_category:
|
||||
songs_by_category[song.main_category] = []
|
||||
songs_by_category[song.main_category].append(song)
|
||||
all_categories.update(song.categories.keys())
|
||||
|
||||
songs_by_category["Sonstige"] = other_songs
|
||||
songs_by_category["Wildcard (nicht a cappella)"] = wildcard_songs
|
||||
songs_by_category["Aktuelles Programm"] = current_songs
|
||||
|
||||
all_categories = list(all_categories)
|
||||
all_categories.sort()
|
||||
|
||||
all_categories.append("Sonstige")
|
||||
all_categories.append("Wildcard (nicht a cappella)")
|
||||
all_categories.append("Aktuelles Programm")
|
||||
|
||||
print(all_categories)
|
||||
# print(all_categories)
|
||||
# with open('/data/songs_by_cat.json', 'w') as f:
|
||||
# json.dump({cat : [s.__dict__ for s in songs] for cat, songs in songs_by_category.items()}, f)
|
||||
|
||||
return templates.TemplateResponse(
|
||||
request=request, name="voting.html", context={
|
||||
"songs_by_category": songs_by_category,
|
||||
"all_categories": {c: i+1 for i, c in enumerate(all_categories)},
|
||||
"session_id": session_id
|
||||
"session_id": session_id,
|
||||
"veto_mode": veto_mode
|
||||
}
|
||||
)
|
||||
|
||||
@@ -24,6 +24,7 @@ class Song(Base):
|
||||
categories: Mapped[Optional[dict[str, bool]]]
|
||||
main_category: Mapped[Optional[str]]
|
||||
singable: Mapped[Optional[bool]]
|
||||
comment: Mapped[Optional[str]]
|
||||
|
||||
|
||||
class Session(Base):
|
||||
@@ -42,6 +43,13 @@ class Vote(Base):
|
||||
song_id: Mapped[int] = mapped_column(Integer, ForeignKey("songs.id"))
|
||||
session_id: Mapped[int] = mapped_column(Integer, ForeignKey("sessions.id"))
|
||||
vote: Mapped[Optional[int]]
|
||||
comment: Mapped[Optional[str]]
|
||||
time_created: Mapped[datetime] = mapped_column(server_default=func.now())
|
||||
time_updated: Mapped[Optional[datetime]
|
||||
] = mapped_column(onupdate=func.now())
|
||||
|
||||
class Config(Base):
|
||||
__tablename__ = 'config'
|
||||
#id: Mapped[int] = mapped_column(primary_key=True)
|
||||
key: Mapped[str] = mapped_column(primary_key=True)
|
||||
value: Mapped[object]
|
||||
|
||||
@@ -8,7 +8,7 @@ from sqlalchemy.orm import Session
|
||||
|
||||
from app.database import get_db, engine, Base
|
||||
from app.routers.user import get_current_user
|
||||
from app.crud import create_song
|
||||
from app.crud import create_song, get_setting, set_setting
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/admin",
|
||||
@@ -66,7 +66,7 @@ def get_spotify_id(url):
|
||||
|
||||
|
||||
@router.post("/load_list")
|
||||
async def create_upload_file(db: Session = Depends(get_db)):
|
||||
async def create_upload_file(include_non_singable: bool = False, db: Session = Depends(get_db)):
|
||||
|
||||
Base.metadata.drop_all(engine)
|
||||
Base.metadata.create_all(engine)
|
||||
@@ -78,16 +78,24 @@ async def create_upload_file(db: Session = Depends(get_db)):
|
||||
category_names = list(song_list.iloc[0][8:17])
|
||||
|
||||
for i, row in song_list[1:].iterrows():
|
||||
if (row[17] == "nein") and not include_non_singable:
|
||||
continue
|
||||
|
||||
row = np.array(row)
|
||||
|
||||
if not row[2]: # no title
|
||||
continue
|
||||
|
||||
yt_id = get_youtube_id(row[3])
|
||||
spfy_id = get_spotify_id(row[3])
|
||||
|
||||
categories = {n: v for n, v in zip(
|
||||
category_names, row[8:17] != None)}
|
||||
|
||||
if (not np.any(list(categories.values()))) and (row[5] != "ja"):
|
||||
continue
|
||||
if (not np.any(list(categories.values()))):
|
||||
main_category = None
|
||||
else:
|
||||
main_category = category_names[get_main_category(row[8:17])]
|
||||
|
||||
create_song(db,
|
||||
og_artist=row[0],
|
||||
@@ -102,6 +110,18 @@ async def create_upload_file(db: Session = Depends(get_db)):
|
||||
is_aca=row[6] == "ja",
|
||||
arng_url=row[7],
|
||||
categories=categories,
|
||||
main_category=category_names[get_main_category(row[8:17])],
|
||||
singable=row[17] != "nein"
|
||||
main_category=main_category,
|
||||
singable=row[17] != "nein",
|
||||
comment=row[18]
|
||||
)
|
||||
|
||||
|
||||
@router.post("/toggle_veto_mode")
|
||||
async def toggle_veto_mode(db: Session = Depends(get_db)) -> bool:
|
||||
veto_setting = get_setting(db, "veto_mode")
|
||||
if veto_setting:
|
||||
set_setting(db, "veto_mode", False)
|
||||
return False
|
||||
else:
|
||||
set_setting(db, "veto_mode", True)
|
||||
return True
|
||||
|
||||
@@ -5,7 +5,7 @@ from sqlalchemy.orm import Session
|
||||
import app.models as models
|
||||
from app.database import get_db
|
||||
from app.schemas import Song
|
||||
from app.crud import get_songs_and_vote_for_session, create_or_update_vote, get_all_songs_and_votes
|
||||
from app.crud import get_songs_and_vote_for_session, create_or_update_vote, get_all_songs_and_votes, create_or_update_comment
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/songs",
|
||||
@@ -16,13 +16,17 @@ router = APIRouter(
|
||||
|
||||
@router.get("/")
|
||||
async def get_songs(session_id: str = "", db: Annotated[Session, Depends(get_db)] = None) -> list[Song]:
|
||||
return [Song(**s.__dict__, vote=v) for s, v in get_songs_and_vote_for_session(db, session_id)]
|
||||
return [Song(**s.__dict__, vote=v, vote_comment=c) for s, v, c in get_songs_and_vote_for_session(db, session_id)]
|
||||
|
||||
|
||||
@router.post("/{song_id}/vote")
|
||||
async def vote(song_id: str, session_id: str, vote: int, db: Annotated[Session, Depends(get_db)]):
|
||||
create_or_update_vote(db, song_id, session_id, vote)
|
||||
|
||||
@router.post("/{song_id}/comment")
|
||||
async def comment(song_id: str, session_id: str, comment: str, db: Annotated[Session, Depends(get_db)]):
|
||||
create_or_update_comment(db, song_id, session_id, comment)
|
||||
#create_or_update_vote(db, song_id, session_id, vote)
|
||||
|
||||
@router.get("/evaluation")
|
||||
async def get_evaluation(db: Annotated[Session, Depends(get_db)] = None) -> dict[int, dict[int, int]]:
|
||||
|
||||
@@ -17,4 +17,6 @@ class Song(BaseModel):
|
||||
categories: Optional[dict[str, bool]]
|
||||
main_category: Optional[str]
|
||||
singable: Optional[bool]
|
||||
comment: Optional[str]
|
||||
vote: Optional[int]
|
||||
vote_comment: Optional[str]
|
||||
|
||||
Reference in New Issue
Block a user