Agua Las LomasLectura

N.º contadorNombreRamalLectura anteriorLectura actualConsumo
Consumo total0

Al abrir un trimestre nuevo, se copian los contadores y la lectura actual anterior pasa a ser la lectura anterior.

Trimestres guardados
Otros dispositivos

Para ver tus datos en todos tus dispositivos, abre esta página desde la app de Claude con tu cuenta. Si trabajáis varias personas: cada una envía su copia con «Enviar programa con mis datos» y la otra la une con «Añadir datos de otro».

","text/html"); var app=null;Array.prototype.slice.call(d.querySelectorAll("script")).forEach(function(x){if(x.id==="app")app=x;else x.parentNode.removeChild(x)}); if(!app)return null; var sd=d.createElement("script");sd.type="application/json";sd.id="seed";sd.setAttribute("data-t",String(Date.now())); sd.textContent=JSON.stringify({cur:S.cur,qs:S.qs,list:S.list,lts:S.lts}).replace(/\n"+d.documentElement.outerHTML)} function mergeSeed(sv){if(!sv||!sv.qs)return; Object.keys(sv.qs).forEach(function(k){if(!/^\d{4}-[1-4]$/.test(k))return;var q=sv.qs[k],c=S.qs[k]; if(!c||empty(c)||(+q.ts||0)>(c.ts||0))S.qs[k]=JSON.parse(JSON.stringify(q))}); if(!S.list&&sv.list){S.list=sv.list;S.lts=sv.lts||0} if(sv.cur&&S.qs[sv.cur]&&!hadLocal)S.cur=sv.cur} $("sendprog").addEventListener("click",function(){var m=function(t){$("progmsg").textContent=t},d=exportProgram(); if(!d){m("No se pudo preparar el programa.");return} var fn="lectura-contadores-con-datos.html";m("Preparando el programa con tus datos…"); shareVia(d,fn,"text/html",m,function(){saveVia(d,fn,m,function(w){m((w?w+" ":"")+"Aquí no se pueden enviar archivos.")})})}); $("saved").addEventListener("click",function(e){ var fv=e.target.closest("[data-fv]");if(fv){openFV(fv.dataset.fv);return} var fs=e.target.closest("[data-fs]");if(fs){openSend(fs.dataset.fs);return} var d=e.target.closest("[data-dk]"); if(d){var k=d.dataset.dk; if(!d.classList.contains("sure")){d.classList.add("sure");d.textContent="¿Borrar?";return} ensureList();delete S.qs[k];S.del[k]=Date.now(); wd("trimestres/"+k);pushDel(); if(k===S.cur){var rest=Object.keys(S.qs).sort(); if(rest.length){open(rest[rest.length-1])}else{S.cur=today.getFullYear()+"-"+(Math.floor(today.getMonth()/3)+1);open(S.cur)}} else{save(true);draw()} return} var b=e.target.closest("[data-k]");if(b)open(b.dataset.k)}); $("rows").addEventListener("input",function(e){ var t=e.target,i=t.dataset.i;if(i===undefined)return; var r=Q().rows[i];r[t.dataset.f]=t.value;if(t.dataset.f==="ant")r.m=t.value!=="";save(); var c=$("c"+i),u=use(r);c.textContent=cell(r);c.className="c"+(u!==null&&u<0?" bad":"");totals()}); $("rows").addEventListener("click",function(e){ var o=e.target.closest("[data-open]");if(o){openOv(+o.dataset.open);return} var m=e.target.closest("[data-up],[data-dn],[data-ins]"); if(m){var R=Q().rows,i=+(m.dataset.up||m.dataset.dn||m.dataset.ins),t; if(m.dataset.up!==undefined){if(i>0){t=R[i];R[i]=R[i-1];R[i-1]=t}} else if(m.dataset.dn!==undefined){if(i=0){var nr=Q().rows[oi];if(nr&&!(nr.n||nr.nom||nr.ram||nr.ant||nr.act)){Q().rows.splice(oi,1);if(!Q().rows.length)Q().rows.push(blank());save()}} ovNew=false;oi=-1;draw()} function ovStore(){var r=Q().rows[oi];r.n=$("on").value;r.nom=$("onom").value;r.ram=$("oram").value;var av=$("oant").value;if(av!==r.ant){r.ant=av;r.m=av!==""}r.act=$("oact").value;save()} function ovGo(d){ovStore();var n=oi+d; if(n<0||n>=Q().rows.length){closeOv();return} oi=n;ovNew=false;ovFill();focusAct()} $("onext").addEventListener("click",function(){ovGo(1)}); $("oprev").addEventListener("click",function(){ovGo(-1)}); $("ovx").addEventListener("click",function(){ovStore();closeOv()}); $("oact").addEventListener("input",ovCons); $("oant").addEventListener("input",ovCons); $("onom").addEventListener("input",grow); $("oact").addEventListener("keydown",function(e){if(e.key==="Enter"){e.preventDefault();ovGo(1)}}); $("on").addEventListener("keydown",function(e){if(e.key==="Enter"){e.preventDefault();$("onom").focus()}}); $("onom").addEventListener("keydown",function(e){if(e.key==="Enter"){e.preventDefault();$("oram").focus()}}); $("oram").addEventListener("keydown",function(e){if(e.key==="Enter"){e.preventDefault();$("oant").focus()}}); $("oant").addEventListener("keydown",function(e){if(e.key==="Enter"){e.preventDefault();$("oact").focus()}}); document.addEventListener("keydown",function(e){if(e.key==="Escape"&&!$("ov").hidden){ovStore();closeOv()}}); $("date").addEventListener("change",function(){var v=this.value;if(!v)return; var p=v.split("-"),key=p[0]+"-"+(Math.floor((parseInt(p[1],10)-1)/3)+1); if(key!==S.cur){ var cq=Q(),unused=cq.rows.every(function(r){return r.act===""||r.act==null}); if(unused&&!S.qs[key]){ var old=S.cur;S.qs[key]=cq;delete S.qs[old];S.del[old]=Date.now();delete S.del[key];S.cur=key; wd("trimestres/"+old);pushDel(); cq.rows.forEach(function(r){if(!r.m)r.ant=""});link(key); cq.date=v;save();draw();return} open(key)} Q().date=v;$("date").value=v;save()}); var HEAD=["N.º contador","Nombre","Ramal","Lectura anterior","Lectura actual","Consumo"]; function lhead(){var p=S.cur.split("-");return"T"+p[1]+" "+p[0]+" · Fecha "+fmt(Q().date)} function buildList(){var R=Q().rows,tot=0,h=""+HEAD.map(function(t){return""+t+""}).join("")+""; R.forEach(function(r){var u=use(r);if(u!==null&&u>=0)tot+=u;h+=""+esc(r.n)+""+esc(r.nom)+""+esc(r.ram)+""+esc(r.ant)+""+esc(r.act)+""+(u===null?"":u)+""}); h+="Consumo total"+Math.round(tot*100)/100+""; $("lst").innerHTML=h; $("lsh").innerHTML="

Agua Las Lomas · Lectura

"+esc(lhead())+"

"} function listText(){var o=["Agua Las Lomas · Lectura",lhead(),"",HEAD.join("\t")]; Q().rows.forEach(function(r){o.push([cl(r.n),cl(r.nom),cl(r.ram),cl(r.ant),cl(r.act),cell(r)].join("\t"))});return o.join("\n")} function lmsg(t){$("lmsg").textContent=t} function openLs(){buildList();lmsg("");$("ls").hidden=false;document.body.style.overflow="hidden"} function askClose(){$("cdmsg").textContent="";$("cd").hidden=false} function copyTxt(m,ok){try{navigator.clipboard.writeText(listText()).then(function(){m(ok)}).catch(function(){m("No se pudo copiar solo. Usa Copiar en el listado y pega.")})}catch(e){m("No se pudo copiar solo. Usa Copiar en el listado y pega.")}} function sendList(){var m=function(t){$("cdmsg").textContent=t}; if(navigator.share){navigator.share({title:"Agua Las Lomas · Lectura",text:listText()}).then(function(){m("Enviado.")}).catch(function(e){if(!e||e.name!=="AbortError")copyTxt(m,"Listado copiado como texto. Pégalo en el correo o mensaje que quieras enviar.")});return} copyTxt(m,"Listado copiado como texto. Pégalo en el correo o mensaje que quieras enviar.")} function closeAll(title,msg){$("cd").hidden=true;$("ls").hidden=true;if(!$("ov").hidden)closeOv();document.body.style.overflow="";$("byet").textContent=title;$("byem").textContent=msg;$("bye").hidden=false} function revert(){if(snapKey===null)return"No había cambios que descartar.";var k=snapKey,msg; if(snapVal===null){delete S.qs[k];S.del[k]=Date.now();wd("trimestres/"+k);pushDel();var rest=Object.keys(S.qs).sort();if(rest.length)S.cur=rest[rest.length-1];msg="Se descartó el trimestre nuevo que habías creado."} else{S.qs[k]=JSON.parse(snapVal);S.qs[k].ts=Date.now();S.cur=k;msg="Se descartaron los cambios hechos desde que abriste este trimestre."} snapKey=null;try{localStorage.setItem(KEY,JSON.stringify(S))}catch(e){} if(DB&&S.qs[S.cur]){pend=S.cur;flush()} return msg} $("showls").addEventListener("click",openLs); $("closeb").addEventListener("click",askClose); $("lsx").addEventListener("click",askClose); $("lclose").addEventListener("click",askClose); function pe(t){var o="";String(t==null?"":t).split("").forEach(function(c){var n=c.charCodeAt(0); if(n===8211||n===8212)c="-";else if(n===8217||n===8216)c="'";else if(n>255){c="?";n=63} n=c.charCodeAt(0); if(c==="("||c===")"||c==="\\")o+="\\"+c;else if(n<32||n>126)o+="\\"+("00"+n.toString(8)).slice(-3);else o+=c});return o} function tw(t,sz,b){var w=0;String(t).split("").forEach(function(c){var n=c.charCodeAt(0); w+=(n>=48&&n<=57)?556:(c===" "||c==="."||c===","||c===":")?278:c==="-"?333:(n>=65&&n<=90)?667:520});return w*sz/1000*(b?1.06:1)} function wrapTxt(t,sz,maxw){t=String(t==null?"":t);var out=[],line=""; t.split(/\s+/).forEach(function(wd){ while(tw(wd,sz,false)>maxw&&wd.length>1){var k=wd.length;while(k>1&&tw(wd.slice(0,k),sz,false)>maxw)k--;if(line){out.push(line);line=""}out.push(wd.slice(0,k));wd=wd.slice(k)} var tryl=line?line+" "+wd:wd;if(tw(tryl,sz,false)<=maxw||!line)line=tryl;else{out.push(line);line=wd}}); if(line||!out.length)out.push(line);return out} function makePdf(items,title,sub,grand){ var PW=595,PH=842,M=40,SZ=9,PAD=4,LH=11; var cols=[{h:"N.º contador",w:72,a:"l"},{h:"Nombre",w:213,a:"l"},{h:"Ramal",w:38,a:"l"},{h:"Lect. anterior",w:70,a:"r"},{h:"Lect. actual",w:67,a:"r"},{h:"Consumo",w:55,a:"r"}]; var pages=[],ops=[],y=0; function f2(n){return n.toFixed(2)} function txt(x,yy,t,b,sz){ops.push("BT /"+(b?"F2":"F1")+" "+(sz||SZ)+" Tf "+f2(x)+" "+f2(yy)+" Td ("+pe(t)+") Tj ET")} function line(x1,y1,x2,y2){ops.push("0.5 w "+f2(x1)+" "+f2(y1)+" m "+f2(x2)+" "+f2(y2)+" l S")} function cellTxt(c,x,yy,t,b,sz){sz=sz||SZ;var px=c.a==="r"?x+c.w-PAD-tw(t,sz,b):x+PAD;txt(px,yy,t,b,sz)} function header(){var x=M;ops.push("0.92 g "+f2(M)+" "+f2(y-18)+" "+f2(PW-2*M)+" 18 re f 0 g"); cols.forEach(function(c){cellTxt(c,x,y-12,c.h,true,8);x+=c.w});line(M,y-18,PW-M,y-18);y-=18} function newPage(first){if(ops.length)pages.push(ops);ops=[];y=PH-M; if(first){txt(M,y-14,title,true,16);y-=22;if(sub){txt(M,y-10,sub,false,10);y-=24}}} var x2=M+cols.slice(0,5).reduce(function(a,c){return a+c.w},0),gtot=0; newPage(true); items.forEach(function(it){ if(y-70=0)tot+=u; var vals=[r.n,r.nom,r.ram,r.ant,r.act,u===null?"":String(u)]; var fs=[];var cells=vals.map(function(v,i){var c=cols[i];v=String(v==null?"":v).replace(/[\t\r\n]+/g," "); if(i===1){var fz=SZ,mw=c.w-2*PAD;while(fz>6.5&&tw(v,fz,false)>mw)fz-=.5;fs[i]=fz;return wrapTxt(v,fz,mw)} var s=v;while(s.length>1&&tw(s,SZ,false)>c.w-2*PAD)s=s.slice(0,-1);return[s]}); var n=Math.max.apply(null,cells.map(function(c){return c.length})),h=n*LH+2*PAD-2; if(y-h>",null,"<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>","<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding >>"]; var kids=[]; pages.forEach(function(o,i){var pid=5+2*i,cid=6+2*i;kids.push(pid+" 0 R"); o.push("BT /F1 8 Tf "+f2(PW/2-30)+" 24 Td ("+pe("Página "+(i+1)+" de "+pages.length)+") Tj ET"); var body=o.join("\n"); objs[pid]="<< /Type /Page /Parent 2 0 R /MediaBox [0 0 "+PW+" "+PH+"] /Resources << /Font << /F1 3 0 R /F2 4 0 R >> >> /Contents "+cid+" 0 R >>"; objs[cid]="<< /Length "+body.length+" >>\nstream\n"+body+"\nendstream"}); objs[2]="<< /Type /Pages /Kids ["+kids.join(" ")+"] /Count "+pages.length+" >>"; var out="%PDF-1.4\n",offs=[]; for(var i=1;i>\nstartxref\n"+xr+"\n%%EOF"; var u8=new Uint8Array(out.length);for(var k=0;k>>1):c>>>1;CRC[n]=c>>>0}} var c=0xFFFFFFFF;for(var i=0;i>>8);return(c^0xFFFFFFFF)>>>0} function utf8(s){return new TextEncoder().encode(s)} function zip(files){var parts=[],cd=[],off=0; files.forEach(function(f){var nm=utf8(f.name),crc=crc32(f.data),sz=f.data.length; var lh=new Uint8Array(30+nm.length),dv=new DataView(lh.buffer); dv.setUint32(0,0x04034b50,true);dv.setUint16(4,20,true);dv.setUint16(6,0x0800,true);dv.setUint16(8,0,true);dv.setUint16(10,0,true);dv.setUint16(12,0x21,true); dv.setUint32(14,crc,true);dv.setUint32(18,sz,true);dv.setUint32(22,sz,true);dv.setUint16(26,nm.length,true);dv.setUint16(28,0,true);lh.set(nm,30); parts.push(lh,f.data); var ch=new Uint8Array(46+nm.length),cv=new DataView(ch.buffer); cv.setUint32(0,0x02014b50,true);cv.setUint16(4,20,true);cv.setUint16(6,20,true);cv.setUint16(8,0x0800,true);cv.setUint16(10,0,true);cv.setUint16(12,0,true);cv.setUint16(14,0x21,true); cv.setUint32(16,crc,true);cv.setUint32(20,sz,true);cv.setUint32(24,sz,true);cv.setUint16(28,nm.length,true);cv.setUint32(42,off,true);ch.set(nm,46); cd.push(ch);off+=lh.length+sz}); var cdSize=0;cd.forEach(function(c){cdSize+=c.length}); var end=new Uint8Array(22),ev=new DataView(end.buffer); ev.setUint32(0,0x06054b50,true);ev.setUint16(8,files.length,true);ev.setUint16(10,files.length,true);ev.setUint32(12,cdSize,true);ev.setUint32(16,off,true); var all=parts.concat(cd,[end]),tot=0;all.forEach(function(a){tot+=a.length}); var out=new Uint8Array(tot),p=0;all.forEach(function(a){out.set(a,p);p+=a.length});return out} function colL(i){var s="";i++;while(i>0){var m=(i-1)%26;s=String.fromCharCode(65+m)+s;i=Math.floor((i-1)/26)}return s} function xe(s){return String(s).replace(/&/g,"&").replace(//g,">").replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g,"")} function makeXlsx(name,rows){var sd=""; rows.forEach(function(r,ri){var cs="";r.forEach(function(v,ci){if(v===""||v==null)return;var ref=colL(ci)+(ri+1); if(typeof v==="number")cs+=''+v+'';else cs+=''+xe(v)+''}); sd+=''+cs+''}); var X='\n',nm=xe(name).replace(/"/g,""").replace(/[:\\\/?*\[\]]/g," ").slice(0,31); return zip([ {name:"[Content_Types].xml",data:utf8(X+'')}, {name:"_rels/.rels",data:utf8(X+'')}, {name:"xl/workbook.xml",data:utf8(X+'')}, {name:"xl/_rels/workbook.xml.rels",data:utf8(X+'')}, {name:"xl/worksheets/sheet1.xml",data:utf8(X+''+sd+'')}])} function quarterXlsx(){var p=S.cur.split("-"),rows=[["Agua Las Lomas · Lectura"],[lhead()],[],HEAD.slice()],tot=0; Q().rows.forEach(function(r){var u=use(r);if(u!==null&&u>=0)tot+=u;rows.push([cl(r.n),cl(r.nom),cl(r.ram),num(r.ant),num(r.act),u===null?"":u])}); rows.push(["Consumo total","","","","",Math.round(tot*100)/100]);return makeXlsx("Lectura T"+p[1]+" "+p[0],rows)} function saveVia(data,fn,say,fail,okMsg){ if(!(window.claude&&claude.use)){fail("");return} claude.use("downloads").then(function(d){ if(!d){fail("El guardado de archivos no está disponible aquí.");return} say("Confirma en la ventana que aparece para guardar el archivo…"); d.save({filename:fn,data:data}).then(function(){say(okMsg||"Archivo guardado en tu dispositivo ("+fn+"). Adjúntalo desde Descargas o Archivos en tu correo o WhatsApp.")}).catch(function(e){ if(e&&e.code==="declined")say("Cancelado: no se guardó nada."); else fail("No se pudo guardar el archivo"+(e&&e.code?" ("+e.code+")":"")+".")}) }).catch(function(){fail("")})} function shareVia(data,fn,mime,say,fail){try{var f=new File([data],fn,{type:mime}); if(navigator.canShare&&navigator.canShare({files:[f]})){navigator.share({files:[f],title:fn}).then(function(){say("Compartido. Elige correo o WhatsApp en el menú que se abrió.")}).catch(function(e){if(e&&e.name==="AbortError")say("Cancelado.");else fail("")});return}}catch(e){} fail("")} function viaPrint(why,say){say=say||lmsg;document.body.classList.add("printing");var done=function(){document.body.classList.remove("printing")}; window.addEventListener("afterprint",done,{once:true}); try{window.print();say((why?why+" ":"")+"Se abrió la impresión: elige tu impresora o «Guardar como PDF».")}catch(e){done();say((why?why+" ":"")+"Aquí no se puede imprimir directamente. Usa Compartir listado (PDF).")}} var OMIME="application/vnd.oasis.opendocument.spreadsheet"; function makeOds(name,rows,boldRows){var X='\n',sd=""; rows.forEach(function(r,ri){var cs="",st=boldRows.indexOf(ri)>=0?' table:style-name="ce1"':""; if(!r.length){sd+="";return} r.forEach(function(v){if(v===""||v==null)cs+=""; else if(typeof v==="number")cs+=''+v+''; else cs+=''+xe(v)+''}); sd+=""+cs+""}); var nm=xe(name).replace(/"/g,""").replace(/[:\\\/?*\[\]]/g," ").slice(0,31); var content=X+''+sd+''; var man=X+''; return zip([{name:"mimetype",data:utf8(OMIME)},{name:"META-INF/manifest.xml",data:utf8(man)},{name:"content.xml",data:utf8(content)}])} function quarterOds(){var p=S.cur.split("-"),rows=[["Agua Las Lomas · Lectura"],[lhead()],[],HEAD.slice()],tot=0; Q().rows.forEach(function(r){var u=use(r);if(u!==null&&u>=0)tot+=u;rows.push([cl(r.n),cl(r.nom),cl(r.ram),num(r.ant),num(r.act),u===null?"":u])}); rows.push(["Consumo total","","","","",Math.round(tot*100)/100]);return makeOds("Lectura T"+p[1]+" "+p[0],rows,[0,3,rows.length-1])} var EX=null; function exm(t){$("exmsg").textContent=t} function exFile(){if(EX.kind==="f")return"lectura-"+EX.y;var p=S.cur.split("-");return"lectura-T"+p[1]+"-"+p[0]} function exItems(){return EX.kind==="f"?folderItems(EX.y):[{label:"",rows:Q().rows}]} function exTitle(){return EX.kind==="f"?"Agua Las Lomas · Lectura · "+EX.y:"Agua Las Lomas · Lectura"} function exSub(){if(EX.kind==="f"){var n=folderItems(EX.y).length;return n+(n===1?" trimestre":" trimestres")}return lhead()} function foldRows(y){var it=folderItems(y),rows=[["Agua Las Lomas · Lectura · "+y],[],["Trimestre","Fecha","N.º contador","Nombre","Ramal","Lectura anterior","Lectura actual","Consumo"]]; it.forEach(function(x){var p=x.key.split("-");x.rows.forEach(function(r){var u=use(r);rows.push(["T"+p[1]+" "+p[0],fmt(S.qs[x.key].date),cl(r.n),cl(r.nom),cl(r.ram),num(r.ant),num(r.act),u===null?"":u])})});return rows} function exOds(){return EX.kind==="f"?makeOds("Carpeta "+EX.y,foldRows(EX.y),[0,2]):quarterOds()} function exPdf(){return makePdf(exItems(),exTitle(),exSub(),EX.kind==="f"&&exItems().length>1)} function pageHtml(){var t=exTitle(),h="",gt=0; exItems().forEach(function(it){var tot=0; var rows=it.rows.map(function(r){var u=use(r);if(u!==null&&u>=0)tot+=u;return""+esc(r.n)+""+esc(r.nom)+""+esc(r.ram)+""+esc(r.ant)+""+esc(r.act)+""+(u===null?"":u)+""}).join(""); gt+=tot;h+=(it.label?"

"+esc(it.label)+"

":"")+""+HEAD.map(function(x,i){return"2?' class="n"':"")+">"+esc(x)+""}).join("")+""+rows+"
Consumo total"+Math.round(tot*100)/100+"
"}); return'\n'+esc(t)+'

'+esc(t)+'

'+esc(exSub())+'

'+h+''} function openEx(ctx){EX=ctx;$("ext").textContent=ctx.kind==="f"?"Enviar carpeta "+ctx.y:"Enviar listado"; $("ex").hidden=false;exm(ctx.kind==="f"&&!folderItems(ctx.y).length?"La carpeta está vacía: no hay nada que enviar.":"")} function exEmpty(){if(EX.kind==="f"&&!folderItems(EX.y).length){exm("La carpeta está vacía: no hay nada que enviar.");return true}return false} function dlFile(data,fn,mime,msg,say){var url=null;try{url=URL.createObjectURL(new Blob([data],{type:mime}))}catch(e){} if(!url){say("Este navegador no permite crear el archivo.");return} try{var a=document.createElement("a");a.href=url;a.download=fn;document.body.appendChild(a);a.click();document.body.removeChild(a);say(msg)}catch(e){say("No se pudo descargar el archivo.")}} function viewPage(say){var data=utf8(pageHtml()),url=null;try{url=URL.createObjectURL(new Blob([data],{type:"text/html"}))}catch(e){} var w=null;if(url){try{w=window.open(url,"_blank")}catch(e){}} if(w){say("Listado abierto en otra pestaña. Desde ahí pulsa el botón Imprimir.");return} var d;try{d=exPdf()}catch(e){say("No se pudo abrir el listado.");return} var fn=exFile()+".pdf",msg="Se ha guardado el listado en PDF ("+fn+"). Ábrelo desde la notificación de descarga y pulsa Imprimir."; if(window.claude&&claude.use)saveVia(d,fn,say,function(){dlFile(d,fn,"application/pdf",msg,say)},msg);else dlFile(d,fn,"application/pdf",msg,say)} $("exview").addEventListener("click",function(){if(exEmpty())return; if(window.claude&&claude.use){viewPage(exm);return} $("ex").hidden=true;if(EX.kind==="f")openFV(EX.y);else openLs(); setTimeout(function(){viaPrint("",function(t){if(EX.kind==="q")lmsg(t)})},150)}); $("expdf").addEventListener("click",function(){if(exEmpty())return;var d;try{d=exPdf()}catch(e){exm("No se pudo crear el PDF.");return} exm("Abriendo el menú de compartir…");shareVia(d,exFile()+".pdf","application/pdf",exm,function(){exm("Este móvil no deja compartir archivos. Usa Ver e imprimir el listado o Descargar PDF.")})}); function quarterRows(){var rows=[["Agua Las Lomas · Lectura"],[lhead()],[],HEAD.slice()],tot=0; Q().rows.forEach(function(r){var u=use(r);if(u!==null&&u>=0)tot+=u;rows.push([cl(r.n),cl(r.nom),cl(r.ram),num(r.ant),num(r.act),u===null?"":u])}); rows.push(["Consumo total","","","","",Math.round(tot*100)/100]);return rows} function toCsv(rows){return utf8(""+rows.map(function(r){return r.map(function(v){v=String(v==null?"":v);return/[",\n;]/.test(v)?'"'+v.replace(/"/g,'""')+'"':v}).join(",")}).join("\r\n"))} $("exshare").addEventListener("click",function(){if(exEmpty())return;var list; try{var f=EX.kind==="f"; list=[{d:exOds(),n:exFile()+".ods",m:OMIME},{d:f?folderXlsx(EX.y):quarterXlsx(),n:exFile()+".xlsx",m:XMIME},{d:toCsv(f?foldRows(EX.y):quarterRows()),n:exFile()+".csv",m:"text/csv"}]}catch(e){exm("No se pudo crear la hoja de cálculo.");return} exm("Abriendo el menú de compartir…"); (function next(i){if(i>=list.length){exm("Este móvil no deja compartir hojas de cálculo. Usa Compartir listado (PDF).");return} shareVia(list[i].d,list[i].n,list[i].m,exm,function(){next(i+1)})})(0)}); $("expage").addEventListener("click",function(){if(exEmpty())return;var d=utf8(pageHtml()); exm("Abriendo el menú de compartir…");shareVia(d,exFile()+".html","text/html",exm,function(){exm("Este móvil no deja compartir ese archivo. Prueba Compartir listado (PDF).")})}); $("exods").addEventListener("click",function(){if(exEmpty())return;var d,fn=exFile()+".ods"; try{d=exOds()}catch(e){exm("No se pudo crear la hoja de cálculo.");return} var msg="Descargada: "+fn+". Baja la barra de notificaciones y toca «Descarga completada», o búscala en Archivos > Descargas. Ábrela con OpenOffice, LibreOffice o Excel."; if(window.claude&&claude.use)saveVia(d,fn,exm,function(){dlFile(d,fn,OMIME,msg,exm)},"Hoja de cálculo guardada ("+fn+").");else dlFile(d,fn,OMIME,msg,exm)}); $("exdl").addEventListener("click",function(){if(exEmpty())return;var d;try{d=exPdf()}catch(e){exm("No se pudo crear el PDF.");return} var fn=exFile()+".pdf",msg="Descargado: "+fn+". Mira en la notificación de descarga o en Archivos > Descargas."; if(window.claude&&claude.use)saveVia(d,fn,exm,function(){dlFile(d,fn,"application/pdf",msg,exm)},"PDF guardado ("+fn+").");else dlFile(d,fn,"application/pdf",msg,exm)}); $("exx").addEventListener("click",function(){$("ex").hidden=true}); $("lcopy").addEventListener("click",function(){openEx({kind:"q"})}); $("lprint").addEventListener("click",function(){EX={kind:"q"};lmsg("");if(window.claude&&claude.use)viewPage(lmsg);else viaPrint("")}); $("cdcancel").addEventListener("click",function(){$("cd").hidden=true}); $("cdsend").addEventListener("click",function(){$("cd").hidden=true;openEx({kind:"q"})}); $("cdno").addEventListener("click",function(){var n=revert();closeAll("Cerrado sin guardar",n)}); $("cdsave").addEventListener("click",function(){ if(!$("ov").hidden)ovStore(); var q=Q(),lbl="T"+S.cur.split("-")[1]+" "+S.cur.split("-")[0]+", lectura del "+fmt(q.date); $("cdmsg").textContent="Guardando…"; saveAll().then(function(r){ if(!r.okL&&r.okC===null){closeAll("No se pudo guardar","Este navegador no permite guardar datos.");return} if(r.okC===null){closeAll("Guardado y cerrado","Todo guardado en este dispositivo ("+lbl+").");return} closeAll(r.okC?"Guardado y cerrado":"Cerrado, pero no se pudo sincronizar",r.okC?"Todo guardado y sincronizado ("+lbl+").":FAIL)})}); $("byeopen").addEventListener("click",function(){$("bye").hidden=true;snapKey=null;open(S.cur)}); var mgPlan=null,mgSv=null; function sq(x){return String(x==null?"":x).slice(0,200)} function findRow(rows,r){var m=null;if(r.n)m=rows.filter(function(p){return p.n===r.n})[0];if(!m&&r.nom)m=rows.filter(function(p){return p.nom===r.nom&&!r.n})[0];return m||null} function planMerge(sv){var pl={newQ:[],fill:[],add:[],conf:[]}; Object.keys(sv.qs||{}).sort().forEach(function(k){if(!/^\d{4}-[1-4]$/.test(k))return;var q=sv.qs[k];if(!q||!Array.isArray(q.rows))return; var c=S.qs[k];if(!c||empty(c)){if(!empty(q))pl.newQ.push(k);return} q.rows.slice(0,500).forEach(function(r){r=r||{};if(!(r.n||r.nom||r.act))return;var m=findRow(c.rows,r); if(!m){pl.add.push({k:k,r:r});return} var ra=sq(r.act),ma=sq(m.act); if(ra!==""&&ma==="")pl.fill.push({k:k,m:m,r:r}); else if(ra!==""&&ma!==""&&ra!==ma)pl.conf.push({k:k,m:m,r:r,ra:ra,ma:ma})})}); return pl} function qlab(k){var p=k.split("-");return"T"+p[1]+" "+p[0]} function openMerge(sv){mgSv=sv;mgPlan=planMerge(sv);var pl=mgPlan,h=""; var tot=pl.newQ.length+pl.fill.length+pl.add.length+pl.conf.length; if(!tot){h='

No hay datos nuevos: todo lo que trae este archivo ya está en tu programa.

';$("mgok").hidden=true} else{$("mgok").hidden=false; h+='

Qué se va a añadir:

    '; if(pl.newQ.length)h+="
  • "+pl.newQ.length+(pl.newQ.length===1?" trimestre completo nuevo: ":" trimestres completos nuevos: ")+esc(pl.newQ.map(qlab).join(", "))+"
  • "; if(pl.fill.length)h+="
  • "+pl.fill.length+(pl.fill.length===1?" lectura actual que te faltaba":" lecturas actuales que te faltaban")+"
  • "; if(pl.add.length)h+="
  • "+pl.add.length+(pl.add.length===1?" contador nuevo":" contadores nuevos")+"
  • "; if(pl.conf.length)h+="
  • "+pl.conf.length+(pl.conf.length===1?" contador con lectura distinta en los dos: elige abajo":" contadores con lectura distinta en los dos: elige abajo")+"
  • "; h+="
"; pl.conf.forEach(function(c,i){h+='
'+esc(qlab(c.k))+" · "+esc(c.m.n||"")+" "+esc(c.m.nom||"")+'
'})} $("mgb").innerHTML=h;$("mg").hidden=false} function applyMerge(){var pl=mgPlan,sv=mgSv,ch={};if(!pl)return; pl.newQ.forEach(function(k){var q=sv.qs[k];S.qs[k]={date:/^\d{4}-\d{2}-\d{2}$/.test(q.date)?q.date:today.toISOString().slice(0,10),rows:q.rows.slice(0,500).map(function(r){r=r||{};var o={n:sq(r.n),nom:sq(r.nom),ram:sq(r.ram),ant:sq(r.ant),act:sq(r.act)};if(r.m===true)o.m=true;return o}),ts:Date.now()};delete S.del[k];ch[k]=1}); pl.fill.forEach(function(f){f.m.act=sq(f.r.act);if(sq(f.m.ant)==="")f.m.ant=sq(f.r.ant);ch[f.k]=1}); pl.add.forEach(function(a){var r=a.r;S.qs[a.k].rows.push({n:sq(r.n),nom:sq(r.nom),ram:sq(r.ram),ant:sq(r.ant),act:sq(r.act)});ch[a.k]=1}); Array.prototype.forEach.call($("mgb").querySelectorAll("select[data-ci]"),function(sel){if(sel.value==="t"){var c=pl.conf[+sel.dataset.ci];c.m.act=c.ra;ch[c.k]=1}}); Object.keys(ch).forEach(function(k){S.qs[k].ts=Date.now()}); if(!S.list&&sv.list){S.list=sv.list;S.lts=sv.lts||0} try{localStorage.setItem(KEY,JSON.stringify(S))}catch(e){} if(DB){Object.keys(ch).forEach(function(k){push(k)});pushDel()} mgPlan=null;mgSv=null;$("mg").hidden=true;draw(); say("Datos añadidos en "+Object.keys(ch).length+(Object.keys(ch).length===1?" trimestre.":" trimestres.")+" Pulsa Guardar para dejarlo todo guardado.")} $("addother").addEventListener("click",function(){$("progmsg").textContent="";$("otherf").value="";$("otherf").click()}); $("otherf").addEventListener("change",function(){var f=this.files&&this.files[0];if(!f)return;var m=function(t){$("progmsg").textContent=t}; if(f.size>20000000){m("El archivo es demasiado grande.");return} var rd=new FileReader();rd.onerror=function(){m("No se pudo leer el archivo.")}; rd.onload=function(){var sv=null;try{var d=new DOMParser().parseFromString(String(rd.result),"text/html"),sn=d.getElementById("seed");sv=sn?JSON.parse(sn.textContent):null}catch(e){} if(!sv||!sv.qs){m("Este archivo no trae datos. Pídele a la otra persona que lo envíe con «Enviar programa con mis datos».");return} m("");openMerge(sv)};rd.readAsText(f)}); $("mgok").addEventListener("click",applyMerge); $("mgx").addEventListener("click",function(){mgPlan=null;mgSv=null;$("mg").hidden=true}); function pick(){var y=parseInt($("y").value,10);if(isNaN(y))return;open(y+"-"+$("q").value)} $("q").addEventListener("change",pick); $("y").addEventListener("change",pick); open(S.cur); $("sync").textContent="Guardado solo en este dispositivo."; if(!(window.claude&&claude.use))noSync(); if(window.claude&&claude.use){claude.use("db").then(function(d){ if(!d){say("Sincronización no disponible aquí: los datos se guardan solo en este dispositivo.");noSync();return}DB=d; d.doc("estado/borrados").get().then(function(b){var bv=b.exists&&b.data();var rd=bv&&bv.del;if(rd)Object.keys(rd).forEach(function(k){var t=+rd[k]||0;if((S.del[k]||0)=(S.lts||0)){S.list=JSON.parse(JSON.stringify(v.rows));S.lts=v.ts||0}else if(S.list&&S.list.length){wr("estado/listado",{rows:S.list,ts:S.lts||0})}}).catch(function(){}).then(function(){return d.collection("trimestres").get()})}).then(function(snap){ var ids={}; snap.docs.forEach(function(x){ids[x.id]=1;var v=x.data(),l=S.qs[x.id],dt=S.del[x.id]||0;if(dt&&(!v||(v.ts||0)<=dt)){wd("trimestres/"+x.id);return}if(dt&&v&&(v.ts||0)>dt){delete S.del[x.id]}if(v&&v.rows&&(!l||(v.ts||0)>=(l.ts||0)))S.qs[x.id]={date:v.date,rows:JSON.parse(JSON.stringify(v.rows)),ts:v.ts||0};else if(l&&v&&(l.ts||0)>(v.ts||0))push(x.id)}); Object.keys(S.qs).forEach(function(k){if(!ids[k])push(k)}); $("sync").textContent="Sincronizado entre tus dispositivos.";banner("Sincronizado con tu cuenta de Claude.",false); function reopen(){snapKey=null;if(!S.qs[S.cur]){var r=Object.keys(S.qs).sort();if(r.length)S.cur=r[r.length-1]}open(S.cur)} d.doc("estado/actual").get().then(function(x){var v=x.exists&&x.data();if(v&&v.cur&&S.qs[v.cur])S.cur=v.cur;reopen()}).catch(reopen)}).catch(function(){say("No se pudo leer de la nube. Se muestran los datos de este dispositivo.")})}).catch(function(){})} })();