Skip to content

Glosario y Ubiquitous Language

Este glosario define los términos clave y el Ubiquitous Language de Bodibly, la app de fitness para tracking en el gimnasio. Su objetivo es alinear la comunicación y el entendimiento entre desarrolladores, diseñadores y cualquier miembro del equipo.

¿Por qué un glosario?

Un glosario y un lenguaje ubicuo (Ubiquitous Language) ayudan a evitar malentendidos y aseguran que todos los conceptos importantes de la aplicación tengan una definición clara y compartida.


Términos principales

Usuario (User)

Persona que utiliza la aplicación Bodibly para registrar y hacer seguimiento de sus entrenamientos.

Equipo (Equipment)

Tipo de equipamiento que un ejercicio requiere. Ejemplo: barra, mancuerna, peso corporal, banda elástica, etc.

Patrón de Movimiento (Movement Pattern)

Forma general en la que se ejecuta un ejercicio, como empuje, jalón, rotación interna, rotación externa, etc.

Grupo Muscular (Muscle Group)

Conjunto grande de músculos relacionados, como piernas, espalda, brazos, pecho, etc.

Músculo (Muscle)

Músculo específico que pertenece a un grupo muscular. Ejemplo: cuádriceps (pertenece a piernas), pectoral mayor (pertenece a pecho).

Disciplina (Discipline)

Estilo o categoría de práctica al que pertenece un ejercicio. Ejemplos: fuerza, culturismo, calistenia, crossfit, powerlifting, halterofilia, cardio, movilidad. Un mismo ejercicio puede pertenecer a varias disciplinas (por ejemplo, una sentadilla con barra es a la vez fuerza, culturismo, crossfit y powerlifting).

Tipo de Medición de Set (Set Measurement Type)

Forma en la que se registra un set de un ejercicio. Define qué datos pide la app al usuario al loggearlo. Ejemplos: peso + repeticiones (press de banca), solo repeticiones (dominadas con peso corporal), solo tiempo (plancha), distancia + tiempo (correr o remar), peso + tiempo (cargas con peso). Cada tipo declara qué campos son obligatorios y cuáles permite opcionalmente — un mismo ejercicio puede ser por tiempo y aún así aceptar peso adicional (ver Carga Opcional).

Tipo de Set (Set Type)

Clasificación de un set según la intención del usuario al ejecutarlo. Cuatro valores iniciales: Calentamiento (carga submáxima de preparación, se excluye de PRs y volúmenes), Set de Trabajo (entrenamiento estándar, valor por defecto), Drop Set (set adicional con carga reducida tras un set de trabajo) y Hasta el Fallo (llevado hasta no poder completar otra repetición). Permite que el usuario revise su historial sabiendo cuál era el objetivo de cada set.

Carga Opcional

Algunos tipos de medición permiten añadir peso opcionalmente aunque no lo requieran (por ejemplo, un plank o una dominada se pueden hacer con peso adicional). El backend admite el peso cuando el set_measurement_type correspondiente lo permite (allows_weight = true); el cliente puede mostrar este campo como opcional en la UI.

Ejercicio (Exercise)

Unidad mínima de trabajo físico que un usuario puede ejecutar y registrar. Combina un Patrón de Movimiento, un Equipo principal sugerido (con alternativas válidas), uno o más Músculos involucrados (con rol primario o secundario), un Tipo de Medición de Set y una o más Disciplinas a las que pertenece. En esta iteración solo existen ejercicios pre-definidos por el sistema; los ejercicios creados por el usuario llegarán en otra iteración.

Músculo Primario (Primary Muscle)

Motor principal de un ejercicio. Es el músculo que realiza el mayor trabajo durante el movimiento (por ejemplo, el pectoral mayor en el press de banca).

Músculo Secundario (Secondary Muscle)

Músculo sinergista o estabilizador en un ejercicio. Aporta al movimiento sin ser el motor principal (por ejemplo, el tríceps en el press de banca).

Sistema de Medición (Measurement System)

Preferencia del usuario sobre el sistema de unidades a usar por defecto en la app. Dos valores posibles: métrico (kg, cm, km) e imperial (lb, ft/in, mi). Se define durante el onboarding y es editable desde el perfil. Este valor decide la unidad por defecto al loggear sets, pero la unidad de cada set en una sesión es editable individualmente porque en el gimnasio es común mezclar equipo en kg y en lb.

Sesión de Entrenamiento (Workout Session)

Periodo durante el cual el usuario realiza ejercicios y registra sus sets. Tiene un inicio (started_at) y un fin (ended_at); mientras ended_at es nulo la sesión está activa. Solo puede haber una sesión activa por usuario a la vez. Al finalizar, el usuario puede asignar un esfuerzo percibido (1-10) que describe qué tan exigente fue la sesión completa.

Resumen al finalizar. POST /sessions/{id}/finish devuelve, además del header de la sesión, un objeto summary con todo lo que el cliente necesita para renderizar la pantalla de celebración sin llamadas adicionales:

  • duration_seconds — derivado de started_at/ended_at.
  • total_volume_kgSUM(weight_kg × reps) cross-ejercicio. No es una partición: un mismo set golpea varios músculos y contribuye a cada uno; sumar muscles_worked.volume_kg excede este total.
  • sets_completed{ total, by_type } con un breakdown por set_type_code.
  • muscles_worked y muscle_groups_worked — atribución por músculo / grupo (id + code + name i18n + sets_count + volume_kg). Cada set cuenta para todos los músculos del ejercicio (sin ponderar por rol primario/secundario en este MVP).
  • personal_records — los PRs nuevos detectados en esta sesión, ya hidratados con exercise_code + exercise_name y con previous_value para mostrar "+5 kg desde tu PR anterior".

El summary es best-effort: si falla el detector de PRs o la query de agregados, la sesión queda cerrada igual y la parte que falló se omite/cero. Clientes deben tolerar ausencia del campo summary.

Hidratación y nomenclatura del historial. Al consultar el detalle de una sesión, cada Ejercicio dentro de ella viene con su nombre traducido vigente (no un texto congelado). Si el equipo renombra un ejercicio en el catálogo, todo el historial muestra el nuevo nombre al instante. El identificador histórico estable es el exercise_code (snapshot tomado al añadir el ejercicio a la sesión); el name siempre refleja el catálogo actual. Un ejercicio archivado sigue siendo visible en el historial con un indicador is_archived: true — el cliente debe mostrarlo de forma diferenciada (gris, badge "archivado") sin romper la pantalla.

Listado de historial. La lista paginada de sesiones finalizadas (GET /sessions) incluye exercises_count y sets_count por sesión para construir cards previews sin llamadas adicionales. La lista no incluye los ejercicios completos; un eventual ?expand=preview se reserva para iteraciones futuras y el frontend no debe asumir su disponibilidad.

Set

Una serie individual de un ejercicio dentro de una sesión, registrada con peso, repeticiones, tiempo y/o distancia, según el Tipo de Medición de Set del ejercicio. Lleva su propio Tipo de Set (calentamiento, trabajo, drop set, hasta el fallo) y opcionalmente RPE, descanso post-set y notas.

Esfuerzo Percibido (Perceived Effort)

Escala 1-10 que el usuario asigna a la sesión completa al finalizarla; refleja qué tan exigente fue el entrenamiento en su totalidad. No confundir con RPE, que se aplica por set.

RPE (Rate of Perceived Exertion)

Escala 1-10 por set indicando qué tan cerca de fallo muscular llegó el usuario en esa serie (10 = fallo completo, 9 = pude hacer una más, etc.). Es opcional y se ingresa al loggear cada set.

Superset

Agrupación de 2 a 10 ejercicios que el usuario realiza en secuencia sin descanso entre ellos. Internamente se modela con un identificador compartido (superset_group_id) entre los ejercicios involucrados, no por contigüidad posicional. El usuario puede crear o deshacer supersets en cualquier momento de la sesión, e incluso reordenar exercises sin perder la membresía del superset.

Récord Personal (Personal Record / PR)

Mejor marca histórica del usuario en un ejercicio para una métrica concreta. Hoy el sistema rastrea cinco tipos de récord:

  • est_1rm — 1 rep máx estimada con la fórmula de Epley: peso × (1 + reps/30). Solo para sets con peso y reps.
  • heaviest_weight — peso máximo levantado en una sola serie, independientemente de las reps.
  • best_set_volume — mayor volumen en una sola serie (peso × reps).
  • best_time — duración máxima registrada (ej. plancha más larga).
  • longest_distance — distancia máxima registrada.

Los pesos se almacenan y comparan en la unidad canónica (weight_kg, columna GENERATED derivada de weight + weight_unit), por lo que un usuario puede registrar en libras o kilogramos sin afectar la detección de récords.

Cuándo se detectan. Al finalizar una sesión (POST /sessions/{id}/finish). Para cada par (ejercicio, tipo de récord) presente en los sets logueados, el server calcula la mejor marca de la sesión y la compara contra el histórico del usuario; si la sesión beat el récord, inserta una nueva fila en personal_records. La detección es best-effort: una falla en este paso queda registrada en logs pero no impide que la sesión se cierre — la sesión es la fuente de verdad y los récords pueden reconstruirse.

Idempotencia. La tabla tiene un UNIQUE (user_id, exercise_id, record_type, session_id); el INSERT usa ON CONFLICT DO NOTHING. Re-ejecutar la detección sobre la misma sesión (replay, recompute manual, futuro backfill) no duplica filas — la primera ejecución gana, las siguientes son no-op silenciosas.

Edición de sets pasados. Si el usuario edita o borra un set después de finalizar la sesión, los récords ya persistidos no se re-evalúan automáticamente. Al borrar un set su PR asociado se elimina por ON DELETE CASCADE (la marca "no ocurrió"), pero un PR previo no resucita. Re-detección retroactiva queda fuera de scope del MVP.

Lectura. Dos endpoints siblings, ambos paginados y ordenados por achieved_at DESC:

  • GET /users/{userId}/personal-records — todos los récords del usuario cross-ejercicio (vista "mis logros" del dashboard).
  • GET /users/{userId}/exercises/{exerciseId}/personal-records — récords del usuario en un ejercicio concreto (vista detalle del ejercicio, hermano de /stats, /history y /last-performance).

Ambos hidratan exercise_code + exercise_name (i18n map) para evitar N+1 al catálogo. Hoy solo se permite leer los propios récords (403 si userId no coincide con el usuario autenticado); el camino quedó abierto para gamificación / perfiles públicos sin renombrar el contrato.

Analítica de Ejercicio (Exercise Stats)

Vista derivada de los datos crudos del entrenamiento — no introduce tablas ni escrituras propias; es una proyección de personal_records + agregaciones sobre workout_sets. Sirve la pantalla de detalle del ejercicio en la app.

GET /users/{userId}/exercises/{exerciseId}/stats devuelve dos bloques en una sola respuesta:

  • current_bests: snapshot de las mejores marcas all-time del usuario para ese ejercicio, una entrada por Tipo de Récord (est_1rm, heaviest_weight, best_set_volume, best_time, longest_distance). Viene de personal_records (DISTINCT ON record_type ORDER BY achieved_at DESC).
  • timeline: serie temporal con un punto por sesión finalizada donde el ejercicio aparece. Cada punto carga la mejor marca de esa sesión por métrica aplicable, además de sets_count y total_volume_kg (suma weight_kg × reps para volumen-por-sesión chart). Sesiones in-progress se excluyen — no contaminan el chart con datos no comprometidos.

Filtros opcionales ?from=&to= (RFC3339) recortan el rango del timeline; current_bests siempre es all-time. El cliente convierte presets ("3m", "1y") a fechas concretas — el server no maneja vocabulario de presets para mantener consistencia con GET /sessions.

Las métricas que no aplican al ejercicio (ej. best_time en bench press) se omiten del JSON con omitempty en lugar de devolver null. La métrica sets_count siempre aparece, las demás son nullable.

Auth y URL siguen el patrón establecido: 403 si userId no coincide con el actor; preparado para gamificación sin rename.

Historial de Ejercicio (Exercise History)

Listado paginado set-por-set de las sesiones finalizadas donde el usuario hizo ese ejercicio, ordenado de la más reciente a la más antigua. Sibling de Analítica de Ejercicio: mismo dominio, shape diferente — stats agrega para charts, history es el ledger crudo para la lista de "sesiones recientes" del detalle del ejercicio.

GET /users/{userId}/exercises/{exerciseId}/history devuelve sesiones con:

  • Header de la sesión (session_id, started_at, ended_at, session_name, perceived_effort).
  • session_exercises[]: una entrada por cada vez que el ejercicio aparece en esa sesión. El esquema permite repetir el mismo ejercicio (técnica + working, por ejemplo) — cada ocurrencia es un bloque independiente con su session_exercise_id, position, exercise_notes y sus sets. Esto evita que sets de bloques distintos se mezclen en una sola bolsa.
  • Cada set carga weight, weight_unit, weight_kg, reps, duration_seconds, distance_meters, rpe, rest_seconds, set_notes, set_type_code y set_type_name (i18n hidratado). Solo sets del ejercicio pedido — otros ejercicios de la misma sesión se omiten (es history centrado en el ejercicio).

Paginado vía ?page=&page_size= (mismo shape que GET /sessions). Filtros opcionales ?from=&to= (RFC3339) recortan por started_at. Hidratación de set_type_name evita N+1 al catálogo, igual que en el detalle de sesión.

Por qué dos endpoints en lugar de uno: el chart-only screen (widget en home, share-card) no debería pagar la cuota de los sets crudos; el history necesita paginación que el timeline de stats no soporta (un timeline sin paginar crece sin límite para usuarios power tras 2-3 años en el mismo ejercicio).


Relación entre recursos

  • Un Usuario puede registrar Sesiones de Entrenamiento y, en el futuro, ejercicios y rutinas propias.
  • Un Ejercicio pertenece a un Patrón de Movimiento y a un Tipo de Medición de Set, sugiere un Equipo principal y acepta uno o más Equipos alternativos, involucra uno o más Músculos con un rol (primario o secundario), y se clasifica bajo una o más Disciplinas.
  • Un mismo Ejercicio puede pertenecer a varias Disciplinas simultáneamente (por ejemplo, una sentadilla con barra es a la vez fuerza, culturismo, crossfit y powerlifting).
  • Los Músculos siempre pertenecen a un Grupo Muscular.
  • Una Sesión de Entrenamiento contiene uno o más Ejercicios posicionados (opcionalmente agrupados en Supersets), y cada uno tiene uno o más Sets logueados. Cada Set tiene un Tipo de Set (calentamiento, trabajo, drop set, hasta el fallo).
  • Solo puede haber una Sesión de Entrenamiento activa por Usuario a la vez.
  • Un Récord Personal referencia un Set y un Ejercicio concretos del Usuario; se inserta cuando el set bate la mejor marca histórica para el par (ejercicio, tipo de récord).

Notas

  • Las definiciones pueden evolucionar a medida que la app crece.
  • Si tienes dudas sobre un término, consulta este glosario antes de nombrar variables, endpoints o pantallas.

¿Falta algún término? ¡Sugiere una definición nueva!