Files
go-common/app/service/ep/footman/service/tapd.go
2019-04-22 18:49:16 +08:00

303 lines
10 KiB
Go

package service
import (
"bytes"
"fmt"
"regexp"
"strconv"
"strings"
"time"
"go-common/app/service/ep/footman/model"
"go-common/library/log"
)
//storyChangeByIteration get stories and story changes for input iterations
func (s *Service) storyChangeByIteration(iterationRes *model.IterationResponse, workspaceID, pattern string, sps, scps int) (iterations []*model.StoryChangeByIteration, err error) {
var (
storyRes *model.StoryResponse
storyChangeRes *model.StoryChangeResponse
)
iterations = make([]*model.StoryChangeByIteration, 0, 5)
for _, itera := range iterationRes.Data {
sci := &model.StoryChangeByIteration{}
sci.IterationName = itera.Iteration.Name
storyURL := fmt.Sprintf(model.StoryURL, workspaceID, itera.Iteration.ID, sps) + "&page=%d"
log.Info("Story:" + fmt.Sprintf(model.StoryURL, workspaceID, itera.Iteration.ID, sps))
if storyRes, err = s.dao.AllStories(sps, storyURL); err != nil {
return
}
if storyRes == nil {
continue
}
storyChanges := make([]*model.TargetStoryChange, 0, 5)
if len(storyRes.Data) == 0 {
continue
}
for _, story := range storyRes.Data {
change := &model.TargetStoryChange{}
change.Story = story.Story
storyChangeURL := fmt.Sprintf(model.StoryChangeURL, workspaceID, change.Story.ID, scps) + "&page=%d"
if storyChangeRes, err = s.dao.AllStoryChanges(scps, storyChangeURL); err != nil {
return
}
if storyChangeRes == nil {
continue
}
statusChanges := make([]*model.StatusChange, 0, 5)
for _, change := range storyChangeRes.Data {
reg := regexp.MustCompile(pattern)
fields := reg.FindStringSubmatch(change.WorkitemChange.Changes)
if len(fields) >= 1 {
statusChange := &model.StatusChange{}
statusChange.Created = change.WorkitemChange.Created
statusChange.Creator = change.WorkitemChange.Creator
statusChange.ValueBefore = fields[2]
statusChange.ValueAfter = fields[4]
statusChanges = append(statusChanges, statusChange)
}
}
change.StatusChanges = statusChanges
storyChanges = append(storyChanges, change)
}
sci.StoryChangeList = storyChanges
sci.StoryCount = len(storyChanges)
iterations = append(iterations, sci)
}
return
}
//storyChangeByIterationWithName get stories and story changes for input iteration name
func (s *Service) storyChangeByIterationWithName(workspaceID, iterationName, pattern string, ips, sps, scps int) (iterations []*model.StoryChangeByIteration, err error) {
var (
iterationRes *model.IterationResponse
)
iterationURL := fmt.Sprintf(model.IterationURL, workspaceID, iterationName, ips) + "&page=%d"
log.Info("Iteration:" + fmt.Sprintf(model.IterationURL, workspaceID, iterationName, ips))
if iterationRes, err = s.dao.AllIterations(ips, iterationURL); err != nil || len(iterationRes.Data) == 0 {
return
}
return s.storyChangeByIteration(iterationRes, workspaceID, pattern, sps, scps)
}
//testTimeByIteration get test time data from story changes
func (s *Service) testTimeByIteration(scis []*model.StoryChangeByIteration, workspaceType, testType string) (iterations []*model.TestTimeByIteration, err error) {
iterations = make([]*model.TestTimeByIteration, 0, 5)
for _, sci := range scis {
itera := &model.TestTimeByIteration{}
itera.IterationName = sci.IterationName
stories := make([]*model.TestTimeByStory, 0, 5)
for _, story := range sci.StoryChangeList {
ts := &model.TestTimeByStory{}
ts.StoryName = story.Story.Name
ts.StorySize = story.Story.Size
ts.StoryEffort = story.Story.Effort
found := 0
var t1, t2 *time.Time
var starttime, endtime time.Time
total := 0.0
for _, change := range story.StatusChanges {
var condition1, condition2 bool
if workspaceType == model.Android && testType == model.Test {
condition1 = change.ValueBefore == "testing" && (change.ValueAfter == "developing" || change.ValueAfter == "status_6" || change.ValueAfter == "product_experience")
condition2 = change.ValueBefore == "status_5" && change.ValueAfter == "testing" && found == 1
}
if workspaceType == model.IOS && testType == model.Test {
condition1 = change.ValueBefore == "testing" && (change.ValueAfter == "developing" || change.ValueAfter == "status_7" || change.ValueAfter == "product_experience")
condition2 = change.ValueBefore == "status_5" && change.ValueAfter == "testing" && found == 1
}
if testType == model.Experience {
condition1 = change.ValueBefore == "product_experience" && (change.ValueAfter == "developing" || change.ValueAfter == "status_5")
condition2 = change.ValueBefore == "developing" && change.ValueAfter == "product_experience" && found == 1
}
if condition1 {
if starttime, err = s.stringToTime(change.Created); err != nil {
return
}
found = 1
t1 = &starttime
} else if condition2 {
if endtime, err = s.stringToTime(change.Created); err != nil {
return
}
found = 2
t2 = &endtime
} else {
found = 0
t1 = nil
}
if t1 != nil && t2 != nil {
total = total + t1.Sub(*t2).Hours() - float64(s.weekendDays(t1, t2)*24)
t1 = nil
t2 = nil
}
}
if ts.TestTime, err = strconv.ParseFloat(strconv.FormatFloat(total, 'f', 2, 64), 64); err != nil {
return
}
stories = append(stories, ts)
}
itera.TimeByStroy = stories
itera.StoryCount = len(stories)
iterations = append(iterations, itera)
}
return
}
//rejectedStoryByIteration get rejected stories
func (s *Service) rejectedStoryByIteration(scis []*model.StoryChangeByIteration, workspaceType, rejectType string) (iterations []*model.RejectedStoryByIteration, err error) {
iterations = make([]*model.RejectedStoryByIteration, 0, 5)
for _, sci := range scis {
itera := &model.RejectedStoryByIteration{}
itera.IterationName = sci.IterationName
stories := make([]string, 0, 5)
for _, story := range sci.StoryChangeList {
for _, change := range story.StatusChanges {
var condition bool
if (workspaceType == model.Android || workspaceType == model.IOS) && rejectType == model.Test {
condition = change.ValueBefore == "testing" && (change.ValueAfter == "developing" || change.ValueAfter == "product_experience")
}
if (workspaceType == model.Android || workspaceType == model.IOS) && rejectType == model.Experience {
condition = change.ValueBefore == "product_experience" && change.ValueAfter == "developing"
}
if condition {
stories = append(stories, story.Story.Name)
break
}
}
}
itera.RejectedStoryList = stories
itera.RejectedStoryCount = len(stories)
iterations = append(iterations, itera)
}
return
}
//waitTimeByIteration get wait time data from story changes
func (s *Service) waitTimeByIteration(scis []*model.StoryChangeByIteration, waitType string) (iterations []*model.WaitTimeByIteration, err error) {
iterations = make([]*model.WaitTimeByIteration, 0, 5)
for _, sci := range scis {
itera := &model.WaitTimeByIteration{}
itera.IterationName = sci.IterationName
stories := make([]*model.WaitTimeByStory, 0, 5)
for _, story := range sci.StoryChangeList {
ws := &model.WaitTimeByStory{}
ws.StoryName = story.Story.Name
ws.StorySize = story.Story.Size
ws.StoryEffort = story.Story.Effort
found := 0
var t1, t2 *time.Time
var starttime, endtime time.Time
total := 0.0
for _, change := range story.StatusChanges {
var condition1, condition2 bool
if waitType == model.Test {
condition1 = change.ValueBefore == "status_5" && change.ValueAfter == "testing"
condition2 = change.ValueBefore == "product_experience" && change.ValueAfter == "status_5" && found == 1
}
if condition1 {
if starttime, err = s.stringToTime(change.Created); err != nil {
return
}
found = 1
t1 = &starttime
} else if condition2 {
if endtime, err = s.stringToTime(change.Created); err != nil {
return
}
found = 2
t2 = &endtime
} else {
found = 0
t1 = nil
}
if t1 != nil && t2 != nil {
total = t1.Sub(*t2).Hours() - float64(s.weekendDays(t1, t2)*24)
break
}
}
if ws.WaitTime, err = strconv.ParseFloat(strconv.FormatFloat(total, 'f', 2, 64), 64); err != nil {
return
}
stories = append(stories, ws)
}
itera.TimeByStroy = stories
itera.StoryCount = len(stories)
iterations = append(iterations, itera)
}
return
}
//storyChangeItems get story change items
func (s *Service) storyChangeItems(workspaceID, storyID, pattern string, scps int) (changes []*model.StoryChangeItem, err error) {
storyChangeURL := fmt.Sprintf(model.StoryChangeURL, workspaceID, storyID, scps) + "&page=%d"
var storyChangeRes *model.StoryChangeResponse
if storyChangeRes, err = s.dao.AllStoryChanges(scps, storyChangeURL); err != nil || storyChangeRes == nil {
return
}
for k, v := range storyChangeRes.Data {
reg := regexp.MustCompile(pattern)
changeStrList := strings.Split(s.unicode2Chinese(v.WorkitemChange.Changes), "},{")
for _, changeStr := range changeStrList {
fields := reg.FindStringSubmatch(changeStr)
if len(fields) >= 1 {
change := &model.StoryChangeItem{}
change.ID = v.WorkitemChange.ID
change.ChangeSummay = v.WorkitemChange.ChangeSummay
change.Comment = v.WorkitemChange.Comment
change.EntityType = v.WorkitemChange.EntityType
change.Number = strconv.Itoa(k)
change.StoryID = v.WorkitemChange.StoryID
change.WorkspaceID = v.WorkitemChange.WorkspaceID
change.Created = v.WorkitemChange.Created
change.Creator = v.WorkitemChange.Creator
change.Field = fields[2]
if fields[2] != "description" {
change.ValueBefore = fields[4]
change.ValueAfter = fields[6]
}
changes = append(changes, change)
}
}
}
return
}
func (s *Service) unicode2Chinese(str string) string {
buf := bytes.NewBuffer(nil)
i, j := 0, len(str)
for i < j {
x := i + 6
if x > j {
buf.WriteString(str[i:])
break
}
if str[i] == '\\' && str[i+1] == 'u' {
hex := str[i+2 : x]
r, err := strconv.ParseUint(hex, 16, 64)
if err == nil {
buf.WriteRune(rune(r))
} else {
buf.WriteString(str[i:x])
}
i = x
} else {
buf.WriteByte(str[i])
i++
}
}
return buf.String()
}