Pull to refresh
4
Андрей@Andrei2025

User

2
Subscribers
Send message

Очень длинная статья, что нужно сделать, просто сравнивать предложенный и реальный маршруты и вести статистику: 9 из 10 изменили маршрут, следовательно есть препятствия и нужно просто предлагать другие варианты

Можно просто отключить ее в настройках для всего

Все разбирай и пиши больше, главное не работать на тех, кто все это устраивает и для кого люди превратились в своего рода Приложения к их приложениям

Очень полезная статья и показывает всю суть приложений, которые хотят иметь доступ к каждой минуте вашей жизни и зарабатывать на этом, зная все ваши маршруты, контакты и много чего еще. Но, как понимать "Ха как вам идея реверсить по одному русскому приложению в месяц пока они не позовут меня к себе работать..." - автор, получается непрочь сам делать такие приложения, просто сейчас без работы", работа в финтехе - все компании в этом секторе используют различные способы слежки и работать у них, помогать им в этом

Построение поведенческой модели и своего рода управление, через триггеры: персонализированная реклама, пуши, сообщения и много чего еще

К примеру, чем человек на заправках Газпрома, отличается от того же ИИ, когда 15 людям в очереди твердит свою мантру о скидках, которого просишь не повторять, а в ответ: "начальство так велело", это тема для другого обсуждения. Если хочешь могу в личку прислать тебе обзор аналитики: человек и ИИ, качество от человека гораздо хуже, чем от ИИ, в одном случае это просто 20 страниц, где большую часть занимают скрины сайтов, в другом аналитика по тысячи источников, конечно нельзя целиком полагаться на такой анализ, но и 50 процентов скриншотов в анализе, уж точно не следует

Привет! Конечно, я использовал ИИ, но лично мне он, условно говоря, «заходит». И вот почему: структурирование и последовательность, особенно в части инструкций.

Мне, например, совсем неинтересно читать что-то в духе: «Однажды на меня нашло вдохновение после прогулки по городу, и я подумал: дай сделаю что-то такое, чего нет у других», для этого можно и другую литературу прочитать.

Да, команды нужно проверять. Многое зависит от того, в какой среде они выполняются. Но я могу с уверенностью сказать, что уже проделал достаточное количество разных кейсов, которые могли бы пригодиться в повседневной работе.

Например: даем команду, получаем вывод, корректируем, а в конце пишем инструкцию с синтетическими данными по реально проделанному сценарию, при помощи ИИ, можно еще добавить скриншоты и показать видео результата. Все зависит от того, что ты хочешь получить на выходе (результат) четкая инструкция с набором команд, что команда означает, можно и в комментариях почитать, что автоматом генерятся здесь. Конечно, хочется более "живого" текста

Очищается, но как экономика при этом работать будет, целые пласты выбиваются, так и до феодализма один шаг, человек начинает экономить: минус подписки, все облака6 все и так можно найти и приценпить SSD к телефону, получаются вышибли людей, но и продажи не пойдут от этого, спрос упадет, ведб в принципе все связано. Конечно ИИ избавляет людей от рутинной работы, особенно, когда эта рутина и есть твоя работа, уж лучше пару скриптов написать при помощи ИИ и дальше идти, целые отделы не заменишь, все еще от того, какой ИИ использовать. С течением времени может получится так, что простым промтом вы напишите платформу, создавать которую будут десятки человек, а результат будет хуже, но перед этим сотни промтов будет и постоянная шлифовка и тестирование того, что он натворил. Что касается разбираться в коде, может оно и хорого, но если не знаешь кода, а нужен результат и результат очень даже ничего, то как?

Скажите, а как раньше без всего этого обходились: биометрия, ИИ, IoT, AR, приложения, видеоаналитика.? Почему именно биометрия, а не билет с кодом, а если бы работал StarLink, могло бы это разгрузить сеть? Понимаете, есть люди и это абсолютно нормально, которым не требуется носить с собой смартфон, а достаточно простого кнопочного телефона и хорошей зеркалки, а репортаж в социальную сеть человек и из дома сделает. Может оно и хорошо, но не здесь, особенно биометрия

<!doctype html>
<html lang="ru">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Universe Rebirth — чёрная дыра и восстановление Вселенной</title>
  <style>
    :root {
      --bg: #030712;
      --panel: rgba(15, 23, 42, .78);
      --text: #eaf0ff;
      --muted: #9ba8c6;
      --line: rgba(255,255,255,.12);
      --blue: #7aa2ff;
      --cyan: #5eead4;
      --violet: #a78bfa;
      --yellow: #fde68a;
      --red: #fb7185;
    }

    * { box-sizing: border-box; }

    body {
      margin: 0;
      min-height: 100vh;
      overflow: hidden;
      font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
      color: var(--text);
      background: var(--bg);
    }

    canvas {
      position: fixed;
      inset: 0;
      width: 100vw;
      height: 100vh;
      display: block;
      background: radial-gradient(circle at center, #0b1020 0%, #030712 56%, #01030a 100%);
    }

    .panel {
      position: fixed;
      left: 20px;
      top: 20px;
      width: min(430px, calc(100vw - 40px));
      max-height: calc(100vh - 40px);
      overflow: auto;
      padding: 18px;
      border: 1px solid var(--line);
      border-radius: 24px;
      background: var(--panel);
      backdrop-filter: blur(18px);
      box-shadow: 0 28px 80px rgba(0,0,0,.42);
    }

    h1 {
      margin: 0 0 8px;
      font-size: 28px;
      line-height: 1;
      letter-spacing: -0.055em;
    }

    .lead {
      margin: 0 0 16px;
      color: var(--muted);
      font-size: 13px;
      line-height: 1.5;
    }

    .formula {
      margin: 0 0 16px;
      padding: 12px;
      border: 1px solid rgba(255,255,255,.1);
      border-radius: 16px;
      background: rgba(0,0,0,.24);
      color: #dbeafe;
      font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
      font-size: 12px;
      line-height: 1.55;
      white-space: pre-wrap;
    }

    .grid { display: grid; gap: 12px; }

    .row {
      display: grid;
      grid-template-columns: 1fr auto;
      gap: 12px;
      align-items: center;
    }

    label {
      display: block;
      color: var(--muted);
      font-size: 12px;
      margin-bottom: 6px;
    }

    input[type="range"] {
      width: 100%;
      accent-color: #7aa2ff;
    }

    select, button {
      width: 100%;
      border: 1px solid var(--line);
      border-radius: 14px;
      background: rgba(15,23,42,.92);
      color: var(--text);
      padding: 10px 12px;
      font-size: 14px;
      outline: none;
    }

    .value {
      min-width: 66px;
      text-align: right;
      color: #dbeafe;
      font-size: 12px;
      font-variant-numeric: tabular-nums;
    }

    button {
      border: 0;
      cursor: pointer;
      font-weight: 800;
      background: linear-gradient(135deg, #4f7cff, #8b5cf6 52%, #14b8a6);
      box-shadow: 0 18px 40px rgba(79,124,255,.22);
      transition: transform .15s ease, filter .15s ease;
      margin-top: 2px;
    }

    button:hover { transform: translateY(-1px); filter: brightness(1.08); }

    .two {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 10px;
    }

    .stats {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 10px;
      margin-top: 14px;
    }

    .stat {
      padding: 10px;
      border: 1px solid rgba(255,255,255,.09);
      border-radius: 16px;
      background: rgba(255,255,255,.045);
    }

    .stat .k {
      color: var(--muted);
      font-size: 11px;
      margin-bottom: 2px;
    }

    .stat .v {
      font-size: 17px;
      font-weight: 800;
      letter-spacing: -0.03em;
    }

    .hint {
      margin-top: 14px;
      color: var(--muted);
      font-size: 12px;
      line-height: 1.45;
    }

    .pill {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      border: 1px solid rgba(255,255,255,.1);
      border-radius: 999px;
      padding: 4px 8px;
      background: rgba(255,255,255,.05);
      color: #dbeafe;
      font-size: 11px;
      margin: 0 4px 4px 0;
    }

    .rightPanel {
      position: fixed;
      right: 20px;
      bottom: 20px;
      width: min(390px, calc(100vw - 40px));
      padding: 14px;
      border: 1px solid var(--line);
      border-radius: 22px;
      background: var(--panel);
      backdrop-filter: blur(18px);
      box-shadow: 0 28px 80px rgba(0,0,0,.42);
    }

    .rightPanel h2 {
      margin: 0 0 8px;
      font-size: 16px;
      letter-spacing: -0.03em;
    }

    .rightPanel p {
      margin: 0;
      color: var(--muted);
      font-size: 12px;
      line-height: 1.45;
    }

    .phaseName {
      color: #fde68a;
      font-weight: 900;
    }

    @media (max-width: 860px) {
      body { overflow: auto; }
      canvas { position: fixed; }
      .panel, .rightPanel {
        position: relative;
        left: auto;
        right: auto;
        top: auto;
        bottom: auto;
        width: calc(100vw - 24px);
        margin: 12px;
      }
      .rightPanel { margin-top: 0; }
    }
  </style>
</head>
<body>
  <canvas id="universe"></canvas>

  <section class="panel">
    <h1>Universe Rebirth</h1>
    <p class="lead">
      Художественная математическая модель: Вселенная расширяется, схлопывается в чёрную дыру,
      почти исчезает за горизонтом событий, а затем в последний момент восстанавливается.
    </p>

    <div class="formula">base:     r = expansion · sqrt(i) + wave · sin(i·k + t)
collapse: r = mix(baseR, blackHoleR, collapseFactor)
black:    θ = θ + vortex · collapseFactor²
rebirth:  r = baseR · rebirthPulse + shockWave</div>

    <div class="grid">
      <div>
        <label for="preset">Сценарий</label>
        <select id="preset">
          <option value="rebirth">Чёрная дыра → восстановление</option>
          <option value="slow">Медленное схлопывание</option>
          <option value="violent">Жёсткий гравитационный шторм</option>
          <option value="calm">Мягкая космическая пульсация</option>
        </select>
      </div>

      <div>
        <label for="particles">Частицы</label>
        <div class="row">
          <input id="particles" type="range" min="2000" max="70000" step="1000" value="26000">
          <div id="particlesVal" class="value">26000</div>
        </div>
      </div>

      <div>
        <label for="cycle">Длительность цикла, секунд</label>
        <div class="row">
          <input id="cycle" type="range" min="8" max="60" step="1" value="24">
          <div id="cycleVal" class="value">24</div>
        </div>
      </div>

      <div>
        <label for="expansion">Базовое расширение</label>
        <div class="row">
          <input id="expansion" type="range" min="0.8" max="8" step="0.1" value="3.4">
          <div id="expansionVal" class="value">3.4</div>
        </div>
      </div>

      <div>
        <label for="blackHole">Сила чёрной дыры</label>
        <div class="row">
          <input id="blackHole" type="range" min="0" max="10" step="0.1" value="7.4">
          <div id="blackHoleVal" class="value">7.4</div>
        </div>
      </div>

      <div>
        <label for="vortex">Закручивание</label>
        <div class="row">
          <input id="vortex" type="range" min="0" max="18" step="0.1" value="9.8">
          <div id="vortexVal" class="value">9.8</div>
        </div>
      </div>

      <div>
        <label for="wave">Гравитационные волны</label>
        <div class="row">
          <input id="wave" type="range" min="0" max="100" step="1" value="24">
          <div id="waveVal" class="value">24</div>
        </div>
      </div>

      <div>
        <label for="rebirthPower">Сила восстановления</label>
        <div class="row">
          <input id="rebirthPower" type="range" min="0" max="10" step="0.1" value="6.5">
          <div id="rebirthPowerVal" class="value">6.5</div>
        </div>
      </div>

      <div class="two">
        <button id="randomBtn">Случайная Вселенная</button>
        <button id="pauseBtn">Пауза</button>
      </div>
    </div>

    <div class="stats">
      <div class="stat"><div class="k">Фаза</div><div id="phase" class="v phaseName">—</div></div>
      <div class="stat"><div class="k">Схлопывание</div><div id="collapseStat" class="v">0%</div></div>
      <div class="stat"><div class="k">Горизонт</div><div id="horizonStat" class="v">—</div></div>
      <div class="stat"><div class="k">FPS</div><div id="fps" class="v">—</div></div>
    </div>

    <p class="hint">
      <span class="pill">Колесо мыши — масштаб</span>
      <span class="pill">Движение мыши — параллакс</span>
      <span class="pill">Цикл сам повторяется</span>
    </p>
  </section>

  <aside class="rightPanel">
    <h2>Как работает эффект</h2>
    <p>
      На фазе схлопывания координаты частиц смешиваются с координатами около центра. Чем ближе конец цикла,
      тем сильнее закручивание и темнее ядро. В момент почти полного поглощения включается «отскок»:
      радиус резко восстанавливается, появляется ударная волна, и структура Вселенной собирается обратно.
    </p>
  </aside>

  <script>
    const canvas = document.getElementById('universe');
    const ctx = canvas.getContext('2d', { alpha: false });

    const els = {
      preset: document.getElementById('preset'),
      particles: document.getElementById('particles'),
      cycle: document.getElementById('cycle'),
      expansion: document.getElementById('expansion'),
      blackHole: document.getElementById('blackHole'),
      vortex: document.getElementById('vortex'),
      wave: document.getElementById('wave'),
      rebirthPower: document.getElementById('rebirthPower'),
      randomBtn: document.getElementById('randomBtn'),
      pauseBtn: document.getElementById('pauseBtn'),
      phase: document.getElementById('phase'),
      collapseStat: document.getElementById('collapseStat'),
      horizonStat: document.getElementById('horizonStat'),
      fps: document.getElementById('fps')
    };

    const valueEls = {
      particles: document.getElementById('particlesVal'),
      cycle: document.getElementById('cycleVal'),
      expansion: document.getElementById('expansionVal'),
      blackHole: document.getElementById('blackHoleVal'),
      vortex: document.getElementById('vortexVal'),
      wave: document.getElementById('waveVal'),
      rebirthPower: document.getElementById('rebirthPowerVal')
    };

    const GOLDEN_ANGLE = Math.PI * (3 - Math.sqrt(5));

    let W = 0;
    let H = 0;
    let DPR = 1;
    let time = 0;
    let paused = false;
    let zoom = 1;
    let mouseX = 0;
    let mouseY = 0;
    let lastTime = performance.now();
    let fpsSmooth = 60;

    const presets = {
      rebirth: {
        particles: 26000,
        cycle: 24,
        expansion: 3.4,
        blackHole: 7.4,
        vortex: 9.8,
        wave: 24,
        rebirthPower: 6.5
      },
      slow: {
        particles: 30000,
        cycle: 42,
        expansion: 3.0,
        blackHole: 5.8,
        vortex: 6.2,
        wave: 18,
        rebirthPower: 4.5
      },
      violent: {
        particles: 46000,
        cycle: 18,
        expansion: 4.9,
        blackHole: 9.6,
        vortex: 16.5,
        wave: 82,
        rebirthPower: 9.2
      },
      calm: {
        particles: 18000,
        cycle: 30,
        expansion: 2.6,
        blackHole: 4.8,
        vortex: 4.5,
        wave: 14,
        rebirthPower: 3.8
      }
    };

    function resize() {
      DPR = Math.max(1, Math.min(window.devicePixelRatio || 1, 2));
      W = window.innerWidth;
      H = window.innerHeight;
      canvas.width = Math.floor(W * DPR);
      canvas.height = Math.floor(H * DPR);
      canvas.style.width = W + 'px';
      canvas.style.height = H + 'px';
      ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
    }

    function num(id) {
      return Number(els[id].value);
    }

    function clamp01(x) {
      return Math.min(1, Math.max(0, x));
    }

    function smoothstep(edge0, edge1, x) {
      const v = clamp01((x - edge0) / Math.max(1e-9, edge1 - edge0));
      return v * v * (3 - 2 * v);
    }

    function mix(a, b, t) {
      return a + (b - a) * t;
    }

    function syncLabels() {
      for (const key of Object.keys(valueEls)) {
        valueEls[key].textContent = els[key].value;
      }
    }

    function applyPreset(name) {
      const p = presets[name];
      for (const key of Object.keys(p)) els[key].value = p[key];
      syncLabels();
    }

    function randomUniverse() {
      els.particles.value = Math.round((8000 + Math.random() * 60000) / 1000) * 1000;
      els.cycle.value = Math.round(10 + Math.random() * 42);
      els.expansion.value = (1.2 + Math.random() * 6.5).toFixed(1);
      els.blackHole.value = (3 + Math.random() * 7).toFixed(1);
      els.vortex.value = (2 + Math.random() * 16).toFixed(1);
      els.wave.value = Math.round(Math.random() * 100);
      els.rebirthPower.value = (2 + Math.random() * 8).toFixed(1);
      syncLabels();
    }

    function getPhase(p) {
      // p — прогресс внутри цикла 0..1
      const expansionPhase = 1 - smoothstep(0.10, 0.38, p);
      const collapsePhase = smoothstep(0.28, 0.72, p) * (1 - smoothstep(0.82, 0.96, p));
      const nearSingularity = smoothstep(0.66, 0.82, p) * (1 - smoothstep(0.84, 0.91, p));
      const rebirth = smoothstep(0.78, 0.91, p) * (1 - smoothstep(0.91, 1.0, p));
      const restoration = smoothstep(0.86, 1.0, p);

      let name = 'расширение';
      if (p > 0.28 && p <= 0.66) name = 'схлопывание';
      if (p > 0.66 && p <= 0.82) name = 'горизонт';
      if (p > 0.82 && p <= 0.91) name = 'отскок';
      if (p > 0.91) name = 'восстановление';

      return { expansionPhase, collapsePhase, nearSingularity, rebirth, restoration, name };
    }

    function colorFor(index, zNorm, radiusNorm, phase, p) {
      let hue = (210 + 90 * Math.sin(index * 0.0008 + time * 0.5) + 80 * radiusNorm) % 360;

      if (phase.nearSingularity > 0.1) {
        hue = mix(hue, 18, phase.nearSingularity);
      }

      if (phase.rebirth > 0.1) {
        hue = mix(hue, 190 + 80 * Math.sin(index), phase.rebirth);
      }

      const sat = 70 + 25 * zNorm;
      const light = 48 + 30 * zNorm + phase.rebirth * 18 - phase.collapsePhase * 10;
      return `hsl(${hue} ${sat}% ${light}%)`;
    }

    function drawBackground(phase) {
      const cx = W / 2;
      const cy = H / 2;
      const danger = phase.nearSingularity;
      const rebirth = phase.rebirth;

      const grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, Math.max(W, H) * 0.76);
      grad.addColorStop(0, `rgba(${Math.round(mix(11, 255, rebirth))}, ${Math.round(mix(16, 255, rebirth))}, ${Math.round(mix(32, 255, rebirth))}, 1)`);
      grad.addColorStop(0.08, danger > 0.2 ? '#050008' : '#0b1020');
      grad.addColorStop(0.48, danger > 0.2 ? '#09020a' : '#030712');
      grad.addColorStop(1, '#01030a');
      ctx.fillStyle = grad;
      ctx.fillRect(0, 0, W, H);

      // Сетка пространства-времени, которая искажается к центру.
      ctx.save();
      ctx.globalAlpha = 0.10 + rebirth * 0.28;
      ctx.strokeStyle = rebirth > 0.2 ? 'rgba(94,234,212,.38)' : 'rgba(122,162,255,.16)';
      ctx.lineWidth = 1;
      const maxR = Math.min(W, H) * 0.50 * zoom;
      const wobble = Math.sin(time * 4) * 8 * phase.collapsePhase;
      for (let i = 1; i <= 9; i++) {
        ctx.beginPath();
        ctx.arc(cx + mouseX * wobble, cy + mouseY * wobble, maxR * i / 9, 0, Math.PI * 2);
        ctx.stroke();
      }
      ctx.restore();
    }

    function drawBlackHole(cx, cy, phase, baseScale) {
      const collapse = phase.collapsePhase;
      const danger = phase.nearSingularity;
      const rebirth = phase.rebirth;
      const blackHole = num('blackHole');

      const horizon = (38 + blackHole * 9 + danger * 80) * baseScale;
      const diskR = horizon * (2.5 + collapse * 1.8);
      const angle = time * (1.5 + num('vortex') * 0.08);

      els.horizonStat.textContent = Math.round(horizon) + ' px';

      ctx.save();
      ctx.translate(cx, cy);
      ctx.rotate(angle);
      ctx.globalCompositeOperation = 'lighter';

      // Аккреционный диск.
      for (let i = 0; i < 7; i++) {
        ctx.globalAlpha = (0.05 + collapse * 0.09 + danger * 0.06) * (1 - i * 0.08);
        ctx.strokeStyle = i % 2 ? 'rgba(251,113,133,.75)' : 'rgba(250,204,21,.72)';
        ctx.lineWidth = Math.max(1, 2.5 * baseScale);
        ctx.beginPath();
        ctx.ellipse(0, 0, diskR * (1 + i * 0.13), diskR * (0.23 + i * 0.018), 0, 0, Math.PI * 2);
        ctx.stroke();
      }

      ctx.restore();

      // Горизонт событий — абсолютная чёрная область.
      ctx.save();
      ctx.globalCompositeOperation = 'source-over';
      const shadow = ctx.createRadialGradient(cx, cy, 0, cx, cy, horizon * 2.4);
      shadow.addColorStop(0, 'rgba(0,0,0,1)');
      shadow.addColorStop(0.55, 'rgba(0,0,0,.98)');
      shadow.addColorStop(0.72, 'rgba(15,3,18,.8)');
      shadow.addColorStop(1, 'rgba(0,0,0,0)');
      ctx.fillStyle = shadow;
      ctx.beginPath();
      ctx.arc(cx, cy, horizon * 2.4, 0, Math.PI * 2);
      ctx.fill();

      // Светящийся край горизонта.
      ctx.globalCompositeOperation = 'lighter';
      ctx.globalAlpha = 0.35 + danger * 0.45 - rebirth * 0.2;
      ctx.strokeStyle = 'rgba(255,220,160,.8)';
      ctx.lineWidth = 2.2 * baseScale;
      ctx.beginPath();
      ctx.arc(cx, cy, horizon * 1.02, 0, Math.PI * 2);
      ctx.stroke();
      ctx.restore();
    }

    function drawRebirthShock(cx, cy, phase, baseScale) {
      if (phase.rebirth <= 0.01 && phase.restoration <= 0.01) return;

      const power = num('rebirthPower');
      const pulse = phase.rebirth;
      const restore = phase.restoration;
      const shockR = (80 + pulse * Math.min(W, H) * 0.62 + restore * Math.min(W, H) * 0.18) * baseScale;

      ctx.save();
      ctx.globalCompositeOperation = 'lighter';

      const grad = ctx.createRadialGradient(cx, cy, Math.max(1, shockR * 0.72), cx, cy, shockR * 1.08);
      grad.addColorStop(0, 'rgba(94,234,212,0)');
      grad.addColorStop(0.5, `rgba(125,211,252,${0.12 + pulse * 0.34})`);
      grad.addColorStop(0.72, `rgba(255,255,255,${0.10 + pulse * 0.55})`);
      grad.addColorStop(1, 'rgba(167,139,250,0)');
      ctx.fillStyle = grad;
      ctx.beginPath();
      ctx.arc(cx, cy, shockR * (1 + power * 0.015), 0, Math.PI * 2);
      ctx.fill();

      ctx.globalAlpha = 0.35 * pulse;
      ctx.strokeStyle = 'rgba(255,255,255,.9)';
      ctx.lineWidth = 2.5 * baseScale;
      ctx.beginPath();
      ctx.arc(cx, cy, shockR, 0, Math.PI * 2);
      ctx.stroke();

      ctx.restore();
    }

    function drawUniverse(dt) {
      const particles = num('particles');
      const cycle = num('cycle');
      const expansion = num('expansion');
      const blackHole = num('blackHole');
      const vortex = num('vortex');
      const wave = num('wave');
      const rebirthPower = num('rebirthPower');

      if (!paused) time += dt * 0.001;

      const p = (time % cycle) / cycle;
      const phase = getPhase(p);

      els.phase.textContent = phase.name;
      els.collapseStat.textContent = Math.round(phase.collapsePhase * 100) + '%';

      drawBackground(phase);

      const cx = W / 2 + mouseX * 26;
      const cy = H / 2 + mouseY * 26;
      const baseScale = Math.min(W, H) / 920 * zoom;
      const k = 0.014 + blackHole * 0.0018;
      const q = 0.009 + wave * 0.00012;

      const collapse = phase.collapsePhase;
      const danger = phase.nearSingularity;
      const rebirth = phase.rebirth;
      const restore = phase.restoration;

      ctx.save();
      ctx.globalCompositeOperation = 'lighter';

      for (let i = 1; i <= particles; i++) {
        const sqrtI = Math.sqrt(i);
        const baseR = (expansion * sqrtI + wave * Math.sin(i * k + time * 1.6)) * baseScale;
        const baseTheta = i * GOLDEN_ANGLE + 0.42 * Math.sin(time + i * q);

        // Во время схлопывания частица стремится к чёрной дыре, но не строго по прямой — она закручивается.
        const sinkR = (10 + 42 * Math.sin(i * 0.019 + time * 3) ** 2) * baseScale;
        const collapseR = mix(baseR, sinkR, collapse);
        const twistedTheta = baseTheta + vortex * collapse * collapse * (1.5 + i / particles * 5.5) + time * collapse * 2.4;

        // В момент восстановления радиус возвращается к базовой структуре через ударную волну.
        const waveFront = smoothstep(0.0, 1.0, rebirth);
        const particleDelay = i / particles;
        const rebirthGate = smoothstep(particleDelay * 0.55, particleDelay * 0.55 + 0.22, waveFront);
        const shock = rebirthPower * 30 * Math.sin((particleDelay - waveFront) * 18) * Math.exp(-Math.abs(particleDelay - waveFront) * 6) * baseScale;

        let r = mix(collapseR, baseR + shock, Math.max(rebirthGate, restore));
        r *= 1 + 0.08 * Math.sin(time * 3 + i * 0.005) * (rebirth + restore);

        let theta = mix(twistedTheta, baseTheta + 0.35 * Math.sin(time * 2 + i * q), Math.max(rebirthGate, restore));

        const depth = 120 * Math.sin(i * q + time * 1.4);
        const zNorm = (Math.sin(i * q + time * 1.4) + 1) / 2;

        const x = cx + r * Math.cos(theta) + mouseX * depth * 0.13;
        const y = cy + r * Math.sin(theta) + mouseY * depth * 0.13;

        const radiusNorm = Math.min(1, r / (Math.min(W, H) * 0.58));
        const swallowed = collapse > 0.7 && r < (54 + blackHole * 9) * baseScale;
        const swallowFade = swallowed ? 0.25 : 1;

        const size = Math.max(0.38, 0.52 + zNorm * 1.55 - radiusNorm * 0.18 + rebirth * 0.9);
        const alpha = Math.max(0.02, (0.13 + zNorm * 0.62 - radiusNorm * 0.15 + rebirth * 0.4 - danger * 0.08) * swallowFade);

        ctx.globalAlpha = alpha;
        ctx.fillStyle = colorFor(i, zNorm, radiusNorm, phase, p);
        ctx.beginPath();
        ctx.arc(x, y, size, 0, Math.PI * 2);
        ctx.fill();

        // Следы падения в чёрную дыру.
        if (collapse > 0.28 && i % 17 === 0) {
          const tail = 1 + collapse * 18;
          const tx = cx + (r + tail) * Math.cos(theta - collapse * 0.18);
          const ty = cy + (r + tail) * Math.sin(theta - collapse * 0.18);
          ctx.globalAlpha = alpha * 0.22 * collapse;
          ctx.strokeStyle = colorFor(i, zNorm, radiusNorm, phase, p);
          ctx.lineWidth = Math.max(0.35, size * 0.45);
          ctx.beginPath();
          ctx.moveTo(x, y);
          ctx.lineTo(tx, ty);
          ctx.stroke();
        }
      }

      ctx.restore();

      drawBlackHole(cx, cy, phase, baseScale);
      drawRebirthShock(cx, cy, phase, baseScale);

      // Финальная вспышка в момент отскока.
      if (rebirth > 0.05) {
        ctx.save();
        ctx.globalCompositeOperation = 'lighter';
        ctx.globalAlpha = 0.12 + rebirth * 0.28;
        ctx.fillStyle = 'rgba(255,255,255,.65)';
        ctx.fillRect(0, 0, W, H);
        ctx.restore();
      }
    }

    function frame(now) {
      const dt = now - lastTime;
      lastTime = now;
      fpsSmooth = fpsSmooth * 0.92 + (1000 / Math.max(1, dt)) * 0.08;
      els.fps.textContent = Math.round(fpsSmooth);
      drawUniverse(dt);
      requestAnimationFrame(frame);
    }

    for (const key of ['particles', 'cycle', 'expansion', 'blackHole', 'vortex', 'wave', 'rebirthPower']) {
      els[key].addEventListener('input', syncLabels);
    }

    els.preset.addEventListener('change', () => applyPreset(els.preset.value));
    els.randomBtn.addEventListener('click', randomUniverse);
    els.pauseBtn.addEventListener('click', () => {
      paused = !paused;
      els.pauseBtn.textContent = paused ? 'Продолжить' : 'Пауза';
    });

    window.addEventListener('resize', resize);
    window.addEventListener('mousemove', (e) => {
      mouseX = (e.clientX / Math.max(1, W) - 0.5) * 2;
      mouseY = (e.clientY / Math.max(1, H) - 0.5) * 2;
    });

    window.addEventListener('wheel', (e) => {
      e.preventDefault();
      const factor = e.deltaY < 0 ? 1.08 : 0.92;
      zoom = Math.min(5, Math.max(0.35, zoom * factor));
    }, { passive: false });

    resize();
    applyPreset('rebirth');
    syncLabels();
    requestAnimationFrame(frame);
  </script>
</body>
</html>

Да, для небольшего домашнего серваера, достаточно. А, у вас компания, что столько сервисов?

Это все ясно, но чем этот Мой офис, отличается от того, что есть в NEXTCLOUD

Уже думает, я сейчас отрабатываю сценарий на WSL, туннель, домен, VPN, сегодня уже не могу открыть сайт по доменному имени, приходится VPN запускать, частично использование Nextcloud как домашнее облако для хранения качественного видео, позже распишу, все, когда ручками пройдусь и все более менее стабильно станет

Тут я, каюсь прибегал к помощи, сейчас другой кейс, делаю, живой и с демонстрацией, не все получается, но вторая жизнь домашнего игрового компа, а уже давно не играю правда

Я другую напишу, более интересную, живую и тогда, Вы поймете мой смысл

Сколько будет стоить такой VPS и не всем возможно получить белый IP

echo “=== CPU ===”; nproc; lscpu | grep -E ‘Model name|CPU\(s\)|Thread|Core|Socket’; echo; echo “=== RAM ===”; free -h; echo; echo “=== DISK ===”; df -h / === CPU === 14 Model name: 12th Gen Intel® Core™ i7-12700 Thread(s) per core: 2 Core(s) per socket: 7 Socket(s): 1

=== RAM === total used free shared buff/cache available Mem: 31Gi 1.8Gi 28Gi 219Mi 1.5Gi 29Gi Swap: 8.0Gi 0B 8.0Gi

=== DISK === Filesystem Size Used Avail Use% Mounted on /dev/sdd 1007G 14G 942G 2% /

Перед отчетом, нужно узнать с какими странами у ФНС есть автоматический обмен данными, как узнали, так и отчет давайте. Отчет, можно давать в любой форме, к примеру, если не можете найти адрес Белорусского банка на латинице, так и заполняйте форму "Netadresanalatinice"

Не, знаю, но как мне кажется пейджеры еще используются, очень быстрый способ оповещения

1

Information

Rating
Does not participate
Location
Россия
Registered
Activity

Specialization

Администратор серверов, Промпт-инженер
Средний