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
// FinalSubmission makes the last submission final.
func FinalSubmission(ctx context.Context, w http.ResponseWriter, r *http.Request) (status int, err error) {
	p, ok := passenger.FromContext(ctx)
	if !ok {
		return http.StatusUnauthorized, nil
	}
	if r.Method != "POST" {
		return http.StatusMethodNotAllowed, nil
	}

	var resultKey *datastore.Key
	if resultKey, err = datastore.DecodeKey(mux.Vars(r)["resultKey"]); err != nil {
		return http.StatusInternalServerError, err
	}

	if !util.HasParent(p.UserKey, resultKey) {
		return http.StatusBadRequest, errors.New("cannot submit answer for other users")
	}

	var index int
	if index, err = strconv.Atoi(mux.Vars(r)["index"]); err != nil {
		return http.StatusInternalServerError, err
	}

	var submissionKey *datastore.Key
	if submissionKey, err = datastore.DecodeKey(mux.Vars(r)["submissionKey"]); err != nil {
		return http.StatusInternalServerError, err
	}
	var result model.Result
	if err = datastore.Get(ctx, resultKey, &result); err != nil {
		return http.StatusInternalServerError, err
	}

	result.FinalSubmissions[index] = submissionKey

	if _, err = result.Save(ctx, resultKey); err != nil {
		return http.StatusInternalServerError, err
	}
	w.Write([]byte("OK"))
	return
}
Example #3
0
// TaskByKey loads a task by key.
func TaskByKey(ctx context.Context, w http.ResponseWriter, r *http.Request) (status int, err error) {
	p, ok := passenger.FromContext(ctx)
	if !ok {
		return http.StatusUnauthorized, nil
	}

	if r.Method != "GET" {
		return http.StatusMethodNotAllowed, nil
	}

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

	// User is a coder
	if p.UserKey.Parent() == nil {
		rk, err := datastore.DecodeKey(r.URL.Query()["result"][0])
		if err != nil {
			return http.StatusInternalServerError, err
		}

		if !util.HasParent(p.UserKey, rk) {
			return http.StatusUnauthorized, nil
		}

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

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

		emptyTime := time.Time{}
		updateResult := false
		for i, val := range challenge.Tasks {
			if taskKey.Equal(val) && result.StartTimes[i] == emptyTime {
				result.StartTimes[i] = time.Now()
				updateResult = true
				break
			}
		}
		if updateResult {
			if _, err = result.Save(ctx, rk); err != nil {
				return http.StatusInternalServerError, err
			}
		}
	}

	switch taskKey.Kind() {
	case model.CodeTaskKind:
		var task model.CodeTask
		if err = datastore.Get(ctx, taskKey, &task); err != nil {
			return http.StatusInternalServerError, err
		}
		json.NewEncoder(w).Encode(task.Key(taskKey))
		return http.StatusOK, nil
	default:
		return http.StatusInternalServerError, errors.New("Not implemented")
	}
}