403Webshell
Server IP : 167.235.67.158  /  Your IP : 216.73.216.95
Web Server : Apache
System : Linux ubuntu-8gb-nbg1-1 6.8.0-111-generic #111-Ubuntu SMP PREEMPT_DYNAMIC Sat Apr 11 23:16:02 UTC 2026 x86_64
User : root ( 0)
PHP Version : 8.3.6
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/bc.the-word.com/timer/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/bc.the-word.com/timer/number-pyramid.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Number Pyramid</title>
<style>
  :root {
    --red: #e02323;
    --orange: #f5a623;
    --bg: #fafafa;
    --panel: rgba(255, 255, 255, 0.92);
    --border: #1a1a1a;
    --text: #1a1a1a;
  }

  * { box-sizing: border-box; }

  html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    overflow: hidden;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    background: var(--bg);
    color: var(--text);
    -webkit-tap-highlight-color: transparent;
  }

  #app { position: fixed; inset: 0; }

  canvas {
    display: block;
    width: 100%;
    height: 100%;
    touch-action: none; /* we handle gestures ourselves */
    cursor: grab;
  }
  canvas:active { cursor: grabbing; }

  /* Layer counter (top right) */
  #counter {
    position: fixed;
    top: 16px;
    right: 16px;
    background: var(--panel);
    backdrop-filter: blur(6px);
    border: 2px solid var(--border);
    border-radius: 10px;
    padding: 8px 14px;
    font-size: 16px;
    font-weight: 700;
    box-shadow: 0 4px 14px rgba(0,0,0,0.12);
    user-select: none;
  }

  /* Bottom-left control cluster */
  #controls {
    position: fixed;
    left: 16px;
    bottom: 16px;
    display: flex;
    gap: 10px;
    align-items: center;
  }

  .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    border: 2px solid var(--border);
    background: var(--panel);
    backdrop-filter: blur(6px);
    color: var(--text);
    border-radius: 10px;
    font-size: 16px;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(0,0,0,0.12);
    user-select: none;
    transition: transform 0.05s ease, background 0.15s ease;
  }
  .btn:hover { background: #fff; }
  .btn:active { transform: translateY(1px) scale(0.98); }

  #addLayer { padding: 10px 18px; }

  .icon-btn {
    width: 46px;
    height: 46px;
    padding: 0;
    font-size: 0;
  }
  .icon-btn svg { width: 22px; height: 22px; }

  /* Zoom controls (bottom right) */
  #zoom {
    position: fixed;
    right: 16px;
    bottom: 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
  }

  #legend {
    position: fixed;
    top: 16px;
    left: 16px;
    background: var(--panel);
    backdrop-filter: blur(6px);
    border: 2px solid var(--border);
    border-radius: 10px;
    padding: 8px 12px;
    font-size: 13px;
    font-weight: 600;
    box-shadow: 0 4px 14px rgba(0,0,0,0.12);
    user-select: none;
    max-width: 230px;
    line-height: 1.45;
  }
  .swatch {
    display: inline-block;
    width: 12px; height: 12px;
    border: 1.5px solid var(--border);
    border-radius: 3px;
    vertical-align: -1px;
    margin-right: 4px;
  }
  .swatch.red { background: var(--red); }
  .swatch.orange { background: var(--orange); }
  .swatch.green { background: #2ea843; }
  #legend .row { white-space: nowrap; }
  #legend .hint { font-weight: 500; color: #555; margin-top: 4px; white-space: normal; }
</style>
</head>
<body>
<div id="app">
  <canvas id="pyramid"></canvas>

  <div id="counter">Layers: <span id="layerCount">1</span></div>

  <div id="legend">
    <div class="row"><span class="swatch green"></span>new number (row center)</div>
    <div class="row"><span class="swatch red"></span>odd # of digits</div>
    <div class="row"><span class="swatch orange"></span>even # of digits</div>
    <div class="hint">value = ⌊13^(d/2)⌋, d = distance from edge</div>
  </div>

  <div id="controls">
    <button id="addLayer" class="btn">+ Add layer</button>
  </div>

  <div id="zoom">
    <button id="zoomIn" class="btn icon-btn" aria-label="Zoom in" title="Zoom in">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
        <circle cx="10.5" cy="10.5" r="6.5"></circle>
        <line x1="15.5" y1="15.5" x2="21" y2="21"></line>
        <line x1="10.5" y1="7.5" x2="10.5" y2="13.5"></line>
        <line x1="7.5" y1="10.5" x2="13.5" y2="10.5"></line>
      </svg>
    </button>
    <button id="zoomOut" class="btn icon-btn" aria-label="Zoom out" title="Zoom out">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
        <circle cx="10.5" cy="10.5" r="6.5"></circle>
        <line x1="15.5" y1="15.5" x2="21" y2="21"></line>
        <line x1="7.5" y1="10.5" x2="13.5" y2="10.5"></line>
      </svg>
    </button>
    <button id="fit" class="btn icon-btn" aria-label="Fit to view" title="Fit to view">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
        <path d="M4 9V5a1 1 0 0 1 1-1h4"></path>
        <path d="M20 9V5a1 1 0 0 0-1-1h-4"></path>
        <path d="M4 15v4a1 1 0 0 0 1 1h4"></path>
        <path d="M20 15v4a1 1 0 0 1-1 1h-4"></path>
      </svg>
    </button>
  </div>
</div>

<script>
(() => {
  "use strict";

  // ---- Geometry constants (world units) ----
  const CELL = 64;          // cell size in world units
  const GAP = 0;            // gap between cells (cells share borders like the screenshot)
  const FIT_PADDING = 80;   // screen px padding when fitting
  const MIN_SCALE = 0.0005;
  const MAX_SCALE = 6;

  // ---- State ----
  let layers = 1;
  let scale = 1;
  let tx = 0;   // screen translation x: screenX = worldX * scale + tx
  let ty = 0;   // screen translation y

  const canvas = document.getElementById("pyramid");
  const ctx = canvas.getContext("2d");
  let dpr = Math.max(1, window.devicePixelRatio || 1);
  let viewW = 0, viewH = 0; // CSS pixels

  // ---- Value computation: value(d) = floor(sqrt(13^d)) using BigInt isqrt ----
  const THIRTEEN = 13n;
  const valueCache = new Map(); // d -> string (decimal)

  function isqrt(n) {
    if (n < 0n) throw new Error("neg");
    if (n < 2n) return n;
    // initial guess via bit length
    let x = 1n << (BigInt(n.toString(2).length + 1) >> 1n);
    while (true) {
      const y = (x + n / x) >> 1n;
      if (y >= x) break;
      x = y;
    }
    // x is now floor-ish; correct it
    while (x * x > n) x -= 1n;
    while ((x + 1n) * (x + 1n) <= n) x += 1n;
    return x;
  }

  function valueStr(d) {
    if (valueCache.has(d)) return valueCache.get(d);
    let s;
    if (d === 0) {
      s = "1";
    } else {
      const pow = THIRTEEN ** BigInt(d);   // 13^d
      s = isqrt(pow).toString();           // floor(sqrt(13^d))
    }
    valueCache.set(d, s);
    return s;
  }

  // Color rule: odd digit count -> red, even digit count -> orange
  function colorFor(str) {
    return (str.length % 2 === 1) ? "#e02323" : "#f5a623";
  }

  // ---- Pyramid layout helpers ----
  // Row r (1-indexed) has 2r-1 cells, centered on x = 0.
  // Bounding box of the whole pyramid:
  function pyramidBounds() {
    const widthCells = 2 * layers - 1;
    const w = widthCells * CELL;
    const h = layers * CELL;
    return {
      minX: -w / 2,
      maxX: w / 2,
      minY: 0,
      maxY: h,
      w, h,
    };
  }

  // ---- View transforms ----
  function worldToScreen(wx, wy) {
    return { x: wx * scale + tx, y: wy * scale + ty };
  }
  function screenToWorld(sx, sy) {
    return { x: (sx - tx) / scale, y: (sy - ty) / scale };
  }

  function clampScale(s) {
    return Math.min(MAX_SCALE, Math.max(MIN_SCALE, s));
  }

  function fitView() {
    const b = pyramidBounds();
    const availW = Math.max(10, viewW - FIT_PADDING * 2);
    const availH = Math.max(10, viewH - FIT_PADDING * 2);
    const s = clampScale(Math.min(availW / b.w, availH / b.h));
    scale = s;
    // center bbox center at canvas center
    const cx = (b.minX + b.maxX) / 2; // = 0
    const cy = (b.minY + b.maxY) / 2;
    tx = viewW / 2 - cx * scale;
    ty = viewH / 2 - cy * scale;
  }

  // Returns true if the pyramid currently fits inside the padded viewport.
  function pyramidFits() {
    const b = pyramidBounds();
    const tl = worldToScreen(b.minX, b.minY);
    const br = worldToScreen(b.maxX, b.maxY);
    return (
      tl.x >= FIT_PADDING &&
      tl.y >= FIT_PADDING &&
      br.x <= viewW - FIT_PADDING &&
      br.y <= viewH - FIT_PADDING
    );
  }

  function zoomAt(sx, sy, factor) {
    const before = screenToWorld(sx, sy);
    scale = clampScale(scale * factor);
    // keep the world point under (sx,sy) fixed
    tx = sx - before.x * scale;
    ty = sy - before.y * scale;
    draw();
  }

  // ---- Rendering ----
  function resize() {
    dpr = Math.max(1, window.devicePixelRatio || 1);
    viewW = canvas.clientWidth;
    viewH = canvas.clientHeight;
    canvas.width = Math.round(viewW * dpr);
    canvas.height = Math.round(viewH * dpr);
    draw();
  }

  function draw() {
    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    ctx.clearRect(0, 0, viewW, viewH);

    const cellScreen = CELL * scale;

    // Visible world rectangle (for culling)
    const vMin = screenToWorld(0, 0);
    const vMax = screenToWorld(viewW, viewH);

    const drawText = cellScreen > 18; // skip text when cells are tiny
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.lineWidth = Math.max(1, Math.min(2, cellScreen * 0.03));
    ctx.strokeStyle = "#1a1a1a";

    const widthCellsBottom = 2 * layers - 1;

    for (let r = 1; r <= layers; r++) {
      const count = 2 * r - 1;
      const rowWorldLeft = -count * CELL / 2;
      const wy = (r - 1) * CELL;

      // cull rows outside view vertically
      if (wy + CELL < vMin.y || wy > vMax.y) continue;

      for (let j = 0; j < count; j++) {
        const wx = rowWorldLeft + j * CELL;
        // cull cols outside view horizontally
        if (wx + CELL < vMin.x || wx > vMax.x) continue;

        const d = Math.min(j, count - 1 - j); // distance from nearest edge
        const str = valueStr(d);
        const isCenter = (j === r - 1); // central cell introduces the new number
        const col = isCenter ? "#2ea843" : colorFor(str);

        const p = worldToScreen(wx, wy);
        const size = cellScreen;

        ctx.fillStyle = col;
        ctx.fillRect(p.x, p.y, size, size);
        ctx.strokeRect(p.x, p.y, size, size);

        if (drawText) {
          ctx.fillStyle = "#1a1a1a";
          // fit font size to cell width
          let fontSize = Math.min(size * 0.42, size * 0.9 / Math.max(1, str.length * 0.62));
          fontSize = Math.max(6, fontSize);
          ctx.font = `700 ${fontSize}px -apple-system, "Segoe UI", Roboto, Arial, sans-serif`;
          // ensure it fits; shrink if measured too wide
          let measured = ctx.measureText(str).width;
          const maxW = size * 0.86;
          if (measured > maxW) {
            fontSize *= maxW / measured;
            fontSize = Math.max(5, fontSize);
            ctx.font = `700 ${fontSize}px -apple-system, "Segoe UI", Roboto, Arial, sans-serif`;
          }
          ctx.fillText(str, p.x + size / 2, p.y + size / 2 + size * 0.02);
        }
      }
    }
  }

  // ---- Add layer ----
  function addLayer() {
    layers += 1;
    document.getElementById("layerCount").textContent = String(layers);
    // If the new (larger) pyramid no longer fits, zoom out to fit it.
    if (!pyramidFits()) {
      fitView();
    }
    draw();
  }

  // ---- Pointer / gesture handling ----
  const pointers = new Map(); // id -> {x, y}
  let pinchPrev = null;       // {dist, midX, midY}

  function getPos(e) {
    const rect = canvas.getBoundingClientRect();
    return { x: e.clientX - rect.left, y: e.clientY - rect.top };
  }

  canvas.addEventListener("pointerdown", (e) => {
    canvas.setPointerCapture(e.pointerId);
    pointers.set(e.pointerId, getPos(e));
    if (pointers.size === 2) {
      pinchPrev = pinchState();
    }
  });

  canvas.addEventListener("pointermove", (e) => {
    if (!pointers.has(e.pointerId)) return;
    const prev = pointers.get(e.pointerId);
    const pos = getPos(e);
    pointers.set(e.pointerId, pos);

    if (pointers.size === 1) {
      // pan
      tx += pos.x - prev.x;
      ty += pos.y - prev.y;
      draw();
    } else if (pointers.size === 2) {
      const cur = pinchState();
      if (pinchPrev) {
        // zoom around midpoint
        const factor = cur.dist / pinchPrev.dist;
        const before = screenToWorld(cur.midX, cur.midY);
        scale = clampScale(scale * factor);
        tx = cur.midX - before.x * scale;
        ty = cur.midY - before.y * scale;
        // pan by midpoint movement
        tx += cur.midX - pinchPrev.midX;
        ty += cur.midY - pinchPrev.midY;
        draw();
      }
      pinchPrev = cur;
    }
  });

  function endPointer(e) {
    if (pointers.has(e.pointerId)) pointers.delete(e.pointerId);
    if (pointers.size < 2) pinchPrev = null;
  }
  canvas.addEventListener("pointerup", endPointer);
  canvas.addEventListener("pointercancel", endPointer);
  canvas.addEventListener("pointerleave", endPointer);

  function pinchState() {
    const pts = [...pointers.values()];
    const dx = pts[0].x - pts[1].x;
    const dy = pts[0].y - pts[1].y;
    return {
      dist: Math.hypot(dx, dy) || 1,
      midX: (pts[0].x + pts[1].x) / 2,
      midY: (pts[0].y + pts[1].y) / 2,
    };
  }

  // Mouse wheel / trackpad zoom around cursor
  canvas.addEventListener("wheel", (e) => {
    e.preventDefault();
    const pos = getPos(e);
    const factor = Math.exp(-e.deltaY * 0.0015);
    zoomAt(pos.x, pos.y, factor);
  }, { passive: false });

  // ---- Buttons ----
  document.getElementById("addLayer").addEventListener("click", addLayer);
  document.getElementById("zoomIn").addEventListener("click", () => zoomAt(viewW / 2, viewH / 2, 1.25));
  document.getElementById("zoomOut").addEventListener("click", () => zoomAt(viewW / 2, viewH / 2, 0.8));
  document.getElementById("fit").addEventListener("click", () => { fitView(); draw(); });

  window.addEventListener("resize", resize);

  // ---- Init ----
  function init() {
    viewW = canvas.clientWidth;
    viewH = canvas.clientHeight;
    resize();
    fitView();
    draw();
  }
  // ensure layout is ready
  requestAnimationFrame(init);
})();
</script>
</body>
</html>

Youez - 2016 - github.com/yon3zu
LinuXploit