Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DOMjura.pro
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#-------------------------------------------------

QT += core gui xml network opengl widgets
greaterThan(QT_MAJOR_VERSION, 5): QT += openglwidgets
CONFIG += c++11

TARGET = DOMjura
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,25 @@ make

Note that the last line may be different on Mac OS X and Windows.

## Weighted scoring

DOMjura ranks teams by total score first and total penalty time second. Problem scores
are read from the DOMjudge problem data using the `points` or `score` field when
available. If no score is exposed, DOMjura automatically scores problem names ending
in `1`, `2`, or `3` as `2`, `5`, and `10` points respectively, so contests with
problems `A1` through `D3` work without extra configuration.

To override the automatic scores, set the `problemScores` Qt setting or the
`DOMJURA_PROBLEM_SCORES` environment variable with comma- or semicolon-separated
entries:

```bash
problemScores=A1=2,A2=5,A3=10
```

Problem IDs, short names, and names are all accepted as keys. Problems without an
explicit score default to `1`, which preserves the original solved-count behavior.

## Todo

In the future, DOMjura will support a mode in which one can use it during the contest as a live scorebaord. This is still in the works and is thus disabled in the UI.
Expand Down
32 changes: 26 additions & 6 deletions contest.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,31 @@
#include "contest.h"

#include <QDebug>
#include <QStringList>

namespace DJ {
namespace Model {
namespace {
int durationToSeconds(QString duration) {
QStringList parts = duration.split(':');
if (parts.size() != 3) {
return 0;
}

bool okHours = false;
bool okMinutes = false;
bool okSeconds = false;
int hours = parts[0].toInt(&okHours);
int minutes = parts[1].toInt(&okMinutes);
double seconds = parts[2].toDouble(&okSeconds);
if (!okHours || !okMinutes || !okSeconds) {
return 0;
}

return hours * 3600 + minutes * 60 + static_cast<int>(seconds);
}
} // namespace

Contest::Contest(QJsonObject contest, QObject *parent) : QObject(parent) {
this->id = contest.value("id").toString();
this->name = contest.value("name").toString("Unknown");
Expand All @@ -13,12 +35,10 @@ Contest::Contest(QJsonObject contest, QObject *parent) : QObject(parent) {
this->end_time = QDateTime::fromString(contest.value("end_time").toString(), Qt::DateFormat::ISODate);
this->freeze_time = QDateTime(this->end_time);

QString freeze_duration = contest.value("scoreboard_freeze_duration").toString();
freeze_duration = freeze_duration.size() < 12 ? "0" + freeze_duration : freeze_duration;
QTime freeze = QTime::fromString(freeze_duration, Qt::ISODateWithMs);
this->freeze_time.setTime(QTime(this->freeze_time.time().hour()-freeze.hour(),
this->freeze_time.time().minute()-freeze.minute(),
this->freeze_time.time().second()-freeze.second()));
int freezeDurationSeconds = durationToSeconds(contest.value("scoreboard_freeze_duration").toString());
if (freezeDurationSeconds > 0) {
this->freeze_time = this->end_time.addSecs(-freezeDurationSeconds);
}
}

Contest::~Contest() {
Expand Down
17 changes: 10 additions & 7 deletions defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
#define RIGHT_MARGIN QSettings().value("rightMargin", 10).toInt()
/** Helper define to compute the width of the name column.
*/
#define NAME_WIDTH (QApplication::desktop()->screenGeometry().width() - LEFT_MARGIN - RIGHT_MARGIN - RANK_WIDTH - SOLVED_WIDTH - TIME_WIDTH)
#define NAME_WIDTH (QApplication::primaryScreen()->geometry().width() - LEFT_MARGIN - RIGHT_MARGIN - RANK_WIDTH - SOLVED_WIDTH - TIME_WIDTH)

/** How many pixels from the right the legenda will be drawn.
*/
Expand All @@ -78,7 +78,7 @@
#define PROBS_BELOW_MARGIN QSettings().value("probsBelowMargin", 5).toInt()
/** The time to wait
*/
#define TIME_TO_WAIT QSettings().value("timeToWait", 1000).toInt()
#define TIME_TO_WAIT QSettings().value("timeToWait", 350).toInt()
/** The time to scroll
*/
#define TIME_TO_SCROLL QSettings().value("timeToScroll", 1000).toInt()
Expand All @@ -96,13 +96,16 @@
#define TIME_FOR_WINNER QSettings().value("timeForWinner", 2000).toInt()
/** The time to move
*/
#define TIME_TO_MOVE QSettings().value("timeToMove", 200).toInt()
#define TIME_TO_MOVE QSettings().value("timeToMove", 90).toInt()
/** The initial time to move
*/
#define TIME_TO_MOVE_INIT QSettings().value("timeToMoveInit", 500).toInt()
#define TIME_TO_MOVE_INIT QSettings().value("timeToMoveInit", 350).toInt()
/** The maximum time to move a team into place
*/
#define TIME_TO_MOVE_MAX QSettings().value("timeToMoveMax", 2500).toInt()
/** The time to blink
*/
#define TIME_TO_BLINK QSettings().value("timeToBlink", 2000).toInt()
#define TIME_TO_BLINK QSettings().value("timeToBlink", 650).toInt()
/** The X offset of the branding image
*/
#define BRANDING_IMAGE_OFFSET_X QSettings().value("brandingImageOffsetX", 5).toInt()
Expand All @@ -113,7 +116,7 @@
#include <QString>
#include <QList>
#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include <QSettings>

namespace DJ {
Expand Down Expand Up @@ -153,7 +156,7 @@ struct ResultTeam {
QString name; /**< Name of this team. */
QString id; /**< ID for this team. */
int rank; /**< Current rank of this team. */
int solved; /**< How many problems this team solved. */
int solved; /**< Score shown in the solved column. */
int time; /**< The total time for this team. */
QList<ResultProblem> problems; /**< The list of problems for this team. */
};
Expand Down
16 changes: 15 additions & 1 deletion domjudgeapimanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,20 @@ void DomjudgeApiManager::loadJudgings(QString cid) {

DomjudgeApiManager::DomjudgeApiRequest::DomjudgeApiRequest(QString method, QList<QPair<QString, QString>> arguments) {
DomjudgeApiManager *apiManager = DomjudgeApiManager::sharedApiManager();
QUrl url(apiManager->protocol + apiManager->url + "/api/" + method);
QString baseUrl = apiManager->url.trimmed();
if (baseUrl.startsWith("http://")) {
baseUrl = baseUrl.mid(QString("http://").length());
} else if (baseUrl.startsWith("https://")) {
baseUrl = baseUrl.mid(QString("https://").length());
}
while (baseUrl.endsWith("/")) {
baseUrl.chop(1);
}
if (baseUrl.endsWith("/api")) {
baseUrl.chop(QString("/api").length());
}

QUrl url(apiManager->protocol + baseUrl + "/api/" + method);

QUrlQuery urlQuery;
foreach (auto argument, arguments) {
Expand Down Expand Up @@ -145,6 +158,7 @@ bool DomjudgeApiManager::processReply(QNetworkReply *reply,
auto possibleRedirectURL = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
if (!possibleRedirectURL.isEmpty()) {
auto newRequest = QNetworkRequest(possibleRedirectURL);
newRequest.setRawHeader("Authorization", reply->request().rawHeader("Authorization"));
if (requests->contains(reply->request())) {
requests->append(newRequest);
requests->removeOne(reply->request());
Expand Down
5 changes: 3 additions & 2 deletions gradientcache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <QPen>
#include <QBrush>
#include <QBitmap>
#include <QScreen>

namespace DJ {
namespace View {
Expand Down Expand Up @@ -105,7 +106,7 @@ QPixmap GradientCache::getColorGradientHighlighted(QColor color1, QColor color2)

QPixmap GradientCache::getMedalGradient(Medal medal) {
if (!this->medalGradient.contains(medal)) {
int screenWidth = QApplication::desktop()->screenGeometry().width();
int screenWidth = QApplication::primaryScreen()->geometry().width();
QPixmap pm(screenWidth, TEAMITEM_HEIGHT);
QPainter *painter = new QPainter(&pm);
QLinearGradient gradient(0, 0, screenWidth, 0);
Expand Down Expand Up @@ -143,7 +144,7 @@ QPixmap GradientCache::getMedalGradient(Medal medal) {

QPixmap GradientCache::getOddEvenHighlightedGradient(int oddEvenHighlighted) {
if (!this->oddEvenHighlightGradient.contains(oddEvenHighlighted)) {
int screenWidth = QApplication::desktop()->screenGeometry().width();
int screenWidth = QApplication::primaryScreen()->geometry().width();
QPixmap pm(screenWidth, TEAMITEM_HEIGHT);
QPainter *painter = new QPainter(&pm);
if (oddEvenHighlighted == 2) { // highlighted
Expand Down
20 changes: 10 additions & 10 deletions headergraphicsitem.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include "headergraphicsitem.h"

#include <QBrush>
#include <QPainter>
#include <QApplication>
#include <QDesktopWidget>
#include <QStyleOptionGraphicsItem>
#include <QBrush>
#include <QPainter>
#include <QApplication>
#include <QScreen>
#include <QStyleOptionGraphicsItem>

#include "defines.h"

Expand Down Expand Up @@ -36,13 +36,13 @@ HeaderGraphicsItem::HeaderGraphicsItem(double screenWidth, QGraphicsItem *parent
this->nameTextItem->setFont(font);

this->timeTextItem = new QGraphicsSimpleTextItem("Time", this);
this->timeTextItem->setPos(QApplication::desktop()->screenGeometry().width() - RIGHT_MARGIN - fm.width("Time"), HEADER_HEIGHT - fm.height());
this->timeTextItem->setPos(QApplication::primaryScreen()->geometry().width() - RIGHT_MARGIN - fm.horizontalAdvance("Time"), HEADER_HEIGHT - fm.height());
this->timeTextItem->setPen(QPen(Qt::white));
this->timeTextItem->setBrush(QBrush(Qt::white));
this->timeTextItem->setFont(font);

this->solvedTextItem = new QGraphicsSimpleTextItem("Solved", this);
this->solvedTextItem->setPos(QApplication::desktop()->screenGeometry().width() - RIGHT_MARGIN - TIME_WIDTH - fm.width("Solved"), HEADER_HEIGHT - fm.height());
this->solvedTextItem = new QGraphicsSimpleTextItem("Score", this);
this->solvedTextItem->setPos(QApplication::primaryScreen()->geometry().width() - RIGHT_MARGIN - TIME_WIDTH - fm.horizontalAdvance("Score"), HEADER_HEIGHT - fm.height());
this->solvedTextItem->setPen(QPen(Qt::white));
this->solvedTextItem->setBrush(QBrush(Qt::white));
this->solvedTextItem->setFont(font);
Expand All @@ -62,8 +62,8 @@ void HeaderGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem

this->rankTextItem->setPos(LEFT_MARGIN, HEADER_HEIGHT - fm.height());
this->nameTextItem->setPos(LEFT_MARGIN + RANK_WIDTH, HEADER_HEIGHT - fm.height());
this->timeTextItem->setPos(QApplication::desktop()->screenGeometry().width() - RIGHT_MARGIN - fm.width("Time"), HEADER_HEIGHT - fm.height());
this->solvedTextItem->setPos(QApplication::desktop()->screenGeometry().width() - RIGHT_MARGIN - TIME_WIDTH - fm.width("Solved"), HEADER_HEIGHT - fm.height());
this->timeTextItem->setPos(QApplication::primaryScreen()->geometry().width() - RIGHT_MARGIN - fm.horizontalAdvance("Time"), HEADER_HEIGHT - fm.height());
this->solvedTextItem->setPos(QApplication::primaryScreen()->geometry().width() - RIGHT_MARGIN - TIME_WIDTH - fm.horizontalAdvance("Score"), HEADER_HEIGHT - fm.height());

QLinearGradient gradient(0, 0, screenWidth, 0);
gradient.setColorAt(0, QColor(0, 0, 0));
Expand Down
12 changes: 6 additions & 6 deletions maincontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,10 @@ void MainController::processJudgingData(QJsonDocument judgingData) {
Model::RankedTeam *rankedTeam = ranking.at(i);
team.name = rankedTeam->getName();
team.id = rankedTeam->getId();
team.solved = rankedTeam->getNumSolved();
team.solved = rankedTeam->getTotalScore();
if (i > 0) {
Model::RankedTeam *prevTeam = ranking.at(i - 1);
if (rankedTeam->getNumSolved() == prevTeam->getNumSolved()
if (rankedTeam->getTotalScore() == prevTeam->getTotalScore()
&& rankedTeam->getTotalTime() == prevTeam->getTotalTime()) {
team.rank = curRank;
} else {
Expand Down Expand Up @@ -351,10 +351,10 @@ void MainController::updateStanding() {
Model::RankedTeam *rankedTeam = ranking.at(i);
team.name = rankedTeam->getName();
team.id = rankedTeam->getId();
team.solved = rankedTeam->getNumSolved();
team.solved = rankedTeam->getTotalScore();
if (i > 0) {
Model::RankedTeam *prevTeam = ranking.at(i - 1);
if (rankedTeam->getNumSolved() == prevTeam->getNumSolved()
if (rankedTeam->getTotalScore() == prevTeam->getTotalScore()
&& rankedTeam->getTotalTime() == prevTeam->getTotalTime()) {
team.rank = curRank;
} else {
Expand Down Expand Up @@ -397,10 +397,10 @@ void MainController::updateStanding() {
Model::RankedTeam *rankedTeam = ranking.at(i);
team.name = rankedTeam->getName();
team.id = rankedTeam->getId();
team.solved = rankedTeam->getNumSolved();
team.solved = rankedTeam->getTotalScore();
if (i > 0) {
Model::RankedTeam *prevTeam = ranking.at(i - 1);
if (rankedTeam->getNumSolved() == prevTeam->getNumSolved()
if (rankedTeam->getTotalScore() == prevTeam->getTotalScore()
&& rankedTeam->getTotalTime() == prevTeam->getTotalTime()) {
team.rank = curRank;
} else {
Expand Down
Loading