Esempio n. 1
0
func advanceState(c appengine.Context, h *hunt.Hunt, currentState int) {
	err := datastore.RunInTransaction(c, func(c appengine.Context) error {
		h := hunt.ID(c, h.ID)
		if h == nil || h.State != currentState {
			// TODO(dneal): Return a real error.
			return nil
		}
		switch h.State {
		case hunt.StatePreLaunch:
			teams := team.All(c, h)
			nonPaperOrder := rand.Perm(len(teams))
			paperOrder := rand.Perm(len(teams))
			for i := range teams {
				puzzle.New(c, h, teams[i], nonPaperOrder[i]+1, false)
				puzzle.New(c, h, teams[i], len(teams)+paperOrder[i]+1, true)
			}
		case hunt.StateSurveying:
			tally.BuildFinalTally(c, h)
		}
		h.State++
		h.Write(c)
		broadcast.SendRefresh(c, h)
		return nil
	}, nil)
	if err != nil {
		c.Errorf("Error: %v", err)
	}
}
Esempio n. 2
0
func (p *Puzzle) UpdatableProgressInfo(c appengine.Context, h *hunt.Hunt, t *team.Team) UpdatableProgressInfo {
	u := UpdatableProgressInfo{
		AvailablePoints: p.PointValue,
		Solved:          false,
		GrantedPoints:   0,
		SolveTimes:      nil,
		Answerable:      t != nil && !t.Key.Equal(p.Team),
	}
	if t != nil {
		var solves []Solve
		_, err := datastore.NewQuery(solveKind).Ancestor(h.Key).Filter("Puzzle =", p.Key).Filter("Team =", t.Key).Limit(1).GetAll(c, &solves)
		if err != nil {
			c.Errorf("Error: %v", err)
		}
		if len(solves) > 0 {
			u.Solved = true
			u.GrantedPoints = solves[0].Points
			u.Answerable = false
		}
	}
	var solves []Solve
	_, err := datastore.NewQuery(solveKind).Ancestor(h.Key).Filter("Puzzle =", p.Key).Order("Time").GetAll(c, &solves)
	if err != nil {
		c.Errorf("Error: %v", err)
	}
	for _, s := range solves {
		u.SolveTimes = append(u.SolveTimes, s.Time.In(h.GetTimezone(c)).Format("15:04:05"))
	}
	return u
}
Esempio n. 3
0
func Log(c appengine.Context, h *hunt.Hunt, message string) {
	m := &Message{message, time.Now()}
	k := datastore.NewIncompleteKey(c, messageKind, h.Key)
	k, err := datastore.Put(c, k, m)
	if err != nil {
		c.Errorf("Error: %v", err)
	}
	broadcast.SendConsoleUpdate(c, h, m.ToString(c, h.GetTimezone(c)))
}
Esempio n. 4
0
func Logs(c appengine.Context, h *hunt.Hunt) []string {
	var messages []*Message
	_, err := datastore.NewQuery(messageKind).Ancestor(h.Key).Order("-Time").Limit(1000).GetAll(c, &messages)
	if err != nil {
		c.Errorf("Error: %v", err)
		return nil
	}
	var result []string
	for _, m := range messages {
		result = append(result, m.ToString(c, h.GetTimezone(c)))
	}
	return result
}
Esempio n. 5
0
func AdminHandler(w http.ResponseWriter, r *http.Request) {
	path := strings.Split(r.URL.Path, "/")
	if len(path) != 4 {
		http.Error(w, "Not found", 404)
		return
	}

	c := appengine.NewContext(r)

	w.Header().Set("Content-Type", "application/json")
	enc := json.NewEncoder(w)

	var h *hunt.Hunt
	if id := r.FormValue("hunt_id"); id != "" {
		h = hunt.ID(c, id)
	}

	var t *team.Team
	if id := r.FormValue("team_id"); h != nil && id != "" {
		t = team.ID(c, id)
	}

	var p *puzzle.Puzzle
	if id := r.FormValue("puzzleid"); h != nil && id != "" {
		p = puzzle.ID(c, id)
	}

	var err error
	switch path[3] {
	case "hunts":
		hunts := hunt.All(c)
		err = enc.Encode(hunts)
	case "addhunt":
		hunt.New(c, r.FormValue("name"), r.FormValue("path"))
	case "deletehunt":
		h.Delete(c)
	case "updateingredients":
		if h != nil && h.State < hunt.StateEarlyAccess {
			h.Ingredients = r.FormValue("ingredients")
			h.Write(c)
			broadcast.SendIngredientsUpdate(c, h)
		}
	case "teams":
		if h != nil {
			err = enc.Encode(TeamsInfo{
				Editable: true,
				Teams:    team.All(c, h),
			})
		}
	case "addteam":
		if h != nil && h.State < hunt.StateEarlyAccess {
			team.New(c, h, r.FormValue("name"), r.FormValue("password"), r.FormValue("novice") == "true")
			broadcast.SendTeamsUpdate(c, h)
		}
	case "deleteteam":
		if t != nil && h.State < hunt.StateEarlyAccess {
			t.Delete(c)
			broadcast.SendTeamsUpdate(c, h)
		}
	case "state":
		if h != nil {
			err = enc.Encode(h.State)
		}
	case "advancestate":
		if h != nil {
			currentState, err := strconv.Atoi(r.FormValue("currentstate"))
			if err == nil {
				advanceState(c, h, currentState)
				broadcast.SendRefresh(c, h)
			}
		}
	case "puzzles":
		if h != nil {
			puzzles := puzzle.All(c, h, nil)
			var admin []*puzzle.AdminPuzzle
			for _, p := range puzzles {
				admin = append(admin, p.Admin(c))
			}
			err = enc.Encode(PuzzleInfo{false, admin})
		}
	case "ingredients":
		err = enc.Encode(IngredientInfo{
			Display:     true,
			Editable:    true,
			Ingredients: h.Ingredients,
		})
	case "leaderboard":
		if h.State >= hunt.StateSolving {
			var l LeaderboardInfo
			fillLeaderboardInfo(c, h, nil, &l)
			err = enc.Encode(l)
		}
	case "leaderboardupdate":
		if p != nil {
			err = enc.Encode(p.UpdatableProgressInfo(c, h, nil))
		}
	case "channel":
		if h != nil {
			err = enc.Encode(broadcast.GetToken(c, h, nil, true))
		}
	case "console":
		if h != nil {
			err = enc.Encode(adminconsole.Logs(c, h))
		}
	case "adminsurvey":
		if h != nil && h.State == hunt.StateSurveying {
			var info AdminSurveyInfo
			info.Display = true
			for _, t := range team.All(c, h) {
				info.Teams = append(info.Teams, TeamSurveyInfo{t.Name, t.Survey != ""})
			}
			err = enc.Encode(info)
		}
	case "finalscores":
		finalScores := tally.Get(c, h, true)
		err = enc.Encode(finalScores)
	}

	if err != nil {
		c.Errorf("Error: %v", err)
		return
	}
}