Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
26 kB
1
Indexable
Never
import {
  getData,
  setData,
  DataStore,
  Quiz,
  User,
  ErrorObject,
  Question,
  Trash,
  Answer
} from './dataStore';
import { validQuizCheck, validQuizNameCheck, getRandomColourName } from './other';

/**
 * Given basic details about a new quiz, create one for the logged in user
 *
 * @param {int} authUserId - id of authorised user
 * @param {string} name - name of quiz
 * @param {string} description - description of quiz
 *
 *
 * @returns {quizId: int} - id of quiz
 */
interface QuizCreateReturn {
  quizId: number;
}
function adminQuizCreate(authUserId: number, name: string, description: string): QuizCreateReturn | ErrorObject {
  // Get data from dataStore
  const data: DataStore = getData();

  const user: User = data.users.find((user: User) => user.id === authUserId);
  // Checks if AuthUserId is not a valid user.
  if (!user) {
    return { error: 'AuthUserId is not a valid user.' };
  }

  // checks if the name is valid and the user does not already have a quiz with
  // this name
  if (validQuizNameCheck(name, authUserId)) {
    return validQuizNameCheck(name, authUserId);
  }

  // Checks if description is too long
  if (description.length > 100) {
    return {
      error: 'Description is more than 100 characters in length'
    };
  }

  let quizId: number;
  if (data.quizzes.length === 0 && data.trash.length === 0) {
    quizId = 1;
  } else {
    const quizIds = data.quizzes.map(ids => ids.id);
    const maxInQuizzes = Math.max.apply(null, quizIds);
    const trashQuizIds = data.trash.map(ids => ids.quiz.id);
    const maxInTrash = Math.max.apply(null, trashQuizIds);
    if (maxInQuizzes > maxInTrash) {
      quizId = maxInQuizzes + 1;
    } else quizId = maxInTrash + 1;
  }
  // add this quiz to the quizzes array in the dataStore
  data.quizzes.push({
    id: quizId,
    ownerId: authUserId,
    name: name,
    description: description,
    timeCreated: Math.floor(Date.now() / 1000),
    timeLastEdited: Math.floor(Date.now() / 1000),
    numQuestions: 0,
    duration: 0,
    questions: [],
  });

  // add the quizId to the ownedId array of the user
  user.ownedQuizIds.push(quizId);
  setData(data);
  return {
    quizId: quizId,
  };
}

/**
 * Given a particular quiz, move the quiz to the trash.
 *
 * @param {int} authUserId
 * @param {int} quizId
 *
 * @returns {} - empty object
 *
 */
function adminQuizRemove(authUserId: number, quizId: number): Record<string, never> | ErrorObject {
  const data: DataStore = getData();

  // checks if authUserId and quizId are valid and the quiz belongs to the user
  if (validQuizCheck(authUserId, quizId)) {
    return validQuizCheck(authUserId, quizId);
  }

  const quiz: Quiz = data.quizzes.find((quiz: Quiz) => quiz.id === quizId);
  // find the user
  const user: User = data.users.find((user: User) => user.id === authUserId);

  // remove the quiz from the quizzes aray in the dataStore
  data.quizzes.splice(
    data.quizzes.findIndex((quiz: Quiz) => quiz.id === quizId),
    1
  );
  // remove the quizId from the user's owned quiz Ids
  user.ownedQuizIds.splice(
    user.ownedQuizIds.findIndex((ownedId: number) => ownedId === quizId),
    1
  );

  quiz.timeLastEdited = Math.floor(Date.now() / 1000);

  data.trash.push({
    ownerId: authUserId,
    quiz: quiz
  });

  setData(data);
  return {};
}

/**
 * Get all of the relevant information about the current quiz.
 *
 * @param {int} authUserId - id of authorised user
 * @param {int} quizId - id of quiz
 *
 * @returns {
*   quizId: int,
*   name: string,
*   timeCreated: int
*   timeLastEdited: int
*   description: string
 * } - information about quiz
 */
interface QuizInfoReturn {
  quizId?: number;
  name?: string;
  timeCreated?: number;
  timeLastEdited?: number;
  description?: string;
  numQuestions?: number,
  duration?: number,
  questions?: Question[],
  error?: string;
}
function adminQuizInfo(authUserId: number, quizId: number): QuizInfoReturn {
  const data: DataStore = getData();

  // checks if authUserId and quizId are valid and the quiz belongs to the user
  if (validQuizCheck(authUserId, quizId)) {
    return validQuizCheck(authUserId, quizId);
  }

  // find the quiz
  const foundQuiz: Quiz = data.quizzes.find((quiz: Quiz) => quiz.id === quizId);

  // return information about the quiz
  return {
    quizId: foundQuiz.id,
    name: foundQuiz.name,
    timeCreated: foundQuiz.timeCreated,
    timeLastEdited: foundQuiz.timeLastEdited,
    description: foundQuiz.description,
    numQuestions: foundQuiz.numQuestions,
    duration: foundQuiz.duration,
    questions: foundQuiz.questions
  };
}

/**
 * Update the name of the relevant quiz.
 *
 * @param {int} authUserId - id of authorised user
 * @param {int} quizId - id of quiz
 * @param {string} name - name of quiz
 *
 * @returns { } - empty object
 *
 */
function adminQuizNameUpdate(authUserId: number, quizId: number, name: string): Record<string, never> | ErrorObject {
  const data: DataStore = getData();

  // checks if authUserId and quizId are valid and the quiz belongs to the user
  if (validQuizCheck(authUserId, quizId)) {
    return validQuizCheck(authUserId, quizId);
  }

  // checks if the name is valid and the user does not already have a quiz with
  // this name
  if (validQuizNameCheck(name, authUserId)) {
    return validQuizNameCheck(name, authUserId);
  }

  // find the quiz
  const foundQuiz: Quiz = data.quizzes.find((quiz: Quiz) => quiz.id === quizId);

  // update name and timeLastEdited of specified quiz
  foundQuiz.timeLastEdited = Math.floor(Date.now() / 1000);
  foundQuiz.name = name;

  setData(data);

  return {};
}

/**
  * Provide a list of allquizzes that are owned by the currently logged in user.
  *
  * @param {number} authUserID - authorised user's id stored as an integer
  * @returns {quizzes : Array<{
  *    quizId: number,
  *    name: string
  *   }>
  * } - an object of an array quizID and name of the quiz
*/
interface QuizList {
  quizId: number;
  name: string;
}
interface QuizListReturn {
  quizzes?: QuizList[];
  error?: string;
}
function adminQuizList(authUserId: number): QuizListReturn {
  const data: DataStore = getData();

  // finds specific user in database
  const foundUser = data.users.find((user: User) => user.id === authUserId);

  // checks if user exists
  if (foundUser === undefined) {
    return { error: 'User id does not correspond to a valid user' };
  }

  // goes through quizzes checking if user owns them and gets its details
  const foundQuizzes = [];
  for (const quiz of data.quizzes) {
    if (foundUser.ownedQuizIds.includes(quiz.id)) {
      const quizId: number = quiz.id;
      const name: string = quiz.name;
      foundQuizzes.push({ quizId: quizId, name: name });
    }
  }

  return {
    quizzes: foundQuizzes
  };
}

/**
 * This function updates the description of the relevant quiz
 *
 * @param {int} authUserId - id of authorised user
 * @param {int} quizId - id of quiz
 * @param {string} description - description of quiz
 *
 * @returns { } - empty object
 *
 */
function adminQuizDescriptionUpdate(authUserId: number, quizId: number, description: string): Record<string, never> | ErrorObject {
  const data: DataStore = getData();

  const foundUser: User = data.users.find((user: User) => user.id === authUserId);

  const foundQuiz: Quiz = data.quizzes.find((quiz: Quiz) => quiz.id === quizId);

  if (!foundUser) {
    return { error: 'authUserId is not a valid user.' };
  }
  if (!foundQuiz) {
    return { error: 'quizId does not refer to a valid quiz.' };
  }

  if (!foundUser.ownedQuizIds.find((quiz) => quiz === quizId)) {
    return { error: 'This user does not own this quiz.' };
  }

  if (description.length > 100) {
    return { error: 'Description is more than 100 characters' };
  }

  foundQuiz.description = description;
  foundQuiz.timeLastEdited = Math.floor(Date.now() / 1000);
  setData(data);

  return {};
}

/**
 * This function transfers ownership of a quiz to a different user based on their email
 *
 * @param {int} authUserId - id of authorised user
 * @param {int} quizId - id of quiz
 * @param {string} userEmail - email of user to transfer ownership to
 *
 * @returns { } - empty object
 *
 */
function adminQuizTransfer(authUserId: number, quizId: number, userEmail: string) {
  const data: DataStore = getData();

  // checks if authUserId and quizId are valid and the quiz belongs to the user
  if (validQuizCheck(authUserId, quizId)) {
    return validQuizCheck(authUserId, quizId);
  }

  const foundUser: User = data.users.find((user: User) => user.id === authUserId);
  const foundUserToRecieve: User = data.users.find((user: User) => user.email === userEmail);

  const foundReplaceQuiz: Quiz = data.quizzes.find((quiz: Quiz) => quiz.id === quizId);

  if (!foundUserToRecieve) {
    return { error: 'userEmail is not a valid email.' };
  }
  if (foundUser.email === userEmail) {
    return { error: 'userEmail is the current logged in user.' };
  }
  for (const quiz of foundUserToRecieve.ownedQuizIds) {
    const foundQuiz: Quiz = data.quizzes.find((specificQuiz: Quiz) => quiz === specificQuiz.id);
    if (foundQuiz.name === foundReplaceQuiz.name) {
      return { error: 'Quiz ID refers to a quiz that has a name that is already used by the target user.' };
    }
  }

  // change ownerId of quiz to new owner
  foundReplaceQuiz.ownerId = foundUserToRecieve.id;
  // add the quizId to the ownedId array of the user
  foundUserToRecieve.ownedQuizIds.push(quizId);
  // remove the quizId from the user's owned quiz Ids
  foundUser.ownedQuizIds.splice(
    foundUser.ownedQuizIds.findIndex((ownedId: number) => ownedId === quizId),
    1
  );
  setData(data);
  return { };
}

/**
 * This function creates a new question and adds it to a quiz
 *
 * @param {int} authUserId - id of authorised user
 * @param {int} quizId - id of quiz
 * @param {string} question - question being asked
 * @param {int} duration - duration of question
 * @param {int} points - how many points the question is worth
 * @param {...{object}} points - possible answers to the question
 *
 * @returns {questionId: int} - id of created question
 *
 */
export interface QuestionCreate {
  questionId: number;
}
function adminQuestionCreate(authUserId: number, quizId: number, question: string, duration: number, points: number, answers: Answer[]): QuestionCreate | ErrorObject {
  const data: DataStore = getData();

  const foundUser: User = data.users.find((user: User) => user.id === authUserId);

  const foundQuiz: Quiz = data.quizzes.find((quiz: Quiz) => quiz.id === quizId);

  if (!foundUser) {
    return { error: 'authUserId is not a valid user.' };
  }

  if (!foundQuiz) {
    return { error: 'quizId does not refer to a valid quiz.' };
  }

  if (!foundUser.ownedQuizIds.includes(quizId)) {
    return { error: 'This user does not own this quiz.' };
  }

  if (question.length < 5 || question.length > 50) {
    return { error: 'The question length invalid' };
  }

  if (duration <= 0) {
    return { error: 'The question duration must be a positive number' };
  }

  if (foundQuiz.duration + duration > 180) {
    return { error: 'The duration of the quiz is longer than 3 minutes' };
  }

  if (points < 1 || points > 10) {
    return { error: 'Invalid point distribution' };
  }

  const answersOnly = answers.map(answer => answer.answer);
  const duplicateAnswers = answersOnly.filter((element, index, arr) => arr.indexOf(element) !== index);

  if (duplicateAnswers.length > 0) {
    return { error: 'There cannot be duplicate answers.' };
  }

  if (answers.length < 2 || answers.length > 6) {
    return { error: 'Invalid amount of answers inputted' };
  }

  if (!answers.find(answers => answers.correct === true)) {
    return { error: 'There must be at least one correct answer' };
  }

  if (answers.find(answer => answer.answer.length < 1 || answer.answer.length > 30)) {
    return { error: 'Invalid answer length' };
  }

  foundQuiz.timeLastEdited = Math.floor(Date.now() / 1000);
  foundQuiz.numQuestions++;

  let questionId: number;
  if (data.questions.length === 0) {
    questionId = 1;
  } else questionId = data.questions[data.questions.length - 1].questionId + 1;

  let answerId: number;
  if (data.answers.length === 0) {
    answerId = 1;
  } else answerId = data.answers[data.answers.length - 1].answerId + 1;

  data.questions.push(
    {
      ownerId: foundQuiz.ownerId,
      quizId: foundQuiz.id,
      questionId: questionId
    }
  );

  const allAnswersInfo = answers.map((answer, index) => ({
    answerId: answerId + index,
    answer: answer.answer,
    colour: getRandomColourName(),
    correct: answer.correct
  }));

  for (const answer of allAnswersInfo) {
    data.answers.push(answer);
  }

  foundQuiz.duration += duration;

  const questionCreated: Question = {
    questionId: questionId,
    question: question,
    duration: duration,
    points: points,
    answers: allAnswersInfo
  };

  foundQuiz.questions.push(questionCreated);

  setData(data);

  return { questionId: questionId };
}

/**
 * This function restores a quiz from the trash back to an active quiz
 *
 * @param {int} authUserId - id of authorised user
 * @param {int} quizId - id of quiz
 *
 * @returns { } - empty object
 *
 */
function adminQuizRestore(authUserId: number, quizId: number) {
  const data: DataStore = getData();

  // assumed valid user due to token (check spec)
  const foundUser: User = data.users.find((user: User) => user.id === authUserId);

  const foundQuiz: Quiz = data.quizzes.find((quiz: Quiz) => quiz.id === quizId);
  const foundQuizTrash: Trash = data.trash.find((trash: Trash) => trash.quiz.id === quizId);

  // Quiz ID does not refer to a valid quiz
  if (!foundQuiz && !foundQuizTrash) {
    return {
      error: 'quizId does not refer to a valid quiz.'
    };
  }

  // Quiz ID does not refer to a quiz that this user owns
  if (!foundQuizTrash && foundUser.id !== foundQuiz.ownerId) {
    return {
      error: 'quizId does not refer to a quiz that this user owns.'
    };
  }

  if (!foundQuiz && foundUser.id !== foundQuizTrash.ownerId) {
    return {
      error: 'quizId does not refer to a quiz that this user owns.'
    };
  }

  // Quiz ID refers to a quiz that is not currently in the trash
  if (foundQuiz) {
    return {
      error: 'quizId refers to a quiz that is not currently in the trash.'
    };
  }
  // add quiz back to quizzes dataStore
  data.quizzes.push(foundQuizTrash.quiz);

  // add the quizId from the user's owned quiz Ids
  foundUser.ownedQuizIds.push(foundQuizTrash.quiz.id);

  // remove quiz from trash
  data.trash.splice(data.trash.findIndex((trashId: Trash) => trashId.quiz.id === quizId), 1);

  setData(data);
  return { };
}

/**
 * This function permanently deletes specific quizzes in the trash
 *
 * @param {int} authUserId - id of authorised user
 * @param {string[]} quizIds - id of quizzes
 *
 * @returns { } - empty object
 *
 */
export function trashEmpty(userId: number, quizIds: string[]) {
  const data: DataStore = getData();
  for (const quiz of quizIds) {
    const id = parseInt(quiz);
    const foundUser: User | undefined = data.users.find((user: User) => user.id === userId);

    const foundQuiz: Quiz | undefined = data.quizzes.find((quiz: Quiz) => quiz.id === id);
    const foundQuizTrash: Trash | undefined = data.trash.find((trash: Trash) => trash.quiz.id === id);

    // Quiz ID does not refer to a valid quiz
    if (!foundQuiz && !foundQuizTrash) {
      return {
        error: 'Invalid QuizId in Input!'
      };
    }

    // Quiz ID does not refer to a quiz that this user owns
    if (!foundQuizTrash && foundUser && foundQuiz && foundUser.id !== foundQuiz.ownerId) {
      return {
        error: 'Not all quizzes belong to this user!'
      };
    }

    if (!foundQuiz && foundUser && foundQuizTrash && foundUser.id !== foundQuizTrash.ownerId) {
      return {
        error: 'Not all quizzes belong to this user!'
      };
    }

    // Quiz ID refers to a quiz that is not currently in the trash
    if (foundQuiz) {
      return {
        error: 'Not all quizzes are in the trash!'
      };
    }
  }
  for (const exists of quizIds) {
    const id = parseInt(exists);
    data.trash.splice(data.trash.findIndex((trashId: Trash) => trashId.quiz.id === id), 1);
  }
  setData(data);
  return { };
}

/**
 * This function returns a list of all quizzes in the trash
 *
 * @param {int} authUserId - id of authorised user
 *
 * @returns {object} - array of quizzes
 */

export interface TrashList {
  quizId: number,
  name: string,
}

export interface viewTrashReturn {
  quizzes: TrashList[]
}

function adminViewTrash(authUserId: number): viewTrashReturn {
  const data = getData();

  // finds all quizzes that belong to user in trash
  const trash = data.trash.filter(trash => trash.ownerId === authUserId);
  const trashList = [];

  for (const element of trash) {
    trashList.push({
      quizId: element.quiz.id,
      name: element.quiz.name,
    });
  }

  setData(data);

  return {
    quizzes: trashList
  };
}

/**
 * This function moves a question in a quiz to a specified position in that quiz
 *
 * @param {int} authUserId - id of authorised user
 * @param {int} quizId - id of quiz
 * @param {int} questionId - id of question
 * @param {int} newPosition - position question will be moved to
 *
 * @returns { } - empty object
 *
*/
function adminQuizMoveQuestion(authUserId: number, quizId: number, questionId: number, newPosition: number): Record<string, never> | ErrorObject {
  const data: DataStore = getData();

  // assumed valid user due to token (check spec)
  const foundUser: User = data.users.find((user: User) => user.id === authUserId);

  const foundQuiz: Quiz = data.quizzes.find((quiz: Quiz) => quiz.id === quizId);

  // Quiz ID does not refer to a valid quiz
  if (!foundQuiz) {
    return {
      error: 'quizId does not refer to a valid quiz.'
    };
  }

  // Quiz ID does not refer to a quiz that this user owns
  if (foundUser.id !== foundQuiz.ownerId) {
    return {
      error: 'quizId does not refer to a quiz that this user owns.'
    };
  }

  const foundQuestion: Question = foundQuiz.questions.find((question: Question) => question.questionId === questionId);
  if (!foundQuestion) {
    return {
      error: 'questionId does not refer to a valid question within this quiz.'
    };
  }

  if (newPosition < 0 || newPosition > foundQuiz.questions.length - 1) {
    return {
      error: 'New position is invalid.',
    };
  }

  const oldPosition = foundQuiz.questions.indexOf(foundQuestion);

  if (oldPosition === newPosition) {
    return {
      error: 'Question is already in that position',
    };
  }

  foundQuiz.questions.splice(oldPosition, 1);
  foundQuiz.questions.splice(newPosition, 0, foundQuestion);
  foundQuiz.timeLastEdited = Math.floor(Date.now() / 1000);

  setData(data);
  return { };
}

/**
 * This function deletes a question from the quiz
 *
 * @param {int} authUserId - id of authorised user
 * @param {int} quizId - id of quiz
 * @param {int} questionId - id of the quiz question
 *
 * @returns { } - empty object
 *
 */
function adminQuestionDelete(authUserId: number, quizId: number, questionId: number): Record<string, never> | ErrorObject {
  const data: DataStore = getData();

  const foundUser: User = data.users.find((user: User) => user.id === authUserId);
  const foundQuiz: Quiz = data.quizzes.find((quiz: Quiz) => quiz.id === quizId);

  if (!foundUser) {
    return { error: 'authUserId is not a valid user.' };
  }

  if (!foundQuiz) {
    return { error: 'quizId does not refer to a valid quiz' };
  }

  if (!foundUser.ownedQuizIds.includes(quizId)) {
    return { error: 'This user does not own this quiz' };
  }

  const foundQuestion = foundQuiz.questions.find(question => question.questionId === questionId);
  if (!foundQuestion) {
    return { error: 'Question Id does not refer to a valid question within this quiz' };
  }

  for (const answer of foundQuestion.answers) {
    const answerToRemove = data.answers.find(foundAnswer => foundAnswer.answerId === answer.answerId);
    data.answers.splice(data.answers.indexOf(answerToRemove), 1);
  }

  const QuestionInData = data.questions.find(question => question.questionId === questionId);
  foundQuiz.questions.splice(foundQuiz.questions.indexOf(foundQuestion), 1);
  data.questions.splice(data.questions.indexOf(QuestionInData), 1);

  foundQuiz.duration -= foundQuestion.duration;
  foundQuiz.numQuestions--;
  foundQuiz.timeLastEdited = Math.floor(Date.now() / 1000);

  setData(data);

  return {};
}
/**
 * This function creates a new question and adds it to a quiz
 *
 * @param {int} authUserId - id of authorised user
 * @param {int} quizId - id of quiz
 * @param {int} questionId - id of question
 * @param {string} question - question being asked
 * @param {int} duration - duration of question
 * @param {int} points - how many points the question is worth
 * @param {...{object}} points - possible answers to the question
 *
 * @returns {}
 *
 */

function adminQuestionUpdate(authUserId: number, quizId: number, questionId: number, question: string, duration: number, points: number, answers: Answer[]): Record<string, never> | ErrorObject {
  const data: DataStore = getData();

  const foundUser: User = data.users.find((user: User) => user.id === authUserId);

  const foundQuiz: Quiz = data.quizzes.find((quiz: Quiz) => quiz.id === quizId);

  if (!foundQuiz) {
    return { error: 'quizId does not refer to a valid quiz.' };
  }

  if (!foundUser.ownedQuizIds.includes(quizId)) {
    return { error: 'This user does not own this quiz.' };
  }

  if (question.length < 5 || question.length > 50) {
    return { error: 'The question length invalid' };
  }

  if (duration <= 0) {
    return { error: 'The question duration must be a positive number' };
  }

  if (points < 1 || points > 10) {
    return { error: 'Invalid point distribution' };
  }

  const answersOnly = answers.map(answer => answer.answer);
  const duplicateAnswers = answersOnly.filter((element, index, arr) => arr.indexOf(element) !== index);

  if (duplicateAnswers.length > 0) {
    return { error: 'There cannot be duplicate answers.' };
  }

  if (answers.length < 2 || answers.length > 6) {
    return { error: 'Invalid amount of answers inputted' };
  }

  if (!answers.find(answers => answers.correct === true)) {
    return { error: 'There must be at least one correct answer' };
  }

  if (answers.find(answer => answer.answer.length < 1 || answer.answer.length > 30)) {
    return { error: 'Invalid answer length' };
  }

  const foundQuestion = foundQuiz.questions.find(question => question.questionId === questionId);
  if (!foundQuestion) {
    return { error: 'Question Id does not refer to a valid question within this quiz' };
  }

  if (foundQuiz.duration - foundQuestion.duration + duration > 180) {
    return { error: 'The duration of the quiz is longer than 3 minutes' };
  }

  foundQuiz.duration = foundQuiz.duration - foundQuestion.duration + duration;
  foundQuiz.timeLastEdited = Math.floor(Date.now() / 1000);

  for (const answer of foundQuestion.answers) {
    const answerToRemove = data.answers.find(foundAnswer => foundAnswer.answerId === answer.answerId);
    data.answers.splice(data.answers.indexOf(answerToRemove), 1);
  }

  let answerId: number;
  if (data.answers.length === 0) {
    answerId = 1;
  } else answerId = data.answers[data.answers.length - 1].answerId + 1;

  const allAnswersInfo = answers.map((answer, index) => ({
    answerId: answerId + index,
    answer: answer.answer,
    colour: getRandomColourName(),
    correct: answer.correct
  }));

  for (const answer of allAnswersInfo) {
    data.answers.push(answer);
  }

  foundQuestion.duration = duration;
  foundQuestion.points = points;
  foundQuestion.question = question;
  foundQuestion.answers = allAnswersInfo;

  return {};
}

/**
 * This function duplicates a question in a quiz
 *
 * @param {int} authUserId - id of authorised user
 * @param {int} quizId - id of quiz
 * @param {int} questionId - id of the quiz question
 *
 * @returns {object} - new id of duplicated question
 *
 */
interface DuplicateReturn {
  newQuestionId: number
}
function adminQuestionDuplicate(authUserId: number, quizId: number, questionId: number): DuplicateReturn | ErrorObject {
  const data: DataStore = getData();

  const foundQuiz: Quiz = data.quizzes.find((quiz: Quiz) => quiz.id === quizId);

  // checks if authUserId and quizId are valid and the quiz belongs to the user
  if (validQuizCheck(authUserId, quizId)) {
    return validQuizCheck(authUserId, quizId);
  }

  const foundQuestion = foundQuiz.questions.find(question => question.questionId === questionId);
  if (!foundQuestion) {
    return { error: 'Question Id does not refer to a valid question within this quiz' };
  }

  if (foundQuiz.duration + foundQuestion.duration > 180) {
    return { error: 'Quiz duration cannot exceed 3 minutes' };
  }

  foundQuiz.numQuestions++;
  foundQuiz.duration += foundQuestion.duration;
  foundQuiz.timeLastEdited = Math.floor(Date.now() / 1000);

  const dupeQuestion = Object.assign({}, foundQuestion);

  const newQuestionId = data.questions[data.questions.length - 1].questionId + 1;

  dupeQuestion.questionId = newQuestionId;

  for (const dupeAnswer of dupeQuestion.answers) {
    dupeAnswer.answerId = data.answers[data.answers.length - 1].answerId + 1;
    data.answers.push(dupeAnswer);
  }

  // add the duplicated question to the index directly after the question that was duplicated
  foundQuiz.questions.splice(foundQuiz.questions.indexOf(foundQuestion) + 1, 0, dupeQuestion);

  data.questions.push(
    {
      ownerId: foundQuiz.ownerId,
      quizId: foundQuiz.id,
      questionId: newQuestionId,
    });

  setData(data);

  return {
    newQuestionId: newQuestionId
  };
}

export {
  adminQuizCreate,
  adminQuizRemove,
  adminQuizInfo,
  adminQuizDescriptionUpdate,
  adminQuizNameUpdate,
  adminQuizList,
  adminQuizTransfer,
  adminQuestionCreate,
  adminQuizRestore,
  adminQuizMoveQuestion,
  adminViewTrash,
  adminQuestionDelete,
  adminQuestionUpdate,
  adminQuestionDuplicate
};