- enhancement: Problem Set Support

- enhancement: Competitive Companion Support
This commit is contained in:
royqh1979@gmail.com 2021-11-02 09:29:35 +08:00
parent f28aac649b
commit 47f10a2105
13 changed files with 112 additions and 10 deletions

View File

@ -4,6 +4,8 @@ Version 0.7.7
- fix: can't parse old c-style enum variable definition like "enum Test test;"
- fix: remove the file change monitor if it's remove from the disk
- fix: don't test if a file is writable before save to it (because qt can't do that test reliably).
- enhancement: Problem Set
- enhancement: Competitive Companion Support
Version 0.7.6
- change: don't auto insert a new line when input an enter between '(' and ')' or between '[' and ']' (indent instead)

View File

@ -1,4 +1,4 @@
QT += core gui printsupport
QT += core gui printsupport network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

View File

@ -66,7 +66,7 @@ void OJProblemCasesRunner::runCase(int index,POJProblemCase problemCase)
if (process.state()!=QProcess::Running) {
break;
}
if (mStop) {
if (mStop) {
process.closeReadChannel(QProcess::StandardOutput);
process.closeReadChannel(QProcess::StandardError);
process.closeWriteChannel();
@ -77,6 +77,7 @@ void OJProblemCasesRunner::runCase(int index,POJProblemCase problemCase)
if (errorOccurred)
break;
}
readed += process.readAll();
if (errorOccurred) {
//qDebug()<<"process error:"<<process.error();
switch (process.error()) {

View File

@ -26,10 +26,14 @@
#include <QDragEnterEvent>
#include <QFileDialog>
#include <QInputDialog>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QMimeData>
#include <QTcpSocket>
#include <QTranslator>
#include "settingsdialog/settingsdialog.h"
@ -209,6 +213,7 @@ MainWindow::MainWindow(QWidget *parent)
ui->btnRemoveProblem->setEnabled(false);
ui->btnRemoveProblemCase->setEnabled(false);
//problem set
mOJProblemSetNameCounter=1;
mOJProblemSetModel.rename(tr("Problem Set %1").arg(mOJProblemSetNameCounter));
ui->lstProblemSet->setModel(&mOJProblemSetModel);
@ -222,6 +227,8 @@ MainWindow::MainWindow(QWidget *parent)
connect(&mOJProblemSetModel, &OJProblemSetModel::problemNameChanged,
this , &MainWindow::onProblemNameChanged);
ui->pbProblemCases->setVisible(false);
connect(&mTcpServer,&QTcpServer::newConnection,
this, &MainWindow::onNewProblemConnection);
//files view
ui->treeFiles->setModel(&mFileSystemModel);
@ -528,6 +535,12 @@ void MainWindow::applySettings()
font.setStyleStrategy(QFont::PreferAntialias);
qApp->setFont(font);
this->setFont(font);
if (!mTcpServer.listen(QHostAddress::LocalHost,10045)) {
QMessageBox::critical(nullptr,
tr("Listen failed"),
tr("Can't listen to port %1").arg(10045));
}
updateDebuggerSettings();
}
@ -2535,11 +2548,12 @@ void MainWindow::onProblemSetIndexChanged(const QModelIndex &current, const QMod
ui->txtProblemCaseInput->clear();
ui->txtProblemCaseOutput->clear();
ui->tabProblem->setEnabled(false);
ui->lblProblem->clear();
} else {
ui->btnRemoveProblem->setEnabled(true);
POJProblem problem = mOJProblemSetModel.problem(idx.row());
mOJProblemModel.setProblem(problem);
ui->lblProblem->setText(problem->name);
ui->lblProblem->setText(mOJProblemModel.getTitle());
ui->lstProblemCases->setCurrentIndex(mOJProblemModel.index(0,0));
openCloseBottomPanel(true);
ui->tabMessages->setCurrentWidget(ui->tabProblem);
@ -2582,10 +2596,53 @@ void MainWindow::onProblemNameChanged(int index)
QModelIndex idx = ui->lstProblemSet->currentIndex();
if (idx.isValid() && index == idx.row()) {
POJProblem problem = mOJProblemSetModel.problem(idx.row());
ui->lblProblem->setText(problem->name);
ui->lblProblem->setText(mOJProblemModel.getTitle());
}
}
void MainWindow::onNewProblemConnection()
{
QTcpSocket* clientConnection = mTcpServer.nextPendingConnection();
mTcpServer.connect(clientConnection, &QAbstractSocket::disconnected,
clientConnection, &QObject::deleteLater);
QByteArray content;
while (clientConnection->state() == QTcpSocket::ConnectedState) {
clientConnection->waitForReadyRead();
content += clientConnection->readAll();
}
content += clientConnection->readAll();
content = getHTTPBody(content);
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(content,&error);
if (error.error!=QJsonParseError::NoError) {
qDebug()<<"Read http content failed!";
qDebug()<<error.errorString();
return;
}
QJsonObject obj=doc.object();
QString name = obj["name"].toString();
if (!mOJProblemSetModel.problemNameUsed(name)) {
POJProblem problem = std::make_shared<OJProblem>();
problem->name = name;
problem->url = obj["url"].toString();
QJsonArray caseArray = obj["tests"].toArray();
foreach ( const QJsonValue& val, caseArray) {
QJsonObject caseObj = val.toObject();
POJProblemCase problemCase = std::make_shared<OJProblemCase>();
problemCase->testState = ProblemCaseTestState::NotTested;
problemCase->name = tr("Problem Case %1").arg(problem->cases.count()+1);
problemCase->input = caseObj["input"].toString();
problemCase->expected = caseObj["output"].toString();
problem->cases.append(problemCase);
}
mOJProblemSetModel.addProblem(problem);
if (!ui->lstProblemSet->currentIndex().isValid()) {
ui->lstProblemSet->setCurrentIndex(mOJProblemSetModel.index(0,0));
}
}
clientConnection->disconnectFromHost();
}
void MainWindow::onShowInsertCodeSnippetMenu()
{
mMenuInsertCodeSnippet->clear();
@ -3386,6 +3443,7 @@ void MainWindow::onOJProblemCaseFinished(const QString &id, int current, int tot
}
ui->pbProblemCases->setMaximum(total);
ui->pbProblemCases->setValue(current);
ui->lblProblem->setText(mOJProblemModel.getTitle());
}
void MainWindow::cleanUpCPUDialog()
@ -4973,8 +5031,9 @@ void MainWindow::on_btnNewProblemSet_clicked()
tr("The current problem set is not empty.")
+"<br />"
+tr("Do you want to save it?"),
QMessageBox::Yes | QMessageBox::No)!=QMessageBox::Yes)
return;
QMessageBox::Yes | QMessageBox::No)==QMessageBox::Yes) {
on_btnSaveProblemSet_clicked();
}
}
mOJProblemSetNameCounter++;
mOJProblemSetModel.create(tr("Problem Set %1").arg(mOJProblemSetNameCounter));
@ -5056,7 +5115,7 @@ void MainWindow::on_btnAddProblemCase_clicked()
}
POJProblemCase problemCase = std::make_shared<OJProblemCase>();
problemCase->name = name;
problemCase->testState = ProblemCaseTestState::NoTested;
problemCase->testState = ProblemCaseTestState::NotTested;
mOJProblemModel.addCase(problemCase);
ui->lstProblemCases->setCurrentIndex(mOJProblemModel.index(mOJProblemModel.count()-1));
}

View File

@ -5,6 +5,7 @@
#include <QMainWindow>
#include <QTimer>
#include <QFileSystemModel>
#include <QTcpServer>
#include "common.h"
#include "widgets/searchresultview.h"
#include "widgets/classbrowser.h"
@ -227,6 +228,7 @@ private slots:
void onProblemSetIndexChanged(const QModelIndex &current, const QModelIndex &previous);
void onProblemCaseIndexChanged(const QModelIndex &current, const QModelIndex &previous);
void onProblemNameChanged(int index);
void onNewProblemConnection();
void onShowInsertCodeSnippetMenu();
@ -524,6 +526,7 @@ private:
bool mClosing;
bool mSystemTurnedOff;
QPoint mEditorContextMenuPos;
QTcpServer mTcpServer;
//actions for compile issue table
QAction * mTableIssuesCopyAction;

View File

@ -1129,6 +1129,9 @@
<property name="text">
<string>Problem</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>

View File

@ -5,7 +5,7 @@
#include <QVector>
enum class ProblemCaseTestState {
NoTested,
NotTested,
Testing,
Passed,
Failed
@ -30,6 +30,7 @@ using POJProblemCase = std::shared_ptr<OJProblemCase>;
struct OJProblem {
QString name;
QString url;
QVector<POJProblemCase> cases;
};

View File

@ -3,7 +3,7 @@
#include <QStringList>
#define DEVCPP_VERSION "0.7.6"
#define DEVCPP_VERSION "0.7.7"
#define APP_SETTSINGS_FILENAME "redpandacpp.ini"
#ifdef Q_OS_WIN

View File

@ -844,3 +844,11 @@ QByteArray ReadFileToByteArray(const QString &fileName)
}
return QByteArray();
}
QByteArray getHTTPBody(const QByteArray& content) {
int i= content.indexOf("\r\n\r\n");
if (i>=0) {
return content.mid(i+4);
}
return "";
}

View File

@ -166,6 +166,7 @@ QString TrimRight(const QString& s);
QString TrimLeft(const QString& s);
bool StringIsBlank(const QString& s);
int compareFileModifiedTime(const QString& filename1, const QString& filename2);
QByteArray getHTTPBody(const QByteArray& content);
//void changeTheme(const QString& themeName);

View File

@ -35,6 +35,9 @@
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Based on Qt %1 (%2)&lt;/p&gt;&lt;p&gt;Build time: %3 %4&lt;/p&gt;&lt;p&gt;Copyright 2020-2021 royqh1979@gmail.com&lt;/p&gt;&lt;p&gt;Homepage: &lt;a href=&quot;https://sourceforge.net/projects/dev-cpp-2020/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;https://sourceforge.net/projects/dev-cpp-2020/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>

View File

@ -86,6 +86,7 @@ void OJProblemSetModel::saveToFile(const QString &fileName)
foreach (const POJProblem& problem, mProblemSet.problems) {
QJsonObject problemObj;
problemObj["name"]=problem->name;
problemObj["url"]=problem->url;
QJsonArray cases;
foreach (const POJProblemCase& problemCase, problem->cases) {
QJsonObject caseObj;
@ -129,6 +130,7 @@ void OJProblemSetModel::loadFromFile(const QString &fileName)
QJsonObject problemObj = problemVal.toObject();
POJProblem problem = std::make_shared<OJProblem>();
problem->name = problemObj["name"].toString();
problem->url = problemObj["url"].toString();
QJsonArray casesArray = problemObj["cases"].toArray();
foreach (const QJsonValue& caseVal, casesArray) {
QJsonObject caseObj = caseVal.toObject();
@ -136,7 +138,7 @@ void OJProblemSetModel::loadFromFile(const QString &fileName)
problemCase->name = caseObj["name"].toString();
problemCase->input = caseObj["input"].toString();
problemCase->expected = caseObj["expected"].toString();
problemCase->testState = ProblemCaseTestState::NoTested;
problemCase->testState = ProblemCaseTestState::NotTested;
problem->cases.append(problemCase);
}
mProblemSet.problems.append(problem);
@ -272,6 +274,24 @@ void OJProblemModel::update(int row)
emit dataChanged(index(row,0),index(row,0));
}
QString OJProblemModel::getTitle()
{
if (!mProblem)
return "";
int total = mProblem->cases.count();
int passed = 0;
foreach (const POJProblemCase& problemCase, mProblem->cases) {
if (problemCase->testState == ProblemCaseTestState::Passed)
passed ++ ;
}
QString title = QString("%1 (%2/%3)").arg(mProblem->name)
.arg(passed).arg(total);
if (!mProblem->url.isEmpty()) {
title = QString("<a href=\"%1\">%2</a>").arg(mProblem->url,title);
}
return title;
}
int OJProblemModel::rowCount(const QModelIndex &) const
{
if (mProblem==nullptr)

View File

@ -19,6 +19,7 @@ public:
void clear();
int count();
void update(int row);
QString getTitle();
private:
POJProblem mProblem;