primocode 8.16.0 → 8.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/effort.js +142 -34
  2. package/package.json +1 -1
package/lib/effort.js CHANGED
@@ -132,29 +132,77 @@ function layoutEffort(idx) {
132
132
  // leem como listras — e listra clara demais apaga o texto branco por cima.
133
133
  // O fundo tem de parecer um pano roxo respirando atrás do painel, não uma
134
134
  // bandeira. Os tons claros ficam de fora por isso.
135
- const ROXOS = [54, 55, 56, 57, 57, 93, 93, 99, 98, 92, 56, 55];
135
+ // A rampa do plasma, do fundo frio ao branco quente.
136
+ //
137
+ // Ela é LONGA de propósito: o degradê é desenhado em meia-célula (▀), então
138
+ // há o dobro de linhas para atravessar, e uma rampa curta viraria degrau
139
+ // visível. Começa quase preta e termina em branco — é a amplitude que faz o
140
+ // pico parecer luz, e não só "roxo mais claro".
141
+ // Começa em roxo PROFUNDO, não em preto.
142
+ //
143
+ // A primeira rampa abria em 16 e 17 (preto e azul-marinho). Os vales da onda
144
+ // caíam neles e viravam buracos escuros furando o pano — parecia defeito de
145
+ // renderização, não sombra. Agora o mais fundo ainda é roxo: o painel inteiro
146
+ // é uma coisa só, do vale ao pico.
147
+ const ROXOS = [53, 54, 54, 55, 56, 57, 93, 129, 135, 141, 177, 183, 219, 225, 231];
136
148
 
137
- function fundoRoxo(x, fase) {
138
- // Duas ondas de períodos diferentes: o encontro delas dá o desenho
139
- // irregular de faixas, em vez de listras repetidas e óbvias.
140
- //
141
- // As frequências caíram (0.55 → 0.13) porque as faixas tinham três
142
- // colunas de largura: de longe aquilo não era um fundo ondulando, era
143
- // chuviscado. Faixa larga anda devagar pela tela, que é o movimento que
144
- // se quer ver — o painel respira em vez de piscar.
145
- const faixa = x / 2;
146
- const onda = Math.sin(faixa * 0.13 + fase) * 0.62 + Math.sin(faixa * 0.041 - fase * 0.55) * 0.38;
147
- // A curva ³ empurra os valores para o MEIO da rampa: os extremos (o mais
148
- // escuro e o mais claro) só aparecem no pico da onda, e o painel passa a
149
- // maior parte do tempo num roxo médio, onde o texto branco se lê.
150
- const suave = Math.pow(onda, 3) * 0.55 + onda * 0.45;
151
- const i = Math.round((suave + 1) / 2 * (ROXOS.length - 1));
149
+ // Quanto o plasma é amortecido nas linhas que têm texto. Pico branco atrás
150
+ // de letra branca some com a letra, e o painel existe para ser lido — o
151
+ // brilho fica para as faixas abertas, logo acima e abaixo.
152
+ const TETO_SOB_TEXTO = 0.5;
153
+
154
+ /* O campo: o que decide a cor de cada meia-célula.
155
+ *
156
+ * Três coisas somadas, e é a soma que dá a sensação de energia em vez de
157
+ * listra:
158
+ *
159
+ * 1. uma ONDA DIAGONAL atravessando o painel, devagar;
160
+ * 2. um PULSO RADIAL saindo do próprio rótulo "ultracode" — é o detalhe
161
+ * que amarra a animação ao que ela significa: a potência irradia de
162
+ * onde você está;
163
+ * 3. uma segunda onda lenta, fora de fase, que impede o padrão de se
164
+ * repetir de forma óbvia.
165
+ *
166
+ * `x` é a coluna, `y` a meia-linha (duas por linha de texto), `foco` a
167
+ * coluna do rótulo selecionado.
168
+ */
169
+ function campoUltra(x, y, fase, foco, altura) {
170
+ // O terminal tem célula alta e estreita: sem corrigir, o pulso radial
171
+ // sairia como uma elipse achatada em vez de círculo.
172
+ const dx = (x - foco) * 0.5;
173
+ const dy = (y - altura / 2) * 1.1;
174
+ const raio = Math.sqrt(dx * dx + dy * dy);
175
+
176
+ const diagonal = Math.sin((x * 0.11) + (y * 0.30) + fase * 1.15);
177
+ const pulso = Math.sin(raio * 0.42 - fase * 2.1) * Math.exp(-raio * 0.035);
178
+ const lenta = Math.sin(x * 0.037 - fase * 0.5 + Math.cos(y * 0.19) * 0.8);
179
+
180
+ const v = diagonal * 0.42 + pulso * 0.78 + lenta * 0.34;
181
+ // O divisor maior que a amplitude puxa a média para baixo: o painel fica
182
+ // a maior parte do tempo em roxo fundo, e o branco vira PICO — evento,
183
+ // não estado. Centrado, o branco virava o normal e não impressionava
184
+ // mais nada.
185
+ return Math.max(0, Math.min(1, (v + 1.15) / 2.75));
186
+ }
187
+
188
+ // `escala` escurece a linha SEM achatá-la.
189
+ //
190
+ // A primeira versão usava Math.min(v, teto): tudo acima do teto virava a
191
+ // mesma cor, e as linhas de texto ganhavam platôs chapados — retângulos
192
+ // visíveis atravessando o plasma. Multiplicar preserva a forma da onda e só
193
+ // baixa a amplitude: a linha fica escura o bastante para ler e continua
194
+ // fazendo parte do mesmo pano.
195
+ function corDoCampo(v, escala) {
196
+ const t = escala ? v * escala : v;
197
+ const i = Math.round(t * (ROXOS.length - 1));
152
198
  return ROXOS[Math.max(0, Math.min(ROXOS.length - 1, i))];
153
199
  }
154
200
 
155
- // Pinta a linha inteira (até a largura do painel) com a onda por baixo.
156
- // `destaque` é o trecho que fica branco e forte (o nível escolhido); o resto
157
- // da linha sai num lilás claro, para o escolhido saltar aos olhos.
201
+ // Guardada para quem já usava a onda antiga (e para o teste da rampa).
202
+ function fundoRoxo(x, fase) {
203
+ return corDoCampo(campoUltra(x, 0, fase, 0, 2));
204
+ }
205
+
158
206
  function pintarLinhaUltra(texto, largura, fase, opts = {}) {
159
207
  const base = opts.base || 231; // branco
160
208
  const apagado = opts.apagado || base;
@@ -179,25 +227,84 @@ function pintarLinhaUltra(texto, largura, fase, opts = {}) {
179
227
  return saida + '\x1b[0m';
180
228
  }
181
229
 
230
+ /* O painel do ultracode, desenhado em MEIA-CÉLULA.
231
+ *
232
+ * O caractere "▀" ocupa a metade de cima da célula. Pintando a frente dele
233
+ * com uma cor e o fundo com outra, cada linha do terminal carrega DUAS
234
+ * linhas de imagem. É o que separa um degradê em blocos de um degradê que
235
+ * parece luz — e é como demo de terminal sempre fez.
236
+ *
237
+ * Onde há letra, a célula deixa de ser meia e vira fundo liso: não dá para
238
+ * ter o glifo do texto e o do meio-bloco na mesma célula. Aí o fundo é a
239
+ * média das duas metades, limitada para o texto continuar legível.
240
+ */
241
+ function painelUltra(L, fase) {
242
+ const alturaMeia = L.linhas.length * 2;
243
+ const foco = (L.destaque.de + L.destaque.ate) / 2;
244
+ const LILAS = 189;
245
+
246
+ const corDoTexto = (l, x) => {
247
+ if (l.tipo === 'titulo') return { cor: 231, negrito: true };
248
+ if (l.tipo === 'nomes') {
249
+ const dentro = x >= L.destaque.de && x < L.destaque.ate;
250
+ return { cor: dentro ? 231 : LILAS, negrito: dentro };
251
+ }
252
+ if (l.tipo === 'resumo' || l.tipo === 'extremos' || l.tipo === 'ajuda') {
253
+ return { cor: LILAS, negrito: false };
254
+ }
255
+ return { cor: 231, negrito: false };
256
+ };
257
+
258
+ return L.linhas.map((l, y) => {
259
+ // A régua "▔" some no ultra: sobre o plasma ela virava uma listra
260
+ // clara cortando o topo do bloco.
261
+ const texto = l.tipo === 'regua' ? '' : l.texto;
262
+ // Linha COM texto é acalmada inteira, não só debaixo das letras.
263
+ //
264
+ // Limitar só a célula do glifo não bastava: o vão entre as palavras
265
+ // recebia o plasma cheio, e um pico branco encostado na letra some
266
+ // com ela do mesmo jeito. A linha toda vira superfície escura, e o
267
+ // brilho fica para as faixas abertas — que é onde ele aparece sem
268
+ // atrapalhar ninguém.
269
+ const linhaCalma = texto.trim().length > 0 ? TETO_SOB_TEXTO : 0;
270
+ let saida = '';
271
+ let fg = -1, bg = -1, forte = null;
272
+
273
+ for (let x = 0; x < L.cols; x++) {
274
+ const ch = texto[x] || ' ';
275
+ const temLetra = ch !== ' ';
276
+ const cima = campoUltra(x, y * 2, fase, foco, alturaMeia);
277
+ const baixo = campoUltra(x, y * 2 + 1, fase, foco, alturaMeia);
278
+
279
+ let glifo, corFrente, corFundo, querForte;
280
+ if (temLetra) {
281
+ const t = corDoTexto(l, x);
282
+ glifo = ch;
283
+ corFrente = t.cor;
284
+ querForte = t.negrito;
285
+ corFundo = corDoCampo((cima + baixo) / 2, TETO_SOB_TEXTO);
286
+ } else {
287
+ glifo = '▀'; // ▀
288
+ corFrente = corDoCampo(cima, linhaCalma);
289
+ corFundo = corDoCampo(baixo, linhaCalma);
290
+ querForte = false;
291
+ }
292
+
293
+ if (corFundo !== bg) { saida += `\x1b[48;5;${corFundo}m`; bg = corFundo; }
294
+ if (corFrente !== fg) { saida += `\x1b[38;5;${corFrente}m`; fg = corFrente; }
295
+ if (querForte !== forte) { saida += querForte ? '\x1b[1m' : '\x1b[22m'; forte = querForte; }
296
+ saida += glifo;
297
+ }
298
+ return saida + '\x1b[0m';
299
+ }).join('\n');
300
+ }
301
+
182
302
  function desenharEffort(idx, fase) {
183
303
  const L = layoutEffort(idx);
184
304
  const ultra = NOMES[idx] === 'ultracode';
185
305
 
186
306
  if (ultra) {
187
- // No ultracode o painel todo vira fundo animado. Cada linha é pintada
188
- // com a MESMA onda, então as faixas ficam alinhadas de cima a baixo.
189
- const LILAS = 189; // lilás bem claro, para o que não é o escolhido
190
- return L.linhas.map((l) => {
191
- // A régua é uma fileira de "▔". Sobre o roxo ela virava uma
192
- // listra clara atravessando o topo e cortava o bloco em dois.
193
- // No ultra ela some e vira fundo liso: a borda de cima do painel
194
- // passa a ser o próprio degradê, que é o que se quer ver.
195
- if (l.tipo === 'regua') return pintarLinhaUltra('', L.cols, fase, {});
196
- if (l.tipo === 'titulo') return pintarLinhaUltra(l.texto, L.cols, fase, { negrito: true });
197
- if (l.tipo === 'nomes') return pintarLinhaUltra(l.texto, L.cols, fase, { destaque: L.destaque, apagado: LILAS });
198
- if (l.tipo === 'resumo' || l.tipo === 'extremos') return pintarLinhaUltra(l.texto, L.cols, fase, { base: LILAS, apagado: LILAS });
199
- return pintarLinhaUltra(l.texto, L.cols, fase, {});
200
- }).join('\n');
307
+ return painelUltra(L, fase);
201
308
  }
202
309
 
203
310
  return L.linhas.map((l) => {
@@ -224,5 +331,6 @@ function desenharEffort(idx, fase) {
224
331
  }
225
332
 
226
333
  module.exports = { NIVEIS, NOMES, normalizar, nivelDe, indiceDe, modeloDe, pesquisaDe,
227
- layoutEffort, fundoRoxo, pintarLinhaUltra, desenharEffort, ROXOS };
334
+ layoutEffort, fundoRoxo, pintarLinhaUltra, desenharEffort, ROXOS,
335
+ campoUltra, corDoCampo, painelUltra };
228
336
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "primocode",
3
- "version": "8.16.0",
3
+ "version": "8.17.0",
4
4
  "description": "PrimoCode — agente de engenharia com IA e cursor próprio. Modelos grátis. Cria arquivos, roda comandos, controla navegador e desktop: abre apps, clica em botões e ícones pelo nome, digita e usa atalhos.",
5
5
  "main": "bin/primocode.js",
6
6
  "bin": {