javascript:(async()=>{function j(o,e){return o.reduce((r,t,i)=>r+t+(e[i]??""),"").replace(/>\s+<").replace(/\s+/g," ").trim()}var q=(o,...e)=>j(o,e),B=(o,...e)=>j(o,e),E=(o,...e)=>j(o,e);(async function(){"use strict";let o="https://uber.nicecloudsvc.com/wfm/webstation/my-schedule";if(!location.href.startsWith(o)){location.href=o;return}let e=document.querySelector("iframe");if(!e){alert("No schedule iframe found. Make sure you're on the NICE schedule page.");return}let r=st(e),t=r?rt(r):new Date,i=await ot(t);if(!i)return;let s=await dt(e,i);if(console.log(`[NICE Export] Total events: ${s.length}`),s.length===0){alert("No events found to export.");return}let n=[...s].sort((f,M)=>f.start.getTime()-M.start.getTime()),a=n[0].start,c=n[n.length-1].start,d=`${G(a)} to ${G(c)}`,u=`NICE Schedule ${d}.ics`,g=_(s),{wfh:h,wfo:p,wfhDaysSet:w}=J(s);at({icsContent:g,fileName:u,events:s,dateRange:d,wfh:h,wfo:p,wfhDaysSet:w})})();function J(o){let e=n=>`${n.getFullYear()}-${n.getMonth()}-${n.getDate()}`,r=new Map;for(let n of o){let a=e(n.start);r.has(a)||r.set(a,[]),r.get(a).push(n)}let t=new Set;for(let[n,a]of r)a.some(c=>c.summary.trimEnd().endsWith("WFH"))&&t.add(n);let i=[],s=[];for(let n of o)t.has(e(n.start))?i.push(n):s.push(n);return{wfh:i,wfo:s,wfhDaysSet:t}}var V=16,Y=60;function Q(o,e,r){let t=u=>`${u.getFullYear()}-${u.getMonth()}-${u.getDate()}`,i=new Map;for(let u of o){let g=t(u.start);i.has(g)||i.set(g,new Date(u.start.getFullYear(),u.start.getMonth(),u.start.getDate()))}let s=[...i.entries()].sort(([,u],[,g])=>u.getTime()-g.getTime()),n=Y/100,a=0,c=s.map(([u])=>!e.has(u)),d=Math.max(2,Math.min(r,s.length||2));return s.map(([,u],g)=>{let h=c[g];h&&a++;let p=g+1,w=p-a,f=null;if(g>=d-1){let D=0;for(let l=g-d+1;l<=g;l++)c[l]&&D++;f=(d-D)/d*100}let M=Math.round(w-p*(1-n));return{date:u,label:u.toLocaleDateString("en-US",{month:"short",day:"numeric"}),isWfo:h,wfhPct:w/p*100,rollingWfhPct:f,wfhBudget:M}})}function tt(o,e){let r=a=>`${a.getFullYear()}-${a.getMonth()}-${a.getDate()}`,t=a=>`${a.getFullYear()}-${a.getMonth()}`,i=new Map;for(let a of o){let c=r(a.start);i.has(c)||i.set(c,new Date(a.start.getFullYear(),a.start.getMonth(),a.start.getDate()))}let s=new Map;for(let[a,c]of i){let d=t(c);s.has(d)||s.set(d,{year:c.getFullYear(),month:c.getMonth(),wfo:0,wfh:0});let u=s.get(d);e.has(a)?u.wfh++:u.wfo++}let n=Y/100;return[...s.values()].sort((a,c)=>a.year-c.year||a.month-c.month).map(({year:a,month:c,wfo:d,wfh:u})=>{let g=d+u,h=g>0?d/g*100:0,p=g*(1-n)-u,w=new Date(a,c,1).toLocaleDateString("en-US",{month:"short",year:"numeric"});return{year:a,month:c,label:w,wfoDays:d,wfhDays:u,totalDays:g,wfoPct:h,wfhRemaining:p}})}function et(o,e,r){let t=tt(e,r);if(t.length===0){o.innerHTML=q`
No data to chart.
`;return}let i=560,s=260,n=42,a=12,c=36,d=42,u=i-n-a,g=s-c-d,h=t.length,p=u/h,w=Math.min(p*.6,48),f=y=>c+(1-y/100)*g,D=[0,25,50,75,100].map(y=>{let $=f(y);return E`${y}%25`}).join(""),l=f(Y),C=E``,k=h>6?8:10,H=t.map((y,$)=>{let F=n+p*$+p/2,I=F-w/2,N=y.wfoPct/100*g,b=c+g-N,R=(y.totalDays>0?y.wfhDays/y.totalDays*100:0)/100*g,P=b-R,W=y.wfhRemaining>=0?"#065f46":"#991b1b",O=`${Math.round(y.wfoPct)}%25`,m=`${y.wfhRemaining>=0?"+":""}${y.wfhRemaining.toFixed(2)}d`,x=E`${y.label}`;return E` ${O}${m} ${x} `}).join(""),L=s-10,A=E` WFOWFHTarget (${Y}%25 WFO) `;o.innerHTML=E` ${D} ${C} ${H} ${A} `}function nt(o,e,r,t="rolling",i=V){let s=o.querySelector(".chart-container");if(t==="monthly"){et(s,e,r);return}let n=Q(e,r,i);if(n.length===0){s.innerHTML=q`
No data to chart.
`;return}let a=560,c=260,d=42,u=12,g=10,h=42,p=a-d-u,w=c-g-h,f=n.length,M=m=>f===1?d+p/2:d+m/(f-1)*p,D=100-Y,l=(()=>{if(t==="cumulative")return{yMin:0,yMax:100,yTicks:[0,25,50,75,100],yFormat:v=>`${v}%25`,targetValue:D,targetLabel:`Target (${D}%25)`,lineColor:"#CC7A00",areaColor:"rgba(204, 122, 0, 0.08)",seriesLabel:"Cumulative WFH %25",values:n.map(v=>v.wfhPct)};if(t==="rolling")return{yMin:0,yMax:100,yTicks:[0,25,50,75,100],yFormat:v=>`${v}%25`,targetValue:D,targetLabel:`Target (${D}%25)`,lineColor:"#CC7A00",areaColor:"rgba(204, 122, 0, 0.08)",seriesLabel:`Rolling ${i}-day WFH %25`,values:n.map(v=>v.rollingWfhPct)};let m=n.map(v=>v.wfhBudget),x=Math.max(1,...m.map(v=>Math.abs(v))),T=Math.ceil(x/5)*5,z=[...m].reverse().find(v=>v!==null&&!Number.isNaN(v))??0,X=z>=0?"#059669":"#dc2626",Z=z>=0?"rgba(5, 150, 105, 0.08)":"rgba(220, 38, 38, 0.08)";return{yMin:-T,yMax:T,yTicks:[-T,-T/2,0,T/2,T].map(v=>Math.round(v)),yFormat:v=>`${v>0?"+":""}${v}d`,targetValue:0,targetLabel:"On target (0)",lineColor:X,areaColor:Z,seriesLabel:"WFH budget (days)",values:m}})(),C=m=>g+(1-(m-l.yMin)/(l.yMax-l.yMin))*w,k=l.yTicks.map(m=>{let x=C(m);return E`${l.yFormat(m)}`}).join(""),H=Math.max(3,Math.min(f,Math.ceil(f/5)+1)),L=[];for(let m=0;m{let x=M(m),T=m===0?"start":m===f-1?"end":"middle";return E`${n[m].label}`}).join(""),y=[],$=[];l.values.forEach((m,x)=>{m==null||Number.isNaN(m)?($.length&&y.push($),$=[]):$.push(`${M(x)},${C(m)}`)}),$.length&&y.push($);let F=y.map(m=>E``).join(""),I=(()=>{if(t==="deficit"||y.length!==1)return"";let m=y[0],x=m[0].split(",")[0],T=m[m.length-1].split(",")[0],z=C(l.yMin);return E``})(),N=C(l.targetValue),b=t==="deficit"?"#6b7280":"#dc2626",S=E``,P=f<=30?l.values.map((m,x)=>m==null||Number.isNaN(m)?"":E``).join(""):"",W=c-10,O=E` ${l.seriesLabel}${l.targetLabel} `;s.innerHTML=E` ${k} ${A} ${I} ${F} ${S} ${P} ${O} `}function ot(o){return new Promise(e=>{let r=G(o),t=document.createElement("dialog");t.innerHTML=q`

Date Range

Leave blank to scrape until an empty week is reached.
`,t.classList.add("date-range");let i=!1,s=n=>{i||(i=!0,t.close(),t.remove(),e(n))};document.body.appendChild(t),t.showModal(),t.querySelector(".btn-start").addEventListener("click",()=>{let n=t.querySelector("#dr-start"),a=t.querySelector("#dr-end");if(!n.value){n.focus();return}let[c,d,u]=n.value.split("-").map(Number),g=new Date(c,d-1,u),h=null;if(a.value){let[p,w,f]=a.value.split("-").map(Number);h=new Date(p,w-1,f)}s({start:g,end:h})}),t.querySelector(".btn-cancel").addEventListener("click",()=>s(null)),t.querySelector(".btn-close").addEventListener("click",()=>s(null)),t.addEventListener("cancel",()=>s(null))})}function at({icsContent:o,fileName:e,events:r,dateRange:t,wfh:i,wfo:s,wfhDaysSet:n}){let a=[...r].sort((b,S)=>b.start.getTime()-S.start.getTime()),c=a[0].start,d=a[a.length-1].start,u=b=>`${b.getFullYear()}-${b.getMonth()}-${b.getDate()}`,g=new Set(s.map(b=>u(b.start))).size,h=new Set(i.map(b=>u(b.start))).size,p=g+h,w=p>0?Math.round(g/p*100):0,f=p>0?100-w:0,M=Math.ceil((d.getTime()-c.getTime())/(10080*60*1e3))+1,D=b=>b.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"}),l=document.createElement("dialog");l.innerHTML=q`

Scraped ${g} WFO days and ${h} WFH days across ${M} weeks, between ${D(c)} and ${D(d)}.

WFO
${w}%25
${g} days
WFH
${f}%25
${h} days
Target (WFH)
40%25
`,document.body.appendChild(l),l.showModal();let C=!1,k="rolling",H=V,L={rolling:"WFH %25 over a rolling window of recent scheduled days. Reacts quickly to recent changes.",cumulative:"WFH %25 from the start of the range. Smooth, but slow to react as history grows.",deficit:"Running WFH budget in days. Positive (green) = WFH days to spare. Negative (red) = too few WFH days so far.",monthly:"Monthly WFH budget. Each bar shows the WFO/WFH split; labels show the signed WFH surplus or deficit."},A=l.querySelector(".view-description"),y=l.querySelector(".window-input"),$=l.querySelector(".window-input input"),F=()=>{A.textContent=L[k]},I=()=>{y.classList.toggle("hidden",k!=="rolling")},N=()=>nt(l,r,n,k,H);$.addEventListener("input",()=>{let b=parseInt($.value,10);if(!Number.isFinite(b))return;H=Math.max(2,Math.round(b)),k==="rolling"&&C&&N()}),$.addEventListener("blur",()=>{$.value=String(H)}),F(),I(),l.querySelectorAll(".view-btn").forEach(b=>{b.addEventListener("click",()=>{let S=b.dataset.view;S!==k&&(k=S,l.querySelectorAll(".view-btn").forEach(R=>R.classList.remove("active")),b.classList.add("active"),F(),I(),N())})}),l.querySelectorAll(".tab").forEach(b=>{b.addEventListener("click",()=>{l.querySelectorAll(".tab").forEach(S=>S.classList.remove("active")),l.querySelectorAll(".tab-content").forEach(S=>S.classList.remove("active")),b.classList.add("active"),l.querySelector(`.tab-content[data-tab="${b.dataset.tab}"]`).classList.add("active"),b.dataset.tab==="analysis"&&!C&&(C=!0,N())})}),l.querySelector(".btn-combined").addEventListener("click",()=>{U(o,e,"text/calendar;charset=utf-8")}),l.querySelector(".btn-split").addEventListener("click",()=>{let b=`NICE Schedule WFO ${t}.ics`,S=`NICE Schedule WFH ${t}.ics`;U(_(s,{calendarName:"NICE Schedule (WFO)"}),b,"text/calendar;charset=utf-8"),U(_(i,{calendarName:"NICE Schedule (WFH)"}),S,"text/calendar;charset=utf-8")}),l.querySelector(".btn-close").addEventListener("click",()=>{l.close()}),l.addEventListener("close",()=>{l.remove()})}function rt(o){let e=parseInt(o.slice(1,3),10),r=parseInt(o.slice(3,5),10),t=parseInt(o.slice(5,7),10);return new Date(2e3+e,r-1,t)}function st(o){return(o.contentWindow?.location.href??o.src??"").match(/startDay=(\d+)/)?.[1]??null}function it(o){let e=String(o.getFullYear()%25100).padStart(2,"0"),r=String(o.getMonth()+1).padStart(2,"0"),t=String(o.getDate()).padStart(2,"0");return`1${e}${r}${t}`}function lt(o){return`https://uber.nicecloudsvc.com/agent/displayMyScheduleAction.mvc?startDay=${o}&viewFormat=weekly`}async function ct(o,e,r=2e4){return new Promise(t=>{let i=setTimeout(()=>{console.log(`[NICE Export] Navigation timed out after ${r}ms`),t(!1)},r);o.addEventListener("load",()=>{clearTimeout(i),t(!0)},{once:!0}),o.contentWindow.location.href=e})}async function dt(o,e){let r=[],t=e.end?1/0:52;console.log(`[NICE Export] Starting from: ${e.start.toDateString()}`+(e.end?`, ending at week containing: ${e.end.toDateString()}`:` (go until done, cap ${t})`));for(let n=0;ne.end)break;let c=lt(it(a));if(console.log(`[NICE Export] Page ${n+1}: navigating to ${c}`),!await ct(o,c)){console.log("[NICE Export] Navigation timed out, stopping");break}let u=o.contentDocument;if(!u){console.log("[NICE Export] No iframe document, stopping");break}let g=ut(u);if(g.length===0){if(e.end){console.log(`[NICE Export] Page ${n+1}: no rows, continuing (end date set)`);continue}console.log(`[NICE Export] Page ${n+1}: no rows, stopping`);break}let h=gt(g);console.log(`[NICE Export] Page ${n+1}: ${h.length} events`),r.push(...h)}let i=new Date(e.start.getFullYear(),e.start.getMonth(),e.start.getDate()),s=e.end?new Date(e.end.getFullYear(),e.end.getMonth(),e.end.getDate(),23,59,59,999):null;return r.filter(n=>!(n.starts))}function ut(o){return Array.from(o.querySelectorAll("#scheduleDetailTableDiv > table tr")).filter(e=>{let r=e.textContent.trim();return!(e.className==="schedTableHdr"||r===""||r==="Add an activity"||r.endsWith("OFF")||r.endsWith("No data available")||e.children.length===1)}).map(e=>Array.from(e.children))}function gt(o){let e=[],r,t,i;for(let s of o){if(s[0]?.querySelector('[title="Trade schedule"]')){let M=s[1]?.textContent?.trim(),[,D]=M?.split(" ")??["",""];[t,i,r]=D.split("/").map(Number)}let a=s[s.length-5]?.textContent?.trim()??"",c=s[s.length-4]?.textContent?.trim()??"12:00 AM",d=s[s.length-3]?.textContent?.trim()??"12:00 AM",[u,g]=K(c),[h,p]=K(d),w=new Date(2e3+r,t-1,i,u,g,0,0),f=new Date(2e3+r,t-1,i,h,p,0,0);f