Created
April 15, 2026 19:23
-
-
Save shuantsu/7c103961ebc71a60caed8b39f530342f to your computer and use it in GitHub Desktop.
Programação diária estudo de A Sentinela
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function() { | |
| const article = document.querySelector('#article'); | |
| const body = document.querySelector('.bodyTxt'); | |
| // 1. EXTRAÇÃO DOS BLOCOS ORIGINAIS | |
| const blocosBase = []; | |
| let currentSub = "Introdução"; | |
| Array.from(body.querySelectorAll('h2, p.qu')).forEach(el => { | |
| if (el.tagName === 'H2') { | |
| currentSub = el.textContent.trim(); | |
| } else { | |
| const rawNum = el.querySelector('strong')?.textContent || el.textContent; | |
| const match = rawNum.match(/^[\d\s\-,.]+/); | |
| const pGroup = match ? match[0].replace(/[.\s]/g, '') : "N/A"; | |
| let peso = 1; | |
| if (pGroup.includes('-')) { | |
| const parts = pGroup.split('-'); | |
| peso = parseInt(parts[1]) - parseInt(parts[0]) + 1; | |
| } else if (pGroup.includes(',')) { | |
| peso = pGroup.split(',').length; | |
| } | |
| const primeiroPar = parseInt(pGroup.split(/[-,]/)[0]); | |
| blocosBase.push({ | |
| subtitulo: currentSub, | |
| displayNum: pGroup, | |
| primeiroPar: primeiroPar, | |
| pergunta: el.textContent.replace(/^[\d\s\-,.]+/ , '').trim(), | |
| peso: peso | |
| }); | |
| } | |
| }); | |
| // 2. INTERFACE OTIMIZADA PARA PDF | |
| const win = window.open("", "_blank"); | |
| win.document.write(` | |
| <html> | |
| <head> | |
| <title>Planner Sentinela - PDF Friendly</title> | |
| <style> | |
| /* Estilos de Tela */ | |
| body { font-family: 'Segoe UI', system-ui, sans-serif; background: #f0f2f5; margin: 0; display: flex; height: 100vh; } | |
| #sidebar { width: 340px; background: #232f3e; color: white; padding: 25px; overflow-y: auto; box-shadow: 4px 0 10px rgba(0,0,0,0.1); flex-shrink: 0; } | |
| #content { flex: 1; padding: 40px; overflow-y: auto; } | |
| .control-item { margin-bottom: 25px; } | |
| label { display: block; margin-bottom: 8px; font-weight: 600; font-size: 12px; color: #aab7c4; text-transform: uppercase; } | |
| select, input { width: 100%; padding: 12px; border-radius: 6px; border: 1px solid #3e4f5f; background: #2d3d4d; color: white; font-size: 14px; outline: none; } | |
| #calendar-container { margin-top: 30px; background: #1b2633; padding: 15px; border-radius: 8px; border: 1px solid #3e4f5f; } | |
| #calendar-header { font-size: 14px; font-weight: bold; text-align: center; margin-bottom: 10px; color: #3498db; text-transform: uppercase; } | |
| .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; text-align: center; font-size: 11px; } | |
| .cal-day-name { font-weight: bold; color: #8492a6; } | |
| .cal-day { padding: 5px 0; border-radius: 4px; color: #bdc3c7; } | |
| .cal-today { background: #3498db; color: white; font-weight: bold; } | |
| .dia-card { background: white; border-radius: 12px; padding: 25px; margin-bottom: 25px; box-shadow: 0 4px 20px rgba(0,0,0,0.08); border-left: 10px solid #3498db; page-break-inside: avoid; } | |
| .dia-num { font-size: 1.4em; font-weight: 800; color: #1a2a3a; margin-bottom: 15px; border-bottom: 2px solid #f0f0f0; padding-bottom: 10px; display: flex; justify-content: space-between; } | |
| .sub-header { color: #d35400; font-weight: bold; font-size: 12px; text-transform: uppercase; margin: 20px 0 10px 0; display: block; background: #fff5eb; padding: 4px 8px; border-radius: 4px; } | |
| .par-item { padding: 10px 0; border-bottom: 1px solid #f9f9f9; font-size: 15px; color: #2c3e50; display: flex; gap: 10px; } | |
| .par-num { font-weight: bold; color: #3498db; min-width: 45px; } | |
| .count-tag { background: #3498db; color: white; padding: 4px 12px; border-radius: 20px; font-size: 13px; } | |
| /* REGRAS DE IMPRESSÃO (PDF) */ | |
| @media print { | |
| body { background: white !important; display: block !important; height: auto !important; } | |
| #sidebar { display: none !important; } | |
| #content { padding: 0 !important; width: 100% !important; overflow: visible !important; } | |
| .dia-card { | |
| box-shadow: none !important; | |
| border: 1px solid #ddd !important; | |
| border-left: 10px solid #3498db !important; | |
| page-break-inside: avoid !important; | |
| margin-bottom: 20px !important; | |
| } | |
| .sub-header { background: #eee !important; color: black !important; -webkit-print-color-adjust: exact; } | |
| .count-tag { border: 1px solid #3498db !important; color: #3498db !important; background: transparent !important; } | |
| h1 { font-size: 18pt !important; margin-bottom: 20px !important; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="sidebar"> | |
| <h2 style="margin-top:0; color:#3498db; font-size: 22px;">Planner Dinâmico</h2> | |
| <p style="font-size: 11px; color: #8492a6;">Ajuste os filtros e aperte <b>Ctrl + P</b> para salvar em PDF.</p> | |
| <div class="control-item"> | |
| <label>Começar do parágrafo:</label> | |
| <input type="number" id="startPar" value="1" min="1"> | |
| </div> | |
| <div class="control-item"> | |
| <label>Dias Restantes (N)</label> | |
| <input type="number" id="inputDias" value="6" min="1"> | |
| </div> | |
| <div class="control-item"> | |
| <label>Fluxo de Subtítulos</label> | |
| <select id="splitSubtitles"> | |
| <option value="keep">Finalizar Dia no Subtítulo</option> | |
| <option value="split">Dividir Subtítulo</option> | |
| </select> | |
| </div> | |
| <div id="calendar-container"> | |
| <div id="calendar-header"></div> | |
| <div class="cal-grid" id="calendar-grid"></div> | |
| </div> | |
| </div> | |
| <div id="content"> | |
| <h1 style="margin-top:0; color: #232f3e;">${article.querySelector('h1')?.textContent.trim()}</h1> | |
| <div id="display"></div> | |
| </div> | |
| <script> | |
| const dadosOriginais = ${JSON.stringify(blocosBase)}; | |
| function buildCalendar() { | |
| const now = new Date(); | |
| const monthNames = ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"]; | |
| document.getElementById('calendar-header').innerText = monthNames[now.getMonth()] + " " + now.getFullYear(); | |
| const grid = document.getElementById('calendar-grid'); | |
| grid.innerHTML = ''; | |
| ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'].forEach(d => { | |
| const div = document.createElement('div'); div.className = 'cal-day-name'; div.innerText = d; grid.appendChild(div); | |
| }); | |
| const firstDay = new Date(now.getFullYear(), now.getMonth(), 1).getDay(); | |
| const daysInMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate(); | |
| for (let i = 0; i < firstDay; i++) grid.appendChild(document.createElement('div')); | |
| for (let d = 1; d <= daysInMonth; d++) { | |
| const div = document.createElement('div'); | |
| div.className = 'cal-day' + (d === now.getDate() ? ' cal-today' : ''); | |
| div.innerText = d; grid.appendChild(div); | |
| } | |
| } | |
| function calcular() { | |
| const startingAt = parseInt(document.getElementById('startPar').value) || 1; | |
| const nDias = parseInt(document.getElementById('inputDias').value) || 1; | |
| const subModo = document.getElementById('splitSubtitles').value; | |
| const filtrados = dadosOriginais.filter(b => { | |
| if (b.displayNum.includes('-')) return parseInt(b.displayNum.split('-')[1]) >= startingAt; | |
| return b.primeiroPar >= startingAt; | |
| }); | |
| const cronograma = Array.from({ length: nDias }, () => []); | |
| const totalPeso = filtrados.reduce((acc, b) => acc + b.peso, 0); | |
| const metaDia = totalPeso / nDias; | |
| let diaAtual = 0, pesoAcumulado = 0; | |
| filtrados.forEach((bloco, index) => { | |
| cronograma[diaAtual].push(bloco); | |
| pesoAcumulado += bloco.peso; | |
| if (diaAtual < nDias - 1) { | |
| let trocar = false; | |
| const atingiuMeta = pesoAcumulado >= (metaDia * 0.85); | |
| if (subModo === 'keep') { | |
| const prox = filtrados[index+1]; | |
| if (prox && bloco.subtitulo !== prox.subtitulo && (atingiuMeta || pesoAcumulado > metaDia * 0.5)) trocar = true; | |
| else if (pesoAcumulado > metaDia * 1.5) trocar = true; | |
| } else if (atingiuMeta) trocar = true; | |
| if (trocar) { diaAtual++; pesoAcumulado = 0; } | |
| } | |
| }); | |
| render(cronograma); | |
| } | |
| function render(cronograma) { | |
| const container = document.getElementById('display'); | |
| container.innerHTML = ''; | |
| cronograma.forEach((dia, i) => { | |
| if (dia.length === 0) return; | |
| const diaDiv = document.createElement('div'); | |
| diaDiv.className = 'dia-card'; | |
| const totalP = dia.reduce((acc, b) => acc + b.peso, 0); | |
| let html = '<div class="dia-num"><span>Dia ' + (i+1) + '</span><span class="count-tag">' + totalP + ' parágrafos</span></div>'; | |
| let lastSub = ""; | |
| dia.forEach(b => { | |
| if (b.subtitulo !== lastSub) { | |
| html += '<span class="sub-header">' + b.subtitulo + '</span>'; | |
| lastSub = b.subtitulo; | |
| } | |
| html += '<div class="par-item"><span class="par-num">§ ' + b.displayNum + '</span><span>' + b.pergunta + '</span></div>'; | |
| }); | |
| diaDiv.innerHTML = html; | |
| container.appendChild(diaDiv); | |
| }); | |
| } | |
| document.querySelectorAll('input, select').forEach(el => el.addEventListener('input', calcular)); | |
| buildCalendar(); | |
| calcular(); | |
| </script> | |
| </body> | |
| </html> | |
| `); | |
| win.document.close(); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment