diff --git a/backend/include/csp/services/wrong_book_service.h b/backend/include/csp/services/wrong_book_service.h index e194634..7a33d30 100644 --- a/backend/include/csp/services/wrong_book_service.h +++ b/backend/include/csp/services/wrong_book_service.h @@ -27,6 +27,8 @@ class WrongBookService { int32_t note_score, int32_t note_rating, const std::string& note_feedback_md); + int32_t GetNoteRating(int64_t user_id, int64_t problem_id); + void AwardNoteRating(int64_t user_id, int64_t problem_id, int delta); void UpsertBySubmission(int64_t user_id, int64_t problem_id, int64_t submission_id, diff --git a/backend/src/controllers/me_controller.cc b/backend/src/controllers/me_controller.cc index e3df3e4..6034e77 100644 --- a/backend/src/controllers/me_controller.cc +++ b/backend/src/controllers/me_controller.cc @@ -342,8 +342,17 @@ void MeController::scoreWrongBookNote( services::WrongBookService wrong_book(csp::AppState::Instance().db()); // ensure note saved wrong_book.UpsertNote(*user_id, problem_id, note); + + // Get previous score to calculate rating delta + const int prev_rating = wrong_book.GetNoteRating(*user_id, problem_id); wrong_book.UpsertNoteScore(*user_id, problem_id, result.score, result.rating, result.feedback_md); + // Award (or adjust) rating points: delta = new_rating - prev_rating + const int delta = result.rating - prev_rating; + if (delta != 0) { + wrong_book.AwardNoteRating(*user_id, problem_id, delta); + } + Json::Value data; data["user_id"] = Json::Int64(*user_id); data["problem_id"] = Json::Int64(problem_id); diff --git a/backend/src/services/learning_note_scoring_service.cc b/backend/src/services/learning_note_scoring_service.cc index 65afff4..322422d 100644 --- a/backend/src/services/learning_note_scoring_service.cc +++ b/backend/src/services/learning_note_scoring_service.cc @@ -121,9 +121,9 @@ LearningNoteScoreResult LearningNoteScoringService::Score( r.model_name = parsed.get("model_name", "").asString(); if (r.score < 0) r.score = 0; - if (r.score > 100) r.score = 100; - if (r.rating < 1) r.rating = 1; - if (r.rating > 10) r.rating = 10; + if (r.score > 60) r.score = 60; + if (r.rating < 0) r.rating = 0; + if (r.rating > 6) r.rating = 6; if (r.feedback_md.empty()) { r.feedback_md = "### 笔记评分\n- 未能生成详细点评,请补充:学习目标、关键概念、代码片段、踩坑与修复。"; diff --git a/backend/src/services/wrong_book_service.cc b/backend/src/services/wrong_book_service.cc index 4c97dff..80ffda5 100644 --- a/backend/src/services/wrong_book_service.cc +++ b/backend/src/services/wrong_book_service.cc @@ -195,4 +195,59 @@ void WrongBookService::Remove(int64_t user_id, int64_t problem_id) { sqlite3_finalize(stmt); } +int32_t WrongBookService::GetNoteRating(int64_t user_id, int64_t problem_id) { + sqlite3* db = db_.raw(); + sqlite3_stmt* stmt = nullptr; + const char* sql = "SELECT note_rating FROM wrong_book WHERE user_id=? AND problem_id=? LIMIT 1"; + CheckSqlite(sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr), db, + "prepare get note_rating"); + CheckSqlite(sqlite3_bind_int64(stmt, 1, user_id), db, "bind user_id"); + CheckSqlite(sqlite3_bind_int64(stmt, 2, problem_id), db, "bind problem_id"); + int32_t rating = 0; + if (sqlite3_step(stmt) == SQLITE_ROW) { + rating = sqlite3_column_int(stmt, 0); + } + sqlite3_finalize(stmt); + return rating; +} + +void WrongBookService::AwardNoteRating(int64_t user_id, int64_t problem_id, int delta) { + sqlite3* db = db_.raw(); + + // Update user rating + { + sqlite3_stmt* stmt = nullptr; + const char* sql = "UPDATE users SET rating=rating+? WHERE id=?"; + CheckSqlite(sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr), db, + "prepare add note rating"); + CheckSqlite(sqlite3_bind_int(stmt, 1, delta), db, "bind delta"); + CheckSqlite(sqlite3_bind_int64(stmt, 2, user_id), db, "bind user_id"); + CheckSqlite(sqlite3_step(stmt), db, "exec add note rating"); + sqlite3_finalize(stmt); + } + + // Log to daily_task_logs for rating history visibility + { + sqlite3_stmt* stmt = nullptr; + const char* sql = + "INSERT INTO daily_task_logs(user_id,task_code,day_key,reward,created_at) " + "VALUES(?,?,?,?,?)"; + CheckSqlite(sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr), db, + "prepare note rating log"); + const std::string task_code = "note_score_" + std::to_string(problem_id); + const int64_t now = NowSec(); + // Use a unique day_key to avoid IGNORE conflicts + const std::string day_key = "note_" + std::to_string(now); + CheckSqlite(sqlite3_bind_int64(stmt, 1, user_id), db, "bind user_id"); + CheckSqlite(sqlite3_bind_text(stmt, 2, task_code.c_str(), -1, SQLITE_TRANSIENT), db, + "bind task_code"); + CheckSqlite(sqlite3_bind_text(stmt, 3, day_key.c_str(), -1, SQLITE_TRANSIENT), db, + "bind day_key"); + CheckSqlite(sqlite3_bind_int(stmt, 4, delta), db, "bind reward"); + CheckSqlite(sqlite3_bind_int64(stmt, 5, now), db, "bind created_at"); + CheckSqlite(sqlite3_step(stmt), db, "insert note rating log"); + sqlite3_finalize(stmt); + } +} + } // namespace csp::services diff --git a/frontend/src/app/me/page.tsx b/frontend/src/app/me/page.tsx index d91aac3..f61e1dd 100644 --- a/frontend/src/app/me/page.tsx +++ b/frontend/src/app/me/page.tsx @@ -143,8 +143,19 @@ export default function MePage() { first_ac: ["首次通过 ⭐", "First AC ⭐"], code_quality: ["代码质量 🛠️", "Code Quality 🛠️"], }; - if (type === "daily_task" && taskLabels[note]) { - return isZh ? taskLabels[note][0] : taskLabels[note][1]; + if (type === "daily_task") { + if (taskLabels[note]) { + return isZh ? taskLabels[note][0] : taskLabels[note][1]; + } + // Note score: "note_score_1234" + const ns = note.match(/^note_score_(\d+)$/); + if (ns) { + return ( + + {isZh ? `📜 探索笔记鉴定 P${ns[1]}` : `📜 Note Appraisal P${ns[1]}`} + + ); + } } // Solution view: "Problem 1234:Title" const m = note.match(/^Problem (\d+):(.*)$/); diff --git a/frontend/src/app/problems/[id]/page.tsx b/frontend/src/app/problems/[id]/page.tsx index 1f0558e..eacd94a 100644 --- a/frontend/src/app/problems/[id]/page.tsx +++ b/frontend/src/app/problems/[id]/page.tsx @@ -1031,15 +1031,15 @@ export default function ProblemDetailPage() {