Fix: www/ movido a raíz, estructura final
@@ -0,0 +1,28 @@
|
||||
# Dependencias
|
||||
node_modules/
|
||||
descargar-curso/node_modules/
|
||||
|
||||
# Archivos de sesión
|
||||
descargar-curso/session.json
|
||||
descargar-curso/.cookies_*.txt
|
||||
descargar-curso/.mapa_videos.json
|
||||
descargar-curso/.videos_descargados.txt
|
||||
descargar-curso/.lista_videos.txt
|
||||
|
||||
# Videos descargados (son grandes, mejor no subirlos)
|
||||
descargar-curso/descargas/videos_offline/
|
||||
|
||||
# Temporales
|
||||
/tmp/
|
||||
*.tmp
|
||||
*.part
|
||||
*.ytdl
|
||||
|
||||
# Logs
|
||||
descargar-curso/descarga_videos.log
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
www/assets/resources/*/*.mp4
|
||||
www/assets/resources/mx_sin-modulo/*.mp4
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* deploy.php — Webhook de deploy automático para ksaldis-dt
|
||||
*
|
||||
* Gitea envía POST a esta URL al hacer push.
|
||||
* Ejecuta deploy_ksaldis.sh para actualizar el contenido.
|
||||
*
|
||||
* Configuración en Gitea:
|
||||
* Settings → Webhooks → Add webhook (Gitea)
|
||||
* URL: https://rmonla.duckdns.org/ksaldis-dt/deploy.php
|
||||
* Content type: application/json
|
||||
* Secret: ksaldis2026deploy
|
||||
* Events: Push events
|
||||
*/
|
||||
|
||||
define('WEBHOOK_SECRET', 'ksaldis2026deploy');
|
||||
|
||||
// Solo POST
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
die('Method not allowed');
|
||||
}
|
||||
|
||||
// Verificar firma de Gitea (X-Gitea-Signature usa HMAC SHA256)
|
||||
$payload = file_get_contents('php://input');
|
||||
$signature = $_SERVER['HTTP_X_GITEA_SIGNATURE'] ?? '';
|
||||
|
||||
if ($signature) {
|
||||
$expected = hash_hmac('sha256', $payload, WEBHOOK_SECRET);
|
||||
if (!hash_equals($expected, $signature)) {
|
||||
http_response_code(403);
|
||||
die('Invalid signature');
|
||||
}
|
||||
}
|
||||
|
||||
// Ejecutar deploy
|
||||
$scriptPath = __DIR__ . '/deploy_ksaldis.sh';
|
||||
$output = [];
|
||||
$returnCode = 0;
|
||||
|
||||
exec("bash $scriptPath 2>&1", $output, $returnCode);
|
||||
|
||||
// Respuesta
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'ok' => $returnCode === 0,
|
||||
'output' => implode("\n", $output),
|
||||
'time' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
# deploy_ksaldis.sh — Script de deploy automático
|
||||
# Llamado por el webhook de Gitea al hacer push
|
||||
#
|
||||
# Clona/actualiza el repo y copia LIBRO_DE_ESTUDIO.html como index.html
|
||||
|
||||
set -e
|
||||
|
||||
REPO_DIR="/var/www/ksaldis-dt/.repo"
|
||||
WEB_DIR="/var/www/ksaldis-dt"
|
||||
REPO_URL="http://10.0.10.205:3000/rmonla/rm-KSALDIS-DT.git"
|
||||
LOG="$WEB_DIR/deploy.log"
|
||||
|
||||
log() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') | $1" >> "$LOG"
|
||||
}
|
||||
|
||||
log "Deploy iniciado"
|
||||
|
||||
# Clonar o actualizar repo
|
||||
GIT="git -c safe.directory=$REPO_DIR"
|
||||
if [ -d "$REPO_DIR/.git" ]; then
|
||||
cd "$REPO_DIR"
|
||||
$GIT fetch origin 2>&1
|
||||
$GIT reset --hard origin/main 2>&1
|
||||
log "git pull OK"
|
||||
else
|
||||
git clone "$REPO_URL" "$REPO_DIR" 2>&1
|
||||
log "git clone OK"
|
||||
fi
|
||||
|
||||
# Copiar el libro como index.html
|
||||
SRC="$REPO_DIR/descargar-curso/descargas/LIBRO_DE_ESTUDIO.html"
|
||||
if [ -f "$SRC" ]; then
|
||||
cp "$SRC" "$WEB_DIR/index.html"
|
||||
log "index.html actualizado ($(wc -c < "$WEB_DIR/index.html") bytes)"
|
||||
else
|
||||
log "ERROR: LIBRO_DE_ESTUDIO.html no encontrado en el repo"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Deploy completado"
|
||||
@@ -0,0 +1,836 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* COMPLETAR OFFLINE — Versión definitiva
|
||||
* =======================================
|
||||
*
|
||||
* 1. Descarga los 42 videos de Vimeo usando las cookies de sesión
|
||||
* 2. Los convierte a formato compatible con navegador (MP4)
|
||||
* 3. Regenera LIBRO_DE_ESTUDIO.html y LIBRO_DE_ESTUDIO.md
|
||||
* con los videos incrustados como <video> local o referencias
|
||||
*
|
||||
* Modo de uso:
|
||||
* node completar_offline.mjs
|
||||
*
|
||||
* Requisitos:
|
||||
* - yt-dlp instalado (pip install yt-dlp)
|
||||
* - session.json de Playwright en la carpeta raíz
|
||||
* - Los HTML descargados (de download_course.mjs)
|
||||
*
|
||||
* Archivos de salida:
|
||||
* descargas/videos_offline/ → videos descargados (.mp4)
|
||||
* descargas/LIBRO_DE_ESTUDIO.html → libro con videos locales
|
||||
* descargas/LIBRO_DE_ESTUDIO.md → libro con referencias
|
||||
*/
|
||||
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { execSync, spawn } from "child_process";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const DOWNLOADS_DIR = path.join(__dirname, "descargas");
|
||||
const SECCIONES_DIR = path.join(DOWNLOADS_DIR, "secciones");
|
||||
const VIDEOS_DIR = path.join(DOWNLOADS_DIR, "videos_offline");
|
||||
const SESSION_JSON = path.join(__dirname, "session.json");
|
||||
const COOKIES_TXT = "/tmp/cookies_netscape_voley.txt";
|
||||
|
||||
// ── Estructura del curso ──
|
||||
const MODULOS = [
|
||||
{
|
||||
titulo: "Módulo 1 — Planificación",
|
||||
carpeta: "Modulo_1_Planificacion",
|
||||
secciones: [
|
||||
{ carpeta: "Planificacion", titulo: "Planificación" },
|
||||
{ carpeta: "Preparacion_Atletica", titulo: "Preparación Atlética" },
|
||||
{ carpeta: "Explicacion_TP", titulo: "Explicación del Trabajo Práctico" },
|
||||
{ carpeta: "Seguimientos_Equipos", titulo: "Seguimientos de Equipos" },
|
||||
{ carpeta: "Analisis_Equipos_1", titulo: "Análisis de Equipos 1" },
|
||||
{ carpeta: "Analisis_Equipos_2", titulo: "Análisis de Equipos 2" },
|
||||
{ carpeta: "TP_Final_Unidad", titulo: "TP Final de la Unidad" },
|
||||
],
|
||||
},
|
||||
{
|
||||
titulo: "Módulo 2 — Entrenamiento",
|
||||
carpeta: "Modulo_2_Entrenamiento",
|
||||
secciones: [
|
||||
{ carpeta: "Centrales_y_Oponentes", titulo: "Centrales y Opuestos/as" },
|
||||
{ carpeta: "Puntas_y_Liberos", titulo: "Puntas y Liberos/as" },
|
||||
{
|
||||
carpeta: "Entrenamiento_Armadoras",
|
||||
titulo: "Entrenamiento de Armadoras",
|
||||
},
|
||||
{ carpeta: "Explicacion_TP", titulo: "Explicación del TP" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// FUNCIONES AUXILIARES
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
function log(msg) {
|
||||
const ts = new Date().toISOString().replace("T", " ").substring(0, 19);
|
||||
console.log(`[${ts}] ${msg}`);
|
||||
}
|
||||
|
||||
function ensureDir(dir) {
|
||||
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise((r) => setTimeout(r, ms));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convierte el session.json de Playwright a cookies en formato Netscape
|
||||
* que yt-dlp pueda usar.
|
||||
*/
|
||||
function convertirCookies() {
|
||||
if (!fs.existsSync(SESSION_JSON)) {
|
||||
log("⚠ No se encontró session.json. Ejecutá primero download_course.mjs");
|
||||
return false;
|
||||
}
|
||||
|
||||
const data = JSON.parse(fs.readFileSync(SESSION_JSON, "utf-8"));
|
||||
const cookies = data.cookies || [];
|
||||
|
||||
const lines = ["# Netscape HTTP Cookie File"];
|
||||
for (const c of cookies) {
|
||||
const domain = c.domain;
|
||||
const flag = domain.startsWith(".") ? "TRUE" : "FALSE";
|
||||
const path = c.path || "/";
|
||||
const secure = c.secure ? "TRUE" : "FALSE";
|
||||
const exp = c.expires > 0 ? String(Math.floor(c.expires)) : "1778594896";
|
||||
const name = c.name;
|
||||
const value = c.value;
|
||||
lines.push(
|
||||
`${domain}\t${flag}\t${path}\t${secure}\t${exp}\t${name}\t${value}`,
|
||||
);
|
||||
}
|
||||
|
||||
fs.writeFileSync(COOKIES_TXT, lines.join("\n") + "\n");
|
||||
log(`✓ Cookies convertidas (${cookies.length} cookies)`);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// PASO 1: EXTRAER TODOS LOS VIDEOS DEL HTML DESCARGADO
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
function extraerTodosLosVideos() {
|
||||
const videos = [];
|
||||
const vistos = new Set();
|
||||
|
||||
for (const modulo of MODULOS) {
|
||||
for (const seccion of modulo.secciones) {
|
||||
const htmlPath = path.join(
|
||||
SECCIONES_DIR,
|
||||
modulo.carpeta,
|
||||
seccion.carpeta,
|
||||
"pagina.html",
|
||||
);
|
||||
if (!fs.existsSync(htmlPath)) continue;
|
||||
|
||||
const html = fs.readFileSync(htmlPath, "utf-8");
|
||||
if (html.includes("500 Internal Server Error")) continue;
|
||||
|
||||
// Buscar todos los IDs de Vimeo en esta página
|
||||
const regex = /player\.vimeo\.com\/video\/(\d+)/g;
|
||||
let match;
|
||||
while ((match = regex.exec(html)) !== null) {
|
||||
const id = match[1];
|
||||
if (vistos.has(id)) continue;
|
||||
vistos.add(id);
|
||||
|
||||
// Extraer el título del tema asociado (buscar hacia atrás)
|
||||
const before = html.substring(
|
||||
Math.max(0, match.index - 400),
|
||||
match.index,
|
||||
);
|
||||
const tituloMatch = before.match(/<em>([^<]+)<\/em>/);
|
||||
const titulo = tituloMatch
|
||||
? tituloMatch[1]
|
||||
.trim()
|
||||
.replace(/[<>:"/\\|?*]+/g, "_")
|
||||
.substring(0, 80)
|
||||
: `video_${id}`;
|
||||
|
||||
// Extraer la página que embebe el video (para pasarla a yt-dlp)
|
||||
const paginaURL = `https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/${modulo.carpeta.includes("1") ? "19096" : "19097"}/s/${seccion.carpeta === "Planificacion" ? "34868" : seccion.carpeta === "Preparacion_Atletica" ? "34869" : seccion.carpeta === "Explicacion_TP" && modulo.carpeta.includes("1") ? "34870" : seccion.carpeta === "Seguimientos_Equipos" ? "35523" : seccion.carpeta === "Analisis_Equipos_1" ? "35524" : seccion.carpeta === "Analisis_Equipos_2" ? "35525" : seccion.carpeta === "TP_Final_Unidad" ? "35526" : seccion.carpeta === "Centrales_y_Oponentes" ? "35519" : seccion.carpeta === "Puntas_y_Liberos" ? "35520" : seccion.carpeta === "Entrenamiento_Armadoras" ? "35521" : seccion.carpeta === "Explicacion_TP" && modulo.carpeta.includes("2") ? "35522" : "35519"}/study-resources/list`;
|
||||
|
||||
videos.push({
|
||||
id,
|
||||
titulo,
|
||||
pagina: seccion.carpeta,
|
||||
modulo: modulo.carpeta,
|
||||
nombreModulo: modulo.titulo,
|
||||
nombreSeccion: seccion.titulo,
|
||||
paginaURL,
|
||||
urlVimeo: `https://player.vimeo.com/video/${id}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return videos;
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// PASO 2: DESCARGA DE VIDEOS
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
async function descargarVideos(videos) {
|
||||
ensureDir(VIDEOS_DIR);
|
||||
|
||||
// Verificar yt-dlp
|
||||
try {
|
||||
execSync("yt-dlp --version", { stdio: "ignore" });
|
||||
} catch {
|
||||
log("✗ yt-dlp no está instalado. Ejecutá: pip install yt-dlp");
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!fs.existsSync(COOKIES_TXT)) {
|
||||
if (!convertirCookies()) return [];
|
||||
}
|
||||
|
||||
const descargados = [];
|
||||
|
||||
for (let i = 0; i < videos.length; i++) {
|
||||
const v = videos[i];
|
||||
const nombreSeguro =
|
||||
`${v.nombreModulo.replace(/[^a-zA-Z0-9_]/g, "_")}_${v.nombreSeccion.replace(/[^a-zA-Z0-9_]/g, "_")}_${v.titulo.replace(/[^a-zA-Z0-9_]/g, "_")}.mp4`.substring(
|
||||
0,
|
||||
120,
|
||||
);
|
||||
const rutaSalida = path.join(VIDEOS_DIR, nombreSeguro);
|
||||
|
||||
if (fs.existsSync(rutaSalida)) {
|
||||
log(
|
||||
` [${i + 1}/${videos.length}] ↺ Ya existe: ${v.titulo.substring(0, 40)}`,
|
||||
);
|
||||
descargados.push({ ...v, archivo: nombreSeguro });
|
||||
continue;
|
||||
}
|
||||
|
||||
log(
|
||||
` [${i + 1}/${videos.length}] ▶ Descargando: ${v.titulo.substring(0, 50)}...`,
|
||||
);
|
||||
|
||||
try {
|
||||
// yt-dlp con la página embebedora como URL y cookies
|
||||
const cmd = [
|
||||
"yt-dlp",
|
||||
"--cookies",
|
||||
COOKIES_TXT,
|
||||
"-o",
|
||||
rutaSalida,
|
||||
"--merge-output-format",
|
||||
"mp4",
|
||||
"--no-playlist",
|
||||
"--progress",
|
||||
"--print",
|
||||
"after_move:OK",
|
||||
v.paginaURL,
|
||||
].join(" ");
|
||||
|
||||
const output = execSync(cmd, {
|
||||
timeout: 300000, // 5 min por video
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
// Verificar que se haya descargado
|
||||
if (fs.existsSync(rutaSalida)) {
|
||||
const sizeMB = (fs.statSync(rutaSalida).size / 1024 / 1024).toFixed(1);
|
||||
log(` ✓ ${sizeMB} MB — ${v.titulo.substring(0, 40)}`);
|
||||
descargados.push({ ...v, archivo: nombreSeguro });
|
||||
} else {
|
||||
log(` ⚠ Archivo no encontrado después de descarga`);
|
||||
}
|
||||
} catch (err) {
|
||||
log(` ✗ Error: ${err.message.substring(0, 100)}`);
|
||||
}
|
||||
|
||||
// Pequeña pausa entre descargas
|
||||
await sleep(1000);
|
||||
}
|
||||
|
||||
return descargados;
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// PASO 3: GENERAR LIBRO DE ESTUDIO CON VIDEOS
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
function extraerTemas(filePath) {
|
||||
const temas = [];
|
||||
try {
|
||||
if (!fs.existsSync(filePath)) return temas;
|
||||
const html = fs.readFileSync(filePath, "utf-8");
|
||||
if (html.includes("500 Internal Server Error")) return temas;
|
||||
|
||||
// Extraer tablas de estudio
|
||||
const tablas = extraerTablas(html);
|
||||
for (const tabla of tablas) {
|
||||
const filas = extraerFilas(tabla);
|
||||
for (const fila of filas) {
|
||||
if (!fila.includes("<td")) continue;
|
||||
const tema = procesarFila(fila);
|
||||
if (tema) temas.push(tema);
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
return temas;
|
||||
}
|
||||
|
||||
function extraerTablas(html) {
|
||||
const tablas = [];
|
||||
let pos = 0;
|
||||
while (true) {
|
||||
const start = html.indexOf(
|
||||
'<table class="table table-bordered study-resources"',
|
||||
pos,
|
||||
);
|
||||
if (start === -1) break;
|
||||
const openEnd = html.indexOf(">", start);
|
||||
if (openEnd === -1) break;
|
||||
|
||||
let depth = 1;
|
||||
let searchPos = openEnd + 1;
|
||||
while (depth > 0 && searchPos < html.length) {
|
||||
const nextOpen = html.indexOf("<table", searchPos);
|
||||
const nextClose = html.indexOf("</table>", searchPos);
|
||||
if (nextClose === -1) break;
|
||||
if (nextOpen !== -1 && nextOpen < nextClose) {
|
||||
depth++;
|
||||
searchPos = nextOpen + 6;
|
||||
} else {
|
||||
depth--;
|
||||
searchPos = nextClose + 8;
|
||||
}
|
||||
}
|
||||
tablas.push(html.substring(start, searchPos));
|
||||
pos = searchPos;
|
||||
}
|
||||
return tablas;
|
||||
}
|
||||
|
||||
function extraerFilas(tablaHTML) {
|
||||
const filas = [];
|
||||
const tbodyStart = tablaHTML.indexOf("<tbody>");
|
||||
if (tbodyStart === -1) return filas;
|
||||
const tbody = tablaHTML.substring(tbodyStart);
|
||||
|
||||
let pos = 0;
|
||||
while (true) {
|
||||
const trStart = tbody.indexOf("<tr", pos);
|
||||
if (trStart === -1) break;
|
||||
let depth = 1;
|
||||
let tableDepth = 0;
|
||||
let searchPos = trStart + 3;
|
||||
while (depth > 0 && searchPos < tbody.length) {
|
||||
const ops = [
|
||||
{ type: "trO", pos: tbody.indexOf("<tr", searchPos) },
|
||||
{ type: "trC", pos: tbody.indexOf("</tr>", searchPos) },
|
||||
{ type: "tableO", pos: tbody.indexOf("<table", searchPos) },
|
||||
{ type: "tableC", pos: tbody.indexOf("</table>", searchPos) },
|
||||
].filter((o) => o.pos !== -1);
|
||||
if (ops.length === 0) break;
|
||||
const earliest = ops.sort((a, b) => a.pos - b.pos)[0];
|
||||
switch (earliest.type) {
|
||||
case "tableO":
|
||||
tableDepth++;
|
||||
searchPos = earliest.pos + 6;
|
||||
break;
|
||||
case "tableC":
|
||||
tableDepth = Math.max(0, tableDepth - 1);
|
||||
searchPos = earliest.pos + 7;
|
||||
break;
|
||||
case "trO":
|
||||
if (tableDepth === 0) depth++;
|
||||
searchPos = earliest.pos + 3;
|
||||
break;
|
||||
case "trC":
|
||||
if (tableDepth === 0) depth--;
|
||||
searchPos = earliest.pos + 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
filas.push(tbody.substring(trStart, searchPos));
|
||||
pos = searchPos;
|
||||
}
|
||||
return filas;
|
||||
}
|
||||
|
||||
function procesarFila(filaHTML) {
|
||||
const tituloMatch = filaHTML.match(/<em>([\s\S]*?)<\/em>/i);
|
||||
const titulo = tituloMatch
|
||||
? limpiarHTML(tituloMatch[1]).trim()
|
||||
: "Sin título";
|
||||
|
||||
const vimeoMatch = filaHTML.match(/player\.vimeo\.com\/video\/(\d+)/i);
|
||||
const vimeoID = vimeoMatch ? vimeoMatch[1] : null;
|
||||
|
||||
const recursoMatch = filaHTML.match(
|
||||
/<a[^>]*href="([^"]*)"[^>]*class="btn[^"]*"[^>]*>(Abrir (?:Archivo|Enlace))<\/a>/i,
|
||||
);
|
||||
const recursoURL = recursoMatch ? recursoMatch[1] : null;
|
||||
const recursoTexto = recursoMatch ? recursoMatch[2] : null;
|
||||
|
||||
const contenidoMatch = filaHTML.match(
|
||||
/<div class="redactor-usr-input">([\s\S]*?)<\/div>/i,
|
||||
);
|
||||
let contenidoHTML = contenidoMatch ? contenidoMatch[1].trim() : "";
|
||||
|
||||
if (!contenidoHTML && !vimeoID && !recursoURL) return null;
|
||||
|
||||
const id = titulo
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9áéíóúüñ]+/gi, "-")
|
||||
.replace(/-+/g, "-")
|
||||
.replace(/^-|-$/g, "");
|
||||
|
||||
return { id, titulo, contenidoHTML, vimeoID, recursoURL, recursoTexto };
|
||||
}
|
||||
|
||||
function limpiarHTML(html) {
|
||||
return html
|
||||
.replace(/<[^>]*>/g, "")
|
||||
.replace(/ /g, " ")
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, "'")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
}
|
||||
|
||||
function htmlAMarkdown(html) {
|
||||
if (!html) return "";
|
||||
let md = html;
|
||||
md = md.replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, "# $1\n\n");
|
||||
md = md.replace(/<h2[^>]*>([\s\S]*?)<\/h2>/gi, "## $1\n\n");
|
||||
md = md.replace(/<h3[^>]*>([\s\S]*?)<\/h3>/gi, "### $1\n\n");
|
||||
md = md.replace(/<h4[^>]*>([\s\S]*?)<\/h4>/gi, "#### $1\n\n");
|
||||
md = md.replace(/<strong>([\s\S]*?)<\/strong>/gi, "**$1**");
|
||||
md = md.replace(/<b>([\s\S]*?)<\/b>/gi, "**$1**");
|
||||
md = md.replace(/<em>([\s\S]*?)<\/em>/gi, "*$1*");
|
||||
md = md.replace(/<i>([\s\S]*?)<\/i>/gi, "*$1*");
|
||||
md = md.replace(/<p[^>]*>([\s\S]*?)<\/p>/gi, "$1\n\n");
|
||||
md = md.replace(/<ul[^>]*>([\s\S]*?)<\/ul>/gi, "$1\n");
|
||||
md = md.replace(/<ol[^>]*>([\s\S]*?)<\/ol>/gi, "$1\n");
|
||||
md = md.replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, "- $1\n");
|
||||
md = md.replace(/<blockquote[^>]*>([\s\S]*?)<\/blockquote>/gi, "> $1\n\n");
|
||||
md = md.replace(/<table[^>]*>([\s\S]*?)<\/table>/gi, (_, t) =>
|
||||
tablaAMarkdown(t),
|
||||
);
|
||||
md = md.replace(/<code[^>]*>([\s\S]*?)<\/code>/gi, "`$1`");
|
||||
md = md.replace(/<hr[^>]*>/gi, "\n---\n");
|
||||
// Entities
|
||||
const ents = {
|
||||
" ": " ",
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
""": '"',
|
||||
"'": "'",
|
||||
"á": "á",
|
||||
"é": "é",
|
||||
"í": "í",
|
||||
"ó": "ó",
|
||||
"ú": "ú",
|
||||
"ñ": "ñ",
|
||||
"Á": "Á",
|
||||
"É": "É",
|
||||
"Í": "Í",
|
||||
"Ó": "Ó",
|
||||
"Ú": "Ú",
|
||||
"Ñ": "Ñ",
|
||||
"ü": "ü",
|
||||
"Ü": "Ü",
|
||||
};
|
||||
for (const [k, v] of Object.entries(ents))
|
||||
md = md.replace(new RegExp(k, "g"), v);
|
||||
md = md.replace(/<[^>]*>/g, "");
|
||||
md = md.replace(/\n{4,}/g, "\n\n\n");
|
||||
md = md.replace(/[ \t]+\n/g, "\n");
|
||||
md = md
|
||||
.split("\n")
|
||||
.map((l) => l.trim())
|
||||
.join("\n");
|
||||
return md.trim();
|
||||
}
|
||||
|
||||
function tablaAMarkdown(tablaHTML) {
|
||||
const filas = [];
|
||||
const rowRegex = /<tr[^>]*>([\s\S]*?)<\/tr>/gi;
|
||||
let match;
|
||||
while ((match = rowRegex.exec(tablaHTML)) !== null) {
|
||||
const celdas = [];
|
||||
const cellRegex = /<t[dh][^>]*>([\s\S]*?)<\/t[dh]>/gi;
|
||||
let cm;
|
||||
while ((cm = cellRegex.exec(match[1])) !== null) {
|
||||
const celda = cm[1]
|
||||
.replace(/<br\s*\/?>/gi, " ")
|
||||
.replace(/<[^>]+>/g, "")
|
||||
.replace(/ /g, " ")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
celdas.push(celda);
|
||||
}
|
||||
if (celdas.length > 0) filas.push(celdas);
|
||||
}
|
||||
if (filas.length === 0) return "";
|
||||
const numCols = Math.max(...filas.map((f) => f.length));
|
||||
let md = "\n";
|
||||
while (filas[0].length < numCols) filas[0].push("");
|
||||
md += "| " + filas[0].join(" | ") + " |\n";
|
||||
md += "| " + filas[0].map(() => "---").join(" | ") + " |\n";
|
||||
for (let i = 1; i < filas.length; i++) {
|
||||
while (filas[i].length < numCols) filas[i].push("");
|
||||
md += "| " + filas[i].join(" | ") + " |\n";
|
||||
}
|
||||
md += "\n";
|
||||
return md;
|
||||
}
|
||||
|
||||
function generarContenido(videosDescargados) {
|
||||
// Mapa de video ID → archivo local
|
||||
const mapaVideos = {};
|
||||
for (const v of videosDescargados) {
|
||||
mapaVideos[v.id] = v.archivo;
|
||||
}
|
||||
|
||||
const libros = [];
|
||||
for (const modulo of MODULOS) {
|
||||
const seccionesConContenido = [];
|
||||
for (const seccion of modulo.secciones) {
|
||||
const htmlPath = path.join(
|
||||
SECCIONES_DIR,
|
||||
modulo.carpeta,
|
||||
seccion.carpeta,
|
||||
"pagina.html",
|
||||
);
|
||||
const temas = extraerTemas(htmlPath);
|
||||
if (temas.length > 0) {
|
||||
// Asignar videos descargados a los temas
|
||||
for (const tema of temas) {
|
||||
if (tema.vimeoID && mapaVideos[tema.vimeoID]) {
|
||||
tema.videoLocal = mapaVideos[tema.vimeoID];
|
||||
}
|
||||
}
|
||||
seccionesConContenido.push({ titulo: seccion.titulo, temas });
|
||||
}
|
||||
}
|
||||
if (seccionesConContenido.length > 0) {
|
||||
libros.push({ titulo: modulo.titulo, secciones: seccionesConContenido });
|
||||
}
|
||||
}
|
||||
return libros;
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// GENERAR MARKDOWN
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
function generarMarkdown(libros) {
|
||||
const fecha = new Date().toLocaleDateString("es-AR", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
});
|
||||
let totalTemas = 0;
|
||||
let md = `# Curso de Entrenador Nacional de Vóley
|
||||
## Material de Estudio Completo
|
||||
|
||||
*Generado el ${fecha}*
|
||||
*Incluye contenido de texto + videos descargados offline*
|
||||
|
||||
---
|
||||
|
||||
`;
|
||||
|
||||
for (const modulo of libros) {
|
||||
md += `# ${modulo.titulo}\n\n`;
|
||||
for (const seccion of modulo.secciones) {
|
||||
md += `## ${seccion.titulo}\n\n`;
|
||||
for (let t = 0; t < seccion.temas.length; t++) {
|
||||
const tema = seccion.temas[t];
|
||||
totalTemas++;
|
||||
md += `### ${t + 1}. ${tema.titulo}\n\n`;
|
||||
|
||||
if (tema.videoLocal) {
|
||||
md += `🎬 **Video:** \`${tema.videoLocal}\` *(archivo local)*\n\n`;
|
||||
} else if (tema.vimeoID) {
|
||||
md += `📹 *Video disponible — ID: ${tema.vimeoID}*\n\n`;
|
||||
}
|
||||
|
||||
if (tema.contenidoHTML) {
|
||||
md += htmlAMarkdown(tema.contenidoHTML);
|
||||
md += "\n\n";
|
||||
}
|
||||
|
||||
if (tema.recursoURL) {
|
||||
const icono = tema.recursoTexto === "Abrir Archivo" ? "📄" : "🔗";
|
||||
md += `${icono} **${tema.recursoTexto}:** ${tema.titulo} — \`${tema.recursoURL}\`\n\n`;
|
||||
}
|
||||
|
||||
if (t < seccion.temas.length - 1) md += "---\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
md += `\n---\n*Fin del material. ${totalTemas} temas · ${Object.keys(mapaVideos).filter((k) => mapaVideos[k]).length} videos descargados.*\n`;
|
||||
return md;
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// GENERAR HTML (con videos incrustados)
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
let mapaVideos = {};
|
||||
|
||||
function generarHTML(libros) {
|
||||
const fecha = new Date().toLocaleDateString("es-AR", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
});
|
||||
let totalModulos = libros.length;
|
||||
let totalSecciones = 0;
|
||||
let totalTemas = 0;
|
||||
for (const m of libros) {
|
||||
totalSecciones += m.secciones.length;
|
||||
for (const s of m.secciones) totalTemas += s.temas.length;
|
||||
}
|
||||
const totalVidsDesc = Object.values(mapaVideos).filter(Boolean).length;
|
||||
|
||||
const videoHTML = (tema) => {
|
||||
if (tema.videoLocal) {
|
||||
const rutaRelativa = `../videos_offline/${tema.videoLocal}`;
|
||||
return `<div class="video-wrapper">
|
||||
<video controls preload="metadata" width="100%">
|
||||
<source src="${rutaRelativa}" type="video/mp4">
|
||||
Tu navegador no soporta video HTML5.
|
||||
</video>
|
||||
<div class="video-label">🎬 ${tema.titulo}</div>
|
||||
</div>`;
|
||||
}
|
||||
if (tema.vimeoID) {
|
||||
return `<p class="video-ref">📹 <em>Video no descargado (ID: ${tema.vimeoID})</em></p>`;
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
const css = `
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: 'Segoe UI', Georgia, serif; background: #f5f3ef; color: #2c2c2c; line-height: 1.8; font-size: 17px; }
|
||||
.portada { background: linear-gradient(135deg, #0d2b3e 0%, #1a5276 50%, #2980b9 100%); color: white; padding: 5rem 2rem; text-align: center; min-height: 70vh; display: flex; flex-direction: column; justify-content: center; align-items: center; }
|
||||
.portada h1 { font-size: 2.8rem; margin-bottom: 0.5rem; font-weight: 700; }
|
||||
.portada h2 { font-size: 1.4rem; font-weight: 300; opacity: 0.9; }
|
||||
.portada .stats { margin-top: 2rem; display: flex; gap: 2rem; flex-wrap: wrap; justify-content: center; }
|
||||
.portada .stat { background: rgba(255,255,255,0.12); padding: 0.6rem 1.2rem; border-radius: 8px; font-size: 0.9rem; }
|
||||
.indice { background: white; padding: 2rem; max-width: 900px; margin: 0 auto; border-bottom: 1px solid #e0e0e0; }
|
||||
.indice h2 { color: #0d2b3e; margin-bottom: 1rem; }
|
||||
.indice ul { list-style: none; }
|
||||
.indice li { padding: 0.3rem 0; }
|
||||
.indice a { color: #1a5276; text-decoration: none; border-bottom: 1px solid #ddd; }
|
||||
.indice a:hover { border-bottom-color: #1a5276; }
|
||||
.indice .mod-tit { font-weight: 600; margin-top: 0.8rem; color: #0d2b3e; font-size: 1.05rem; }
|
||||
.contenido { max-width: 900px; margin: 0 auto; padding: 2rem; background: white; }
|
||||
.contenido h1 { color: #0d2b3e; font-size: 2rem; border-bottom: 3px solid #2980b9; padding-bottom: 0.5rem; margin: 3rem 0 1.5rem; }
|
||||
.contenido h2 { color: #1a5276; font-size: 1.5rem; margin: 2rem 0 1rem; border-left: 4px solid #2980b9; padding-left: 0.8rem; }
|
||||
.contenido h3 { color: #0d2b3e; font-size: 1.15rem; margin: 1.5rem 0 0.5rem; }
|
||||
.contenido p { margin: 0.6rem 0; text-align: justify; }
|
||||
.contenido ul, .contenido ol { margin: 0.6rem 0; padding-left: 1.5rem; }
|
||||
.contenido li { margin: 0.3rem 0; }
|
||||
.contenido strong { color: #0d2b3e; }
|
||||
.contenido hr { border: none; border-top: 1px solid #e0e0e0; margin: 1.5rem 0; }
|
||||
.contenido table { width: 100%; border-collapse: collapse; margin: 1rem 0; font-size: 0.9rem; }
|
||||
.contenido th, .contenido td { border: 1px solid #ddd; padding: 0.5rem; text-align: left; }
|
||||
.contenido th { background: #0d2b3e; color: white; }
|
||||
.contenido tr:nth-child(even) { background: #f9f9f9; }
|
||||
.contenido blockquote { border-left: 4px solid #2980b9; margin: 1rem 0; padding: 0.5rem 1rem; background: #f0f5fa; font-style: italic; color: #555; }
|
||||
.contenido .tema-num { background: #2980b9; color: white; display: inline-block; padding: 0.1rem 0.5rem; border-radius: 4px; font-size: 0.8rem; margin-right: 0.5rem; }
|
||||
.video-wrapper { margin: 1rem 0; background: #000; border-radius: 8px; overflow: hidden; }
|
||||
.video-wrapper video { display: block; max-height: 500px; }
|
||||
.video-label { background: #0d2b3e; color: white; padding: 0.4rem 0.8rem; font-size: 0.85rem; text-align: center; }
|
||||
.video-ref { color: #888; font-style: italic; font-size: 0.9rem; margin: 0.5rem 0; padding: 0.3rem 0.6rem; border-left: 3px solid #ccc; background: #fafafa; }
|
||||
.recurso-link { display: inline-block; background: #e8f4f8; border: 1px solid #b3d9e8; border-radius: 4px; padding: 0.2rem 0.6rem; font-size: 0.85rem; margin: 0.3rem 0; color: #1a5276; text-decoration: none; }
|
||||
.recurso-link:hover { background: #d0ebf5; }
|
||||
.footer { text-align: center; padding: 3rem 2rem; color: #999; font-size: 0.85rem; max-width: 900px; margin: 0 auto; }
|
||||
|
||||
@media (max-width: 600px) {
|
||||
body { font-size: 15px; }
|
||||
.portada { padding: 2rem 1rem; min-height: auto; }
|
||||
.portada h1 { font-size: 1.8rem; }
|
||||
.contenido { padding: 1rem; }
|
||||
}
|
||||
`;
|
||||
|
||||
// Índice
|
||||
let idx = '<div class="indice"><h2>📑 Índice de contenidos</h2><ul>';
|
||||
for (const modulo of libros) {
|
||||
idx += `<li class="mod-tit">${modulo.titulo}</li><ul>`;
|
||||
for (let j = 0; j < modulo.secciones.length; j++) {
|
||||
const s = modulo.secciones[j];
|
||||
const anchor = `sec-${modulo.titulo.replace(/[^a-zA-Z0-9]/g, "")}-${s.titulo.replace(/[^a-zA-Z0-9]/g, "")}`;
|
||||
idx += `<li><a href="#${anchor}">${s.titulo} (${s.temas.length} temas)</a></li>`;
|
||||
}
|
||||
idx += "</ul>";
|
||||
}
|
||||
idx += "</ul></div>";
|
||||
|
||||
// Cuerpo
|
||||
let body = "";
|
||||
for (const modulo of libros) {
|
||||
body += `<h1>${modulo.titulo}</h1>\n`;
|
||||
for (const seccion of modulo.secciones) {
|
||||
const anchor = `sec-${modulo.titulo.replace(/[^a-zA-Z0-9]/g, "")}-${seccion.titulo.replace(/[^a-zA-Z0-9]/g, "")}`;
|
||||
body += `<h2 id="${anchor}">${seccion.titulo}</h2>\n`;
|
||||
for (let t = 0; t < seccion.temas.length; t++) {
|
||||
const tema = seccion.temas[t];
|
||||
body += `<h3><span class="tema-num">${t + 1}</span> ${tema.titulo}</h3>\n`;
|
||||
body += videoHTML(tema);
|
||||
if (tema.contenidoHTML) {
|
||||
body += `<div class="estudio-contenido">${tema.contenidoHTML}</div>\n`;
|
||||
}
|
||||
if (tema.recursoURL) {
|
||||
const icono = tema.recursoTexto === "Abrir Archivo" ? "📄" : "🔗";
|
||||
const urlCompleta = tema.recursoURL.startsWith("http")
|
||||
? tema.recursoURL
|
||||
: `https://voley.onlineeducation.center${tema.recursoURL}`;
|
||||
body += `<p><a class="recurso-link" href="${urlCompleta}" target="_blank">${icono} ${tema.recursoTexto}: ${tema.titulo}</a></p>\n`;
|
||||
}
|
||||
if (t < seccion.temas.length - 1) body += "<hr>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Footer
|
||||
body += `<p style="text-align:center;color:#999;margin-top:3rem;font-size:0.85rem;">— Fin del material de estudio —</p>`;
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Curso de Vóley — Material de Estudio Completo</title>
|
||||
<style>${css}</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="portada">
|
||||
<h1>🏐 Curso de Entrenador Nacional de Vóley</h1>
|
||||
<h2>Material de Estudio Completo</h2>
|
||||
<p>Contenido + videos descargados — 100% offline</p>
|
||||
<div class="stats">
|
||||
<div class="stat">📚 ${totalModulos} módulos</div>
|
||||
<div class="stat">📖 ${totalSecciones} secciones</div>
|
||||
<div class="stat">🎯 ${totalTemas} temas</div>
|
||||
<div class="stat">🎬 ${totalVidsDesc} videos</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${idx}
|
||||
|
||||
<div class="contenido">
|
||||
${body}
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>Generado el ${fecha} — Online Education Center</p>
|
||||
<p>Material de estudio 100% offline</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// MAIN
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
async function main() {
|
||||
console.log("");
|
||||
console.log("═══════════════════════════════════════════════════");
|
||||
console.log(" COMPLETAR OFFLINE — Videos + Libro de Estudio");
|
||||
console.log("═══════════════════════════════════════════════════");
|
||||
console.log("");
|
||||
|
||||
// Paso 1: Extraer videos del HTML
|
||||
log("Paso 1: Extrayendo videos del contenido descargado...");
|
||||
const todosLosVideos = extraerTodosLosVideos();
|
||||
log(` ✓ ${todosLosVideos.length} videos únicos encontrados`);
|
||||
log("");
|
||||
|
||||
// Paso 2: Descargar videos
|
||||
log("Paso 2: Descargando videos de Vimeo...");
|
||||
log(" (Puede tomar tiempo dependiendo de tu conexión)");
|
||||
log("");
|
||||
|
||||
const videosDescargados = await descargarVideos(todosLosVideos);
|
||||
log("");
|
||||
log(
|
||||
` ✓ ${videosDescargados.length}/${todosLosVideos.length} videos descargados`,
|
||||
);
|
||||
|
||||
// Construir mapa global
|
||||
globalThis.mapaVideos = {};
|
||||
for (const v of videosDescargados) {
|
||||
globalThis.mapaVideos[v.id] = v.archivo;
|
||||
}
|
||||
|
||||
// Paso 3: Generar libro de estudio
|
||||
log("");
|
||||
log("Paso 3: Generando libro de estudio con videos...");
|
||||
const libros = generarContenido(videosDescargados);
|
||||
|
||||
// Markdown
|
||||
const md = generarMarkdown(libros);
|
||||
const mdPath = path.join(DOWNLOADS_DIR, "LIBRO_DE_ESTUDIO.md");
|
||||
fs.writeFileSync(mdPath, md, "utf-8");
|
||||
log(` ✓ ${mdPath} (${(md.length / 1024).toFixed(0)} KB)`);
|
||||
|
||||
// HTML
|
||||
const html = generarHTML(libros);
|
||||
const htmlPath = path.join(DOWNLOADS_DIR, "LIBRO_DE_ESTUDIO.html");
|
||||
fs.writeFileSync(htmlPath, html, "utf-8");
|
||||
log(` ✓ ${htmlPath} (${(html.length / 1024).toFixed(0)} KB)`);
|
||||
|
||||
// Estadísticas
|
||||
let totalPalabras = 0;
|
||||
let totalTemas = 0;
|
||||
for (const m of libros) {
|
||||
for (const s of m.secciones) {
|
||||
for (const t of s.temas) {
|
||||
totalTemas++;
|
||||
if (t.contenidoHTML) {
|
||||
totalPalabras += t.contenidoHTML
|
||||
.replace(/<[^>]*>/g, "")
|
||||
.split(/\s+/).length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log("");
|
||||
log("═══════════════════════════════════════════════════");
|
||||
log(" COMPLETADO");
|
||||
log("═══════════════════════════════════════════════════");
|
||||
log("");
|
||||
log(` 📚 ${libros.length} módulos · ${totalTemas} temas`);
|
||||
log(` 📝 ~${(totalPalabras / 1000).toFixed(1)}k palabras de contenido`);
|
||||
log(
|
||||
` 🎬 ${videosDescargados.length} videos descargados (en videos_offline/)`,
|
||||
);
|
||||
log("");
|
||||
log(" Para abrir el libro de estudio:");
|
||||
log(` file://${htmlPath}`);
|
||||
log("");
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error("Error:", err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
# Copiar recursos (PDFs, etc) de secciones a assets/resources/
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
declare -A MAP
|
||||
MAP["Modulo_1_Planificacion/Planificacion"]="m1_planificacion"
|
||||
MAP["Modulo_1_Planificacion/Preparacion_Atletica"]="m1_preparacion-atletica"
|
||||
MAP["Modulo_1_Planificacion/Explicacion_TP"]="m1_explicacion-tp"
|
||||
MAP["Modulo_1_Planificacion/Seguimientos_Equipos"]="m1_seguimientos-equipos"
|
||||
MAP["Modulo_1_Planificacion/Analisis_Equipos_1"]="m1_analisis-equipos-1"
|
||||
MAP["Modulo_1_Planificacion/Analisis_Equipos_2"]="m1_analisis-equipos-2"
|
||||
MAP["Modulo_1_Planificacion/TP_Final_Unidad"]="m1_tp-final"
|
||||
MAP["Modulo_2_Entrenamiento/Centrales_y_Oponentes"]="m2_centrales-opuestos"
|
||||
MAP["Modulo_2_Entrenamiento/Puntas_y_Liberos"]="m2_puntas-liberos"
|
||||
MAP["Modulo_2_Entrenamiento/Entrenamiento_Armadoras"]="m2_entrenamiento-armadoras"
|
||||
MAP["Modulo_2_Entrenamiento/Explicacion_TP"]="m2_explicacion-tp"
|
||||
|
||||
total=0
|
||||
for key in "${!MAP[@]}"; do
|
||||
target="${MAP[$key]}"
|
||||
src="descargar-curso/descargas/secciones/$key"
|
||||
count=0
|
||||
|
||||
for f in "$src"/*; do
|
||||
fn=$(basename "$f")
|
||||
case "$fn" in
|
||||
pagina.html|contenido.md|videos.md|recursos.json|.gitkeep) ;;
|
||||
*)
|
||||
cp "$f" "www-ksaldis-dt/assets/resources/$target/" 2>/dev/null
|
||||
count=$((count+1))
|
||||
total=$((total+1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
echo " $target: $count archivos"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "✅ Total: $total archivos copiados"
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
REPO_DIR="/var/www/ksaldis-dt/.repo"
|
||||
WEB_DIR="/var/www/ksaldis-dt"
|
||||
REPO_URL="http://10.0.10.205:3000/rmonla/rm-KSALDIS-DT.git"
|
||||
LOG="$WEB_DIR/deploy.log"
|
||||
GIT="git -c safe.directory=$REPO_DIR"
|
||||
|
||||
log() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') | $1" >> "$LOG"
|
||||
}
|
||||
|
||||
log "Deploy iniciado"
|
||||
|
||||
if [ -d "$REPO_DIR/.git" ]; then
|
||||
cd "$REPO_DIR"
|
||||
$GIT fetch origin 2>&1
|
||||
$GIT reset --hard origin/main 2>&1
|
||||
log "git pull OK"
|
||||
else
|
||||
rm -rf "$REPO_DIR"
|
||||
git clone "$REPO_URL" "$REPO_DIR" 2>&1
|
||||
log "git clone OK"
|
||||
fi
|
||||
|
||||
SRC="$REPO_DIR/descargar-curso/descargas/LIBRO_DE_ESTUDIO.html"
|
||||
if [ -f "$SRC" ]; then
|
||||
cp "$SRC" "$WEB_DIR/index.html"
|
||||
log "index.html actualizado ($(wc -c < "$WEB_DIR/index.html") bytes)"
|
||||
fi
|
||||
|
||||
# Copiar secciones
|
||||
SECCIONES_SRC="$REPO_DIR/descargar-curso/descargas/secciones"
|
||||
if [ -d "$SECCIONES_SRC" ]; then
|
||||
rsync -a --delete "$SECCIONES_SRC/" "$WEB_DIR/secciones/"
|
||||
log "secciones/ actualizadas"
|
||||
fi
|
||||
|
||||
# Copiar otros assets
|
||||
for asset in campus imagenes screenshots subpaginas; do
|
||||
ASSET_SRC="$REPO_DIR/descargar-curso/descargas/$asset"
|
||||
if [ -d "$ASSET_SRC" ]; then
|
||||
rsync -a "$ASSET_SRC/" "$WEB_DIR/$asset/"
|
||||
log "$asset/ actualizado"
|
||||
fi
|
||||
done
|
||||
|
||||
log "Deploy completado"
|
||||
@@ -0,0 +1,482 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# DESCARGAR VIDEOS DEL CURSO DE VOLEY
|
||||
# ====================================
|
||||
# Descarga los 42 videos de Vimeo con reanudación automática.
|
||||
# Puede detenerse y reanudarse cuando quieras.
|
||||
#
|
||||
# Modo de uso:
|
||||
# bash descargar_videos.sh
|
||||
#
|
||||
# Opciones:
|
||||
# bash descargar_videos.sh --resume # Reanuda descargas pendientes
|
||||
# bash descargar_videos.sh --status # Ver estado de descargas
|
||||
# bash descargar_videos.sh --clean # Borrar todo y empezar de nuevo
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# ─── CONFIGURACIÓN ───────────────────────────────────────────
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
SESSION_JSON="$SCRIPT_DIR/session.json"
|
||||
COOKIES_FILE="$SCRIPT_DIR/.cookies_voley.txt"
|
||||
VIDEOS_DIR="$SCRIPT_DIR/descargas/videos_offline"
|
||||
REGISTRO="$SCRIPT_DIR/.videos_descargados.txt"
|
||||
LISTA_VIDEOS="$SCRIPT_DIR/.lista_videos.txt"
|
||||
DEST_DIR="$SCRIPT_DIR/descargas"
|
||||
LIMIT_RATE="" # Ej: "5M" para limitar a 5 MB/s, vacío = sin límite
|
||||
|
||||
# ─── COLORES ─────────────────────────────────────────────────
|
||||
VERDE='\033[0;32m'
|
||||
AMARILLO='\033[1;33m'
|
||||
ROJO='\033[0;31m'
|
||||
AZUL='\033[0;34m'
|
||||
RESET='\033[0m'
|
||||
|
||||
ok() { echo -e " ${VERDE}✓${RESET} $1"; }
|
||||
warn() { echo -e " ${AMARILLO}⚠${RESET} $1"; }
|
||||
err() { echo -e " ${ROJO}✗${RESET} $1"; }
|
||||
info() { echo -e " ${AZUL}→${RESET} $1"; }
|
||||
|
||||
# ─── HELPERS ─────────────────────────────────────────────────
|
||||
|
||||
timestamp() {
|
||||
date '+%Y-%m-%d %H:%M:%S'
|
||||
}
|
||||
|
||||
log() {
|
||||
echo "[$(timestamp)] $1"
|
||||
}
|
||||
|
||||
check_dependencies() {
|
||||
if ! command -v yt-dlp &>/dev/null; then
|
||||
err "yt-dlp no está instalado."
|
||||
echo " Instalálo con: pip install yt-dlp"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v python3 &>/dev/null; then
|
||||
err "python3 no está instalado."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ─── CONVERTIR COOKIES ──────────────────────────────────────
|
||||
|
||||
convertir_cookies() {
|
||||
if [ ! -f "$SESSION_JSON" ]; then
|
||||
err "No se encontró $SESSION_JSON"
|
||||
echo " Ejecutá primero: node download_course.mjs"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Convirtiendo cookies de Playwright a formato Netscape..."
|
||||
|
||||
python3 -c "
|
||||
import json
|
||||
|
||||
with open('$SESSION_JSON') as f:
|
||||
data = json.load(f)
|
||||
|
||||
cookies = data.get('cookies', [])
|
||||
lines = ['# Netscape HTTP Cookie File']
|
||||
|
||||
for c in cookies:
|
||||
domain = c.get('domain', '')
|
||||
if not domain:
|
||||
continue
|
||||
flag = 'TRUE' if domain.startswith('.') else 'FALSE'
|
||||
path = c.get('path', '/')
|
||||
secure = 'TRUE' if c.get('secure', False) else 'FALSE'
|
||||
exp = c.get('expires', 0)
|
||||
if exp <= 0:
|
||||
exp = 1778594896 # fecha lejana
|
||||
name = c.get('name', '')
|
||||
value = c.get('value', '')
|
||||
lines.append(f'{domain}\t{flag}\t{path}\t{secure}\t{int(exp)}\t{name}\t{value}')
|
||||
|
||||
with open('$COOKIES_FILE', 'w') as f:
|
||||
f.write('\n'.join(lines) + '\n')
|
||||
|
||||
print(f'{len(cookies)}')
|
||||
" 2>/dev/null
|
||||
|
||||
if [ -f "$COOKIES_FILE" ]; then
|
||||
local count=$(wc -l < "$COOKIES_FILE")
|
||||
ok "Cookies convertidas ($((count - 1)))"
|
||||
else
|
||||
err "Error al convertir cookies"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ─── EXTRAER LISTA DE VIDEOS ─────────────────────────────────
|
||||
|
||||
extraer_lista_videos() {
|
||||
log "Extrayendo lista de videos del HTML descargado..."
|
||||
|
||||
python3 -c "
|
||||
import os, re, json
|
||||
|
||||
base = '$DEST_DIR/secciones'
|
||||
modulos = ['Modulo_1_Planificacion', 'Modulo_2_Entrenamiento']
|
||||
|
||||
# Mapeo de carpetas a IDs de sección
|
||||
mapeo_secciones = {
|
||||
'Planificacion': ('m/19096', 's/34868'),
|
||||
'Preparacion_Atletica': ('m/19096', 's/34869'),
|
||||
'Explicacion_TP': ('m/19096', 's/34870'),
|
||||
'Seguimientos_Equipos': ('m/19096', 's/35523'),
|
||||
'Analisis_Equipos_1': ('m/19096', 's/35524'),
|
||||
'Analisis_Equipos_2': ('m/19096', 's/35525'),
|
||||
'TP_Final_Unidad': ('m/19096', 's/35526'),
|
||||
'Centrales_y_Oponentes': ('m/19097', 's/35519'),
|
||||
'Puntas_y_Liberos': ('m/19097', 's/35520'),
|
||||
'Entrenamiento_Armadoras': ('m/19097', 's/35521'),
|
||||
'Explicacion_TP': ('m/19097', 's/35522'),
|
||||
}
|
||||
|
||||
# Nombre humano de cada sección
|
||||
nombres = {
|
||||
'Planificacion': 'Planificacion',
|
||||
'Preparacion_Atletica': 'Preparacion_Atletica',
|
||||
'Explicacion_TP': 'Explicacion_TP',
|
||||
'Seguimientos_Equipos': 'Seguimientos_Equipos',
|
||||
'Analisis_Equipos_1': 'Analisis_Equipos_1',
|
||||
'Analisis_Equipos_2': 'Analisis_Equipos_2',
|
||||
'TP_Final_Unidad': 'TP_Final_Unidad',
|
||||
'Centrales_y_Oponentes': 'Centrales_y_Oponentes',
|
||||
'Puntas_y_Liberos': 'Puntas_y_Liberos',
|
||||
'Entrenamiento_Armadoras': 'Entrenamiento_Armadoras',
|
||||
}
|
||||
|
||||
videos = []
|
||||
vistos = set()
|
||||
|
||||
for mod in modulos:
|
||||
mod_path = os.path.join(base, mod)
|
||||
if not os.path.isdir(mod_path):
|
||||
continue
|
||||
for sec in os.listdir(mod_path):
|
||||
html_path = os.path.join(mod_path, sec, 'pagina.html')
|
||||
if not os.path.isfile(html_path):
|
||||
continue
|
||||
|
||||
html = open(html_path, 'r', errors='ignore').read()
|
||||
if '500 Internal Server Error' in html:
|
||||
continue
|
||||
|
||||
for m in re.finditer(r'player\.vimeo\.com/video/(\d+)', html):
|
||||
vid = m.group(1)
|
||||
if vid in vistos:
|
||||
continue
|
||||
vistos.add(vid)
|
||||
|
||||
# Buscar título del tema
|
||||
idx = m.start()
|
||||
before = html[max(0, idx - 400):idx]
|
||||
tm = re.search(r'<em>([^<]+)</em>', before)
|
||||
titulo = tm.group(1).strip() if tm else f'video_{vid}'
|
||||
# Limpiar caracteres no válidos para文件名
|
||||
titulo = re.sub(r'[<>:\"/\\\\|?*]+', '_', titulo)[:80]
|
||||
|
||||
# Construir URL de la página embebedora
|
||||
mapa = mapeo_secciones.get(sec)
|
||||
if mapa:
|
||||
mod_id, sec_id = mapa
|
||||
pagina_url = f'https://voley.onlineeducation.center/es/campus/student/training/e/14197/{mod_id}/{sec_id}/study-resources/list'
|
||||
else:
|
||||
pagina_url = ''
|
||||
|
||||
videos.append({
|
||||
'id': vid,
|
||||
'titulo': titulo,
|
||||
'seccion': nombres.get(sec, sec),
|
||||
'modulo': 'M1' if '1' in mod else 'M2',
|
||||
'url': pagina_url,
|
||||
})
|
||||
|
||||
with open('$LISTA_VIDEOS', 'w') as f:
|
||||
json.dump(videos, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print(len(videos))
|
||||
" 2>/dev/null
|
||||
|
||||
local total=$(wc -l < "$LISTA_VIDEOS" 2>/dev/null || echo 0)
|
||||
if [ "$total" -gt 0 ] 2>/dev/null; then
|
||||
ok "Lista de videos generada"
|
||||
python3 -c "import json; print(f' Total: {len(json.load(open(\"$LISTA_VIDEOS\")))} videos')" 2>/dev/null
|
||||
else
|
||||
err "No se encontraron videos en el HTML descargado"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ─── DESCARGAR VIDEOS ───────────────────────────────────────
|
||||
|
||||
descargar_videos() {
|
||||
mkdir -p "$VIDEOS_DIR"
|
||||
touch "$REGISTRO"
|
||||
|
||||
# Leer videos ya descargados
|
||||
local descargados=()
|
||||
while IFS= read -r line; do
|
||||
descargados+=("$line")
|
||||
done < "$REGISTRO"
|
||||
|
||||
# Obtener lista completa
|
||||
local total=$(python3 -c "import json; print(len(json.load(open('$LISTA_VIDEOS'))))" 2>/dev/null || echo 0)
|
||||
|
||||
if [ "$total" -eq 0 ]; then
|
||||
err "Lista de videos vacía"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo " Total: $total videos"
|
||||
echo " Ya descargados: ${#descargados[@]}"
|
||||
echo " Pendientes: $((total - ${#descargados[@]}))"
|
||||
echo ""
|
||||
|
||||
# Procesar cada video
|
||||
for i in $(seq 0 $((total - 1))); do
|
||||
local data=$(python3 -c "
|
||||
import json
|
||||
with open('$LISTA_VIDEOS') as f:
|
||||
v = json.load(f)
|
||||
v = v[$i]
|
||||
print(f'{v[\"id\"]}|{v[\"titulo\"]}|{v[\"seccion\"]}|{v[\"modulo\"]}|{v[\"url\"]}')" 2>/dev/null)
|
||||
|
||||
local id=$(echo "$data" | cut -d'|' -f1)
|
||||
local titulo=$(echo "$data" | cut -d'|' -f2)
|
||||
local seccion=$(echo "$data" | cut -d'|' -f3)
|
||||
local modulo=$(echo "$data" | cut -d'|' -f4)
|
||||
local pagina_url=$(echo "$data" | cut -d'|' -f5-)
|
||||
|
||||
# Verificar si ya se descargó
|
||||
if grep -q "^$id|" "$REGISTRO" 2>/dev/null; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Nombre del archivo de salida
|
||||
local safe_name="${modulo}_${seccion}_${titulo}"
|
||||
safe_name=$(echo "$safe_name" | sed 's/[^a-zA-Z0-9_]/_/g' | cut -c1-120)
|
||||
local output_path="$VIDEOS_DIR/${safe_name}.mp4"
|
||||
|
||||
# Si el archivo ya existe en disco pero no en el registro, agregarlo
|
||||
if [ -f "$output_path" ]; then
|
||||
echo "${id}|${safe_name}.mp4" >> "$REGISTRO"
|
||||
ok "[$((i+1))/$total] Ya existe: ${titulo:0:50}"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo " ─────────────────────────────────────────────"
|
||||
printf " [%d/%d] 🎬 %s\n" $((i+1)) "$total" "${titulo:0:70}"
|
||||
echo " ─────────────────────────────────────────────"
|
||||
echo ""
|
||||
|
||||
if [ -z "$pagina_url" ]; then
|
||||
warn "Sin URL de página embebedora, intentando con URL directa..."
|
||||
pagina_url="https://player.vimeo.com/video/${id}"
|
||||
fi
|
||||
|
||||
# Construir comando yt-dlp
|
||||
local cmd="yt-dlp"
|
||||
cmd+=" --cookies \"$COOKIES_FILE\""
|
||||
cmd+=" -o \"$output_path\""
|
||||
cmd+=" --merge-output-format mp4"
|
||||
cmd+=" --no-playlist"
|
||||
cmd+=" --no-progress"
|
||||
cmd+=" --console-title"
|
||||
cmd+=" --retries 3"
|
||||
cmd+=" --continue"
|
||||
if [ -n "$LIMIT_RATE" ]; then
|
||||
cmd+=" --limit-rate $LIMIT_RATE"
|
||||
fi
|
||||
cmd+=" \"$pagina_url\""
|
||||
|
||||
# Ejecutar descarga
|
||||
if eval "$cmd" 2>&1; then
|
||||
if [ -f "$output_path" ]; then
|
||||
local size=$(du -h "$output_path" | cut -f1)
|
||||
echo "${id}|${safe_name}.mp4" >> "$REGISTRO"
|
||||
ok "Descargado: ${titulo:0:40} ($size)"
|
||||
else
|
||||
# Buscar archivo con otro nombre
|
||||
local found=$(find "$VIDEOS_DIR" -name "*${id}*" -o -name "*${titulo:0:20}*" 2>/dev/null | head -1)
|
||||
if [ -n "$found" ]; then
|
||||
local fname=$(basename "$found")
|
||||
echo "${id}|${fname}" >> "$REGISTRO"
|
||||
local size=$(du -h "$found" | cut -f1)
|
||||
ok "Descargado (con otro nombre): ${titulo:0:40} ($size)"
|
||||
else
|
||||
warn "Puede que se haya descargado pero no se encontró el archivo esperado."
|
||||
warn "Ruta buscada: $output_path"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
err "Error descargando: ${titulo:0:50}"
|
||||
fi
|
||||
|
||||
# Pequeña pausa entre descargas para no saturar
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo ""
|
||||
local pendientes=$((total - $(wc -l < "$REGISTRO" 2>/dev/null || echo 0)))
|
||||
if [ "$pendientes" -le 0 ]; then
|
||||
echo " 🎉 ¡Todos los videos descargados!"
|
||||
else
|
||||
echo " Quedan $pendientes videos pendientes."
|
||||
echo " Para reanudar: bash $0"
|
||||
fi
|
||||
}
|
||||
|
||||
# ─── GENERAR LIBRO CON VIDEOS ───────────────────────────────
|
||||
|
||||
generar_libro() {
|
||||
log "Generando libro de estudio con videos locales..."
|
||||
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Leer registro de videos descargados
|
||||
const registro = '$REGISTRO';
|
||||
const videosMap = {};
|
||||
if (fs.existsSync(registro)) {
|
||||
const lines = fs.readFileSync(registro, 'utf-8').trim().split('\n');
|
||||
for (const line of lines) {
|
||||
const [id, archivo] = line.split('|');
|
||||
if (id && archivo) videosMap[id] = archivo;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(' Videos mapeados:', Object.keys(videosMap).length);
|
||||
|
||||
// Guardar mapa para que lo use el script principal
|
||||
const mapaPath = '$SCRIPT_DIR/.mapa_videos.json';
|
||||
fs.writeFileSync(mapaPath, JSON.stringify(videosMap, null, 2));
|
||||
" 2>/dev/null
|
||||
|
||||
# Ahora regenerar el libro usando el script existente
|
||||
if [ -f "$SCRIPT_DIR/generar_dashboard.mjs" ]; then
|
||||
node "$SCRIPT_DIR/generar_dashboard.mjs" 2>&1
|
||||
else
|
||||
warn "No se encontró generar_dashboard.mjs"
|
||||
warn "El libro se generará sin videos la próxima vez que ejecutes node generar_dashboard.mjs"
|
||||
fi
|
||||
}
|
||||
|
||||
# ─── ESTADO ──────────────────────────────────────────────────
|
||||
|
||||
mostrar_estado() {
|
||||
echo ""
|
||||
echo " ─── ESTADO DE DESCARGA ───"
|
||||
echo ""
|
||||
|
||||
if [ ! -f "$LISTA_VIDEOS" ]; then
|
||||
echo " Lista de videos no generada."
|
||||
echo " Ejecutá primero: bash $0"
|
||||
return
|
||||
fi
|
||||
|
||||
local total=$(python3 -c "import json; print(len(json.load(open('$LISTA_VIDEOS'))))" 2>/dev/null || echo 0)
|
||||
local descargados=$(wc -l < "$REGISTRO" 2>/dev/null || echo 0)
|
||||
local pendientes=$((total - descargados))
|
||||
|
||||
echo " Total videos: $total"
|
||||
echo " Descargados: $descargados"
|
||||
echo " Pendientes: $pendientes"
|
||||
echo ""
|
||||
|
||||
if [ "$descargados" -gt 0 ] && [ -d "$VIDEOS_DIR" ]; then
|
||||
local total_size=$(du -sh "$VIDEOS_DIR" 2>/dev/null | cut -f1)
|
||||
echo " Espacio usado: $total_size"
|
||||
echo ""
|
||||
|
||||
echo " Últimos descargados:"
|
||||
tail -5 "$REGISTRO" 2>/dev/null | while IFS='|' read -r id archivo; do
|
||||
if [ -n "$archivo" ] && [ -f "$VIDEOS_DIR/$archivo" ]; then
|
||||
local size=$(du -h "$VIDEOS_DIR/$archivo" 2>/dev/null | cut -f1)
|
||||
echo " ✓ $archivo ($size)"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ─── LIMPIAR ─────────────────────────────────────────────────
|
||||
|
||||
limpiar() {
|
||||
echo ""
|
||||
warn "¿Borrar todos los videos descargados? (s/N): "
|
||||
read -r respuesta
|
||||
if [ "$respuesta" = "s" ] || [ "$respuesta" = "S" ]; then
|
||||
rm -rf "$VIDEOS_DIR" "$REGISTRO" "$LISTA_VIDEOS" "$COOKIES_FILE"
|
||||
ok "Eliminado. Listo para empezar de nuevo."
|
||||
else
|
||||
ok "Operación cancelada."
|
||||
fi
|
||||
}
|
||||
|
||||
# ─── MAIN ────────────────────────────────────────────────────
|
||||
|
||||
main() {
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════"
|
||||
echo " 🏐 DESCARGAR VIDEOS — Curso de Vóley"
|
||||
echo "═══════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
check_dependencies
|
||||
|
||||
# Procesar argumentos
|
||||
case "${1:-}" in
|
||||
--status|-s)
|
||||
convertir_cookies
|
||||
extraer_lista_videos
|
||||
mostrar_estado
|
||||
exit 0
|
||||
;;
|
||||
--clean|-c)
|
||||
limpiar
|
||||
exit 0
|
||||
;;
|
||||
--resume|-r)
|
||||
true # simplemente continua
|
||||
;;
|
||||
*)
|
||||
# Primer ejecución: setup completo
|
||||
if [ ! -f "$COOKIES_FILE" ]; then
|
||||
convertir_cookies
|
||||
fi
|
||||
if [ ! -f "$LISTA_VIDEOS" ]; then
|
||||
extraer_lista_videos
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Asegurar cookies
|
||||
if [ ! -f "$COOKIES_FILE" ]; then
|
||||
convertir_cookies
|
||||
fi
|
||||
if [ ! -f "$LISTA_VIDEOS" ]; then
|
||||
extraer_lista_videos
|
||||
fi
|
||||
|
||||
descargar_videos
|
||||
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════"
|
||||
echo " Listo."
|
||||
echo "═══════════════════════════════════════════════════"
|
||||
echo ""
|
||||
echo " Videos en: $VIDEOS_DIR"
|
||||
echo " Para retomar: bash $0 --resume"
|
||||
echo " Para ver estado: bash $0 --status"
|
||||
echo ""
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -0,0 +1,227 @@
|
||||
[
|
||||
{
|
||||
"text": "Políticas de cookies",
|
||||
"href": "https://kb.onlineeducation.center/es/cookies/",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Políticas de privacidad",
|
||||
"href": "https://kb.onlineeducation.center/es/privacy/",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Términos de uso",
|
||||
"href": "https://kb.onlineeducation.center/es/terms/",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Aceptar",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list#agree",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "",
|
||||
"href": "https://voley.onlineeducation.center/es/campus",
|
||||
"title": "Voley"
|
||||
},
|
||||
{
|
||||
"text": "Elva Karina Saldis",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list#",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Su cuenta",
|
||||
"href": "https://account.onlineeducation.center/es/",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Configuración regional",
|
||||
"href": "https://account.onlineeducation.center/es/config?bth=https%3A//voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Datos para certificados",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/e/14197/user/account?r=https%3A//voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Mesa de ayuda",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/help-desk/tickets",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Cerrar sesión",
|
||||
"href": "https://voley.onlineeducation.center/es/logout",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "English",
|
||||
"href": "https://voley.onlineeducation.center/en/campus/student/training/e/14197/m/19097/s/35519/study-resources/list?hl=en&locale_switcher=1",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Inicio",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Información",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/info",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Auditorio",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/auditorium/sessions",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Material de estudio",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/study-resources",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Foros",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/forum",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Evaluaciones",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list#",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Trabajos prácticos",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/practice-work",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Administración",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Calificaciones",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/course-results",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Certificaciones",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/certificate/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Su opinión",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/review/make",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Mesa de ayuda",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/help-desk/tickets",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Ir a la encuesta",
|
||||
"href": "https://onlineeducation.center/es/encuesta/modulo/curso-entrenador-nacional-dos-edicion-2022-t-261ca228f64845?email=saldis_karina%40hotmail.com&studentname=Elva%20Karina%20Saldis&editionnumber=5&modulenumber=1",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Opinar",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/review/make",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Módulo 1",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list#collapse1",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "PLANIFICACION",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "PREPARACION ATLETICA",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "EXPLICACION DEL TRABAJO PRACTICO A PRESENTAR",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34870/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "SEGUIMIENTOS DE EQUIPOS",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35523/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "ANALISIS DE EQUIPOS DE VOLEIBOL",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "ANALISIS DE EQUIPOS DE VOLEIBOL 2",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "TRABAJO PRACTICO FINAL DE LA UNIDAD",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35526/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Módulo 2",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list#collapse2",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "ENTRENAMIENTO DE LOS CENTRALES Y OPUESTOS/AS",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "PUNTAS Y LIBEROS/AS",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35520/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "ENTRENAMIENTO DE LOS Y LAS ARMADORAS",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35521/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "EXPLICACION DEL TRABAJO PRACTICO A PRESENTAR",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35522/study-resources/list",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Abrir Archivo",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/46874/show?me=142960",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Abrir Archivo",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/46805/show?me=142961",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Términos de uso",
|
||||
"href": "https://kb.onlineeducation.center/es/terms/",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Política de privacidad",
|
||||
"href": "https://kb.onlineeducation.center/es/privacy/",
|
||||
"title": ""
|
||||
},
|
||||
{
|
||||
"text": "Powered by",
|
||||
"href": "https://onlineeducation.center/",
|
||||
"title": "powered by Online Education Center"
|
||||
}
|
||||
]
|
||||
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
@@ -0,0 +1,305 @@
|
||||
<!doctype html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>KSALDIS-DT — Curso de Entrenador Nacional de Vóley</title>
|
||||
<meta name="description" content="Material de estudio offline del Curso de Entrenador Nacional de Vóley — 2 módulos, 11 secciones, 42 videos" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
font-family: 'Inter', 'Segoe UI', system-ui, sans-serif;
|
||||
background: #0a0e1a;
|
||||
color: #e0e4ef;
|
||||
min-height: 100vh;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* ── HERO ── */
|
||||
.hero {
|
||||
position: relative;
|
||||
min-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
padding: 3rem 2rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background:
|
||||
radial-gradient(ellipse 80% 50% at 50% 0%, rgba(41, 128, 185, 0.25) 0%, transparent 60%),
|
||||
radial-gradient(ellipse 60% 40% at 80% 100%, rgba(142, 68, 173, 0.15) 0%, transparent 50%),
|
||||
radial-gradient(ellipse 50% 30% at 10% 60%, rgba(52, 152, 219, 0.1) 0%, transparent 50%);
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.hero::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 600px;
|
||||
height: 600px;
|
||||
transform: translate(-50%, -50%);
|
||||
background: radial-gradient(circle, rgba(41, 128, 185, 0.08) 0%, transparent 70%);
|
||||
animation: pulse-glow 4s ease-in-out infinite;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
@keyframes pulse-glow {
|
||||
0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.6; }
|
||||
50% { transform: translate(-50%, -50%) scale(1.15); opacity: 1; }
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
.hero-icon {
|
||||
font-size: 5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
filter: drop-shadow(0 0 30px rgba(41, 128, 185, 0.4));
|
||||
animation: float 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-12px); }
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 2.8rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: -1px;
|
||||
background: linear-gradient(135deg, #ffffff 0%, #a8c8e8 50%, #7fb3d8 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
margin-bottom: 0.8rem;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.hero .subtitle {
|
||||
font-size: 1.15rem;
|
||||
font-weight: 300;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
margin-bottom: 2rem;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
/* ── STATS ── */
|
||||
.stats-row {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.stat-badge {
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
padding: 0.6rem 1.4rem;
|
||||
border-radius: 100px;
|
||||
font-size: 0.88rem;
|
||||
font-weight: 500;
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.stat-badge:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-color: rgba(41, 128, 185, 0.3);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.stat-badge .num {
|
||||
font-weight: 700;
|
||||
color: #5dade2;
|
||||
}
|
||||
|
||||
/* ── CARDS ── */
|
||||
.cards-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 1.2rem;
|
||||
max-width: 960px;
|
||||
width: 100%;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
position: relative;
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
border-radius: 16px;
|
||||
padding: 2rem 1.5rem;
|
||||
text-decoration: none;
|
||||
color: #e0e4ef;
|
||||
transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
.card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 16px;
|
||||
padding: 1px;
|
||||
background: linear-gradient(135deg, rgba(41, 128, 185, 0.3), transparent 50%);
|
||||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
opacity: 0;
|
||||
transition: opacity 0.35s;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-6px);
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3), 0 0 40px rgba(41, 128, 185, 0.1);
|
||||
}
|
||||
|
||||
.card:hover::before { opacity: 1; }
|
||||
|
||||
.card.primary {
|
||||
background: linear-gradient(135deg, rgba(231, 76, 60, 0.15), rgba(192, 57, 43, 0.08));
|
||||
border-color: rgba(231, 76, 60, 0.2);
|
||||
}
|
||||
|
||||
.card.primary::before {
|
||||
background: linear-gradient(135deg, rgba(231, 76, 60, 0.5), transparent 50%);
|
||||
}
|
||||
|
||||
.card.primary:hover {
|
||||
background: linear-gradient(135deg, rgba(231, 76, 60, 0.25), rgba(192, 57, 43, 0.15));
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3), 0 0 40px rgba(231, 76, 60, 0.15);
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
font-size: 2.2rem;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.card-desc {
|
||||
font-size: 0.82rem;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* ── FOOTER ── */
|
||||
.footer {
|
||||
text-align: center;
|
||||
padding: 3rem 2rem;
|
||||
color: rgba(255, 255, 255, 0.25);
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: rgba(255, 255, 255, 0.35);
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.footer a:hover {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
border-bottom-color: rgba(41, 128, 185, 0.4);
|
||||
}
|
||||
|
||||
.footer .separator {
|
||||
margin: 0 0.5rem;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
/* ── RESPONSIVE ── */
|
||||
@media (max-width: 640px) {
|
||||
.hero { min-height: 60vh; padding: 2rem 1rem; }
|
||||
.hero h1 { font-size: 1.8rem; }
|
||||
.hero .subtitle { font-size: 0.95rem; }
|
||||
.hero-icon { font-size: 3.5rem; }
|
||||
.cards-grid { grid-template-columns: 1fr 1fr; gap: 0.8rem; }
|
||||
.card { padding: 1.4rem 1rem; }
|
||||
.stat-badge { font-size: 0.8rem; padding: 0.5rem 1rem; }
|
||||
}
|
||||
|
||||
@media (max-width: 380px) {
|
||||
.cards-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<section class="hero" id="hero">
|
||||
<div class="hero-content">
|
||||
<div class="hero-icon">🏐</div>
|
||||
<h1>Curso de Entrenador Nacional de Vóley</h1>
|
||||
<p class="subtitle">Material de Estudio — Versión Offline</p>
|
||||
|
||||
<div class="stats-row">
|
||||
<div class="stat-badge">📚 <span class="num">2</span> módulos</div>
|
||||
<div class="stat-badge">📂 <span class="num">11</span> secciones</div>
|
||||
<div class="stat-badge">🎥 <span class="num">42</span> videos</div>
|
||||
</div>
|
||||
|
||||
<div class="cards-grid">
|
||||
<a href="LIBRO_DE_ESTUDIO.html" class="card primary" id="link-libro">
|
||||
<div class="card-icon">📖</div>
|
||||
<div class="card-title">Libro de Estudio</div>
|
||||
<div class="card-desc">Contenido completo navegable</div>
|
||||
</a>
|
||||
<a href="secciones/" class="card" id="link-secciones">
|
||||
<div class="card-icon">📂</div>
|
||||
<div class="card-title">Secciones</div>
|
||||
<div class="card-desc">Explorar por módulo</div>
|
||||
</a>
|
||||
<a href="videos/" class="card" id="link-videos">
|
||||
<div class="card-icon">🎥</div>
|
||||
<div class="card-title">Videos</div>
|
||||
<div class="card-desc">Referencias Vimeo</div>
|
||||
</a>
|
||||
<a href="screenshots/" class="card" id="link-screenshots">
|
||||
<div class="card-icon">🖼️</div>
|
||||
<div class="card-title">Capturas</div>
|
||||
<div class="card-desc">Screenshots del campus</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="footer">
|
||||
<p>KSALDIS-DT <span class="separator">·</span> Contenido extraído del campus Online Education Center</p>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,217 @@
|
||||
[
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://account.onlineeducation.center/es/config?bth=https%3A//voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list",
|
||||
"text": "Configuración regional"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/e/14197/user/account?r=https%3A//voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list",
|
||||
"text": "Datos para certificados"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/en/campus/student/training/e/14197/m/19097/s/35519/study-resources/list?hl=en&locale_switcher=1",
|
||||
"text": "English"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/study-resources",
|
||||
"text": "Material de estudio"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/list",
|
||||
"text": "PLANIFICACION"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/list",
|
||||
"text": "PREPARACION ATLETICA"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34870/study-resources/list",
|
||||
"text": "EXPLICACION DEL TRABAJO PRACTICO A PRESENTAR"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35523/study-resources/list",
|
||||
"text": "SEGUIMIENTOS DE EQUIPOS"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/list",
|
||||
"text": "ANALISIS DE EQUIPOS DE VOLEIBOL"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/list",
|
||||
"text": "ANALISIS DE EQUIPOS DE VOLEIBOL 2"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35526/study-resources/list",
|
||||
"text": "TRABAJO PRACTICO FINAL DE LA UNIDAD"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/list",
|
||||
"text": "ENTRENAMIENTO DE LOS CENTRALES Y OPUESTOS/AS"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35520/study-resources/list",
|
||||
"text": "PUNTAS Y LIBEROS/AS"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35521/study-resources/list",
|
||||
"text": "ENTRENAMIENTO DE LOS Y LAS ARMADORAS"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35522/study-resources/list",
|
||||
"text": "EXPLICACION DEL TRABAJO PRACTICO A PRESENTAR"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/46874/show?me=142960",
|
||||
"text": "Abrir Archivo"
|
||||
},
|
||||
{
|
||||
"type": "pdf-link",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19097/s/35519/study-resources/46805/show?me=142961",
|
||||
"text": "Abrir Archivo"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919369433?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919369433?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/1179197191?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/1179197191?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919341704?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919341704?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919342668?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919342668?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919346562?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919346562?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919347866?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919347866?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919348493?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919348493?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919351892?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919351892?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919352848?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919352848?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919353448?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919353448?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919354134?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919354134?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919355668?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919355668?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919356423?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919356423?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919357109?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919357109?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919358607?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919358607?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919359386?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919359386?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919359855?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919359855?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919360318?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919360318?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919363158?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919363158?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919363728?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919363728?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919364522?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919364522?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919365485?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919365485?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "iframe",
|
||||
"url": "https://player.vimeo.com/video/919366263?nocache=1777730642",
|
||||
"title": "https://player.vimeo.com/video/919366263?nocache=1777730642"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"url": "https://voley.onlineeducation.center/uploads/institucion/d15ddc66bd4cd881200ee3c3abacd7396367ddaa.png",
|
||||
"alt": "Voley"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"url": "https://voley.onlineeducation.center/img/user-default.jpg",
|
||||
"alt": ""
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"url": "https://voley.onlineeducation.center/img/oec-logo-grey.png",
|
||||
"alt": "Online Education Center"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,68 @@
|
||||
[
|
||||
{
|
||||
"seccion": "Planificacion",
|
||||
"modulo": "Modulo_1_Planificacion",
|
||||
"ok": true,
|
||||
"recursos": 10
|
||||
},
|
||||
{
|
||||
"seccion": "Preparacion_Atletica",
|
||||
"modulo": "Modulo_1_Planificacion",
|
||||
"ok": true,
|
||||
"recursos": 16
|
||||
},
|
||||
{
|
||||
"seccion": "Explicacion_TP",
|
||||
"modulo": "Modulo_1_Planificacion",
|
||||
"ok": true,
|
||||
"recursos": 3
|
||||
},
|
||||
{
|
||||
"seccion": "Seguimientos_Equipos",
|
||||
"modulo": "Modulo_1_Planificacion",
|
||||
"ok": true,
|
||||
"recursos": 0
|
||||
},
|
||||
{
|
||||
"seccion": "Analisis_Equipos_1",
|
||||
"modulo": "Modulo_1_Planificacion",
|
||||
"ok": true,
|
||||
"recursos": 0
|
||||
},
|
||||
{
|
||||
"seccion": "Analisis_Equipos_2",
|
||||
"modulo": "Modulo_1_Planificacion",
|
||||
"ok": true,
|
||||
"recursos": 0
|
||||
},
|
||||
{
|
||||
"seccion": "TP_Final_Unidad",
|
||||
"modulo": "Modulo_1_Planificacion",
|
||||
"ok": true,
|
||||
"recursos": 0
|
||||
},
|
||||
{
|
||||
"seccion": "Centrales_y_Oponentes",
|
||||
"modulo": "Modulo_2_Entrenamiento",
|
||||
"ok": true,
|
||||
"recursos": 26
|
||||
},
|
||||
{
|
||||
"seccion": "Puntas_y_Liberos",
|
||||
"modulo": "Modulo_2_Entrenamiento",
|
||||
"ok": true,
|
||||
"recursos": 14
|
||||
},
|
||||
{
|
||||
"seccion": "Entrenamiento_Armadoras",
|
||||
"modulo": "Modulo_2_Entrenamiento",
|
||||
"ok": true,
|
||||
"recursos": 2
|
||||
},
|
||||
{
|
||||
"seccion": "Explicacion_TP",
|
||||
"modulo": "Modulo_2_Entrenamiento",
|
||||
"ok": true,
|
||||
"recursos": 2
|
||||
}
|
||||
]
|
||||
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 467 KiB |
|
After Width: | Height: | Size: 601 KiB |
|
After Width: | Height: | Size: 593 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 578 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 289 KiB |
@@ -0,0 +1,5 @@
|
||||
# Analisis Equipos 1
|
||||
|
||||
Oops! An Error Occurred
|
||||
The server returned a "500 Internal Server Error".
|
||||
Something is broken. Please let us know what you were doing when this error occurred. We will fix it as soon as possible. Sorry for any inconvenience caused.
|
||||
@@ -0,0 +1,166 @@
|
||||
[
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53294/show?me=142938",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53294/show?me=142938",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53294"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50262/show?me=142080",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50262/show?me=142080",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50262"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53180/show?me=142693",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53180/show?me=142693",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53180"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53185/show?me=142698",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53185/show?me=142698",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53185"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53181/show?me=142694",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53181/show?me=142694",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53181"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50276/show?me=142081",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50276/show?me=142081",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50276"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50236/show?me=142098",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50236/show?me=142098",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50236"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53080/show?me=142591",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53080/show?me=142591",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53080"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50233/show?me=142087",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50233/show?me=142087",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50233"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50234/show?me=142089",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50234/show?me=142089",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50234"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50235/show?me=142088",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50235/show?me=142088",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50235"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50237/show?me=142092",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50237/show?me=142092",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50237"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53182/show?me=142695",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53182/show?me=142695",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53182"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50278/show?me=142090",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50278/show?me=142090",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50278"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50280/show?me=142091",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50280/show?me=142091",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50280"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53079/show?me=142590",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53079/show?me=142590",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53079"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50282/show?me=142093",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50282/show?me=142093",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50282"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50283/show?me=142096",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/50283/show?me=142096",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50283"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53186/show?me=142699",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53186/show?me=142699",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53186"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53183/show?me=142696",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53183/show?me=142696",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53183"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "https://voley.onlineeducation.center/es/campus/coord/training/edition/14197/module/19096/subject/35524/study-resources/50260/show?me=142084",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/coord/training/edition/14197/module/19096/subject/35524/study-resources/50260/show?me=142084",
|
||||
"texto": "",
|
||||
"id": "50260"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53184/show?me=142697",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35524/study-resources/53184/show?me=142697",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53184"
|
||||
},
|
||||
{
|
||||
"tipo": "video-embed",
|
||||
"url": "https://player.vimeo.com/video/1073484590?nocache=1777790295",
|
||||
"id": "1073484590"
|
||||
},
|
||||
{
|
||||
"tipo": "video-embed",
|
||||
"url": "https://player.vimeo.com/video/876705933?nocache=1777790295",
|
||||
"id": "876705933"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,5 @@
|
||||
# Analisis Equipos 2
|
||||
|
||||
Oops! An Error Occurred
|
||||
The server returned a "500 Internal Server Error".
|
||||
Something is broken. Please let us know what you were doing when this error occurred. We will fix it as soon as possible. Sorry for any inconvenience caused.
|
||||
@@ -0,0 +1,51 @@
|
||||
[
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53295/show?me=142939",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53295/show?me=142939",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53295"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53194/show?me=142710",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53194/show?me=142710",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53194"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53190/show?me=142706",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53190/show?me=142706",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53190"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53191/show?me=142707",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53191/show?me=142707",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53191"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53192/show?me=142708",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53192/show?me=142708",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53192"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53193/show?me=142709",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53193/show?me=142709",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53193"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53201/show?me=142717",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/35525/study-resources/53201/show?me=142717",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53201"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
# Explicacion TP
|
||||
|
||||
> Extraído el 2026-05-02
|
||||
|
||||
PLANIFICACION
|
||||
PREPARACION ATLETICA
|
||||
EXPLICACION DEL TRABAJO PRACTICO A PRESENTAR
|
||||
SEGUIMIENTOS DE EQUIPOS
|
||||
ANALISIS DE EQUIPOS DE VOLEIBOL
|
||||
ANALISIS DE EQUIPOS DE VOLEIBOL 2
|
||||
TRABAJO PRACTICO FINAL DE LA UNIDAD
|
||||
@@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34870/study-resources/53173/show?me=142686",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34870/study-resources/53173/show?me=142686",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53173"
|
||||
},
|
||||
{
|
||||
"tipo": "video-embed",
|
||||
"url": "https://player.vimeo.com/video/1173576229?nocache=1777790278",
|
||||
"id": "1173576229"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,12 @@
|
||||
# Videos - Explicacion TP
|
||||
|
||||
> Sección: https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34870/study-resources/list
|
||||
|
||||
## Video Vimeo ID: 1173576229
|
||||
|
||||
- **Plataforma**: Vimeo
|
||||
- **URL**: https://player.vimeo.com/video/1173576229?nocache=1777731170
|
||||
- **ID**: 1173576229
|
||||
|
||||
Para descargar: yt-dlp "https://player.vimeo.com/video/1173576229"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Planificacion
|
||||
|
||||
> Extraído el 2026-05-02
|
||||
|
||||
PLANIFICACION
|
||||
PREPARACION ATLETICA
|
||||
EXPLICACION DEL TRABAJO PRACTICO A PRESENTAR
|
||||
SEGUIMIENTOS DE EQUIPOS
|
||||
ANALISIS DE EQUIPOS DE VOLEIBOL
|
||||
ANALISIS DE EQUIPOS DE VOLEIBOL 2
|
||||
TRABAJO PRACTICO FINAL DE LA UNIDAD
|
||||
@@ -0,0 +1,63 @@
|
||||
[
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/50320/show?me=140219",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/50320/show?me=140219",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50320"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/52903/show?me=142139",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/52903/show?me=142139",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "52903"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/46541/show?me=140221",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/46541/show?me=140221",
|
||||
"texto": "Abrir Enlace",
|
||||
"id": "46541"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/46723/show?me=140222",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/46723/show?me=140222",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "46723"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/46724/show?me=140223",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/46724/show?me=140223",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "46724"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/50142/show?me=140224",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/50142/show?me=140224",
|
||||
"texto": "Abrir Enlace",
|
||||
"id": "50142"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/50145/show?me=140225",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/50145/show?me=140225",
|
||||
"texto": "Abrir Enlace",
|
||||
"id": "50145"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/50144/show?me=140226",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/50144/show?me=140226",
|
||||
"texto": "Abrir Enlace",
|
||||
"id": "50144"
|
||||
},
|
||||
{
|
||||
"tipo": "video-embed",
|
||||
"url": "https://player.vimeo.com/video/1170245111?nocache=1777790245",
|
||||
"id": "1170245111"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,12 @@
|
||||
# Videos - Planificacion
|
||||
|
||||
> Sección: https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34868/study-resources/list
|
||||
|
||||
## Video Vimeo ID: 1170245111
|
||||
|
||||
- **Plataforma**: Vimeo
|
||||
- **URL**: https://player.vimeo.com/video/1170245111?nocache=1777731162
|
||||
- **ID**: 1170245111
|
||||
|
||||
Para descargar: yt-dlp "https://player.vimeo.com/video/1170245111"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Preparacion Atletica
|
||||
|
||||
> Extraído el 2026-05-02
|
||||
|
||||
PLANIFICACION
|
||||
PREPARACION ATLETICA
|
||||
EXPLICACION DEL TRABAJO PRACTICO A PRESENTAR
|
||||
SEGUIMIENTOS DE EQUIPOS
|
||||
ANALISIS DE EQUIPOS DE VOLEIBOL
|
||||
ANALISIS DE EQUIPOS DE VOLEIBOL 2
|
||||
TRABAJO PRACTICO FINAL DE LA UNIDAD
|
||||
@@ -0,0 +1,101 @@
|
||||
[
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/53012/show?me=142522",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/53012/show?me=142522",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53012"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/53137/show?me=142648",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/53137/show?me=142648",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53137"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/53138/show?me=142649",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/53138/show?me=142649",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53138"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/53139/show?me=142650",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/53139/show?me=142650",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "53139"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/46719/show?me=140229",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/46719/show?me=140229",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "46719"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/50329/show?me=140232",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/50329/show?me=140232",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "50329"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/46726/show?me=140233",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/46726/show?me=140233",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "46726"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/50139/show?me=140234",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/50139/show?me=140234",
|
||||
"texto": "Abrir Enlace",
|
||||
"id": "50139"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/46725/show?me=140235",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/46725/show?me=140235",
|
||||
"texto": "Abrir Archivo",
|
||||
"id": "46725"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/50140/show?me=140236",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/50140/show?me=140236",
|
||||
"texto": "Abrir Enlace",
|
||||
"id": "50140"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/50143/show?me=140237",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/50143/show?me=140237",
|
||||
"texto": "Abrir Enlace",
|
||||
"id": "50143"
|
||||
},
|
||||
{
|
||||
"tipo": "archivo-curso",
|
||||
"href": "/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/50141/show?me=140238",
|
||||
"url": "https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/50141/show?me=140238",
|
||||
"texto": "Abrir Enlace",
|
||||
"id": "50141"
|
||||
},
|
||||
{
|
||||
"tipo": "video-embed",
|
||||
"url": "https://player.vimeo.com/video/1173231315?nocache=1777790263",
|
||||
"id": "1173231315"
|
||||
},
|
||||
{
|
||||
"tipo": "video-embed",
|
||||
"url": "https://player.vimeo.com/video/1063655414?nocache=1777790263",
|
||||
"id": "1063655414"
|
||||
},
|
||||
{
|
||||
"tipo": "video-embed",
|
||||
"url": "https://player.vimeo.com/video/1063657248?nocache=1777790263",
|
||||
"id": "1063657248"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,28 @@
|
||||
# Videos - Preparacion Atletica
|
||||
|
||||
> Sección: https://voley.onlineeducation.center/es/campus/student/training/e/14197/m/19096/s/34869/study-resources/list
|
||||
|
||||
## Video Vimeo ID: 1173231315
|
||||
|
||||
- **Plataforma**: Vimeo
|
||||
- **URL**: https://player.vimeo.com/video/1173231315?nocache=1777731166
|
||||
- **ID**: 1173231315
|
||||
|
||||
Para descargar: yt-dlp "https://player.vimeo.com/video/1173231315"
|
||||
|
||||
## Video Vimeo ID: 1063655414
|
||||
|
||||
- **Plataforma**: Vimeo
|
||||
- **URL**: https://player.vimeo.com/video/1063655414?nocache=1777731166
|
||||
- **ID**: 1063655414
|
||||
|
||||
Para descargar: yt-dlp "https://player.vimeo.com/video/1063655414"
|
||||
|
||||
## Video Vimeo ID: 1063657248
|
||||
|
||||
- **Plataforma**: Vimeo
|
||||
- **URL**: https://player.vimeo.com/video/1063657248?nocache=1777731166
|
||||
- **ID**: 1063657248
|
||||
|
||||
Para descargar: yt-dlp "https://player.vimeo.com/video/1063657248"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Seguimientos Equipos
|
||||
|
||||
Oops! An Error Occurred
|
||||
The server returned a "500 Internal Server Error".
|
||||
Something is broken. Please let us know what you were doing when this error occurred. We will fix it as soon as possible. Sorry for any inconvenience caused.
|
||||