<commit_before>/// Module for all typings specific to the app.

import { Handler } from "express";


/**
 * Format of the application's routes.
 */
export interface appRoutes {
  [routeUrl: string]: {
    [methodType: string]: Handler;
  }
}

/**
 * A `user`.
 */
export interface user {
  _id?: string;
  email: string;
  password?: string;
}

/**
 * A namespace for encapsulating all structures.
 *
 * Structures are used to model `type`s and `interface`s so that validation
 * can be performed at runtime based on the interface/type for a given
 * model. On top of the structure of a given model which can (hopefully) be
 * automatically created from a given interface/type, custom validation can
 * be added.
 */
export namespace structures {

  /**
   * A `typeStructure` is one of the following four categories.
   */
  export enum typeCategory {
    primitive,
    array,
    union,
    interface
  }

  /**
   * The 6 Javascript primitive types.
   */
  export enum primitiveType {
    string,
    number,
    boolean,
    null,
    undefined,
    symbol
  }

  /**
   * Every type should extend `baseType` so that it specifies what category
   * it is in, this makes programmtically sifting through types simpler.
   */
  export interface baseType {
    typeCategory: typeCategory;
  }

  /**
   * A restriction can be placed on any `restrictableType`, for which it should
   * `Promise.reject(new invalidModelError)` if the `modelInstance` is invalid,
   * otherwise it should `Promise.resolve()`` or simply return void.
   *
   * NOTE: There seems to be slightly strange behaviour when using throwing
   * errors instead of `reject`ing them, so avoid directly throwing errors.
   */
  export type restriction = (modelInstance: any) => void | Promise<void>;

  /**
   * A restrictable type represents a type which can have restrictions.
   * Currently all categories of types support restrictions except for
   * unions (because in a union, each type should have it's own
   * restrictions).
   */
  export interface restrictableType extends baseType {
    restriction?: restriction;
  }

  /**
   * A formal representation of the structure of a `type`.
   */
  export type typeStructure = primitiveStructure | arrayStructure | unionStructure | interfaceStructure;

 /**
  * A formal representation of the structure of an `interface`.
  */
  export interface interfaceStructure extends restrictableType {
    /**
     * The properties on the interface.
     */
    properties: {
      /**
       * Each property has a type.
       */
      [propertyName: string]: typeStructure;
    };
  }

  /**
   * A formal representation of the structure of a primitive.
   */
  export interface primitiveStructure extends restrictableType {
    /**
     * The primitive type.
     */
    type: primitiveType;
  }

  /**
   * A formal representation of the structure of an array.
   *
   * NOTE: The restrictions apply to the array itself, not the elements in
   * the array, the restrictions on the elements themselves will be
   * determined from the restrictions placed on the `type` of the element
   * itself.
   */
  export interface arrayStructure extends restrictableType {
    /**
     * The type of a single element in the array.
     */
    type: typeStructure;
  }

  /**
   * A formal representation of the structure of a union of types.
   *
   * NOTE: that a union has no restrictions because the restrcitions will be
   * present on each individual type in the union.
   */
  export interface unionStructure extends baseType {
    /**
     * A union of all the types in `types`.
     */
    types: typeStructure[];
  }
}

/**
 * All models (in `/models`) should export an implementation of this
 * interface.
 */
export interface model<T> {

  /**
   * Unique name, should be identical to the name of interface `T`.
   */
  name: string;

  /**
   * Prior to responding to an HTTP request with a model, this method should
   * be called to strip sensitive data, eg you don't wanna be sending the
   * user his data with the password attached.
   */
  stripSensitiveDataForResponse: (model: T) => T;
}

/**
 * All errorCodes for simpler programmatic communication between the client and
 * server.
 *
 * NOTE An identical enum should be kept on the frontend/backend.
 */
export enum errorCodes {
  youAreUnauthorized = 1,
  emailAddressAlreadyRegistered,
  noAccountExistsForEmail,
  incorrectPasswordForEmail,
  phoneNumberAlreadyTaken,
  invalidMongoID,
  invalidEmail,
  invalidPassword,
  modelHasInvalidTypeStructure,     // This implies that the API was queried direclty with an incorrectly formed object.
  internalError,                    // For errors that are not handleable
  modelUnionTypeHasMultipleErrors,
  passwordDoesNotMatchConfirmPassword
}
<commit_msg>Data Structures for a User and Workout and Exercises and Preferences and Badges.<commit_after>/// Module for all typings specific to the app.

import { Handler } from "express";


type mongoID = string;

/**
 * Format of the application's routes.
 */
export interface appRoutes {
  [routeUrl: string]: {
    [methodType: string]: Handler;
  }
}

/**
 * A `user`.
 */
export interface user {
  _id?: mongoID;
  name: string;
  email: string;
  password: <PASSWORD>;
  level: number; //default level is 1
  friends: mongoID[]; //default is empty list
  pictureURL: string;
  badges: mongoID[];
  workoutStats: workout[];
  preferences: preferences;
  numberOfWorkoutsDoneToday: number;
  totalPoints: number; // default is 0
}

/**
 * A single workout the user has done.
 */
export interface workout {
  date: Date;
  exercise: exercise;
  numberOfReps: number; //e.g. 23

}

/**
 * User preferences
 */
export interface preferences {
  difficulty: number; // 1 is easy, 2 is medium, 3 is hard
  upperBody: boolean; // does the user want to do upper body exercises?
  lowerBody: boolean; // does the user want to do lower body exercises?
  cardio: boolean; // does the user want to do cardio?
  numberOfWorkoutsPerDay: number;

  // TODO: add time preferences
}

/**
 * An exercise
 */
export interface exercise {
  name: string; //e.g. "pushup"
  difficulty: number; // 1 is easy, 2 is medium, 3 is hard
  description: string;
  type: string; // either "upper body" or "lower body" or "cardio"
}

/**
 * User's weekly progress.
 */
export interface weekly_progress {
  progress: number; // scale of 0-10, 0 means no progress, 10 means user has finished all of the week's tasks
  date: Date;

}

/**
 * A badge that a user is in the progress of earning.
 */
export interface badge {
  _id?: mongoID;
  pictureURL: string;
  name: string;
  description: string;
  progress: number; // scale of 0-10, 0 means no progress, 10 means user has earned the badge
}



/**
 * A namespace for encapsulating all structures.
 *
 * Structures are used to model `type`s and `interface`s so that validation
 * can be performed at runtime based on the interface/type for a given
 * model. On top of the structure of a given model which can (hopefully) be
 * automatically created from a given interface/type, custom validation can
 * be added.
 */
export namespace structures {

  /**
   * A `typeStructure` is one of the following four categories.
   */
  export enum typeCategory {
    primitive,
    array,
    union,
    interface
  }

  /**
   * The 6 Javascript primitive types.
   */
  export enum primitiveType {
    string,
    number,
    boolean,
    null,
    undefined,
    symbol
  }

  /**
   * Every type should extend `baseType` so that it specifies what category
   * it is in, this makes programmtically sifting through types simpler.
   */
  export interface baseType {
    typeCategory: typeCategory;
  }

  /**
   * A restriction can be placed on any `restrictableType`, for which it should
   * `Promise.reject(new invalidModelError)` if the `modelInstance` is invalid,
   * otherwise it should `Promise.resolve()`` or simply return void.
   *
   * NOTE: There seems to be slightly strange behaviour when using throwing
   * errors instead of `reject`ing them, so avoid directly throwing errors.
   */
  export type restriction = (modelInstance: any) => void | Promise<void>;

  /**
   * A restrictable type represents a type which can have restrictions.
   * Currently all categories of types support restrictions except for
   * unions (because in a union, each type should have it's own
   * restrictions).
   */
  export interface restrictableType extends baseType {
    restriction?: restriction;
  }

  /**
   * A formal representation of the structure of a `type`.
   */
  export type typeStructure = primitiveStructure | arrayStructure | unionStructure | interfaceStructure;

 /**
  * A formal representation of the structure of an `interface`.
  */
  export interface interfaceStructure extends restrictableType {
    /**
     * The properties on the interface.
     */
    properties: {
      /**
       * Each property has a type.
       */
      [propertyName: string]: typeStructure;
    };
  }

  /**
   * A formal representation of the structure of a primitive.
   */
  export interface primitiveStructure extends restrictableType {
    /**
     * The primitive type.
     */
    type: primitiveType;
  }

  /**
   * A formal representation of the structure of an array.
   *
   * NOTE: The restrictions apply to the array itself, not the elements in
   * the array, the restrictions on the elements themselves will be
   * determined from the restrictions placed on the `type` of the element
   * itself.
   */
  export interface arrayStructure extends restrictableType {
    /**
     * The type of a single element in the array.
     */
    type: typeStructure;
  }

  /**
   * A formal representation of the structure of a union of types.
   *
   * NOTE: that a union has no restrictions because the restrcitions will be
   * present on each individual type in the union.
   */
  export interface unionStructure extends baseType {
    /**
     * A union of all the types in `types`.
     */
    types: typeStructure[];
  }
}

/**
 * All models (in `/models`) should export an implementation of this
 * interface.
 */
export interface model<T> {

  /**
   * Unique name, should be identical to the name of interface `T`.
   */
  name: string;

  /**
   * Prior to responding to an HTTP request with a model, this method should
   * be called to strip sensitive data, eg you don't wanna be sending the
   * user his data with the password attached.
   */
  stripSensitiveDataForResponse: (model: T) => T;
}

/**
 * All errorCodes for simpler programmatic communication between the client and
 * server.
 *
 * NOTE An identical enum should be kept on the frontend/backend.
 */
export enum errorCodes {
  youAreUnauthorized = 1,
  emailAddressAlreadyRegistered,
  noAccountExistsForEmail,
  incorrectPasswordForEmail,
  phoneNumberAlreadyTaken,
  invalidMongoID,
  invalidEmail,
  invalidPassword,
  modelHasInvalidTypeStructure,     // This implies that the API was queried direclty with an incorrectly formed object.
  internalError,                    // For errors that are not handleable
  modelUnionTypeHasMultipleErrors,
  passwordDoesNotMatchConfirmPassword
}

{'fraction_non_alphanumeric': 0.08395238521435604, 'fraction_numerical': 0.002327038396133536, 'mean_word_length': 3.0339350180505416, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7179508', 'n_tokens_mistral': 3051, 'n_tokens_neox': 2981, 'n_words': 1276}