package api import ( "context" "copter-train/db/model" "copter-train/db/repo" "errors" "fmt" "strconv" "time" "github.com/gin-gonic/gin" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" ) // 本年每月学习时长 func StatisticsLearnProcess(c *gin.Context, apictx *ApiSession) (interface{}, error) { db := c.Param("scope") if len(db) == 0 { return nil, errors.New("scope不能为空") } // 如果没有uid参数,则查询当前用户的 uid := c.Query("uid") if len(uid) == 0 { uid = apictx.User.ID } _type := c.Query("type") // 如果没有年份参数,则查询当前年份的 _year := c.Query("year") year := 2024 if len(_year) == 0 { year = time.Now().Year() } else { year_, err := strconv.Atoi(_year) if err != nil { return nil, errors.New("year参数错误") } year = year_ } fmt.Println("year:", year) colls := apictx.CreateRepoCtx().Client.GetDbCollection(db, repo.CollectionLearnLog) return AggregateMonthlyLearnTime(colls, uid, _type, year) } // 整个模块的学习时长 不需要cid约束 func AggregateMonthlyLearnTime(colls *mongo.Collection, uid string, learnType string, year int) ([]bson.M, error) { chinaTimeZone := time.FixedZone("CST", 8*60*60) // 中国时区 pipeline := mongo.Pipeline{ // { // {Key: "$addFields", Value: bson.D{ // {Key: "dateParts", Value: bson.D{ // {Key: "$dateToParts", Value: bson.M{ // "date": "$createTime", // "timezone": "Asia/Shanghai", // }}, // }}, // }}, // }, // { // {Key: "$match", Value: bson.D{ // {Key: "uid", Value: uid}, // {Key: "dateParts.year", Value: year}, // // {Key: "dateParts.month", Value: bson.D{ // // {Key: "$gte", Value: 1}, // // {Key: "$lt", Value: 13}, // // }}, // }}, // }, // { // {Key: "$project", Value: bson.D{ // {Key: "month", Value: bson.D{ // {Key: "$month", Value: "$createTime"}, // }}, // {Key: "learnTime", Value: 1}, // }}, // }, // { // {Key: "$group", Value: bson.D{ // {Key: "_id", Value: "$month"}, { {Key: "$match", Value: bson.D{ {Key: "createTime", Value: bson.D{ {Key: "$gte", Value: time.Date(year, time.January, 1, 0, 0, 0, 0, chinaTimeZone)}, {Key: "$lt", Value: time.Date(year+1, time.January, 1, 0, 0, 0, 0, chinaTimeZone)}, }}, }}, }, // 将 createTime 字段分解为年和月 { {Key: "$addFields", Value: bson.D{ // {"year", bson.D{{"$year", bson.D{{"$add", []interface{}{"$createTime", 8 * 60 * 60 * 1000}}}}}}, {Key: "month", Value: bson.D{{Key: "$month", Value: bson.D{{Key: "$add", Value: []interface{}{"$createTime", 8 * 60 * 60 * 1000}}}}}}, }}, }, // 按年和月分组,并计算每个月的正确和错误数量 { {Key: "$group", Value: bson.D{ {Key: "_id", Value: "$month"}, {Key: "totalLearnTime", Value: bson.D{ {Key: "$sum", Value: "$learnTime"}, }}, }}, }, { {Key: "$sort", Value: bson.D{ {Key: "_id", Value: 1}, }}, }, } cursor, err := colls.Aggregate(context.TODO(), pipeline) if err != nil { return nil, err } var results []bson.M if err = cursor.All(context.TODO(), &results); err != nil { return nil, err } return results, nil } // 个人:上次学习时长 // 获取最新一条数据 func StatisticsLastLearnTime(c *gin.Context, apictx *ApiSession) (interface{}, error) { db := c.Param("scope") if len(db) == 0 { return nil, errors.New("scope不能为空") } // 如果没有uid参数,则查询当前用户的 uid := c.Query("uid") if len(uid) == 0 { uid = apictx.User.ID } learnLog := &model.LearnLog{} found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ Db: db, CollectName: repo.CollectionLearnLog, Query: repo.Map{"uid": uid}, Sort: bson.M{"createTime": -1}, }, learnLog) if err != nil { return nil, err } if !found { return 0, nil } return learnLog.LearnTime, nil } // 个人:用户总学习时长 func StatisticsTotalLearnTime(c *gin.Context, apictx *ApiSession) (interface{}, error) { db := c.Param("scope") if len(db) == 0 { return nil, errors.New("scope不能为空") } // 如果没有uid参数,则查询当前用户的 uid := c.Query("uid") if len(uid) == 0 { uid = apictx.User.ID } colls := apictx.CreateRepoCtx().Client.GetDbCollection(db, repo.CollectionLearnLog) return AggregateTotalLearnTime(colls, uid) } // 查询用户学习总时长 func AggregateTotalLearnTime(colls *mongo.Collection, uid string) (int, error) { pipeline := mongo.Pipeline{ { {Key: "$match", Value: bson.D{ {Key: "uid", Value: uid}, }}, }, { {Key: "$group", Value: bson.D{ {Key: "_id", Value: "$uid"}, {Key: "totalLearnTime", Value: bson.D{ {Key: "$sum", Value: "$learnTime"}, }}, }}, }, } cursor, err := colls.Aggregate(context.TODO(), pipeline) if err != nil { return 0, err } var results []bson.M if err = cursor.All(context.TODO(), &results); err != nil { return 0, err } if len(results) > 0 { if v, ok := results[0]["totalLearnTime"].(int32); ok { return int(v), nil } return 0, nil } return 0, nil } // 个人: 获取最后一场考试的成绩 func StatisticsLastExeamScore(c *gin.Context, apictx *ApiSession) (interface{}, error) { db := c.Param("scope") if len(db) == 0 { return nil, errors.New("scope不能为空") } // 如果没有uid参数,则查询当前用户的 uid := c.Query("uid") if len(uid) == 0 { uid = apictx.User.ID } exeamLog := &model.ExeamLog{} found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ Db: db, CollectName: repo.CollectionExeamLog, Query: repo.Map{"uid": uid}, Sort: bson.M{"createTime": -1}, }, exeamLog) if err != nil { return nil, err } if !found { return 0, nil } fmt.Println(exeamLog) return exeamLog.Score, nil } // 个人: 获取历史最好成绩 func StatisticsBestExeamScore(c *gin.Context, apictx *ApiSession) (interface{}, error) { db := c.Param("scope") if len(db) == 0 { return nil, errors.New("scope不能为空") } // 如果没有uid参数,则查询当前用户的 uid := c.Query("uid") if len(uid) == 0 { uid = apictx.User.ID } exeamLog := &model.ExeamLog{} found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ Db: db, CollectName: repo.CollectionExeamLog, Query: repo.Map{"uid": uid}, Sort: bson.M{"score": -1}, }, exeamLog) if err != nil { return nil, err } if !found { return 0, nil } return exeamLog.Score, nil } // 个人: 已学习模块数 // 统计各个模块的学习总时长,根据总时长时间判断是否已学习 // 只需要返回统计各个模块的时长汇总,cid相同的为同一个模块 func StatisticsLearnedModules(c *gin.Context, apictx *ApiSession) (interface{}, error) { db := c.Param("scope") if len(db) == 0 { return nil, errors.New("scope不能为空") } // 如果没有uid参数,则查询当前用户的 uid := c.Query("uid") if len(uid) == 0 { uid = apictx.User.ID } colls := apictx.CreateRepoCtx().Client.GetDbCollection(db, repo.CollectionLearnLog) pipeline := mongo.Pipeline{ { {Key: "$match", Value: bson.D{ {Key: "uid", Value: uid}, }}, }, { {Key: "$group", Value: bson.D{ {Key: "_id", Value: "$cid"}, {Key: "totalLearnTime", Value: bson.D{{Key: "$sum", Value: "$learnTime"}}}, }}, }, } cursor, err := colls.Aggregate(apictx.CreateRepoCtx().Ctx, pipeline) if err != nil { return nil, err } var results []bson.M if err = cursor.All(apictx.CreateRepoCtx().Ctx, &results); err != nil { return nil, err } return results, nil } // 个人: 统计用户本年每月考核正确和错误数 func StatisticsExeamTFRate(c *gin.Context, apictx *ApiSession) (interface{}, error) { db := c.Param("scope") if len(db) == 0 { return nil, errors.New("scope不能为空") } // 如果没有uid参数,则查询当前用户的 uid := c.Query("uid") if len(uid) == 0 { uid = apictx.User.ID } _year := c.Query("year") year := 2024 if len(_year) == 0 { year = time.Now().Year() } else { year_, err := strconv.Atoi(_year) if err != nil { return nil, errors.New("year参数错误") } year = year_ } fmt.Println(year) colls := apictx.CreateRepoCtx().Client.GetDbCollection(db, repo.CollectionExeamLog) chinaTimeZone := time.FixedZone("CST", 8*60*60) // 中国时区 fmt.Println(uid) pipeline := mongo.Pipeline{ // 筛选出特定时间范围的记录 { {Key: "$match", Value: bson.D{ {Key: "createTime", Value: bson.D{ {Key: "$gte", Value: time.Date(year, time.January, 1, 0, 0, 0, 0, chinaTimeZone)}, {Key: "$lt", Value: time.Date(year+1, time.January, 1, 0, 0, 0, 0, chinaTimeZone)}, }}, }}, }, // 将 createTime 字段分解为年和月 { {Key: "$addFields", Value: bson.D{ // {"year", bson.D{{"$year", bson.D{{"$add", []interface{}{"$createTime", 8 * 60 * 60 * 1000}}}}}}, {Key: "month", Value: bson.D{{Key: "$month", Value: bson.D{{Key: "$add", Value: []interface{}{"$createTime", 8 * 60 * 60 * 1000}}}}}}, }}, }, // 按年和月分组,并计算每个月的正确和错误数量 { {Key: "$group", Value: bson.D{ {Key: "_id", Value: "$month"}, {Key: "correct", Value: bson.D{{Key: "$sum", Value: "$correct"}}}, {Key: "error", Value: bson.D{{Key: "$sum", Value: "$error"}}}, }}, }, // 排序结果 { {Key: "$sort", Value: bson.D{{Key: "_id", Value: 1}}}, }, } cursor, err := colls.Aggregate(context.TODO(), pipeline) if err != nil { return nil, err } var results []bson.M if err = cursor.All(apictx.CreateRepoCtx().Ctx, &results); err != nil { return nil, err } return results, nil }