- Problems page: replace Luogu pass rate with local submission stats
(local_submit_count, local_ac_count)
- Problems page: add user AC/fail status column (user_ac, user_fail_count)
- Admin users: add total_submissions and total_ac columns
- Admin users: add detail panel with submissions/rating/redeem tabs
- Admin: new endpoint GET /api/v1/admin/users/{id}/rating-history
- Rating history: note field includes problem title via JOIN
- Me page: translate task codes to friendly labels with icons
- Me page: problem links in rating history are clickable
- Wrong book service, learning note scoring, note image controller
- Backend SQL uses batch queries for performance
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
122 行
3.3 KiB
C++
122 行
3.3 KiB
C++
#include "csp/domain/json.h"
|
|
|
|
namespace csp::domain {
|
|
|
|
Json::Value ToPublicJson(const User& u) {
|
|
Json::Value j;
|
|
j["id"] = Json::Int64(u.id);
|
|
j["username"] = u.username;
|
|
j["rating"] = u.rating;
|
|
j["created_at"] = Json::Int64(u.created_at);
|
|
return j;
|
|
}
|
|
|
|
Json::Value ToJson(const Problem& p) {
|
|
Json::Value j;
|
|
j["id"] = Json::Int64(p.id);
|
|
j["slug"] = p.slug;
|
|
j["title"] = p.title;
|
|
j["statement_md"] = p.statement_md;
|
|
j["difficulty"] = p.difficulty;
|
|
j["source"] = p.source;
|
|
j["statement_url"] = p.statement_url;
|
|
j["llm_profile_json"] = p.llm_profile_json;
|
|
j["sample_input"] = p.sample_input;
|
|
j["sample_output"] = p.sample_output;
|
|
j["created_at"] = Json::Int64(p.created_at);
|
|
return j;
|
|
}
|
|
|
|
Json::Value ToJson(const Submission& s) {
|
|
Json::Value j;
|
|
j["id"] = Json::Int64(s.id);
|
|
j["user_id"] = Json::Int64(s.user_id);
|
|
j["problem_id"] = Json::Int64(s.problem_id);
|
|
if (s.contest_id.has_value()) {
|
|
j["contest_id"] = Json::Int64(*s.contest_id);
|
|
} else {
|
|
j["contest_id"] = Json::nullValue;
|
|
}
|
|
j["language"] = ToString(s.language);
|
|
j["status"] = ToString(s.status);
|
|
j["score"] = s.score;
|
|
j["rating_delta"] = s.rating_delta;
|
|
j["time_ms"] = s.time_ms;
|
|
j["memory_kb"] = s.memory_kb;
|
|
j["compile_log"] = s.compile_log;
|
|
j["runtime_log"] = s.runtime_log;
|
|
j["created_at"] = Json::Int64(s.created_at);
|
|
return j;
|
|
}
|
|
|
|
Json::Value ToJson(const WrongBookItem& w) {
|
|
Json::Value j;
|
|
j["user_id"] = Json::Int64(w.user_id);
|
|
j["problem_id"] = Json::Int64(w.problem_id);
|
|
if (w.last_submission_id.has_value()) {
|
|
j["last_submission_id"] = Json::Int64(*w.last_submission_id);
|
|
} else {
|
|
j["last_submission_id"] = Json::nullValue;
|
|
}
|
|
j["note"] = w.note;
|
|
j["note_score"] = w.note_score;
|
|
j["note_rating"] = w.note_rating;
|
|
j["note_feedback_md"] = w.note_feedback_md;
|
|
if (!w.note_images_json.empty()) {
|
|
Json::Value parsed;
|
|
Json::CharReaderBuilder b;
|
|
std::string errs;
|
|
std::unique_ptr<Json::CharReader> r(b.newCharReader());
|
|
if (r->parse(w.note_images_json.data(), w.note_images_json.data() + w.note_images_json.size(), &parsed, &errs) && parsed.isArray()) {
|
|
j["note_images"] = parsed;
|
|
} else {
|
|
j["note_images"] = Json::arrayValue;
|
|
}
|
|
} else {
|
|
j["note_images"] = Json::arrayValue;
|
|
}
|
|
j["note_scored_at"] = Json::Int64(w.note_scored_at);
|
|
j["updated_at"] = Json::Int64(w.updated_at);
|
|
return j;
|
|
}
|
|
|
|
Json::Value ToJson(const Contest& c) {
|
|
Json::Value j;
|
|
j["id"] = Json::Int64(c.id);
|
|
j["title"] = c.title;
|
|
j["starts_at"] = Json::Int64(c.starts_at);
|
|
j["ends_at"] = Json::Int64(c.ends_at);
|
|
j["rule_json"] = c.rule_json;
|
|
return j;
|
|
}
|
|
|
|
Json::Value ToJson(const KbArticle& a) {
|
|
Json::Value j;
|
|
j["id"] = Json::Int64(a.id);
|
|
j["slug"] = a.slug;
|
|
j["title"] = a.title;
|
|
j["content_md"] = a.content_md;
|
|
j["created_at"] = Json::Int64(a.created_at);
|
|
return j;
|
|
}
|
|
|
|
Json::Value ToJson(const GlobalLeaderboardEntry& e) {
|
|
Json::Value j;
|
|
j["user_id"] = Json::Int64(e.user_id);
|
|
j["username"] = e.username;
|
|
j["rating"] = e.rating;
|
|
j["created_at"] = Json::Int64(e.created_at);
|
|
return j;
|
|
}
|
|
|
|
Json::Value ToJson(const ContestLeaderboardEntry& e) {
|
|
Json::Value j;
|
|
j["user_id"] = Json::Int64(e.user_id);
|
|
j["username"] = e.username;
|
|
j["solved"] = e.solved;
|
|
j["penalty_sec"] = Json::Int64(e.penalty_sec);
|
|
return j;
|
|
}
|
|
|
|
} // namespace csp::domain
|