func RegisterThreadImg(r *RequestTakePictureStatus) (*RequestTakePictureStatus, error) {
	l.PutInfo(l.I_M_RegisterCol, r, nil)

	defer SetPlayerCol([]string{r.UserId})

	if len(r.ThreadId) == 0 {
		return nil, errors.New("there is not thread id")
	}

	if len(r.PhotoUrl) == 0 {
		return nil, errors.New("there is not pthoto url ")
	}

	threadFindQuery := bson.M{"threadid": r.ThreadId}
	threadSetQuery := bson.M{"$set": bson.M{"imgurl": r.PhotoUrl}}
	if err = UpdateMongoData("thread", threadFindQuery, threadSetQuery); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_Update, r.PhotoUrl)
		return &RequestTakePictureStatus{Status: "failed"}, err
	}

	var photoKey string
	if r.Positive {
		photoKey = "positivephotourl"
	} else {
		photoKey = "negativephotourl"
	}
	playerFindQuery := bson.M{"userid": r.UserId}
	playerSetQuery := bson.M{"$set": bson.M{photoKey: r.PhotoUrl}}

	if err = UpdateMongoData("player", playerFindQuery, playerSetQuery); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_Update, r.PhotoUrl)
		return &RequestTakePictureStatus{Status: "failed"}, err
	}

	SetAllThreadCol()
	thread := &Thread{
		ThreadId:  r.ThreadId,
		UserId:    threads[r.ThreadId].UserId,
		UserName:  threads[r.ThreadId].UserName,
		Msg:       threads[r.ThreadId].Msg,
		ImgUrl:    threads[r.ThreadId].ImgUrl,
		ColorCode: threads[r.ThreadId].ColorCode,
		Positive:  threads[r.ThreadId].Positive,
		CreatedAt: threads[r.ThreadId].CreatedAt,
	}

	ThreadChan <- thread

	requestTakePictureStatus, err := RequestTakePicture(r.TeamUserIds)
	if err != nil {
		return nil, err
	}

	if len(requestTakePictureStatus.ThreadId) != 0 {
		return requestTakePictureStatus, nil
	}

	return &RequestTakePictureStatus{Status: "success"}, nil

}
func UpsertNewTimeLine(thread *Thread) error {
	l.PutInfo(l.I_M_PostPage, thread, nil)

	//更新情報をGlobal変数に格納する
	defer SetAllThreadCol()

	defaultColor := "#c0c0c0"

	if len(thread.ThreadId) != 0 {
		l.PutErr(nil, l.Trace(), l.E_WrongData, thread)
		return errors.New("thread id exists")
	}

	db, session := mongoConn()
	threadCol := db.C("thread")
	defer session.Close()

	thread.ThreadId = make20lengthHashString()
	thread.CreatedAt = time.Now().Format(c.DatetimeFormat)
	thread.ColorCode = defaultColor
	if err = threadCol.Insert(thread); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_Insert, thread)
		return err
	}

	ThreadChan <- thread

	return nil
}
func RegisterFieldColData(date string, fieldCols []FieldCol) (*Status, error) {
	l.PutInfo(l.I_M_RegisterCol, date, fieldCols)

	defer SetAllFieldCol()

	db, session := mongoConn()
	fieldC := db.C("field")
	defer session.Close()

	var createCnt, updateCnt int
	for _, fieldCol := range fieldCols {
		if fieldCol.Hole > 18 || fieldCol.Hole < 0 {
			l.PutErr(nil, l.Trace(), l.E_WrongData, fieldCol.Hole)
			return &Status{"this is not hole number"}, err
		}

		fieldCol.Ignore = false
		fieldCol.Date = date
		findQuery := bson.M{"hole": fieldCol.Hole}

		change, err := fieldC.Upsert(findQuery, fieldCol)
		if err != nil {
			l.PutErr(err, l.Trace(), l.E_M_Upsert, fieldCol.Hole)
			return &Status{"can not upsert"}, err
		}
		if change.Updated == 0 {
			createCnt += 1
		} else {
			updateCnt += 1
		}
	}

	return &Status{"success"}, nil
}
func RegisterTeamColData(date string, teamCols []TeamCol) (*Status, error) {
	l.PutInfo(l.I_M_RegisterCol, date, teamCols)

	defer SetAllPlayerCol()
	defer SetAllTeamCol()

	db, session := mongoConn()
	playerC := db.C("player")
	teamC := db.C("team")
	defer session.Close()

	var OneBeforebyteOfA byte = 64
	alphabet := make([]byte, 1)
	alphabet[0] = OneBeforebyteOfA

	totalHoleNum := 18

	for _, teamCol := range teamCols {
		if len(teamCol.UserIds) == 0 {
			l.PutErr(nil, l.Trace(), l.E_Nil, teamCol)
			return &Status{"this team do not have user id"}, nil
		}

		alphabet[0] += 1
		teamCol.Name = string(alphabet)
		teamCol.Defined = false
		teamCol.Date = date

		if err := teamC.Insert(teamCol); err != nil {
			l.PutErr(err, l.Trace(), l.E_M_Insert, teamCol)
			return &Status{"can not insert"}, err
		}

		for _, userId := range teamCol.UserIds {
			scores := []bson.M{}
			for holeNum := 1; holeNum <= totalHoleNum; holeNum++ {
				score := bson.M{
					"hole":  holeNum,
					"putt":  0,
					"total": 0,
				}
				scores = append(scores, score)

			}

			player := PlayerCol{
				UserId: userId,
				Score:  scores,
				Date:   date,
			}
			if err := playerC.Insert(player); err != nil {
				l.PutErr(err, l.Trace(), l.E_M_Insert, player)
				return &Status{"can not insert"}, err
			}
		}
	}
	return &Status{"success"}, nil
}
func PostScoreEntrySheetPageData(teamName string, holeString string, teamScore *PostTeamScore) (*RequestTakePictureStatus, error) {
	l.PutInfo(l.I_M_PostPage, teamName, teamScore)

	userIds := teams[teamName].UserIds
	//更新情報をGlobal変数に格納する
	defer SetPlayerCol(userIds)

	if len(holeString) == 0 {
		l.PutErr(nil, l.Trace(), l.E_Nil, teamName)
		return &RequestTakePictureStatus{Status: "failed"}, errors.New("hole is not string")
	}

	holeNum, _ := strconv.Atoi(holeString)
	holeIndex := holeNum - 1
	holeIndexString := strconv.Itoa(holeIndex)

	if teamScore.Excnt != excnt[teamName][holeNum] {
		return &RequestTakePictureStatus{Status: "other updated"}, nil
	} else {
		excnt[teamName][holeNum]++
	}

	for playerIndex, userId := range teamScore.UserIds {
		total, putt := teamScore.Total[playerIndex], teamScore.Putt[playerIndex]

		findQuery := bson.M{"userid": userId}
		setQuery := bson.M{
			"$set": bson.M{
				"score." + holeIndexString + ".total": total,
				"score." + holeIndexString + ".putt":  putt,
			},
		}
		if err = UpdateMongoData("player", findQuery, setQuery); err != nil {
			l.PutErr(err, l.Trace(), l.E_M_Update, userId)
			return &RequestTakePictureStatus{Status: "failed update score"}, err
		}
	}
	//	Thread登録
	if err := RegisterThreadOfScore(holeString, teamScore); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_RegisterThread, teamScore)
		return nil, err
	}

	//	チーム内に写真リクエストがあるか確認する
	requestTakePictureStatus, err := RequestTakePicture(userIds)
	if err != nil {
		l.PutErr(err, l.Trace(), l.E_M_SearchPhotoTask, userIds)
		return nil, err
	}

	return requestTakePictureStatus, nil
}
func GetScoreEntrySheetPageData(teamName string, holeString string) (*ScoreEntrySheet, error) {
	l.PutInfo(l.I_M_GetPage, teamName, holeString)

	if len(holeString) == 0 {
		l.PutErr(nil, l.Trace(), l.E_Nil, teamName)
		return nil, errors.New("hole string is nil")
	}
	holeNum, _ := strconv.Atoi(holeString)
	holeIndex := holeNum - 1

	field := fields[holeNum]

	userIds := teams[teamName].UserIds
	member := make([]string, len(userIds))
	total := make([]int, len(userIds))
	putt := make([]int, len(userIds))
	for i, userId := range userIds {
		member[i] = users[userId].Name
		total[i] = players[userId].Score[holeIndex]["total"].(int)
		putt[i] = players[userId].Score[holeIndex]["putt"].(int)
	}

	scoreEntrySheet := ScoreEntrySheet{
		Team:    teamName,
		Hole:    holeNum,
		Member:  member,
		UserIds: userIds,
		Par:     field.Par,
		Yard:    field.Yard,
		Total:   total,
		Putt:    putt,
		Excnt:   excnt[teamName][holeNum],
	}
	return &scoreEntrySheet, nil
}
func PostApplyScoreData(teamName string, ApplyScore *PostApplyScore) (*Status, error) {
	l.PutInfo(l.I_M_PostPage, teamName, ApplyScore)

	//更新情報をGlobal変数に格納する
	defer SetPlayerCol(ApplyScore.UserIds)

	AUserIdInTheTeam := teams[teamName].UserIds[0]
	if players[AUserIdInTheTeam].Apply != 0 {
		l.Output(
			logrus.Fields{
				"User Apply": l.Sprintf(players[AUserIdInTheTeam].Apply),
			},
			"Apply score is already registered",
			l.Debug,
		)
		return &Status{"already registered"}, nil
	}
	for playerIndex, userId := range ApplyScore.UserIds {

		findQuery := bson.M{"userid": userId}
		setQuery := bson.M{"$set": bson.M{"apply": ApplyScore.Apply[playerIndex]}}
		if err = UpdateMongoData("player", findQuery, setQuery); err != nil {
			l.PutErr(err, l.Trace(), l.E_M_Update, ApplyScore.Apply[playerIndex])
			return &Status{"failed"}, err
		}
	}

	return &Status{"success"}, nil
}
func make20lengthHashString() string {
	b := make([]byte, 32)
	if _, err := io.ReadFull(rand.Reader, b); err != nil {
		l.PutErr(err, l.Trace(), l.E_MakeHash, rand.Reader)
	}
	longHash := strings.TrimRight(base32.StdEncoding.EncodeToString(b), "=")

	return string([]rune(longHash)[:20])
}
func SetAllPlayerCol() {
	db, session := mongoConn()
	col := db.C("player")
	defer session.Close()
	playersCol := []PlayerCol{}
	if err = col.Find(nil).All(&playersCol); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_FindEntireCol, nil)
	}

	for _, playerCol := range playersCol {
		players[playerCol.UserId] = playerCol
	}
}
Example #10
0
func SetAllUserCol() {
	db, session := mongoConn()
	col := db.C("user")
	defer session.Close()
	usersCol := []UserCol{}
	if err = col.Find(nil).All(&usersCol); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_FindEntireCol, nil)
	}

	for _, userCol := range usersCol {
		users[userCol.UserId] = userCol
	}
}
Example #11
0
func SetAllThreadCol() {
	db, session := mongoConn()
	col := db.C("thread")
	defer session.Close()
	threadsCol := []ThreadCol{}
	if err = col.Find(nil).All(&threadsCol); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_FindEntireCol, nil)
	}

	for _, threadCol := range threadsCol {
		threads[threadCol.ThreadId] = threadCol
	}
}
Example #12
0
func SetAllTeamCol() {
	db, session := mongoConn()
	col := db.C("team")
	defer session.Close()
	teamsCol := []TeamCol{}
	if err = col.Find(nil).All(&teamsCol); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_FindEntireCol, nil)
	}

	for _, teamCol := range teamsCol {
		teams[teamCol.Name] = teamCol
	}
}
Example #13
0
func SetAllFieldCol() {
	db, session := mongoConn()
	col := db.C("field")
	defer session.Close()
	fieldsCol := []FieldCol{}
	if err = col.Find(nil).All(&fieldsCol); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_FindEntireCol, nil)
	}

	for _, fieldCol := range fieldsCol {
		fields[fieldCol.Hole] = fieldCol
	}
}
Example #14
0
func SetTeamCol(teamName string) {
	db, session := mongoConn()
	col := db.C("team")
	defer session.Close()

	teamCol := TeamCol{}
	findQuery := bson.M{"name": teamName}

	if err = col.Find(findQuery).One(&teamCol); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_FindCol, findQuery)
	}

	teams[teamName] = teamCol
}
Example #15
0
func SetFieldCol(hole int) {
	db, session := mongoConn()
	col := db.C("field")
	defer session.Close()

	fieldCol := FieldCol{}
	findQuery := bson.M{"hole": hole}

	if err = col.Find(findQuery).One(&fieldCol); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_FindCol, findQuery)
	}

	fields[hole] = fieldCol
}
Example #16
0
func SetThreadCol(threadId string) {
	db, session := mongoConn()
	col := db.C("thread")
	defer session.Close()

	threadCol := ThreadCol{}
	findQuery := bson.M{"threadid": threadId}

	if err = col.Find(findQuery).One(&threadCol); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_FindCol, findQuery)
	}

	threads[threadId] = threadCol
}
func RegisterUserColData(userCols []UserCol) (*Status, error) {
	l.PutInfo(l.I_M_RegisterCol, userCols, nil)

	defer SetAllUserCol()

	db, session := mongoConn()
	col := db.C("user")
	defer session.Close()

	var createCnt, updateCnt int

	for _, userCol := range userCols {
		if len(userCol.Name) == 0 {
			l.PutErr(nil, l.Trace(), l.E_Nil, userCol.Name)
			return &Status{"this user do not have name"}, nil
		}
		if len(userCol.UserId) == 0 {
			userCol.UserId = make20lengthHashString()
		}
		if len(userCol.CreatedAt) == 0 {
			userCol.CreatedAt = time.Now().Format(c.DatetimeFormat)
		}
		findQuery := bson.M{"userid": userCol.UserId}
		change, err := col.Upsert(findQuery, userCol)
		if err != nil {
			l.PutErr(err, l.Trace(), l.E_M_Upsert, userCol.UserId)
			return &Status{"can not upsert"}, err
		}
		if change.Updated == 0 {
			createCnt += 1
		} else {
			updateCnt += 1
		}
	}

	return &Status{"success"}, nil
}
func PostScoreViewSheetPageData(teamName string, definedTeam *PostDefinedTeam) (*Status, error) {
	l.PutInfo(l.I_M_PostPage, teamName, definedTeam)

	//更新情報をGlobal変数に格納する
	defer SetTeamCol(teamName)

	findQuery := bson.M{"name": teamName}
	setQuery := bson.M{"$set": bson.M{"defined": true}}
	if err = UpdateMongoData("team", findQuery, setQuery); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_Update, teamName)
		return &Status{"failed"}, err
	}

	return &Status{"success"}, nil
}
Example #19
0
func UpdateMongoData(collection string, findQuery bson.M, updateQuery bson.M) error {

	db, session := mongoConn()
	c := db.C(collection)
	defer session.Close()

	if err = c.Update(findQuery, updateQuery); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_Update,
			map[string]bson.M{
				"findQuery":   findQuery,
				"updateQuery": updateQuery,
			},
		)
		return err
	}
	return nil
}
Example #20
0
func SetPlayerCol(userIds []string) {
	db, session := mongoConn()
	col := db.C("player")
	defer session.Close()

	for _, userId := range userIds {

		playerCol := PlayerCol{}
		findQuery := bson.M{"userid": userId}

		if err = col.Find(findQuery).One(&playerCol); err != nil {
			l.PutErr(err, l.Trace(), l.E_M_FindCol, findQuery)
		}

		players[userId] = playerCol
	}
}
Example #21
0
func register(c *gin.Context) {
	date := c.Params.ByName("date")
	collection := c.Params.ByName("collection")
	//		if origin := req.HeaderParameter(restful.HEADER_Origin); origin != "" {
	//			if len(resp.Header().Get(restful.HEADER_AccessControlAllowOrigin)) == 0 {
	//				resp.AddHeader(restful.HEADER_AccessControlAllowOrigin, origin)
	//			}
	//		}

	pp.Println(date)
	l.Output(
		logrus.Fields{
			"Date":       date,
			"Collection": collection,
			"Context":    l.Sprintf(c),
		},
		"Post access to register router",
		l.Debug,
	)

	switch collection {

	case "user":

		userCols := new([]m.UserCol)
		if !c.Bind(userCols) {
			c.JSON(404, gin.H{"status": "wrong queries"})
			return
		}

		status, err := m.RegisterUserColData(*userCols)
		if err != nil {
			l.PutErr(err, l.Trace(), l.E_R_RegisterCol, userCols)
		}
		c.JSON(200, status)

	case "team":

		teamCols := new([]m.TeamCol)
		if !c.Bind(teamCols) {
			c.JSON(404, gin.H{"status": "wrong queries"})
			return
		}

		status, err := m.RegisterTeamColData(date, *teamCols)
		if err != nil {
			l.PutErr(err, l.Trace(), l.E_R_RegisterCol, teamCols)
		}
		c.JSON(200, status)

	case "field":

		fieldCols := new([]m.FieldCol)
		if !c.Bind(fieldCols) {
			c.JSON(404, gin.H{"status": "wrong queries"})
			return
		}

		status, err := m.RegisterFieldColData(date, *fieldCols)
		if err != nil {
			l.PutErr(err, l.Trace(), l.E_R_RegisterCol, fieldCols)
		}
		c.JSON(200, status)

	case "thread":

		requestTakePictureStatus := new(m.RequestTakePictureStatus)
		if !c.Bind(requestTakePictureStatus) {
			c.JSON(404, gin.H{"status": "wrong queries"})
			return
		}

		status, err := m.RegisterThreadImg(requestTakePictureStatus)
		if err != nil {
			l.PutErr(err, l.Trace(), l.E_R_RegisterCol, requestTakePictureStatus)
		}

		c.JSON(200, status)
	}
}
Example #22
0
func postOne(c *gin.Context) {
	page := c.Params.ByName("page")
	team := c.Params.ByName("team")
	hole := c.Params.ByName("hole")
	//		if origin := req.HeaderParameter(restful.HEADER_Origin); origin != "" {
	//			if len(resp.Header().Get(restful.HEADER_AccessControlAllowOrigin)) == 0 {
	//				resp.AddHeader(restful.HEADER_AccessControlAllowOrigin, origin)
	//			}
	//		}

	l.Output(
		logrus.Fields{
			"Page":    page,
			"Team":    team,
			"Hole":    hole,
			"Context": l.Sprintf(c),
		},
		"Post access to page router",
		l.Debug,
	)
	switch page {

	case "login":

		loginInfo := new(m.PostLogin)
		if !c.Bind(loginInfo) {
			c.JSON(404, gin.H{"status": "wrong queries"})
			return
		}

		status, err := m.PostLoginPageData(loginInfo)
		if err != nil {
			l.PutErr(err, l.Trace(), l.E_R_PostPage, loginInfo)
		}
		c.JSON(200, status)

	case "scoreViewSheet":

		definedTeam := new(m.PostDefinedTeam)
		if !c.Bind(definedTeam) {
			c.JSON(404, gin.H{"status": "wrong queries"})
			return
		}

		status, err := m.PostScoreViewSheetPageData(team, definedTeam)
		if err != nil {
			l.PutErr(err, l.Trace(), l.E_R_PostPage, definedTeam)
		}
		c.JSON(200, status)

	case "scoreEntrySheet":

		updatedTeamScore := new(m.PostTeamScore)
		if !c.Bind(updatedTeamScore) {
			c.JSON(404, gin.H{"status": "wrong queries"})
			return
		}

		status, err := m.PostScoreEntrySheetPageData(team, hole, updatedTeamScore)
		if err != nil {
			l.PutErr(err, l.Trace(), l.E_R_PostPage, updatedTeamScore)
		}
		c.JSON(200, status)

	case "applyScore":
		if hole != "" {
			return
		}
		registeredApplyScore := new(m.PostApplyScore)
		if !c.Bind(registeredApplyScore) {
			c.JSON(404, gin.H{"status": "wrong queries"})
			return
		}

		status, err := m.PostApplyScoreData(team, registeredApplyScore)
		if err != nil {
			l.PutErr(err, l.Trace(), l.E_R_PostPage, registeredApplyScore)
		}
		c.JSON(200, status)
	}
}
func UpdateExistingTimeLine(thread *Thread) (*Thread, error) {
	l.PutInfo(l.I_M_PostPage, thread, nil)

	targetThreadId := thread.ThreadId
	//更新情報をGlobal変数に格納する
	defer SetAllThreadCol()

	colorFeeling := make(map[string]string)
	colorFeeling["default"] = "#c0c0c0"
	colorFeeling["angry"] = "#ff7f7f"
	colorFeeling["great"] = "#ffff7f"
	colorFeeling["sad"] = "#7fbfff"
	colorFeeling["vexing"] = "#7fff7f"

	if len(targetThreadId) == 0 {
		l.PutErr(nil, l.Trace(), l.E_Nil, thread)
		return nil, errors.New("thread id do not exist")
	}

	if len(thread.ColorCode) == 0 {
		l.PutErr(err, l.Trace(), l.E_Nil, thread.ColorCode)
		return nil, errors.New("current colorCode do not contain in posted thread")
	}
	if len(thread.Reactions) > 1 {
		l.PutErr(err, l.Trace(), l.E_TooManyData, thread.Reactions)
		return nil, errors.New("reactions is not 1")
	}

	currentFeeling := ""
	currentColor := threads[targetThreadId].ColorCode
	postedFeeling := getFeelingFromAWSUrl(thread.Reactions[0].Content)
	postedColor := colorFeeling[postedFeeling]

	for feeling, code := range colorFeeling {
		if currentColor == code {
			currentFeeling = feeling
		}
	}

	thread.Reactions[0].DateTime = time.Now().Format(c.DatetimeFormat)
	findQuery := bson.M{"threadid": targetThreadId}
	pushQuery := bson.M{"$push": bson.M{"reactions": thread.Reactions[0]}}
	if err = UpdateMongoData("thread", findQuery, pushQuery); err != nil {
		l.PutErr(err, l.Trace(), l.E_M_Update, thread.Reactions[0])
		return nil, err
	}

	//投稿された感情と、現在の感情に相違がある場合
	if currentFeeling != postedFeeling {
		var setColor string
		var currentFeelingCount, postedFeelingCount int

		if currentColor == colorFeeling["default"] {
			setColor = postedColor
		} else {

			//直前の更新を反映させる
			SetAllThreadCol()

			for _, r := range threads[targetThreadId].Reactions {
				switch getFeelingFromAWSUrl(r["content"].(string)) {
				case currentFeeling:
					currentFeelingCount++
				case postedFeeling:
					postedFeelingCount++
				}
			}

			if currentFeelingCount >= postedFeelingCount {
				setColor = currentColor
			} else {
				setColor = postedColor
			}
		}

		setQuery := bson.M{"$set": bson.M{"colorcode": setColor}}

		if err = UpdateMongoData("thread", findQuery, setQuery); err != nil {
			l.PutErr(err, l.Trace(), l.E_M_Update, setColor)
			return nil, err
		}
		thread.ColorCode = setColor
	}
	return thread, nil
}
Example #24
0
func RegisterThreadOfScore(holeString string, teamScore *PostTeamScore) error {

	defer SetAllThreadCol()
	holeNum, _ := strconv.Atoi(holeString)
	//	holeIndex := holeNum - 1

	threadMsg := make(map[string]string)
	threadPositive := make(map[string]bool)

	threadMsg[holeInOne] = "ホールインワン"
	threadMsg[albatross] = "アルバトロス"
	threadMsg[eagle] = "イーグル"
	threadMsg[birdie] = "バーディー"
	threadMsg[par] = "パー"
	threadMsg[twoPointFiveTimes] = "2.5倍以上のスコア"

	threadPositive[holeInOne] = true
	threadPositive[albatross] = true
	threadPositive[eagle] = true
	threadPositive[birdie] = true
	threadPositive[par] = true
	threadPositive[twoPointFiveTimes] = false

	parInThisHole := fields[holeNum].Par

	for playerIndex, userId := range teamScore.UserIds {
		var threadKey, imgUrl, inOut string
		var holeInOutNum int

		switch teamScore.Total[playerIndex] {
		case 1:
			threadKey = holeInOne
		case parInThisHole - 3:
			threadKey = albatross
		case parInThisHole - 2:
			threadKey = eagle
		case parInThisHole - 1:
			threadKey = birdie
		case parInThisHole:
			threadKey = par
		default:
			if teamScore.Total[playerIndex] > int(float64(parInThisHole)*2.5) {
				threadKey = twoPointFiveTimes
			} else {
				continue
			}
		}

		if holeNum > 9 {
			holeInOutNum = holeNum - 9
			inOut = "IN"
		} else {
			holeInOutNum = holeNum
			inOut = "OUT"
		}
		holeInOutString := strconv.Itoa(holeInOutNum)

		if threadPositive[threadKey] {
			if len(players[userId].PositivePhotoUrl) != 0 {
				imgUrl = players[userId].PositivePhotoUrl
			}
		} else {
			if len(players[userId].NegativePhotoUrl) != 0 {
				imgUrl = players[userId].NegativePhotoUrl
			}
		}

		msg := makeScoreThreadMsg(
			threadPositive[threadKey],
			inOut,
			holeInOutString,
			users[userId].Name,
			threadMsg[threadKey],
		)

		thread := &Thread{
			UserId:   userId,
			UserName: users[userId].Name,
			Msg:      msg,
			ImgUrl:   imgUrl,
			Positive: threadPositive[threadKey],
		}

		if err := UpsertNewTimeLine(thread); err != nil {
			l.PutErr(err, l.Trace(), l.E_M_Upsert, thread)
			return err
		}
	}

	//	holeThreadScore := make(map[string]int)
	//	holeThreadUserId := make(map[string]string)
	//	holeThreadMsg := make(map[string]string)
	//	holeThreadPositive := make(map[string]string)
	//
	//	holeThreadScore[bestTheHole] = parInThisHole * 3
	//	holeThreadScore[worstTheHole] = 0
	//	holeThreadPositive[bestTheHole] = true
	//	holeThreadPositive[worstTheHole] = false
	//
	//
	//	for userId, player := range players {
	//		total := player.Score[holeIndex]["total"].(int)
	//		if total == 0 {
	//			return nil
	//		}
	//		if total < holeThreadScore[bestTheHole] {
	//			holeThreadScore[bestTheHole] = total
	//			holeThreadUserId[bestTheHole] = userId
	//		} else if total < holeThreadScore[worstTheHole] {
	//			holeThreadScore[worstTheHole] = total
	//			holeThreadUserId[worstTheHole] = userId
	//		}
	//	}
	//
	//	 msg := makeMsg(
	//		 holeThreadPositive[bestTheHole],
	//		 inOut,
	//		 holeString,
	//		 users[holeThreadUserId[bestTheHole]].Name,
	//		 strconv.Itoa(holeThreadScore[bestTheHole]),
	//	 )

	return nil
}