Example #1
0
func createFinalResult(ctx context.Context, w http.ResponseWriter, resultKey *datastore.Key, result model.Result) (int, error) {
	go computeFinalScore(ctx, result)

	var challenge model.Challenge
	if err := datastore.Get(ctx, result.Challenge, &challenge); err != nil {
		return http.StatusInternalServerError, nil
	}

	var taskKey *datastore.Key
	for _, taskKey = range challenge.Tasks {
		switch taskKey.Kind() {
		case model.CodeTaskKind:
			var submissions model.CodeSubmissions
			keys, err := doQuery(ctx, model.NewQueryForCodeSubmission(), resultKey, taskKey, submissions)
			if err != nil {
				return http.StatusInternalServerError, nil
			}
			if len(keys) == 0 {
				// Most likely the authenticated user called this endpoint
				// before finishing the challenge
				return http.StatusUnauthorized, nil
			}
			result.FinalSubmissions = append(result.FinalSubmissions, keys[0])
		//TODO(pbochis, vbalan, flowlo): Add more cases when more task kinds are added.
		default:
			return http.StatusBadRequest, errors.New("Unknown submission kind.")
		}
	}
	key, err := result.Save(ctx, resultKey)
	if err != nil {
		return http.StatusInternalServerError, err
	}
	json.NewEncoder(w).Encode(result.Key(key))
	return http.StatusOK, nil
}
Example #2
0
func createFinalResult(ctx context.Context, w http.ResponseWriter, resultKey *datastore.Key, result model.Result) (int, error) {
	var challenge model.Challenge
	if err := datastore.Get(ctx, result.Challenge, &challenge); err != nil {
		return http.StatusInternalServerError, nil
	}

	result.Finished = time.Now()

	for i, taskKey := range challenge.Tasks {
		key, err := getLatestSubmissionKey(ctx, resultKey, taskKey)
		if err != nil {
			return http.StatusInternalServerError, err
		}
		result.FinalSubmissions[i] = key
	}
	key, err := result.Put(ctx, resultKey)
	if err != nil {
		return http.StatusInternalServerError, err
	}
	json.NewEncoder(w).Encode(result.Key(key))

	go computeFinalScore(ctx, challenge, result, resultKey)

	return http.StatusOK, nil
}
Example #3
0
func GetResult(ctx context.Context, w http.ResponseWriter, r *http.Request) (int, error) {
	if !util.CheckMethod(r, "GET") {
		return http.StatusMethodNotAllowed, nil
	}

	resultKey, err := datastore.DecodeKey(mux.Vars(r)["resultKey"])
	if err != nil {
		return http.StatusBadRequest, err
	}

	var result model.Result
	if err := datastore.Get(ctx, resultKey, &result); err != nil {
		return http.StatusInternalServerError, nil
	}

	p, ok := passenger.FromContext(ctx)
	if !ok {
		return http.StatusUnauthorized, nil
	}

	if p.UserKey.Parent() != nil {
		json.NewEncoder(w).Encode(result.Key(resultKey))
		return http.StatusOK, nil
	}

	if !util.HasParent(resultKey, p.UserKey) {
		return http.StatusUnauthorized, nil
	}
	return createFinalResult(ctx, w, resultKey, result)
}
Example #4
0
func GetResult(ctx context.Context, w http.ResponseWriter, r *http.Request) (int, error) {
	if r.Method != "GET" {
		return http.StatusMethodNotAllowed, nil
	}

	resultKey, err := datastore.DecodeKey(mux.Vars(r)["resultKey"])
	if err != nil {
		return http.StatusBadRequest, err
	}

	var result model.Result
	if err := datastore.Get(ctx, resultKey, &result); err != nil {
		return http.StatusInternalServerError, nil
	}

	p, ok := passenger.FromContext(ctx)
	if !ok {
		return http.StatusUnauthorized, nil
	}

	var u model.User
	if err = datastore.Get(ctx, p.User, &u); err != nil {
		return http.StatusInternalServerError, nil
	}

	if u.Company == nil && !util.HasParent(p.User, resultKey) {
		return http.StatusUnauthorized, nil
	}

	if result.Finished.Equal(time.Time{}) {
		if util.HasParent(p.User, resultKey) {
			return createFinalResult(ctx, w, *result.Key(resultKey))
		}
		var challenge model.Challenge
		if err := datastore.Get(ctx, result.Challenge, &challenge); err != nil {
			return http.StatusInternalServerError, err
		}
		if u.Company != nil && result.Started.Add(challenge.Duration).Before(time.Now()) {
			return createFinalResult(ctx, w, *result.Key(resultKey))
		}
	}

	json.NewEncoder(w).Encode(result.Key(resultKey))
	return http.StatusOK, nil
}
Example #5
0
// CreateResult saves a new result when a coder starts a challenge.
func CreateResult(ctx context.Context, w http.ResponseWriter, r *http.Request) (int, error) {
	if r.Method != "POST" {
		return http.StatusMethodNotAllowed, nil
	}

	var body = struct {
		ChallengeKey string
	}{}

	p, ok := passenger.FromContext(ctx)

	if !ok {
		return http.StatusUnauthorized, nil
	}

	var profiles model.Profiles
	keys, err := model.NewQueryForProfile().
		Ancestor(p.User).
		GetAll(ctx, &profiles)

	if len(keys) != 1 {
		return http.StatusInternalServerError, errors.New("Profile not found")
	}

	err = json.NewDecoder(r.Body).Decode(&body)

	if err != nil {
		return http.StatusBadRequest, err
	}

	key, err := datastore.DecodeKey(body.ChallengeKey)

	if err != nil {
		return http.StatusBadRequest, err
	}

	var results []model.Result

	resultKeys, err := model.NewQueryForResult().
		Ancestor(keys[0]).
		Filter("Challenge = ", key).
		Limit(1).
		GetAll(ctx, &results)

	if err != nil {
		return http.StatusInternalServerError, err
	}

	if len(resultKeys) == 1 {
		json.NewEncoder(w).Encode(results[0].Key(resultKeys[0]))
		return http.StatusOK, nil
	}

	var challenge model.Challenge
	if err = datastore.Get(ctx, key, &challenge); err != nil {
		return http.StatusInternalServerError, err
	}

	result := model.Result{
		Challenge:        key,
		StartTimes:       make([]time.Time, len(challenge.Tasks)),
		FinalSubmissions: make([]*datastore.Key, len(challenge.Tasks)),
		Started:          time.Now(),
	}
	key, err = result.PutWithParent(ctx, keys[0])
	if err != nil {
		return http.StatusInternalServerError, err
	}

	json.NewEncoder(w).Encode(result.Key(key))
	return http.StatusOK, nil
}