@@ -2,7 +2,7 @@ | |||||
<h1><img src="public/img/favicon.png" alt="logo" width="30" height="30">AiForge - 启智AI开发协作平台</h1> | <h1><img src="public/img/favicon.png" alt="logo" width="30" height="30">AiForge - 启智AI开发协作平台</h1> | ||||
[](https://git.openi.org.cn/OpenI/aiforge/releases/latest) | |||||
[](https://git.openi.org.cn/OpenI/aiforge/releases/latest) | |||||
[](https://opensource.org/licenses/MIT) | [](https://opensource.org/licenses/MIT) | ||||
@@ -29,6 +29,7 @@ const ( | |||||
JobTypeBenchmark JobType = "BENCHMARK" | JobTypeBenchmark JobType = "BENCHMARK" | ||||
JobTypeSnn4imagenet JobType = "SNN4IMAGENET" | JobTypeSnn4imagenet JobType = "SNN4IMAGENET" | ||||
JobTypeBrainScore JobType = "BRAINSCORE" | JobTypeBrainScore JobType = "BRAINSCORE" | ||||
JobTypeTrain JobType = "TRAIN" | |||||
ModelArtsCreateQueue ModelArtsJobStatus = "CREATE_QUEUING" //免费资源创建排队中 | ModelArtsCreateQueue ModelArtsJobStatus = "CREATE_QUEUING" //免费资源创建排队中 | ||||
ModelArtsCreating ModelArtsJobStatus = "CREATING" //创建中 | ModelArtsCreating ModelArtsJobStatus = "CREATING" //创建中 | ||||
@@ -153,7 +154,8 @@ type CloudbrainsOptions struct { | |||||
SortType string | SortType string | ||||
CloudbrainIDs []int64 | CloudbrainIDs []int64 | ||||
// JobStatus CloudbrainStatus | // JobStatus CloudbrainStatus | ||||
Type int | |||||
Type int | |||||
JobType string | |||||
} | } | ||||
type TaskPod struct { | type TaskPod struct { | ||||
TaskRoleStatus struct { | TaskRoleStatus struct { | ||||
@@ -846,6 +848,12 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { | |||||
) | ) | ||||
} | } | ||||
if (opts.JobType) != "" { | |||||
cond = cond.And( | |||||
builder.Eq{"cloudbrain.job_type": opts.JobType}, | |||||
) | |||||
} | |||||
// switch opts.JobStatus { | // switch opts.JobStatus { | ||||
// case JobWaiting: | // case JobWaiting: | ||||
// cond.And(builder.Eq{"cloudbrain.status": int(JobWaiting)}) | // cond.And(builder.Eq{"cloudbrain.status": int(JobWaiting)}) | ||||
@@ -14,11 +14,8 @@ const ( | |||||
) | ) | ||||
const ( | const ( | ||||
TypeCloudBrainOne = 0 | |||||
TypeCloudBrainNotebook = 1 | |||||
TypeCloudBrainTrainJob = 2 | |||||
TypeCloudBrainTwo = 1 | |||||
TypeCloudBrainOne int = iota | |||||
TypeCloudBrainTwo | |||||
) | ) | ||||
type FileChunk struct { | type FileChunk struct { | ||||
@@ -1356,6 +1356,15 @@ func GetIssueStats(opts *IssueStatsOptions) (*IssueStats, error) { | |||||
return accum, nil | return accum, nil | ||||
} | } | ||||
func GetPullCountByUserAndRepoId(repoId int64, userId int64) int64 { | |||||
issue := new(Issue) | |||||
total, err := x.Where("is_pull=true and repo_id=? and poster_id=?", repoId, userId).Count(issue) | |||||
if err != nil { | |||||
return 0 | |||||
} | |||||
return total | |||||
} | |||||
func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats, error) { | func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats, error) { | ||||
stats := &IssueStats{} | stats := &IssueStats{} | ||||
@@ -2,12 +2,18 @@ package models | |||||
import ( | import ( | ||||
"fmt" | "fmt" | ||||
"sort" | |||||
"strings" | "strings" | ||||
"time" | "time" | ||||
"code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
) | ) | ||||
type ContributorWithUserId struct { | |||||
git.Contributor | |||||
UserId int64 | |||||
} | |||||
func GetRepoKPIStats(repo *Repository) (*git.RepoKPIStats, error) { | func GetRepoKPIStats(repo *Repository) (*git.RepoKPIStats, error) { | ||||
wikiPath := "" | wikiPath := "" | ||||
if repo.HasWiki() { | if repo.HasWiki() { | ||||
@@ -63,22 +69,39 @@ func getRepoKPIStats(repoPath string, wikiPath string) (*git.RepoKPIStats, error | |||||
} | } | ||||
if recentlyContributors != nil { | if recentlyContributors != nil { | ||||
resentlyContributorDistinctDict := make(map[string]int, 0) | |||||
for _, recentlyContributor := range recentlyContributors { | for _, recentlyContributor := range recentlyContributors { | ||||
user, err := GetUserByActivateEmail(recentlyContributor.Email) | user, err := GetUserByActivateEmail(recentlyContributor.Email) | ||||
var ok bool | |||||
if err == nil { | if err == nil { | ||||
_, ok = contributorDistinctDict[user.Email] | |||||
value, ok := resentlyContributorDistinctDict[user.Email] | |||||
if !ok { | |||||
resentlyContributorDistinctDict[user.Email] = recentlyContributor.CommitCnt | |||||
} else { | |||||
resentlyContributorDistinctDict[user.Email] = value + recentlyContributor.CommitCnt | |||||
} | |||||
} else { | } else { | ||||
_, ok = contributorDistinctDict[recentlyContributor.Email] | |||||
value, ok := resentlyContributorDistinctDict[recentlyContributor.Email] | |||||
if !ok { | |||||
resentlyContributorDistinctDict[recentlyContributor.Email] = recentlyContributor.CommitCnt | |||||
} else { | |||||
resentlyContributorDistinctDict[recentlyContributor.Email] = value + recentlyContributor.CommitCnt | |||||
} | |||||
} | } | ||||
if !ok { | |||||
} | |||||
for k, v := range resentlyContributorDistinctDict { | |||||
count, ok := contributorDistinctDict[k] | |||||
if ok && count == v { | |||||
stats.ContributorsAdded++ | stats.ContributorsAdded++ | ||||
newContributersDict[recentlyContributor.Email] = struct{}{} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
stats.Contributors = int64(len(contributorDistinctDict)) | stats.Contributors = int64(len(contributorDistinctDict)) | ||||
@@ -101,6 +124,64 @@ func getRepoKPIStats(repoPath string, wikiPath string) (*git.RepoKPIStats, error | |||||
} | } | ||||
func GetTop10Contributor(repoPath string) ([]ContributorWithUserId, error) { | |||||
contributors, err := git.GetContributors(repoPath) | |||||
if err != nil { | |||||
return make([]ContributorWithUserId, 0), err | |||||
} | |||||
contributorDistinctDict := make(map[string]ContributorWithUserId, 0) | |||||
if contributors != nil { | |||||
for _, contributor := range contributors { | |||||
if strings.Compare(contributor.Email, "") == 0 { | |||||
continue | |||||
} | |||||
user, err := GetUserByActivateEmail(contributor.Email) | |||||
if err == nil { | |||||
value, ok := contributorDistinctDict[user.Email] | |||||
if !ok { | |||||
contributorDistinctDict[user.Email] = ContributorWithUserId{ | |||||
contributor, | |||||
user.ID, | |||||
} | |||||
} else { | |||||
value.CommitCnt += contributor.CommitCnt | |||||
} | |||||
} else { | |||||
value, ok := contributorDistinctDict[contributor.Email] | |||||
if !ok { | |||||
contributorDistinctDict[contributor.Email] = ContributorWithUserId{ | |||||
contributor, | |||||
-1, | |||||
} | |||||
} else { | |||||
value.CommitCnt += contributor.CommitCnt | |||||
} | |||||
} | |||||
} | |||||
v := make([]ContributorWithUserId, 0, len(contributorDistinctDict)) | |||||
for _, value := range contributorDistinctDict { | |||||
v = append(v, value) | |||||
} | |||||
sort.Slice(v, func(i, j int) bool { | |||||
return v[i].CommitCnt > v[j].CommitCnt | |||||
}) | |||||
if len(v) <= 10 { | |||||
return v, nil | |||||
} else { | |||||
return v[0:10], nil | |||||
} | |||||
} | |||||
return make([]ContributorWithUserId, 0), nil | |||||
} | |||||
func setKeyContributerDict(contributorDistinctDict map[string]int, email string, keyContributorsDict map[string]struct{}) { | func setKeyContributerDict(contributorDistinctDict map[string]int, email string, keyContributorsDict map[string]struct{}) { | ||||
if contributorDistinctDict[email] >= 3 { | if contributorDistinctDict[email] >= 3 { | ||||
_, ok := keyContributorsDict[email] | _, ok := keyContributorsDict[email] | ||||
@@ -114,6 +114,17 @@ func (repo *Repository) isCollaborator(e Engine, userID int64) (bool, error) { | |||||
return e.Get(&Collaboration{RepoID: repo.ID, UserID: userID}) | return e.Get(&Collaboration{RepoID: repo.ID, UserID: userID}) | ||||
} | } | ||||
func (repo *Repository) GetCollaboratorMode(userID int64) int { | |||||
collaboration := &Collaboration{RepoID: repo.ID, UserID: userID} | |||||
has, err := x.Get(&collaboration) | |||||
if err != nil || !has { | |||||
return -1 | |||||
} else { | |||||
return int(collaboration.Mode) | |||||
} | |||||
} | |||||
// IsCollaborator check if a user is a collaborator of a repository | // IsCollaborator check if a user is a collaborator of a repository | ||||
func (repo *Repository) IsCollaborator(userID int64) (bool, error) { | func (repo *Repository) IsCollaborator(userID int64) (bool, error) { | ||||
return repo.isCollaborator(x, userID) | return repo.isCollaborator(x, userID) | ||||
@@ -9,56 +9,56 @@ import ( | |||||
// RepoStatistic statistic info of all repository | // RepoStatistic statistic info of all repository | ||||
type RepoStatistic struct { | type RepoStatistic struct { | ||||
ID int64 `xorm:"pk autoincr"` | |||||
RepoID int64 `xorm:"unique(s) NOT NULL"` | |||||
Name string `xorm:"INDEX"` | |||||
IsPrivate bool | |||||
Date string `xorm:"unique(s) NOT NULL"` | |||||
NumWatches int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumWatchesAdded int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumStars int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumStarsAdded int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumForks int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumForksAdded int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumDownloads int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumDownloadsAdded int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumComments int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumCommentsAdded int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumVisits int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumClosedIssues int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumClosedIssuesAdded int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumVersions int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumDevMonths int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
RepoSize int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
DatasetSize int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumModels int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumWikiViews int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumCommits int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumCommitsAdded int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumIssues int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumIssuesAdded int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumPulls int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumPullsAdded int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
IssueFixedRate float32 `xorm:"NOT NULL"` | |||||
NumContributor int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumContributorAdded int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumKeyContributor int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumContributorsGrowth int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumCommitsGrowth int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumCommitLinesGrowth int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumIssuesGrowth int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
NumCommentsGrowth int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
Impact float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
Completeness float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
Liveness float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
ProjectHealth float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
TeamHealth float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
Growth float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
RadarTotal float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
ID int64 `xorm:"pk autoincr" json:"-"` | |||||
RepoID int64 `xorm:"unique(s) NOT NULL" json:"repo_id"` | |||||
Name string `xorm:"INDEX" json:"name"` | |||||
IsPrivate bool `json:"isPrivate"` | |||||
Date string `xorm:"unique(s) NOT NULL" json:"date"` | |||||
NumWatches int64 `xorm:"NOT NULL DEFAULT 0" json:"watch"` | |||||
NumWatchesAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumStars int64 `xorm:"NOT NULL DEFAULT 0" json:"star"` | |||||
NumStarsAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumForks int64 `xorm:"NOT NULL DEFAULT 0" json:"fork"` | |||||
NumForksAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumDownloads int64 `xorm:"NOT NULL DEFAULT 0" json:"download"` | |||||
NumDownloadsAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumComments int64 `xorm:"NOT NULL DEFAULT 0" json:"comment"` | |||||
NumCommentsAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumVisits int64 `xorm:"NOT NULL DEFAULT 0" json:"view"` | |||||
NumClosedIssues int64 `xorm:"NOT NULL DEFAULT 0" json:"issueClosed"` | |||||
NumClosedIssuesAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumVersions int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumDevMonths int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
RepoSize int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
DatasetSize int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumModels int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumWikiViews int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumCommits int64 `xorm:"NOT NULL DEFAULT 0" json:"commit"` | |||||
NumCommitsAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumIssues int64 `xorm:"NOT NULL DEFAULT 0" json:"issue"` | |||||
NumIssuesAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumPulls int64 `xorm:"NOT NULL DEFAULT 0" json:"pr"` | |||||
NumPullsAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
IssueFixedRate float32 `xorm:"NOT NULL" json:"issueClosedRatio"` | |||||
NumContributor int64 `xorm:"NOT NULL DEFAULT 0" json:"contributor"` | |||||
NumContributorAdded int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumKeyContributor int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumContributorsGrowth int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumCommitsGrowth int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumCommitLinesGrowth int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumIssuesGrowth int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
NumCommentsGrowth int64 `xorm:"NOT NULL DEFAULT 0" json:"-"` | |||||
Impact float64 `xorm:"NOT NULL DEFAULT 0" json:"impact"` | |||||
Completeness float64 `xorm:"NOT NULL DEFAULT 0" json:"completeness"` | |||||
Liveness float64 `xorm:"NOT NULL DEFAULT 0" json:"liveness"` | |||||
ProjectHealth float64 `xorm:"NOT NULL DEFAULT 0" json:"projectHealth"` | |||||
TeamHealth float64 `xorm:"NOT NULL DEFAULT 0" json:"teamHealth"` | |||||
Growth float64 `xorm:"NOT NULL DEFAULT 0" json:"growth"` | |||||
RadarTotal float64 `xorm:"NOT NULL DEFAULT 0" json:"openi"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created" json:"-"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated" json:"-"` | |||||
} | } | ||||
func DeleteRepoStatDaily(date string) error { | func DeleteRepoStatDaily(date string) error { | ||||
@@ -81,6 +81,57 @@ func DeleteRepoStatDaily(date string) error { | |||||
return nil | return nil | ||||
} | } | ||||
func CountRepoStatByRawSql(sql string) (int64, error) { | |||||
return xStatistic.SQL(sql).Count() | |||||
} | |||||
func GetRepoStatisticByRawSql(sql string) []*RepoStatistic { | |||||
repoStatistics := make([]*RepoStatistic, 0) | |||||
xStatistic.SQL(sql).Find(&repoStatistics) | |||||
return repoStatistics | |||||
} | |||||
func GetRepoStatLastUpdatedTime(repoId ...string) (string, string, error) { | |||||
repoStatistic := new(RepoStatistic) | |||||
var has bool | |||||
var err error | |||||
if len(repoId) == 0 { | |||||
has, err = xStatistic.Desc("created_unix").Limit(1).Cols("created_unix", "date").Get(repoStatistic) | |||||
} else { | |||||
has, err = xStatistic.Where("repo_id=?", repoId[0]).Desc("created_unix").Limit(1).Cols("created_unix", "date").Get(repoStatistic) | |||||
} | |||||
if err != nil { | |||||
return "", "", err | |||||
} else { | |||||
if has { | |||||
return repoStatistic.CreatedUnix.Format("2006-01-02 15:04:05"), repoStatistic.Date, nil | |||||
} else { | |||||
return "", "", fmt.Errorf("Can not get the latest record.") | |||||
} | |||||
} | |||||
} | |||||
func GetRepoStatisticByDateAndRepoId(date string, repoId int64) (*RepoStatistic, error) { | |||||
repoStatistic := new(RepoStatistic) | |||||
has, err := xStatistic.Where("date=? and repo_id=?", date, repoId).Get(repoStatistic) | |||||
if err != nil { | |||||
return nil, err | |||||
} else { | |||||
if has { | |||||
return repoStatistic, nil | |||||
} else { | |||||
return nil, fmt.Errorf("The num of return records is 0.") | |||||
} | |||||
} | |||||
} | |||||
func GetRepoStatisticByDate(date string) ([]*RepoStatistic, error) { | func GetRepoStatisticByDate(date string) ([]*RepoStatistic, error) { | ||||
repoStatistics := make([]*RepoStatistic, 0) | repoStatistics := make([]*RepoStatistic, 0) | ||||
err := xStatistic.Where("date = ?", date).Find(&repoStatistics) | err := xStatistic.Where("date = ?", date).Find(&repoStatistics) | ||||
@@ -159,7 +159,7 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description string) error | |||||
JobID: jobResult.ID, | JobID: jobResult.ID, | ||||
JobName: jobName, | JobName: jobName, | ||||
JobType: string(models.JobTypeDebug), | JobType: string(models.JobTypeDebug), | ||||
Type: models.TypeCloudBrainNotebook, | |||||
Type: models.TypeCloudBrainTwo, | |||||
Uuid: uuid, | Uuid: uuid, | ||||
}) | }) | ||||
@@ -207,8 +207,8 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) error { | |||||
RepoID: ctx.Repo.Repository.ID, | RepoID: ctx.Repo.Repository.ID, | ||||
JobID: strconv.FormatInt(jobResult.JobID, 10), | JobID: strconv.FormatInt(jobResult.JobID, 10), | ||||
JobName: req.JobName, | JobName: req.JobName, | ||||
JobType: string(models.JobTypeDebug), | |||||
Type: models.TypeCloudBrainTrainJob, | |||||
JobType: string(models.JobTypeTrain), | |||||
Type: models.TypeCloudBrainTwo, | |||||
VersionID: jobResult.VersionID, | VersionID: jobResult.VersionID, | ||||
VersionName: jobResult.VersionName, | VersionName: jobResult.VersionName, | ||||
Uuid: req.Uuid, | Uuid: req.Uuid, | ||||
@@ -544,6 +544,7 @@ var ( | |||||
GrowthContributors float64 | GrowthContributors float64 | ||||
GrowthCommit float64 | GrowthCommit float64 | ||||
GrowthComments float64 | GrowthComments float64 | ||||
RecordBeginTime string | |||||
}{} | }{} | ||||
) | ) | ||||
@@ -1324,6 +1325,7 @@ func SetRadarMapConfig() { | |||||
RadarMap.GrowthContributors = sec.Key("growth_contributors").MustFloat64(0.2) | RadarMap.GrowthContributors = sec.Key("growth_contributors").MustFloat64(0.2) | ||||
RadarMap.GrowthCommit = sec.Key("growth_commit").MustFloat64(0.2) | RadarMap.GrowthCommit = sec.Key("growth_commit").MustFloat64(0.2) | ||||
RadarMap.GrowthComments = sec.Key("growth_comments").MustFloat64(0.2) | RadarMap.GrowthComments = sec.Key("growth_comments").MustFloat64(0.2) | ||||
RadarMap.RecordBeginTime = sec.Key("record_beigin_time").MustString("2021-11-04") | |||||
} | } | ||||
@@ -785,7 +785,12 @@ cloudbrain_operate = Operate | |||||
cloudbrain_status_createtime = Status/Createtime | cloudbrain_status_createtime = Status/Createtime | ||||
cloudbrain_status_runtime = Running Time | cloudbrain_status_runtime = Running Time | ||||
record_begintime_get_err=Can not get the record begin time. | |||||
parameter_is_wrong=The input parameter is wrong. | |||||
total_count_get_error=Can not get the total page. | |||||
last_update_time_error=Can not get the last updated time. | |||||
get_repo_stat_error=Can not get the statistics of the repository. | |||||
get_repo_info_error=Can not get the information of the repository. | |||||
modelarts.notebook=Debug Task | modelarts.notebook=Debug Task | ||||
modelarts.train_job=Train Task | modelarts.train_job=Train Task | ||||
modelarts.train_job.new_debug= New Debug Task | modelarts.train_job.new_debug= New Debug Task | ||||
@@ -787,6 +787,12 @@ cloudbrain_status_createtime=状态/创建时间 | |||||
cloudbrain_status_runtime = 运行时长 | cloudbrain_status_runtime = 运行时长 | ||||
cloudbrain_jobname_err=只能以小写字母或数字开头且只包含小写字母、数字、_和-,不能以_结尾,最长36个字符。 | cloudbrain_jobname_err=只能以小写字母或数字开头且只包含小写字母、数字、_和-,不能以_结尾,最长36个字符。 | ||||
record_begintime_get_err=无法获取统计开始时间。 | |||||
parameter_is_wrong=输入参数错误,请检查输入参数。 | |||||
total_count_get_error=查询总页数失败。 | |||||
last_update_time_error=查询最新更新时间失败。 | |||||
get_repo_stat_error=查询当前仓库的统计信息失败。 | |||||
get_repo_info_error=查询当前仓库信息失败。 | |||||
modelarts.notebook=调试任务 | modelarts.notebook=调试任务 | ||||
modelarts.train_job=训练任务 | modelarts.train_job=训练任务 | ||||
modelarts.train_job.new_debug=新建调试任务 | modelarts.train_job.new_debug=新建调试任务 | ||||
@@ -523,6 +523,19 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
Get(notify.GetThread). | Get(notify.GetThread). | ||||
Patch(notify.ReadThread) | Patch(notify.ReadThread) | ||||
}, reqToken()) | }, reqToken()) | ||||
adminReq := context.Toggle(&context.ToggleOptions{SignInRequired: true, AdminRequired: true}) | |||||
//Project board | |||||
m.Group("/projectboard", func() { | |||||
m.Group("/project", func() { | |||||
m.Get("", adminReq, repo.GetAllProjectsPeriodStatistics) | |||||
m.Group("/:id", func() { | |||||
m.Get("", adminReq, repo.GetProjectLatestStatistics) | |||||
m.Get("/period", adminReq, repo.GetProjectPeriodStatistics) | |||||
}) | |||||
}) | |||||
}) | |||||
// Users | // Users | ||||
m.Group("/users", func() { | m.Group("/users", func() { | ||||
@@ -0,0 +1,362 @@ | |||||
package repo | |||||
import ( | |||||
"fmt" | |||||
"net/http" | |||||
"strconv" | |||||
"time" | |||||
"code.gitea.io/gitea/models" | |||||
"code.gitea.io/gitea/modules/log" | |||||
"code.gitea.io/gitea/modules/context" | |||||
"code.gitea.io/gitea/modules/setting" | |||||
) | |||||
const DEFAULT_PAGE_SIZE = 10 | |||||
const DATE_FORMAT = "2006-01-02" | |||||
type ProjectsPeriodData struct { | |||||
RecordBeginTime string `json:"recordBeginTime"` | |||||
LastUpdatedTime string `json:"lastUpdatedTime"` | |||||
PageSize int `json:"pageSize"` | |||||
TotalPage int `json:"totalPage"` | |||||
PageRecords []*models.RepoStatistic `json:"pageRecords"` | |||||
} | |||||
type UserInfo struct { | |||||
User string `json:"user"` | |||||
Mode int `json:"mode"` | |||||
PR int64 `json:"pr"` | |||||
Commit int `json:"commit"` | |||||
} | |||||
type ProjectLatestData struct { | |||||
RecordBeginTime string `json:"recordBeginTime"` | |||||
LastUpdatedTime string `json:"lastUpdatedTime"` | |||||
CreatTime string `json:"creatTime"` | |||||
OpenI float64 `json:"openi"` | |||||
Comment int64 `json:"comment"` | |||||
View int64 `json:"view"` | |||||
Download int64 `json:"download"` | |||||
IssueClosedRatio float32 `json:"issueClosedRatio"` | |||||
Impact float64 `json:"impact"` | |||||
Completeness float64 `json:"completeness"` | |||||
Liveness float64 `json:"liveness"` | |||||
ProjectHealth float64 `json:"projectHealth"` | |||||
TeamHealth float64 `json:"teamHealth"` | |||||
Growth float64 `json:"growth"` | |||||
Description string `json:"description"` | |||||
Top10 []UserInfo `json:"top10"` | |||||
} | |||||
func GetAllProjectsPeriodStatistics(ctx *context.Context) { | |||||
recordBeginTime, err := getRecordBeginTime() | |||||
if err != nil { | |||||
log.Error("Can not get record begin time", err) | |||||
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) | |||||
return | |||||
} | |||||
beginTime, endTime, err := getTimePeroid(ctx, recordBeginTime) | |||||
if err != nil { | |||||
log.Error("Parameter is wrong", err) | |||||
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.parameter_is_wrong")) | |||||
return | |||||
} | |||||
q := ctx.QueryTrim("q") | |||||
page := ctx.QueryInt("page") | |||||
if page <= 0 { | |||||
page = 1 | |||||
} | |||||
pageSize := ctx.QueryInt("pagesize") | |||||
if pageSize <= 0 { | |||||
pageSize = DEFAULT_PAGE_SIZE | |||||
} | |||||
orderBy := getOrderBy(ctx) | |||||
latestUpdatedTime, latestDate, err := models.GetRepoStatLastUpdatedTime() | |||||
if err != nil { | |||||
log.Error("Can not query the last updated time.", err) | |||||
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.last_update_time_error")) | |||||
return | |||||
} | |||||
countSql := generateCountSql(beginTime, endTime, latestDate, q) | |||||
total, err := models.CountRepoStatByRawSql(countSql) | |||||
if err != nil { | |||||
log.Error("Can not query total count.", err) | |||||
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.total_count_get_error")) | |||||
return | |||||
} | |||||
projectsPeriodData := ProjectsPeriodData{ | |||||
RecordBeginTime: recordBeginTime.Format(DATE_FORMAT), | |||||
PageSize: pageSize, | |||||
TotalPage: getTotalPage(total, pageSize), | |||||
LastUpdatedTime: latestUpdatedTime, | |||||
PageRecords: models.GetRepoStatisticByRawSql(generatePageSql(beginTime, endTime, latestDate, q, orderBy, page, pageSize)), | |||||
} | |||||
ctx.JSON(http.StatusOK, projectsPeriodData) | |||||
} | |||||
func GetProjectLatestStatistics(ctx *context.Context) { | |||||
repoId := ctx.Params(":id") | |||||
recordBeginTime, err := getRecordBeginTime() | |||||
if err != nil { | |||||
log.Error("Can not get record begin time", err) | |||||
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) | |||||
return | |||||
} | |||||
latestUpdatedTime, latestDate, err := models.GetRepoStatLastUpdatedTime(repoId) | |||||
repoIdInt, _ := strconv.ParseInt(repoId, 10, 64) | |||||
repoStat, err := models.GetRepoStatisticByDateAndRepoId(latestDate, repoIdInt) | |||||
if err != nil { | |||||
log.Error("Can not get the repo statistics "+repoId, err) | |||||
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.get_repo_stat_error")) | |||||
return | |||||
} | |||||
repository, err := models.GetRepositoryByID(repoIdInt) | |||||
if err != nil { | |||||
log.Error("Can not get the repo info "+repoId, err) | |||||
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.get_repo_info_error")) | |||||
return | |||||
} | |||||
projectLatestData := ProjectLatestData{ | |||||
RecordBeginTime: recordBeginTime.Format(DATE_FORMAT), | |||||
CreatTime: time.Unix(int64(repository.CreatedUnix), 0).Format(DATE_FORMAT), | |||||
LastUpdatedTime: latestUpdatedTime, | |||||
OpenI: repoStat.RadarTotal, | |||||
Comment: repoStat.NumComments, | |||||
View: repoStat.NumVisits, | |||||
Download: repoStat.NumDownloads, | |||||
IssueClosedRatio: repoStat.IssueFixedRate, | |||||
Impact: repoStat.Impact, | |||||
Completeness: repoStat.Completeness, | |||||
Liveness: repoStat.Liveness, | |||||
ProjectHealth: repoStat.ProjectHealth, | |||||
TeamHealth: repoStat.TeamHealth, | |||||
Growth: repoStat.Growth, | |||||
Description: repository.Description, | |||||
} | |||||
contributors, err := models.GetTop10Contributor(repository.RepoPath()) | |||||
if err != nil { | |||||
log.Error("can not get contributors", err) | |||||
} | |||||
users := make([]UserInfo, 0) | |||||
for _, contributor := range contributors { | |||||
mode := repository.GetCollaboratorMode(contributor.UserId) | |||||
pr := models.GetPullCountByUserAndRepoId(repoIdInt, contributor.UserId) | |||||
userInfo := UserInfo{ | |||||
User: contributor.Committer, | |||||
Commit: contributor.CommitCnt, | |||||
Mode: mode, | |||||
PR: pr, | |||||
} | |||||
users = append(users, userInfo) | |||||
} | |||||
projectLatestData.Top10 = users | |||||
ctx.JSON(http.StatusOK, projectLatestData) | |||||
} | |||||
func GetProjectPeriodStatistics(ctx *context.Context) { | |||||
repoId := ctx.Params(":id") | |||||
recordBeginTime, err := getRecordBeginTime() | |||||
if err != nil { | |||||
log.Error("Can not get record begin time", err) | |||||
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) | |||||
return | |||||
} | |||||
repoIdInt, _ := strconv.ParseInt(repoId, 10, 64) | |||||
if err != nil { | |||||
log.Error("Can not get record begin time", err) | |||||
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) | |||||
return | |||||
} | |||||
beginTime, endTime, err := getTimePeroid(ctx, recordBeginTime) | |||||
isOpenI := ctx.QueryBool("openi") | |||||
var repositorys []*models.RepoStatistic | |||||
if isOpenI { | |||||
repositorys = models.GetRepoStatisticByRawSql(generateRadarSql(beginTime, endTime, repoIdInt)) | |||||
} else { | |||||
repositorys = models.GetRepoStatisticByRawSql(generateTargetSql(beginTime, endTime, repoIdInt)) | |||||
} | |||||
ctx.JSON(http.StatusOK, repositorys) | |||||
} | |||||
func generateRadarSql(beginTime time.Time, endTime time.Time, repoId int64) string { | |||||
sql := "SELECT date, impact, completeness, liveness, project_health, team_health, growth, radar_total FROM repo_statistic" + | |||||
" where repo_id=" + strconv.FormatInt(repoId, 10) + " and created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) | |||||
return sql | |||||
} | |||||
func generateTargetSql(beginTime time.Time, endTime time.Time, repoId int64) string { | |||||
sql := "SELECT date, num_visits,num_downloads,num_commits FROM repo_statistic" + | |||||
" where repo_id=" + strconv.FormatInt(repoId, 10) + " and created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) | |||||
return sql | |||||
} | |||||
func generateCountSql(beginTime time.Time, endTime time.Time, yesterday string, q string) string { | |||||
countSql := "SELECT count(*) FROM " + | |||||
"(SELECT repo_id FROM repo_statistic where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + " group by repo_id) A," + | |||||
"(SELECT repo_id,name,is_private,radar_total from public.repo_statistic where date='" + yesterday + "') B" + | |||||
" where A.repo_id=B.repo_id" | |||||
if q != "" { | |||||
countSql = countSql + " and B.name like '%" + q + "%'" | |||||
} | |||||
return countSql | |||||
} | |||||
func generatePageSql(beginTime time.Time, endTime time.Time, yesterday string, q string, orderBy string, page int, pageSize int) string { | |||||
countSql := "SELECT A.repo_id,name,is_private,radar_total,num_watches,num_visits,num_downloads,num_pulls,num_commits,num_stars,num_forks,num_issues,num_closed_issues,num_contributor FROM " + | |||||
"(SELECT repo_id,sum(num_watches_added) as num_watches,sum(num_visits) as num_visits, sum(num_downloads_added) as num_downloads,sum(num_pulls_added) as num_pulls,sum(num_commits_added) as num_commits,sum(num_stars_added) as num_stars,sum(num_forks_added) num_forks,sum(num_issues_added) as num_issues,sum(num_closed_issues_added) as num_closed_issues,sum(num_contributor_added) as num_contributor " + | |||||
" FROM repo_statistic where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) + | |||||
" and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + " group by repo_id) A," + | |||||
"(SELECT repo_id,name,is_private,radar_total from public.repo_statistic where date='" + yesterday + "') B" + | |||||
" where A.repo_id=B.repo_id" | |||||
if q != "" { | |||||
countSql = countSql + " and B.name like '%" + q + "%'" | |||||
} | |||||
countSql = countSql + " order by " + orderBy + " desc,A.repo_id" + " limit " + strconv.Itoa(pageSize) + " offset " + strconv.Itoa((page-1)*pageSize) | |||||
return countSql | |||||
} | |||||
func getOrderBy(ctx *context.Context) string { | |||||
orderBy := "" | |||||
switch ctx.Query("sort") { | |||||
case "openi": | |||||
orderBy = "B.radar_total" | |||||
case "view": | |||||
orderBy = "A.num_visits" | |||||
case "download": | |||||
orderBy = "A.num_downloads" | |||||
case "pr": | |||||
orderBy = "A.num_pulls" | |||||
case "commit": | |||||
orderBy = "A.num_commits" | |||||
case "watch": | |||||
orderBy = "A.num_watches" | |||||
case "star": | |||||
orderBy = "A.num_stars" | |||||
case "fork": | |||||
orderBy = "A.num_forks" | |||||
case "issue": | |||||
orderBy = "A.num_issues" | |||||
case "issue_closed": | |||||
orderBy = "A.num_closed_issues" | |||||
case "contributor": | |||||
orderBy = "A.num_contributor" | |||||
default: | |||||
orderBy = "B.radar_total" | |||||
} | |||||
return orderBy | |||||
} | |||||
func getTimePeroid(ctx *context.Context, recordBeginTime time.Time) (time.Time, time.Time, error) { | |||||
queryType := ctx.QueryTrim("type") | |||||
now := time.Now() | |||||
recordBeginTimeTemp := recordBeginTime.AddDate(0, 0, 1) | |||||
beginTimeStr := ctx.QueryTrim("beginTime") | |||||
endTimeStr := ctx.QueryTrim("endTime") | |||||
var beginTime time.Time | |||||
var endTime time.Time | |||||
if queryType != "" { | |||||
if queryType == "all" { | |||||
beginTime = recordBeginTimeTemp | |||||
endTime = now | |||||
} else if queryType == "yesterday" { | |||||
endTime = now | |||||
beginTime = time.Date(endTime.Year(), endTime.Month(), endTime.Day(), 0, 0, 0, 0, now.Location()) | |||||
} else if queryType == "current_week" { | |||||
beginTime = now.AddDate(0, 0, -int(time.Now().Weekday())+1) | |||||
beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location()) | |||||
endTime = now | |||||
} else if queryType == "current_month" { | |||||
endTime = now | |||||
beginTime = time.Date(endTime.Year(), endTime.Month(), 2, 0, 0, 0, 0, now.Location()) | |||||
} else if queryType == "monthly" { | |||||
endTime = now | |||||
beginTime = now.AddDate(0, -1, 1) | |||||
beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location()) | |||||
} else if queryType == "current_year" { | |||||
endTime = now | |||||
beginTime = time.Date(endTime.Year(), 1, 2, 0, 0, 0, 0, now.Location()) | |||||
} else if queryType == "last_month" { | |||||
lastMonthTime := now.AddDate(0, -1, 0) | |||||
beginTime = time.Date(lastMonthTime.Year(), lastMonthTime.Month(), 2, 0, 0, 0, 0, now.Location()) | |||||
endTime = time.Date(now.Year(), now.Month(), 2, 0, 0, 0, 0, now.Location()) | |||||
} else { | |||||
return now, now, fmt.Errorf("The value of type parameter is wrong.") | |||||
} | |||||
} else { | |||||
if beginTimeStr == "" || endTimeStr == "" { | |||||
//如果查询类型和开始时间结束时间都未设置,按queryType=all处理 | |||||
beginTime = recordBeginTimeTemp | |||||
endTime = now | |||||
} else { | |||||
beginTime, err := time.Parse("2006-01-02", beginTimeStr) | |||||
if err != nil { | |||||
return now, now, err | |||||
} | |||||
endTime, err := time.Parse("2006-01-02", endTimeStr) | |||||
if err != nil { | |||||
return now, now, err | |||||
} | |||||
beginTime = beginTime.AddDate(0, 0, 1) | |||||
endTime = endTime.AddDate(0, 0, 1) | |||||
} | |||||
} | |||||
if beginTime.Before(recordBeginTimeTemp) { | |||||
beginTime = recordBeginTimeTemp | |||||
} | |||||
return beginTime, endTime, nil | |||||
} | |||||
func getRecordBeginTime() (time.Time, error) { | |||||
return time.Parse(DATE_FORMAT, setting.RadarMap.RecordBeginTime) | |||||
} | |||||
func getTotalPage(total int64, pageSize int) int { | |||||
another := 0 | |||||
if int(total)%pageSize != 0 { | |||||
another = 1 | |||||
} | |||||
return int(total)/pageSize + another | |||||
} |
@@ -146,7 +146,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { | |||||
ctx.Data["SortType"] = "hot" | ctx.Data["SortType"] = "hot" | ||||
orderBy = models.SearchOrderByHot | orderBy = models.SearchOrderByHot | ||||
} | } | ||||
orderBy = orderBy + ",id" | |||||
//todo:support other topics | //todo:support other topics | ||||
keyword := strings.Trim(ctx.Query("q"), " ") | keyword := strings.Trim(ctx.Query("q"), " ") | ||||
topic := strings.Trim(ctx.Query("topic"), " ") | topic := strings.Trim(ctx.Query("topic"), " ") | ||||
@@ -1020,7 +1020,7 @@ func queryDatasets(ctx *context.Context, attachs []*models.AttachmentUsername) { | |||||
} | } | ||||
func checkTypeCloudBrain(typeCloudBrain int) error { | func checkTypeCloudBrain(typeCloudBrain int) error { | ||||
if typeCloudBrain != models.TypeCloudBrainOne && typeCloudBrain != models.TypeCloudBrainNotebook { | |||||
if typeCloudBrain != models.TypeCloudBrainOne && typeCloudBrain != models.TypeCloudBrainTwo { | |||||
log.Error("type error:", typeCloudBrain) | log.Error("type error:", typeCloudBrain) | ||||
return errors.New("type error") | return errors.New("type error") | ||||
} | } | ||||
@@ -287,7 +287,8 @@ func NotebookIndex(ctx *context.Context) { | |||||
PageSize: setting.UI.IssuePagingNum, | PageSize: setting.UI.IssuePagingNum, | ||||
}, | }, | ||||
RepoID: repo.ID, | RepoID: repo.ID, | ||||
Type: models.TypeCloudBrainNotebook, | |||||
Type: models.TypeCloudBrainTwo, | |||||
JobType: string(models.JobTypeDebug), | |||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("Cloudbrain", err) | ctx.ServerError("Cloudbrain", err) | ||||
@@ -512,7 +513,8 @@ func TrainJobIndex(ctx *context.Context) { | |||||
PageSize: setting.UI.IssuePagingNum, | PageSize: setting.UI.IssuePagingNum, | ||||
}, | }, | ||||
RepoID: repo.ID, | RepoID: repo.ID, | ||||
Type: models.TypeCloudBrainTrainJob, | |||||
Type: models.TypeCloudBrainTwo, | |||||
JobType: string(models.JobTypeTrain), | |||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("Cloudbrain", err) | ctx.ServerError("Cloudbrain", err) | ||||
@@ -355,7 +355,7 @@ | |||||
<form id="stopForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/stop" method="post" style="margin-left:-1px;"> | <form id="stopForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/stop" method="post" style="margin-left:-1px;"> | ||||
{{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | {{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | ||||
<a id="stop-model-debug-{{.JobID}}" class="ui basic {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING"}}disabled {{else}}blue {{end}}button" onclick="document.getElementById('stopForm-{{.JobID}}').submit();"> | |||||
<a id="stop-model-debug-{{.JobID}}" class="ui basic {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED"}}disabled {{else}}blue {{end}}button" onclick="document.getElementById('stopForm-{{.JobID}}').submit();"> | |||||
{{$.i18n.Tr "repo.stop"}} | {{$.i18n.Tr "repo.stop"}} | ||||
</a> | </a> | ||||
{{else}} | {{else}} | ||||