{"id":92,"date":"2025-10-12T11:11:58","date_gmt":"2025-10-12T11:11:58","guid":{"rendered":"https:\/\/cartografies.com\/?page_id=92"},"modified":"2025-10-12T11:11:58","modified_gmt":"2025-10-12T11:11:58","slug":"chainflex-nfc","status":"publish","type":"page","link":"https:\/\/cartografies.com\/index.php\/chainflex-nfc\/","title":{"rendered":"Chainflex NFC"},"content":{"rendered":"\n<!-- Chainflex NFC \u2013 Prototipo MINIMAL (WordPress > Bloque HTML). UI inspirada en tu mockup -->\n<div id=\"rc-app\" class=\"rc-wrap\">\n  <style>\n    :root{--brand:#F07C00;--text:#0f172a;--muted:#6b7280;--line:#e5e7eb}\n    .rc-wrap{font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,\"Helvetica Neue\",Arial,\"Noto Sans\",sans-serif;max-width:420px;margin:0 auto;padding:16px}\n    .rc-card{background:#fff;border-radius:28px;overflow:hidden;box-shadow:0 14px 40px rgba(0,0,0,.08)}\n    .rc-hero{background:var(--brand);color:#fff;padding:28px 22px}\n    .rc-hero h1{margin:0;font-size:32px;line-height:1.1;font-weight:800;letter-spacing:.2px}\n    .rc-body{padding:22px}\n    .rc-group{margin-bottom:18px}\n    .rc-label{display:block;font-weight:700;color:var(--text);margin:0 0 8px;font-size:16px}\n    .rc-input,.rc-select{width:100%;border:1px solid var(--line);border-radius:14px;padding:12px 14px;font-size:16px;outline:none;background:#fff}\n    .rc-input:focus,.rc-select:focus{border-color:#cbd5e1;box-shadow:0 0 0 4px rgba(240,124,0,.12)}\n    .rc-btn{width:100%;display:block;border:none;border-radius:14px;padding:14px 16px;font-weight:800;font-size:18px;cursor:pointer}\n    .rc-btn.primary{background:var(--brand);color:#fff;}\n    .rc-btn.primary:disabled{opacity:.6;cursor:not-allowed}\n    .rc-divider{height:1px;background:var(--line);margin:18px 0}\n    .rc-status{color:var(--text);font-weight:700;margin:0 0 6px;font-size:16px}\n    .rc-k{color:var(--text);font-size:16px;font-weight:700}\n    .rc-sub{color:var(--muted);margin:0}\n    .rc-foot{color:var(--muted);font-size:12px;margin-top:12px}\n    .rc-pill{display:inline-block;margin-top:8px;background:#fff7ed;color:#9a3412;border:1px solid #fed7aa;border-radius:999px;padding:6px 10px;font-weight:700;font-size:12px}\n  <\/style>\n\n  <div class=\"rc-card\">\n    <div class=\"rc-hero\">\n      <h1>Chainflex\u00ae<\/h1>\n    <\/div>\n    <div class=\"rc-body\">\n      <!-- Inputs -->\n      <div class=\"rc-group\">\n        <label class=\"rc-label\" for=\"totalCycles\">Estimated number of cycles<\/label>\n        <input id=\"totalCycles\" class=\"rc-input\" type=\"number\" min=\"1\" step=\"1\" placeholder=\"1000000\" value=\"1000000\" \/>\n      <\/div>\n      <div class=\"rc-group\">\n        <label class=\"rc-label\" for=\"cyclesPer\">Number of cycles<\/label>\n        <input id=\"cyclesPer\" class=\"rc-input\" type=\"number\" min=\"0\" step=\"1\" placeholder=\"300\" value=\"300\" \/>\n      <\/div>\n      <div class=\"rc-group\">\n        <label class=\"rc-label\" for=\"periodUnit\">Period<\/label>\n        <select id=\"periodUnit\" class=\"rc-select\">\n          <option value=\"day\" selected>Day<\/option>\n          <option value=\"hour\">Hour<\/option>\n          <option value=\"week\">Week<\/option>\n          <option value=\"month\">Month (\u224830 days)<\/option>\n        <\/select>\n      <\/div>\n\n      <button id=\"btnStart\" class=\"rc-btn primary\">Start<\/button>\n\n      <div class=\"rc-divider\"><\/div>\n\n      <!-- Status -->\n      <p class=\"rc-status\">Status:<\/p>\n      <p id=\"kStatus\" class=\"rc-sub\">Not started<\/p>\n\n      <p class=\"rc-status\" style=\"margin-top:12px\">Estimated end-of-life:<\/p>\n      <p id=\"kETA\" class=\"rc-k\">\u2013<\/p>\n\n      <span id=\"kAlert\" class=\"rc-pill\" style=\"display:none;\">20% life remaining<\/span>\n\n      <p class=\"rc-foot\">Demo local sin servidor. Los c\u00e1lculos se basan en uso continuo a la tasa indicada. Para alarmas en background \u2192 PWA o backend.<\/p>\n    <\/div>\n  <\/div>\n\n  <script>\n  (function(){\n    const $ = (id)=>document.getElementById(id);\n    const elTotal = $(\"totalCycles\");\n    const elCyclesPer = $(\"cyclesPer\");\n    const elUnit = $(\"periodUnit\");\n    const btnStart = $(\"btnStart\");\n    const kStatus = $(\"kStatus\");\n    const kETA = $(\"kETA\");\n    const kAlert = $(\"kAlert\");\n\n    \/\/ Estado m\u00ednimo\n    let state = {\n      totalCycles: Number(elTotal.value||1000000),\n      cyclesPer: Number(elCyclesPer.value||300),\n      unit: elUnit.value||'day',\n      startedAt: null,       \/\/ ISO string\n      running: false,\n      accumActiveSec: 0,     \/\/ para futuras pausas si las a\u00f1ades\n      notifyArmed: false\n    };\n\n    function unitSeconds(u){\n      switch(u){\n        case 'hour': return 3600;\n        case 'day': return 86400;\n        case 'week': return 604800;\n        case 'month': return 2592000; \/\/ 30 d\u00edas aprox\n        default: return 86400;\n      }\n    }\n    function cyclesPerSecond(){\n      const per = Number(elCyclesPer.value||0); const sec = unitSeconds(elUnit.value);\n      return per>0? per\/sec : 0;\n    }\n    function requiredActiveSeconds(){\n      const cps = cyclesPerSecond();\n      return cps>0 ? Number(elTotal.value||0)\/cps : Infinity;\n    }\n    function activeSecondsNow(){\n      if(!state.startedAt || !state.running) return state.accumActiveSec||0;\n      return (state.accumActiveSec||0) + Math.max(0, (Date.now() - new Date(state.startedAt).getTime())\/1000);\n    }\n    function usedCyclesNow(){ return activeSecondsNow()*cyclesPerSecond(); }\n    function clamp(n,min,max){ return Math.min(Math.max(n,min),max); }\n\n    function fmtDMY(d){\n      if(!d) return '\u2013';\n      const pad=(n)=>String(n).padStart(2,'0');\n      return pad(d.getDate()) + '\/' + pad(d.getMonth()+1) + '\/' + d.getFullYear();\n    }\n\n    function update(){\n      \/\/ Estado\n      kStatus.textContent = state.running ? 'Running' : (state.startedAt? 'Paused' : 'Not started');\n\n      \/\/ ETA\n      if(!state.startedAt){ kETA.textContent = '\u2013'; kAlert.style.display='none'; return; }\n      const req = requiredActiveSeconds();\n      const used = usedCyclesNow();\n      const leftPct = 100 - (state.totalCycles>0 ? (used\/state.totalCycles*100) : 0);\n      const remainingSec = Math.max(0, req - activeSecondsNow());\n      const eta = new Date(Date.now() + remainingSec*1000);\n      kETA.textContent = fmtDMY(eta);\n      kAlert.style.display = leftPct <= 20 ? 'inline-block' : 'none';\n    }\n\n    btnStart.addEventListener('click', ()=>{\n      \/\/ al pulsar Start empezamos desde ahora (prototipo simple)\n      state.totalCycles = Number(elTotal.value||0);\n      state.unit = elUnit.value;\n      state.startedAt = new Date().toISOString();\n      state.running = true;\n      update();\n      \/\/ feedback\n      btnStart.disabled = true;\n      btnStart.textContent = 'Running';\n    });\n\n    \/\/ Cambios de par\u00e1metros refrescan ETA si ya arranc\u00f3\n    [elTotal, elCyclesPer, elUnit].forEach(el=>{\n      el.addEventListener('input', ()=>{ if(state.startedAt){ update(); } });\n    });\n\n    update();\n  })();\n  <\/script>\n<\/div>\n\n\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Chainflex\u00ae Estimated number of cycles Number of cycles Period DayHourWeekMonth (\u224830 days) Start Status: Not started Estimated end-of-life: \u2013 20% life remaining Demo local sin servidor. Los c\u00e1lculos se basan en uso continuo a la tasa indicada. Para alarmas en background \u2192 PWA o backend.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-92","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/cartografies.com\/index.php\/wp-json\/wp\/v2\/pages\/92","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cartografies.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/cartografies.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/cartografies.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cartografies.com\/index.php\/wp-json\/wp\/v2\/comments?post=92"}],"version-history":[{"count":3,"href":"https:\/\/cartografies.com\/index.php\/wp-json\/wp\/v2\/pages\/92\/revisions"}],"predecessor-version":[{"id":95,"href":"https:\/\/cartografies.com\/index.php\/wp-json\/wp\/v2\/pages\/92\/revisions\/95"}],"wp:attachment":[{"href":"https:\/\/cartografies.com\/index.php\/wp-json\/wp\/v2\/media?parent=92"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}