diff --git a/db/db.ddl b/db/db.ddl index 378c9d9e3c41fe291c43f032ab993f0387d3ed9c..f6dc6f5beada03e45c29e40d127817c76175fd5c 100644 --- a/db/db.ddl +++ b/db/db.ddl @@ -151,6 +151,7 @@ CREATE TABLE contests ( round_id int NOT NULL REFERENCES rounds(round_id), place_id int NOT NULL REFERENCES places(place_id), state round_state NOT NULL DEFAULT 'preparing', -- používá se, pokud round.state='delegate', jinak kopíruje round.state + scoretable_id int DEFAULT NULL, -- odkaz na snapshot představující oficiální výsledkovou listinu soutěže UNIQUE (round_id, place_id) ); @@ -439,3 +440,18 @@ CREATE TABLE scan_pages ( -- -4 pro stránku, která nepatří do této soutěže UNIQUE (job_id, file_nr, page_nr) ); + +-- Uložené výsledkové listiny (pro zveřejnění) + +CREATE TABLE score_tables ( + scoretable_id serial PRIMARY KEY, + contest_id int NOT NULL REFERENCES contests(contest_id) ON DELETE CASCADE, -- soutěž ke které patří + created_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, -- datum vytvoření snapshotu + created_by int NOT NULL REFERENCES users(user_id), -- autor snapshotu + score_mode score_mode NOT NULL, -- mód výsledkovky + note text NOT NULL, -- poznámka viditelná pro orgy + tasks jsonb NOT NULL, -- seznam názvů a kódů úloh + rows jsonb NOT NULL -- seznam řádků výsledkové listiny +); + +ALTER TABLE contests ADD CONSTRAINT "contests_scoretable_id" FOREIGN KEY (scoretable_id) REFERENCES score_tables(scoretable_id); diff --git a/db/upgrade-20211204.sql b/db/upgrade-20211204.sql new file mode 100644 index 0000000000000000000000000000000000000000..eecfd5bf5a714b538c6ab5442f24be8adfebecab --- /dev/null +++ b/db/upgrade-20211204.sql @@ -0,0 +1,15 @@ +SET ROLE 'mo_osmo'; + +CREATE TABLE score_tables ( + scoretable_id serial PRIMARY KEY, + contest_id int NOT NULL REFERENCES contests(contest_id) ON DELETE CASCADE, -- soutěž ke které patří + created_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, -- datum vytvoření snapshotu + created_by int NOT NULL REFERENCES users(user_id), -- autor snapshotu + score_mode score_mode NOT NULL, -- mód výsledkovky + note text NOT NULL, -- poznámka viditelná pro orgy + tasks jsonb NOT NULL, -- seznam názvů a kódů úloh + rows jsonb NOT NULL -- seznam řádků výsledkové listiny +); + +ALTER TABLE contests ADD COLUMN + scoretable_id int DEFAULT NULL REFERENCES score_tables(scoretable_id); diff --git a/mo/db.py b/mo/db.py index b9f1d42693cff5c9bad3cada8a2a000346fab85b..af3d60184be11bb64566afc4ea681fdb4b013209 100644 --- a/mo/db.py +++ b/mo/db.py @@ -10,7 +10,7 @@ import re from sqlalchemy import \ Boolean, Column, DateTime, ForeignKey, Integer, String, Text, UniqueConstraint, \ text, func, \ - create_engine, inspect, select, or_, and_ + create_engine, inspect, select from sqlalchemy.engine import Engine from sqlalchemy.orm import relationship, sessionmaker, Session, class_mapper, joinedload, aliased from sqlalchemy.orm.attributes import get_history @@ -391,10 +391,12 @@ class Contest(Base): round_id = Column(Integer, ForeignKey('rounds.round_id'), nullable=False) place_id = Column(Integer, ForeignKey('places.place_id'), nullable=False) state = Column(Enum(RoundState, name='round_state'), nullable=False, server_default=text("'preparing'::round_state")) + scoretable_id = Column(Integer, ForeignKey('score_tables.scoretable_id'), nullable=True) master = relationship('Contest', primaryjoin='Contest.master_contest_id == Contest.contest_id', remote_side='Contest.contest_id', post_update=True) place = relationship('Place') round = relationship('Round') + scoretable = relationship('ScoreTable', primaryjoin='Contest.scoretable_id == ScoreTable.scoretable_id') def is_subcontest(self) -> bool: return self.master_contest_id != self.contest_id @@ -869,6 +871,22 @@ SCAN_PAGE_CONTINUE = -3 SCAN_PAGE_UFO = -4 +class ScoreTable(Base): + __tablename__ = 'score_tables' + + scoretable_id = Column(Integer, primary_key=True, server_default=text("nextval('score_tables_scoretable_id_seq'::regclass)")) + contest_id = Column(Integer, ForeignKey('contests.contest_id', ondelete='CASCADE'), nullable=False) + created_at = Column(DateTime(True), nullable=False, server_default=text("CURRENT_TIMESTAMP")) + created_by = Column(Integer, ForeignKey('users.user_id'), nullable=False) + score_mode = Column(Enum(RoundScoreMode, name='score_mode'), nullable=False) + note = Column(Text, nullable=False) + tasks = Column(JSONB, nullable=False) + rows = Column(JSONB, nullable=False) + + user = relationship('User') + contest = relationship('Contest', primaryjoin='Contest.scoretable_id == ScoreTable.scoretable_id') + + _engine: Optional[Engine] = None _session: Optional[Session] = None flask_db: Any = None