feat: Minecraft theme overhaul, fix points bug, add history

这个提交包含在:
X
2026-02-15 09:41:54 -08:00
父节点 37266bb846
当前提交 ef6d71ef54
修改 28 个文件,包含 1821 行新增1053 行删除

查看文件

@@ -7,43 +7,62 @@
namespace csp::controllers {
class MeController : public drogon::HttpController<MeController> {
public:
public:
METHOD_LIST_BEGIN
ADD_METHOD_TO(MeController::profile, "/api/v1/me", drogon::Get);
ADD_METHOD_TO(MeController::listRedeemItems, "/api/v1/me/redeem/items", drogon::Get);
ADD_METHOD_TO(MeController::listRedeemRecords, "/api/v1/me/redeem/records", drogon::Get);
ADD_METHOD_TO(MeController::createRedeemRecord, "/api/v1/me/redeem/records", drogon::Post);
ADD_METHOD_TO(MeController::listDailyTasks, "/api/v1/me/daily-tasks", drogon::Get);
ADD_METHOD_TO(MeController::listWrongBook, "/api/v1/me/wrong-book", drogon::Get);
ADD_METHOD_TO(MeController::upsertWrongBookNote, "/api/v1/me/wrong-book/{1}", drogon::Patch);
ADD_METHOD_TO(MeController::deleteWrongBookItem, "/api/v1/me/wrong-book/{1}", drogon::Delete);
ADD_METHOD_TO(MeController::listRedeemItems, "/api/v1/me/redeem/items",
drogon::Get);
ADD_METHOD_TO(MeController::listRedeemRecords, "/api/v1/me/redeem/records",
drogon::Get);
ADD_METHOD_TO(MeController::createRedeemRecord, "/api/v1/me/redeem/records",
drogon::Post);
ADD_METHOD_TO(MeController::listDailyTasks, "/api/v1/me/daily-tasks",
drogon::Get);
ADD_METHOD_TO(MeController::listWrongBook, "/api/v1/me/wrong-book",
drogon::Get);
ADD_METHOD_TO(MeController::upsertWrongBookNote, "/api/v1/me/wrong-book/{1}",
drogon::Patch);
ADD_METHOD_TO(MeController::deleteWrongBookItem, "/api/v1/me/wrong-book/{1}",
drogon::Delete);
ADD_METHOD_TO(MeController::listRatingHistory, "/api/v1/me/rating-history",
drogon::Get);
METHOD_LIST_END
void profile(const drogon::HttpRequestPtr& req,
std::function<void(const drogon::HttpResponsePtr&)>&& cb);
void profile(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&cb);
void listRedeemItems(const drogon::HttpRequestPtr& req,
std::function<void(const drogon::HttpResponsePtr&)>&& cb);
void
listRedeemItems(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&cb);
void listRedeemRecords(const drogon::HttpRequestPtr& req,
std::function<void(const drogon::HttpResponsePtr&)>&& cb);
void
listRedeemRecords(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&cb);
void createRedeemRecord(const drogon::HttpRequestPtr& req,
std::function<void(const drogon::HttpResponsePtr&)>&& cb);
void
createRedeemRecord(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&cb);
void listDailyTasks(const drogon::HttpRequestPtr& req,
std::function<void(const drogon::HttpResponsePtr&)>&& cb);
void
listDailyTasks(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&cb);
void listWrongBook(const drogon::HttpRequestPtr& req,
std::function<void(const drogon::HttpResponsePtr&)>&& cb);
void listWrongBook(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&cb);
void upsertWrongBookNote(const drogon::HttpRequestPtr& req,
std::function<void(const drogon::HttpResponsePtr&)>&& cb,
int64_t problem_id);
void
upsertWrongBookNote(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&cb,
int64_t problem_id);
void deleteWrongBookItem(const drogon::HttpRequestPtr& req,
std::function<void(const drogon::HttpResponsePtr&)>&& cb,
int64_t problem_id);
void
deleteWrongBookItem(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&cb,
int64_t problem_id);
void
listRatingHistory(const drogon::HttpRequestPtr &req,
std::function<void(const drogon::HttpResponsePtr &)> &&cb);
};
} // namespace csp::controllers
} // namespace csp::controllers

查看文件

@@ -5,9 +5,17 @@
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
namespace csp::services {
struct SolutionViewStats {
int total_views = 0;
int total_cost = 0;
std::optional<int64_t> last_viewed_at;
bool has_viewed = false;
};
struct SolutionViewChargeResult {
bool granted = true;
bool charged = false;
@@ -21,24 +29,29 @@ struct SolutionViewChargeResult {
std::string deny_reason;
};
struct SolutionViewStats {
bool has_viewed = false;
int total_views = 0;
int total_cost = 0;
std::optional<int64_t> last_viewed_at;
struct RatingHistoryItem {
std::string type;
int64_t created_at;
int change;
std::string note;
};
class SolutionAccessService {
public:
explicit SolutionAccessService(db::SqliteDb& db) : db_(db) {}
public:
explicit SolutionAccessService(db::SqliteDb &db) : db_(db) {}
// Daily policy: first answer view is free, then each full view costs 2 rating.
SolutionViewChargeResult ConsumeSolutionView(int64_t user_id, int64_t problem_id);
// Daily policy: first answer view is free, then each full view costs 2
// rating.
SolutionViewChargeResult ConsumeSolutionView(int64_t user_id,
int64_t problem_id);
SolutionViewStats QueryUserProblemViewStats(int64_t user_id, int64_t problem_id);
SolutionViewStats QueryUserProblemViewStats(int64_t user_id,
int64_t problem_id);
private:
db::SqliteDb& db_;
std::vector<RatingHistoryItem> ListRatingHistory(int64_t user_id, int limit);
private:
db::SqliteDb &db_;
};
} // namespace csp::services
} // namespace csp::services