feat: note scoring 60/6 with rating award + Minecraft theme
- Score max changed from 100 to 60, rating max from 10 to 6 - Note scoring now awards actual rating points (delta-based) - Re-scoring only awards/deducts the difference - Rating history shows note_score entries with problem link - LLM prompt includes problem statement context for better evaluation - LLM scoring dimensions: 题意理解/思路算法/代码记录/踩坑反思 (15 each) - Minecraft-themed UI: 矿石鉴定, 探索笔记, 存入宝典, etc. - Fallback scoring adjusted for 60-point scale - Handle LLM markdown code fence wrapping in response Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
这个提交包含在:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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- 未能生成详细点评,请补充:学习目标、关键概念、代码片段、踩坑与修复。";
|
||||
|
||||
@@ -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
|
||||
|
||||
在新工单中引用
屏蔽一个用户