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 }
// readPump pumps messages from the websocket connection to the hub. func (c *connection) readPump() { defer func() { H.Unregister <- c c.ws.Close() }() c.ws.SetReadLimit(maxMessageSize) c.ws.SetReadDeadline(time.Now().Add(pongWait)) c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil }) for { err := c.ws.ReadJSON(&thread) if err != nil { if thread == nil { break } l.Output( logrus.Fields{ l.ErrMsg: l.ErrToStr(err), l.TraceMsg: l.TraceToStr(l.Trace()), "Thread": l.Sprintf(thread), }, "can not read JSON or Closed Websocket", l.Debug, ) break } if newThread, err = m.UpdateExistingTimeLine(thread); err != nil { l.PutErr(err, l.Trace(), l.E_R_Upsert, thread) } H.Broadcast <- newThread } }
// writePump pumps messages from the hub to the websocket connection. func (c *connection) writePump() { ticker := time.NewTicker(pingPeriod) defer func() { ticker.Stop() c.ws.Close() }() for { select { case threadToResponse, ok := <-c.send: if !ok { c.write(websocket.CloseMessage, []byte{}) return } if err := c.ws.WriteJSON(threadToResponse); err != nil { l.Output( logrus.Fields{ l.ErrMsg: l.ErrToStr(err), l.TraceMsg: l.TraceToStr(l.Trace()), "Thread": l.Sprintf(threadToResponse), }, "can not write JSON", l.Debug, ) return } case <-ticker.C: if err := c.write(websocket.PingMessage, []byte{}); err != nil { l.PutErr(err, l.Trace(), l.E_R_PingMsg, websocket.PingMessage) return } } } }
func register(req *restful.Request, resp *restful.Response) { date := req.PathParameter("date") collection := req.PathParameter("collection") 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{ "Date": date, "Collection": collection, "Request": l.Sprintf(req), "Response": l.Sprintf(resp), }, "Post access to register router", l.Debug, ) switch collection { case "user": userCols := new([]m.UserCol) if err := req.ReadEntity(userCols); err != nil { resp.WriteErrorString(http.StatusBadRequest, err.Error()) return } status, err := m.RegisterUserColData(*userCols) if err != nil { l.PutErr(err, l.Trace(), l.E_R_RegisterCol, userCols) } resp.WriteAsJson(status) case "team": teamCols := new([]m.TeamCol) if err := req.ReadEntity(teamCols); err != nil { resp.WriteErrorString(http.StatusBadRequest, err.Error()) return } status, err := m.RegisterTeamColData(date, *teamCols) if err != nil { l.PutErr(err, l.Trace(), l.E_R_RegisterCol, teamCols) } resp.WriteAsJson(status) case "field": fieldCols := new([]m.FieldCol) if err := req.ReadEntity(fieldCols); err != nil { resp.WriteErrorString(http.StatusBadRequest, err.Error()) return } status, err := m.RegisterFieldColData(date, *fieldCols) if err != nil { l.PutErr(err, l.Trace(), l.E_R_RegisterCol, fieldCols) } resp.WriteAsJson(status) case "thread": requestTakePictureStatus := new(m.RequestTakePictureStatus) if err := req.ReadEntity(requestTakePictureStatus); err != nil { resp.WriteErrorString(http.StatusBadRequest, err.Error()) return } status, err := m.RegisterThreadImg(requestTakePictureStatus) if err != nil { l.PutErr(err, l.Trace(), l.E_R_RegisterCol, requestTakePictureStatus) } resp.WriteAsJson(status) } }
func postOne(req *restful.Request, resp *restful.Response) { page := req.PathParameter("page") team := req.PathParameter("team") hole := req.PathParameter("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, "Request": l.Sprintf(req), "Response": l.Sprintf(resp), }, "Post access to page router", l.Debug, ) switch page { case "login": loginInfo := new(m.PostLogin) err := req.ReadEntity(loginInfo) if err != nil { // bad request resp.WriteErrorString(http.StatusBadRequest, err.Error()) return } status, err := m.PostLoginPageData(loginInfo) if err != nil { l.PutErr(err, l.Trace(), l.E_R_PostPage, loginInfo) } resp.WriteAsJson(status) case "scoreViewSheet": definedTeam := new(m.PostDefinedTeam) err := req.ReadEntity(definedTeam) if err != nil { // bad request resp.WriteErrorString(http.StatusBadRequest, err.Error()) return } status, err := m.PostScoreViewSheetPageData(team, definedTeam) if err != nil { l.PutErr(err, l.Trace(), l.E_R_PostPage, definedTeam) } resp.WriteAsJson(status) case "scoreEntrySheet": updatedTeamScore := new(m.PostTeamScore) err := req.ReadEntity(updatedTeamScore) if err != nil { // bad request resp.WriteErrorString(http.StatusBadRequest, err.Error()) return } status, err := m.PostScoreEntrySheetPageData(team, hole, updatedTeamScore) if err != nil { l.PutErr(err, l.Trace(), l.E_R_PostPage, updatedTeamScore) } resp.WriteAsJson(status) case "applyScore": if hole != "" { return } registeredApplyScore := new(m.PostApplyScore) err := req.ReadEntity(registeredApplyScore) if err != nil { resp.WriteErrorString(http.StatusBadRequest, err.Error()) return } status, err := m.PostApplyScoreData(team, registeredApplyScore) if err != nil { l.PutErr(err, l.Trace(), l.E_R_PostPage, registeredApplyScore) } resp.WriteAsJson(status) } }
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 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 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 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]) }
// serveWs handles websocket requests from the peer. func ServeWs(w http.ResponseWriter, r *http.Request) { ws, err := upgrader.Upgrade(w, r, nil) if err != nil { l.PutErr(err, l.Trace(), l.E_R_Upgrader, nil) return } c := &connection{send: make(chan *m.Thread, 256), ws: ws} H.Register <- c go c.writePump() c.readPump() }
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 } }
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 } }
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 } }
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 } }
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 } }
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 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 }
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 }
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 }
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 }
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 } }
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 }
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 }