@xcpcio/board-app 0.51.2 → 0.52.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/404.html +1 -1
  2. package/dist/assets/Board-b5bf1828.js +1 -0
  3. package/dist/assets/{Board-3491f2da.css → Board-f05c0366.css} +1 -1
  4. package/dist/assets/DataSourceInput.vue_vue_type_script_setup_true_lang-47ff726d.js +1 -0
  5. package/dist/assets/TheInput.vue_vue_type_script_setup_true_lang-9cc92a14.js +1 -0
  6. package/dist/assets/_...all_-80d9c58d.js +1 -0
  7. package/dist/assets/{_...all_-61cb8860.js → _...all_-efc1d81f.js} +2 -2
  8. package/dist/assets/{_name_-f901a5ed.js → _name_-5f588c5c.js} +1 -1
  9. package/dist/assets/{about-9fdb1313.js → about-86489903.js} +1 -1
  10. package/dist/assets/board-428898fa.js +1 -0
  11. package/dist/assets/{board-layout-598f9ee4.js → board-layout-f4b42426.js} +1 -1
  12. package/dist/assets/{headless-e015e9d1.js → headless-464cd216.js} +1 -1
  13. package/dist/assets/{home-89f287c8.js → home-1c2da293.js} +1 -1
  14. package/dist/assets/index-1426f0a6.js +1 -0
  15. package/dist/assets/index-5271d2f0.css +1 -0
  16. package/dist/assets/index-8a3db893.js +1 -0
  17. package/dist/assets/index-accb347c.css +1 -0
  18. package/dist/assets/{index-9dd86d68.css → index-ae8b398e.css} +1 -1
  19. package/dist/assets/index-c4a296e0.js +25 -0
  20. package/dist/assets/{index-d8432aad.js → index-f813b721.js} +133 -133
  21. package/dist/assets/index-fe6090d1.js +1 -0
  22. package/dist/assets/{index-layout-60ef1a96.js → index-layout-6dbef8c0.js} +1 -1
  23. package/dist/assets/{pagination-95a79aa6.js → pagination-959b8075.js} +1 -1
  24. package/dist/assets/query-8d6474f1.js +1 -0
  25. package/dist/assets/{test-5c739ae1.js → test-ce57205f.js} +1 -1
  26. package/dist/assets/{user-03dfbe5d.js → user-5e4a4fb1.js} +1 -1
  27. package/dist/assets/{virtual_pwa-register-6ca2d3a0.js → virtual_pwa-register-ab60e448.js} +1 -1
  28. package/dist/index.html +1 -1
  29. package/dist/sw.js +1 -1
  30. package/package.json +4 -3
  31. package/src/components/Balloon.vue +3 -3
  32. package/src/components/BalloonBlock.vue +1 -1
  33. package/src/components/Countdown.vue +3 -8
  34. package/src/components/CustomResolver.vue +25 -0
  35. package/src/components/Resolver.vue +216 -0
  36. package/src/components/ResolverTeamRow.vue +127 -0
  37. package/src/components/board/Board.vue +1 -1
  38. package/src/components/board/StandingsAnnotate.vue +4 -2
  39. package/src/components/board/Utility.vue +7 -12
  40. package/src/components.d.ts +3 -0
  41. package/src/composables/useQueryBoardData.ts +11 -5
  42. package/src/pages/resolver/index.vue +10 -0
  43. package/uno.config.ts +2 -0
  44. package/dist/assets/Board-a6a37adf.js +0 -1
  45. package/dist/assets/DataSourceInput.vue_vue_type_script_setup_true_lang-d2ea1ac6.js +0 -1
  46. package/dist/assets/TheInput.vue_vue_type_script_setup_true_lang-1ce252e6.js +0 -1
  47. package/dist/assets/_...all_-198e3528.js +0 -1
  48. package/dist/assets/board-65f3126c.js +0 -1
  49. package/dist/assets/index-67b2a8c5.css +0 -1
  50. package/dist/assets/index-7af0a9ca.js +0 -1
  51. package/dist/assets/index-8e5373fd.js +0 -1
  52. package/dist/assets/index-ea20d191.js +0 -1
  53. package/dist/assets/query-67fd6c27.js +0 -1
@@ -0,0 +1 @@
1
+ var q=(i,t,e)=>{if(!t.has(i))throw TypeError("Cannot "+e)};var s=(i,t,e)=>(q(i,t,"read from private field"),e?e.call(i):t.get(i)),u=(i,t,e)=>{if(t.has(i))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(i):t.set(i,e)},l=(i,t,e,n)=>(q(i,t,"write to private field"),n?n.call(i,e):t.set(i,e),e);var f=(i,t,e)=>(q(i,t,"access private method"),e);import{ax as It,ay as O,az as tt,aA as Y,aB as Qt,aC as ft,aD as pt,aE as Et,aF as Dt,aG as Ft,aH as bt,aI as Tt,aJ as Ut,aK as jt,aL as xt,h as Ot,aM as Pt,aN as Mt,v as H,aO as yt,aP as At,aQ as vt,aR as Lt,aS as $t,am as St}from"./index-f813b721.js";var y,a,N,b,E,P,g,W,M,A,D,F,w,L,T,$,_,et,B,st,k,it,V,nt,z,at,K,rt,G,ot,J,Ct,gt,Nt=(gt=class extends It{constructor(t,e){super();u(this,T);u(this,_);u(this,B);u(this,k);u(this,V);u(this,z);u(this,K);u(this,G);u(this,J);u(this,y,void 0);u(this,a,void 0);u(this,N,void 0);u(this,b,void 0);u(this,E,void 0);u(this,P,void 0);u(this,g,void 0);u(this,W,void 0);u(this,M,void 0);u(this,A,void 0);u(this,D,void 0);u(this,F,void 0);u(this,w,void 0);u(this,L,new Set);this.options=e,l(this,y,t),l(this,g,null),this.bindMethods(),this.setOptions(e)}bindMethods(){this.refetch=this.refetch.bind(this)}onSubscribe(){this.listeners.size===1&&(s(this,a).addObserver(this),mt(s(this,a),this.options)?f(this,T,$).call(this):this.updateResult(),f(this,V,nt).call(this))}onUnsubscribe(){this.hasListeners()||this.destroy()}shouldFetchOnReconnect(){return ht(s(this,a),this.options,this.options.refetchOnReconnect)}shouldFetchOnWindowFocus(){return ht(s(this,a),this.options,this.options.refetchOnWindowFocus)}destroy(){this.listeners=new Set,f(this,z,at).call(this),f(this,K,rt).call(this),s(this,a).removeObserver(this)}setOptions(t,e){const n=this.options,o=s(this,a);if(this.options=s(this,y).defaultQueryOptions(t),this.options.enabled!==void 0&&typeof this.options.enabled!="boolean"&&typeof this.options.enabled!="function"&&typeof O(this.options.enabled,s(this,a))!="boolean")throw new Error("Expected enabled to be a boolean or a callback that returns a boolean");f(this,G,ot).call(this),s(this,a).setOptions(this.options),n._defaulted&&!tt(this.options,n)&&s(this,y).getQueryCache().notify({type:"observerOptionsUpdated",query:s(this,a),observer:this});const r=this.hasListeners();r&&Rt(s(this,a),o,this.options,n)&&f(this,T,$).call(this),this.updateResult(e),r&&(s(this,a)!==o||O(this.options.enabled,s(this,a))!==O(n.enabled,s(this,a))||Y(this.options.staleTime,s(this,a))!==Y(n.staleTime,s(this,a)))&&f(this,_,et).call(this);const c=f(this,B,st).call(this);r&&(s(this,a)!==o||O(this.options.enabled,s(this,a))!==O(n.enabled,s(this,a))||c!==s(this,w))&&f(this,k,it).call(this,c)}getOptimisticResult(t){const e=s(this,y).getQueryCache().build(s(this,y),t),n=this.createResult(e,t);return _t(this,n)&&(l(this,b,n),l(this,P,this.options),l(this,E,s(this,a).state)),n}getCurrentResult(){return s(this,b)}trackResult(t,e){const n={};return Object.keys(t).forEach(o=>{Object.defineProperty(n,o,{configurable:!1,enumerable:!0,get:()=>(this.trackProp(o),e==null||e(o),t[o])})}),n}trackProp(t){s(this,L).add(t)}getCurrentQuery(){return s(this,a)}refetch({...t}={}){return this.fetch({...t})}fetchOptimistic(t){const e=s(this,y).defaultQueryOptions(t),n=s(this,y).getQueryCache().build(s(this,y),e);return n.isFetchingOptimistic=!0,n.fetch().then(()=>this.createResult(n,e))}fetch(t){return f(this,T,$).call(this,{...t,cancelRefetch:t.cancelRefetch??!0}).then(()=>(this.updateResult(),s(this,b)))}createResult(t,e){var dt;const n=s(this,a),o=this.options,r=s(this,b),c=s(this,E),p=s(this,P),I=t!==n?t.state:s(this,N),{state:v}=t;let d={...v},Q=!1,h;if(e._optimisticResults){const m=this.hasListeners(),Z=!m&&mt(t,e),wt=m&&Rt(t,n,e,o);(Z||wt)&&(d={...d,...Ft(v.data,t.options)}),e._optimisticResults==="isRestoring"&&(d.fetchStatus="idle")}let{error:S,errorUpdatedAt:U,status:R}=d;if(e.select&&d.data!==void 0)if(r&&d.data===(c==null?void 0:c.data)&&e.select===s(this,W))h=s(this,M);else try{l(this,W,e.select),h=e.select(d.data),h=bt(r==null?void 0:r.data,h,e),l(this,M,h),l(this,g,null)}catch(m){l(this,g,m)}else h=d.data;if(e.placeholderData!==void 0&&h===void 0&&R==="pending"){let m;if(r!=null&&r.isPlaceholderData&&e.placeholderData===(p==null?void 0:p.placeholderData))m=r.data;else if(m=typeof e.placeholderData=="function"?e.placeholderData((dt=s(this,A))==null?void 0:dt.state.data,s(this,A)):e.placeholderData,e.select&&m!==void 0)try{m=e.select(m),l(this,g,null)}catch(Z){l(this,g,Z)}m!==void 0&&(R="success",h=bt(r==null?void 0:r.data,m,e),Q=!0)}s(this,g)&&(S=s(this,g),h=s(this,M),U=Date.now(),R="error");const j=d.fetchStatus==="fetching",x=R==="pending",X=R==="error",ct=x&&j,lt=h!==void 0;return{status:R,fetchStatus:d.fetchStatus,isPending:x,isSuccess:R==="success",isError:X,isInitialLoading:ct,isLoading:ct,data:h,dataUpdatedAt:d.dataUpdatedAt,error:S,errorUpdatedAt:U,failureCount:d.fetchFailureCount,failureReason:d.fetchFailureReason,errorUpdateCount:d.errorUpdateCount,isFetched:d.dataUpdateCount>0||d.errorUpdateCount>0,isFetchedAfterMount:d.dataUpdateCount>I.dataUpdateCount||d.errorUpdateCount>I.errorUpdateCount,isFetching:j,isRefetching:j&&!x,isLoadingError:X&&!lt,isPaused:d.fetchStatus==="paused",isPlaceholderData:Q,isRefetchError:X&&lt,isStale:ut(t,e),refetch:this.refetch}}updateResult(t){const e=s(this,b),n=this.createResult(s(this,a),this.options);if(l(this,E,s(this,a).state),l(this,P,this.options),s(this,E).data!==void 0&&l(this,A,s(this,a)),tt(n,e))return;l(this,b,n);const o={},r=()=>{if(!e)return!0;const{notifyOnChangeProps:c}=this.options,p=typeof c=="function"?c():c;if(p==="all"||!p&&!s(this,L).size)return!0;const C=new Set(p??s(this,L));return this.options.throwOnError&&C.add("error"),Object.keys(s(this,b)).some(I=>{const v=I;return s(this,b)[v]!==e[v]&&C.has(v)})};(t==null?void 0:t.listeners)!==!1&&r()&&(o.listeners=!0),f(this,J,Ct).call(this,{...o,...t})}onQueryUpdate(){this.updateResult(),this.hasListeners()&&f(this,V,nt).call(this)}},y=new WeakMap,a=new WeakMap,N=new WeakMap,b=new WeakMap,E=new WeakMap,P=new WeakMap,g=new WeakMap,W=new WeakMap,M=new WeakMap,A=new WeakMap,D=new WeakMap,F=new WeakMap,w=new WeakMap,L=new WeakMap,T=new WeakSet,$=function(t){f(this,G,ot).call(this);let e=s(this,a).fetch(this.options,t);return t!=null&&t.throwOnError||(e=e.catch(Qt)),e},_=new WeakSet,et=function(){f(this,z,at).call(this);const t=Y(this.options.staleTime,s(this,a));if(ft||s(this,b).isStale||!pt(t))return;const n=Et(s(this,b).dataUpdatedAt,t)+1;l(this,D,setTimeout(()=>{s(this,b).isStale||this.updateResult()},n))},B=new WeakSet,st=function(){return(typeof this.options.refetchInterval=="function"?this.options.refetchInterval(s(this,a)):this.options.refetchInterval)??!1},k=new WeakSet,it=function(t){f(this,K,rt).call(this),l(this,w,t),!(ft||O(this.options.enabled,s(this,a))===!1||!pt(s(this,w))||s(this,w)===0)&&l(this,F,setInterval(()=>{(this.options.refetchIntervalInBackground||Dt.isFocused())&&f(this,T,$).call(this)},s(this,w)))},V=new WeakSet,nt=function(){f(this,_,et).call(this),f(this,k,it).call(this,f(this,B,st).call(this))},z=new WeakSet,at=function(){s(this,D)&&(clearTimeout(s(this,D)),l(this,D,void 0))},K=new WeakSet,rt=function(){s(this,F)&&(clearInterval(s(this,F)),l(this,F,void 0))},G=new WeakSet,ot=function(){const t=s(this,y).getQueryCache().build(s(this,y),this.options);if(t===s(this,a))return;const e=s(this,a);l(this,a,t),l(this,N,t.state),this.hasListeners()&&(e==null||e.removeObserver(this),t.addObserver(this))},J=new WeakSet,Ct=function(t){Tt.batch(()=>{t.listeners&&this.listeners.forEach(e=>{e(s(this,b))}),s(this,y).getQueryCache().notify({query:s(this,a),type:"observerResultsUpdated"})})},gt);function Wt(i,t){return O(t.enabled,i)!==!1&&i.state.data===void 0&&!(i.state.status==="error"&&t.retryOnMount===!1)}function mt(i,t){return Wt(i,t)||i.state.data!==void 0&&ht(i,t,t.refetchOnMount)}function ht(i,t,e){if(O(t.enabled,i)!==!1){const n=typeof e=="function"?e(i):e;return n==="always"||n!==!1&&ut(i,t)}return!1}function Rt(i,t,e,n){return(i!==t||O(n.enabled,i)===!1)&&(!e.suspense||i.state.status!=="error")&&ut(i,e)}function ut(i,t){return O(t.enabled,i)!==!1&&i.isStaleByTime(Y(t.staleTime,i))}function _t(i,t){return!tt(i.getCurrentResult(),t)}function Bt(i=""){if(!Ut())throw new Error("vue-query hooks can only be used inside setup() function or functions that support injection context.");const t=xt(i),e=jt(t);if(!e)throw new Error("No 'queryClient' found in Vue context, use 'VueQueryPlugin' to properly initialize the library.");return e}function kt(i,t,e){const n=e||Bt(),o=Ot(()=>{const h=Pt(t);typeof h.enabled=="function"&&(h.enabled=h.enabled());const S=n.defaultQueryOptions(h);return S._optimisticResults=n.isRestoring.value?"isRestoring":"optimistic",S}),r=new i(n,o.value),c=Mt(r.getCurrentResult());let p=()=>{};H(n.isRestoring,h=>{h||(p(),p=r.subscribe(S=>{yt(c,S)}))},{immediate:!0});const C=()=>{r.setOptions(o.value),yt(c,r.getCurrentResult())};H(o,C),At(()=>{p()});const I=(...h)=>(C(),c.refetch(...h)),v=()=>new Promise((h,S)=>{let U=()=>{};const R=()=>{if(o.value.enabled!==!1){r.setOptions(o.value);const j=r.getOptimisticResult(o.value);j.isStale?(U(),r.fetchOptimistic(o.value).then(h,x=>{vt(o.value.throwOnError,[x,r.getCurrentQuery()])?S(x):h(r.getCurrentResult())})):(U(),h(j))}};R(),U=H(o,R)});H(()=>c.error,h=>{if(c.isError&&!c.isFetching&&vt(o.value.throwOnError,[h,r.getCurrentQuery()]))throw h});const Q=Lt(c);for(const h in c)typeof c[h]=="function"&&(Q[h]=c[h]);return Q.suspense=v,Q.refetch=I,Q}function Vt(i,t){return kt(Nt,i,t)}const zt=3;async function Kt(i,t){const e=i.startsWith("/")?i.slice(1):i;let n=`${window.DATA_HOST}${e}`;i.startsWith("http")&&(n=i),n.endsWith("/")&&(n=n.slice(0,-1));const o=await fetch(`${n}/config.json?t=${t??0}`),r=await fetch(`${n}/team.json?t=${t??0}`),c=await fetch(`${n}/run.json?t=${t??0}`),{status:p,statusText:C}=o;if(p>=300||p<200)throw new Error(`fetch data failed. [status=${p}] [statusText=${C}]`);return Promise.all([o.json(),r.json(),c.json()]).then(v=>({contest:v[0],teams:v[1],submissions:v[2]}))}function Jt(i,t,e=!1){let n=3e4,o=n;const r=Ot(()=>Math.floor(t.value.getTime()/1e3/10));return $t.value==="I18N"&&(n=10*1e3,o=n),e&&(n=Number.POSITIVE_INFINITY,o=!1),Vt({queryKey:[i,r.value],queryFn:()=>Kt(i,r.value),retry:zt,staleTime:n,refetchInterval:o})}function Xt(){return St("data-source","",{transform:String})}function Zt(){return St("battle-of-giants","",{transform:String})}export{Zt as a,Xt as g,Jt as u};
@@ -1 +1 @@
1
- import{_ as p}from"./TheInput.vue_vue_type_script_setup_true_lang-1ce252e6.js";import{g as c,i as f,M as _,n as b,o as v,c as h,d as e,t as a,j as s,b as y,N as x,O as g,y as i}from"./index-d8432aad.js";import{u as V}from"./user-03dfbe5d.js";const k={flex:"","flex-col":"","justify-center":"","items-center":""},w={"text-sm":"","opacity-75":""},I={"w-48":""},N={class:"hidden",for:"input"},B=["disabled"],C=c({name:"IndexPage",__name:"test",setup(R){const r=V(),o=f(r.savedName),u=_();function l(){o.value&&u.push(`/hi/${encodeURIComponent(o.value)}`)}const{t:n}=b();return(U,t)=>{const d=p;return v(),h("div",k,[t[1]||(t[1]=e("div",{"text-4xl":""},[e("div",{"i-carbon-campsite":""})],-1)),t[2]||(t[2]=e("p",null,[e("a",{rel:"noreferrer",href:"https://github.com/antfu/vitesse",target:"_blank"}," Vitesse ")],-1)),e("p",null,[e("em",w,a(s(n)("intro.desc")),1)]),t[3]||(t[3]=e("div",{"py-4":""},null,-1)),e("div",I,[y(d,{modelValue:s(o),"onUpdate:modelValue":t[0]||(t[0]=m=>x(o)?o.value=m:null),placeholder:s(n)("intro.whats-your-name"),autocomplete:"false",onKeydown:g(l,["enter"])},null,8,["modelValue","placeholder"]),e("label",N,a(s(n)("intro.whats-your-name")),1)]),e("div",null,[e("button",{"m-3":"","text-sm":"",btn:"",disabled:!s(o),onClick:l},a(s(n)("button.go")),9,B)])])}}});typeof i=="function"&&i(C);export{C as default};
1
+ import{_ as p}from"./TheInput.vue_vue_type_script_setup_true_lang-9cc92a14.js";import{g as c,i as f,U as _,q as b,o as v,c as h,d as e,t as a,u as s,b as x,V as y,W as g,E as i}from"./index-f813b721.js";import{u as V}from"./user-5e4a4fb1.js";const k={flex:"","flex-col":"","justify-center":"","items-center":""},w={"text-sm":"","opacity-75":""},I={"w-48":""},U={class:"hidden",for:"input"},B=["disabled"],C=c({name:"IndexPage",__name:"test",setup(N){const r=V(),o=f(r.savedName),u=_();function l(){o.value&&u.push(`/hi/${encodeURIComponent(o.value)}`)}const{t:n}=b();return(R,t)=>{const d=p;return v(),h("div",k,[t[1]||(t[1]=e("div",{"text-4xl":""},[e("div",{"i-carbon-campsite":""})],-1)),t[2]||(t[2]=e("p",null,[e("a",{rel:"noreferrer",href:"https://github.com/antfu/vitesse",target:"_blank"}," Vitesse ")],-1)),e("p",null,[e("em",w,a(s(n)("intro.desc")),1)]),t[3]||(t[3]=e("div",{"py-4":""},null,-1)),e("div",I,[x(d,{modelValue:s(o),"onUpdate:modelValue":t[0]||(t[0]=m=>y(o)?o.value=m:null),placeholder:s(n)("intro.whats-your-name"),autocomplete:"false",onKeydown:g(l,["enter"])},null,8,["modelValue","placeholder"]),e("label",U,a(s(n)("intro.whats-your-name")),1)]),e("div",null,[e("button",{"m-3":"","text-sm":"",btn:"",disabled:!s(o),onClick:l},a(s(n)("button.go")),9,B)])])}}});typeof i=="function"&&i(C);export{C as default};
@@ -1 +1 @@
1
- import{aT as m,i as r,h as t}from"./index-d8432aad.js";const l=m("user",()=>{const e=r(""),s=r(new Set),o=t(()=>Array.from(s.value)),u=t(()=>o.value.filter(a=>a!==e.value));function n(a){e.value&&s.value.add(e.value),e.value=a}return{setNewName:n,otherNames:u,savedName:e}});export{l as u};
1
+ import{aW as m,i as r,h as t}from"./index-f813b721.js";const l=m("user",()=>{const e=r(""),s=r(new Set),o=t(()=>Array.from(s.value)),u=t(()=>o.value.filter(a=>a!==e.value));function n(a){e.value&&s.value.add(e.value),e.value=a}return{setNewName:n,otherNames:u,savedName:e}});export{l as u};
@@ -1 +1 @@
1
- import{_}from"./index-d8432aad.js";function f(c={}){const{immediate:d=!1,onNeedRefresh:m,onOfflineReady:i,onRegistered:r,onRegisteredSW:s,onRegisterError:a}=c;let t,o;const l=async(n=!0)=>{await o};async function p(){if("serviceWorker"in navigator){const{Workbox:n}=await _(()=>import("./workbox-window.prod.es5-c46a1faa.js"),[],import.meta.url);t=new n("/sw.js",{scope:"/",type:"classic"}),t.addEventListener("activated",e=>{(e.isUpdate||e.isExternal)&&window.location.reload()}),t.addEventListener("installed",e=>{e.isUpdate||i==null||i()}),t.register({immediate:d}).then(e=>{s?s("/sw.js",e):r==null||r(e)}).catch(e=>{a==null||a(e)})}}return o=p(),l}export{f as registerSW};
1
+ import{_}from"./index-f813b721.js";function f(c={}){const{immediate:d=!1,onNeedRefresh:m,onOfflineReady:i,onRegistered:r,onRegisteredSW:s,onRegisterError:a}=c;let t,o;const l=async(n=!0)=>{await o};async function p(){if("serviceWorker"in navigator){const{Workbox:n}=await _(()=>import("./workbox-window.prod.es5-c46a1faa.js"),[],import.meta.url);t=new n("/sw.js",{scope:"/",type:"classic"}),t.addEventListener("activated",e=>{(e.isUpdate||e.isExternal)&&window.location.reload()}),t.addEventListener("installed",e=>{e.isUpdate||i==null||i()}),t.register({immediate:d}).then(e=>{s?s("/sw.js",e):r==null||r(e)}).catch(e=>{a==null||a(e)})}}return o=p(),l}export{f as registerSW};
package/dist/index.html CHANGED
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="UTF-8"><link rel="apple-touch-icon" href="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.51.2/dist/balloon-192x192.png"><link rel="mask-icon" href="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.51.2/dist/balloon-512x512.svg" color="#00aba9"><meta name="msapplication-TileColor" content="#00aba9"><script>function normalizePath(_){for(;_.endsWith("/");)_=_.slice(0,-1);return`${_}/`}{let _="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.51.2/dist";_=normalizePath(_),window.CDN_HOST=_}try{let _=__DATA_HOST__;_=normalizePath(_),window.DATA_HOST=_}catch(_){window.DATA_HOST="/data/"}try{let _=__DATA_REGION__;window.DATA_REGION=_}catch(_){window.DATA_REGION="CN"}try{let _=__DEFAULT_LANG__;window.DEFAULT_LANG=_}catch(_){window.DEFAULT_LANG="en"}</script><script>!function(){localStorage.getItem("vueuse-color-scheme")||localStorage.setItem("vueuse-color-scheme","light");const e=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches,o=localStorage.getItem("vueuse-color-scheme")||"auto";("dark"===o||e&&"light"!==o)&&document.documentElement.classList.toggle("dark",!0)}()</script><script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.51.2/dist/assets/index-d8432aad.js"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.51.2/dist/assets/index-9dd86d68.css"><link rel="manifest" href="/manifest.webmanifest"></head><body class="font-sans"><div id="app"></div><noscript>This website requires JavaScript to function properly. Please enable JavaScript to continue.</noscript><script>try{var umamiJSUrl=__UMAMI_JS_URL__,umamiWebsiteId=__UMAMI_WEBSITE_ID__;!function(){var e=document.createElement("script");e.src=umamiJSUrl,e.defer=!0,e.setAttribute("data-website-id",umamiWebsiteId);var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()}catch(e){}try{var plausibleJSUrl=__PLAUSIBLE_JS_URL__,plausibleDataDomain=__PLAUSIBLE_DATA_DOMAIN__;!function(){var e=document.createElement("script");e.src=plausibleJSUrl,e.defer=!0,e.setAttribute("data-domain",plausibleDataDomain);var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()}catch(e){}try{var baiduAnalyticsId=__BAIDU_ANALYTICS_ID__,_hmt=_hmt||[];!function(){var e=document.createElement("script");e.src=`https://hm.baidu.com/hm.js?${baiduAnalyticsId}`;var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()}catch(e){}try{var googleAnalyticsId=__GOOGLE_ANALYTICS_ID__;!function(){var e,t,a,r,c,n;location.port||(e=window,t=document,a="script",r="ga",e.GoogleAnalyticsObject=r,e[r]=e[r]||function(){(e[r].q=e[r].q||[]).push(arguments)},e[r].l=1*new Date,c=t.createElement(a),n=t.getElementsByTagName(a)[0],c.async=1,c.src="//www.google-analytics.com/analytics.js",n.parentNode.insertBefore(c,n),ga("create",`${googleAnalyticsId}`,"auto"),ga("send","pageview"))}()}catch(e){}</script></body></html>
1
+ <!doctype html><html lang="en"><head><meta charset="UTF-8"><link rel="apple-touch-icon" href="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.52.1/dist/balloon-192x192.png"><link rel="mask-icon" href="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.52.1/dist/balloon-512x512.svg" color="#00aba9"><meta name="msapplication-TileColor" content="#00aba9"><script>function normalizePath(_){for(;_.endsWith("/");)_=_.slice(0,-1);return`${_}/`}{let _="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.52.1/dist";_=normalizePath(_),window.CDN_HOST=_}try{let _=__DATA_HOST__;_=normalizePath(_),window.DATA_HOST=_}catch(_){window.DATA_HOST="/data/"}try{let _=__DATA_REGION__;window.DATA_REGION=_}catch(_){window.DATA_REGION="CN"}try{let _=__DEFAULT_LANG__;window.DEFAULT_LANG=_}catch(_){window.DEFAULT_LANG="en"}</script><script>!function(){localStorage.getItem("vueuse-color-scheme")||localStorage.setItem("vueuse-color-scheme","light");const e=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches,o=localStorage.getItem("vueuse-color-scheme")||"auto";("dark"===o||e&&"light"!==o)&&document.documentElement.classList.toggle("dark",!0)}()</script><script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.52.1/dist/assets/index-f813b721.js"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xcpcio/board-app@0.52.1/dist/assets/index-ae8b398e.css"><link rel="manifest" href="/manifest.webmanifest"></head><body class="font-sans"><div id="app"></div><noscript>This website requires JavaScript to function properly. Please enable JavaScript to continue.</noscript><script>try{var umamiJSUrl=__UMAMI_JS_URL__,umamiWebsiteId=__UMAMI_WEBSITE_ID__;!function(){var e=document.createElement("script");e.src=umamiJSUrl,e.defer=!0,e.setAttribute("data-website-id",umamiWebsiteId);var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()}catch(e){}try{var plausibleJSUrl=__PLAUSIBLE_JS_URL__,plausibleDataDomain=__PLAUSIBLE_DATA_DOMAIN__;!function(){var e=document.createElement("script");e.src=plausibleJSUrl,e.defer=!0,e.setAttribute("data-domain",plausibleDataDomain);var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()}catch(e){}try{var baiduAnalyticsId=__BAIDU_ANALYTICS_ID__,_hmt=_hmt||[];!function(){var e=document.createElement("script");e.src=`https://hm.baidu.com/hm.js?${baiduAnalyticsId}`;var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()}catch(e){}try{var googleAnalyticsId=__GOOGLE_ANALYTICS_ID__;!function(){var e,t,a,r,c,n;location.port||(e=window,t=document,a="script",r="ga",e.GoogleAnalyticsObject=r,e[r]=e[r]||function(){(e[r].q=e[r].q||[]).push(arguments)},e[r].l=1*new Date,c=t.createElement(a),n=t.getElementsByTagName(a)[0],c.async=1,c.src="//www.google-analytics.com/analytics.js",n.parentNode.insertBefore(c,n),ga("create",`${googleAnalyticsId}`,"auto"),ga("send","pageview"))}()}catch(e){}</script></body></html>
package/dist/sw.js CHANGED
@@ -1 +1 @@
1
- if(!self.define){let s,e={};const l=(l,n)=>(l=new URL(l+".js",n).href,e[l]||new Promise((e=>{if("document"in self){const s=document.createElement("script");s.src=l,s.onload=e,document.head.appendChild(s)}else s=l,importScripts(l),e()})).then((()=>{let s=e[l];if(!s)throw new Error(`Module ${l} didn’t register its module`);return s})));self.define=(n,i)=>{const r=s||("document"in self?document.currentScript.src:"")||location.href;if(e[r])return;let a={};const u=s=>l(s,r),t={module:{uri:r},exports:a,require:u};e[r]=Promise.all(n.map((s=>t[s]||u(s)))).then((s=>(i(...s),a)))}}define(["./workbox-86deb690"],(function(s){"use strict";self.skipWaiting(),s.clientsClaim(),s.precacheAndRoute([{url:"assets/_...all_-198e3528.js",revision:null},{url:"assets/_...all_-61cb8860.js",revision:null},{url:"assets/_...all_-c60acc8c.css",revision:null},{url:"assets/_name_-f901a5ed.js",revision:null},{url:"assets/about-9fdb1313.js",revision:null},{url:"assets/Board-3491f2da.css",revision:null},{url:"assets/board-65f3126c.js",revision:null},{url:"assets/Board-a6a37adf.js",revision:null},{url:"assets/board-layout-598f9ee4.js",revision:null},{url:"assets/DataSourceInput.vue_vue_type_script_setup_true_lang-d2ea1ac6.js",revision:null},{url:"assets/en-c9a8dbb5.js",revision:null},{url:"assets/headless-e015e9d1.js",revision:null},{url:"assets/home-89f287c8.js",revision:null},{url:"assets/index-241beb5a.css",revision:null},{url:"assets/index-67b2a8c5.css",revision:null},{url:"assets/index-7af0a9ca.js",revision:null},{url:"assets/index-8e5373fd.js",revision:null},{url:"assets/index-9dd86d68.css",revision:null},{url:"assets/index-d8432aad.js",revision:null},{url:"assets/index-ea20d191.js",revision:null},{url:"assets/index-layout-60ef1a96.js",revision:null},{url:"assets/pagination-95a79aa6.js",revision:null},{url:"assets/query-67fd6c27.js",revision:null},{url:"assets/test-5c739ae1.js",revision:null},{url:"assets/TheInput.vue_vue_type_script_setup_true_lang-1ce252e6.js",revision:null},{url:"assets/user-03dfbe5d.js",revision:null},{url:"assets/virtual_pwa-register-6ca2d3a0.js",revision:null},{url:"assets/workbox-window.prod.es5-c46a1faa.js",revision:null},{url:"assets/zh-CN-8e545f66.js",revision:null},{url:"index.html",revision:"deec9e7b65e453899edd84352ba7cdb1"},{url:"favicon.svg",revision:"5a744f4ccbb122d4a0575be779ddcd43"},{url:"safari-pinned-tab.svg",revision:"5eaf74d1c43d30e0af743b68a3f48504"},{url:"balloon2-192x192.png",revision:"c857ae6d9dfae118ab4397d4358422bd"},{url:"balloon2-512x512.png",revision:"065594f4f743fe3884793c03d3fe7d9e"},{url:"manifest.webmanifest",revision:"3082e8d8ebc9619c6c1055ff243a02a8"}],{}),s.cleanupOutdatedCaches(),s.registerRoute(new s.NavigationRoute(s.createHandlerBoundToURL("index.html")))}));
1
+ if(!self.define){let s,e={};const l=(l,n)=>(l=new URL(l+".js",n).href,e[l]||new Promise((e=>{if("document"in self){const s=document.createElement("script");s.src=l,s.onload=e,document.head.appendChild(s)}else s=l,importScripts(l),e()})).then((()=>{let s=e[l];if(!s)throw new Error(`Module ${l} didn’t register its module`);return s})));self.define=(n,i)=>{const r=s||("document"in self?document.currentScript.src:"")||location.href;if(e[r])return;let u={};const a=s=>l(s,r),t={module:{uri:r},exports:u,require:a};e[r]=Promise.all(n.map((s=>t[s]||a(s)))).then((s=>(i(...s),u)))}}define(["./workbox-86deb690"],(function(s){"use strict";self.skipWaiting(),s.clientsClaim(),s.precacheAndRoute([{url:"assets/_...all_-80d9c58d.js",revision:null},{url:"assets/_...all_-c60acc8c.css",revision:null},{url:"assets/_...all_-efc1d81f.js",revision:null},{url:"assets/_name_-5f588c5c.js",revision:null},{url:"assets/about-86489903.js",revision:null},{url:"assets/board-428898fa.js",revision:null},{url:"assets/Board-b5bf1828.js",revision:null},{url:"assets/Board-f05c0366.css",revision:null},{url:"assets/board-layout-f4b42426.js",revision:null},{url:"assets/DataSourceInput.vue_vue_type_script_setup_true_lang-47ff726d.js",revision:null},{url:"assets/en-c9a8dbb5.js",revision:null},{url:"assets/headless-464cd216.js",revision:null},{url:"assets/home-1c2da293.js",revision:null},{url:"assets/index-1426f0a6.js",revision:null},{url:"assets/index-241beb5a.css",revision:null},{url:"assets/index-5271d2f0.css",revision:null},{url:"assets/index-8a3db893.js",revision:null},{url:"assets/index-accb347c.css",revision:null},{url:"assets/index-ae8b398e.css",revision:null},{url:"assets/index-c4a296e0.js",revision:null},{url:"assets/index-f813b721.js",revision:null},{url:"assets/index-fe6090d1.js",revision:null},{url:"assets/index-layout-6dbef8c0.js",revision:null},{url:"assets/pagination-959b8075.js",revision:null},{url:"assets/query-8d6474f1.js",revision:null},{url:"assets/test-ce57205f.js",revision:null},{url:"assets/TheInput.vue_vue_type_script_setup_true_lang-9cc92a14.js",revision:null},{url:"assets/user-5e4a4fb1.js",revision:null},{url:"assets/virtual_pwa-register-ab60e448.js",revision:null},{url:"assets/workbox-window.prod.es5-c46a1faa.js",revision:null},{url:"assets/zh-CN-8e545f66.js",revision:null},{url:"index.html",revision:"151bd75bced66b023f21768a3389ea1f"},{url:"favicon.svg",revision:"5a744f4ccbb122d4a0575be779ddcd43"},{url:"safari-pinned-tab.svg",revision:"5eaf74d1c43d30e0af743b68a3f48504"},{url:"balloon2-192x192.png",revision:"c857ae6d9dfae118ab4397d4358422bd"},{url:"balloon2-512x512.png",revision:"065594f4f743fe3884793c03d3fe7d9e"},{url:"manifest.webmanifest",revision:"3082e8d8ebc9619c6c1055ff243a02a8"}],{}),s.cleanupOutdatedCaches(),s.registerRoute(new s.NavigationRoute(s.createHandlerBoundToURL("index.html")))}));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xcpcio/board-app",
3
3
  "type": "module",
4
- "version": "0.51.2",
4
+ "version": "0.52.1",
5
5
  "description": "XCPCIO Board App",
6
6
  "author": "Dup4 <lyuzhi.pan@gmail.com>",
7
7
  "license": "MIT",
@@ -41,6 +41,7 @@
41
41
  "file-saver": "^2.0.5",
42
42
  "floating-vue": "2.0.0-beta.24",
43
43
  "flowbite": "^1.8.1",
44
+ "gsap": "^3.12.5",
44
45
  "highcharts": "^11.4.8",
45
46
  "highcharts-vue": "^1.4.3",
46
47
  "lodash": "^4.17.21",
@@ -53,8 +54,8 @@
53
54
  "vue-router": "^4.4.5",
54
55
  "vue-search-select": "^3.2.0",
55
56
  "vue-toast-notification": "^3.1.3",
56
- "@xcpcio/types": "0.51.2",
57
- "@xcpcio/core": "0.51.2"
57
+ "@xcpcio/core": "0.52.1",
58
+ "@xcpcio/types": "0.52.1"
58
59
  },
59
60
  "devDependencies": {
60
61
  "@antfu/eslint-config": "^0.39.8",
@@ -40,7 +40,7 @@ watch(data, async () => {
40
40
  reBuildBalloons();
41
41
 
42
42
  firstLoaded.value = true;
43
- });
43
+ }, { immediate: true });
44
44
 
45
45
  const balloons = computed(() => {
46
46
  return rank.value.balloons.sort(Balloon.compare).reverse().slice(0, 256);
@@ -51,13 +51,13 @@ const balloons = computed(() => {
51
51
  <div
52
52
  class="bg-[#323443]"
53
53
  text-gray-200
54
+ w-screen h-screen
54
55
  >
55
56
  <div v-if="!firstLoaded">
56
57
  <div
57
58
  flex flex-col
58
59
  justify-center items-center
59
- w-screen
60
- h-screen
60
+ w-screen h-screen
61
61
  text-xl italic
62
62
  >
63
63
  <div>
@@ -30,7 +30,7 @@ const balloonColor = computed(() => balloon.value.problem.balloonColor);
30
30
  h-24
31
31
  flex flex-row gap-x-4
32
32
  font-mono text-4xl
33
- :class="[index % 2 === 0 ? 'bg-resolver-bg-zero' : 'bg-resolver-bg-one']"
33
+ :class="[index % 2 === 0 ? 'bg-resolver-bg-0' : 'bg-resolver-bg-1']"
34
34
  >
35
35
  <div
36
36
  w-20
@@ -25,15 +25,14 @@ watch(data, async () => {
25
25
  title.value = `${contest.value.name} | ${COUNTDOWN_TITLE_SUFFIX}`;
26
26
 
27
27
  firstLoaded.value = true;
28
- });
28
+ }, { immediate: true });
29
29
  </script>
30
30
 
31
31
  <template>
32
32
  <div
33
- class="background"
33
+ class="bg-[#323443]"
34
34
  text-gray-200
35
- w-screen
36
- h-screen
35
+ w-screen h-screen
37
36
  >
38
37
  <div v-if="!firstLoaded">
39
38
  <div
@@ -91,10 +90,6 @@ watch(data, async () => {
91
90
  </template>
92
91
 
93
92
  <style scoped>
94
- .background {
95
- background-color: #333443;
96
- }
97
-
98
93
  .PENDING {
99
94
  color: #3bb4f2;
100
95
  }
@@ -0,0 +1,25 @@
1
+ <script setup lang="ts">
2
+ import { getDataSourceUrl } from "~/composables/query";
3
+
4
+ const dataSourceUrl = getDataSourceUrl();
5
+ </script>
6
+
7
+ <template>
8
+ <div
9
+ v-if="dataSourceUrl.length === 0"
10
+ >
11
+ <div
12
+ mt-20
13
+ >
14
+ <DataSourceInput />
15
+ </div>
16
+ </div>
17
+
18
+ <div
19
+ v-if="dataSourceUrl.length > 0"
20
+ >
21
+ <Resolver
22
+ :data-source-url="dataSourceUrl"
23
+ />
24
+ </div>
25
+ </template>
@@ -0,0 +1,216 @@
1
+ <script setup lang="ts">
2
+ import { onKeyUp } from "@vueuse/core";
3
+ import { ResolverVue, createContest, createSubmissions, createTeams } from "@xcpcio/core";
4
+ import type { Contest, Submissions, Teams } from "@xcpcio/core";
5
+ import type { Contest as IContest, Submissions as ISubmissions, Teams as ITeams } from "@xcpcio/types";
6
+ import { gsap } from "gsap";
7
+ import { ScrollToPlugin } from "gsap/ScrollToPlugin";
8
+
9
+ const props = defineProps<{
10
+ dataSourceUrl: string,
11
+ }>();
12
+
13
+ gsap.registerPlugin(ScrollToPlugin);
14
+
15
+ const title = useTitle(RESOLVER_TITLE_SUFFIX);
16
+ const { t } = useI18n();
17
+
18
+ const firstLoaded = ref(false);
19
+ const startFirstScroll = ref(false);
20
+ const finishedFirstScroll = ref(false);
21
+ const contest = ref({} as Contest);
22
+ const teams = ref([] as Teams);
23
+ const submissions = ref([] as Submissions);
24
+ const resolver = ref({} as ResolverVue);
25
+ const now = useNow();
26
+
27
+ function reBuildResolver() {
28
+ const newResolver = new ResolverVue(contest.value, teams.value, submissions.value);
29
+ newResolver.buildResolver();
30
+ resolver.value = newResolver;
31
+ }
32
+
33
+ const { data, isError, error } = useQueryBoardData(props.dataSourceUrl, now, /* queryOnce= */true);
34
+ watch(data, async () => {
35
+ if (data.value === null || data.value === undefined) {
36
+ return;
37
+ }
38
+
39
+ contest.value = createContest(data.value?.contest as IContest);
40
+ title.value = `${contest.value.name} | ${RESOLVER_TITLE_SUFFIX}`;
41
+
42
+ teams.value = createTeams(data.value?.teams as ITeams);
43
+ submissions.value = createSubmissions(data.value?.submissions as ISubmissions);
44
+
45
+ reBuildResolver();
46
+
47
+ firstLoaded.value = true;
48
+ }, { immediate: true });
49
+
50
+ onKeyStroke([" "], (e) => {
51
+ e.preventDefault();
52
+ });
53
+
54
+ onKeyUp(["n", " "], () => {
55
+ if (!finishedFirstScroll.value) {
56
+ startFirstScroll.value = true;
57
+ return;
58
+ }
59
+
60
+ resolver.value.next();
61
+ }, { dedupe: true });
62
+
63
+ onKeyUp(["r"], () => {
64
+ resolver.value.rewind();
65
+ }, { dedupe: true });
66
+
67
+ onKeyUp(["w"], () => {
68
+ resolver.value.currentIndex--;
69
+ });
70
+
71
+ onKeyUp(["s"], () => {
72
+ resolver.value.currentIndex++;
73
+ });
74
+
75
+ const resolverRef = ref<HTMLElement | null>(null);
76
+ const currentRowRef = ref<HTMLElement | null>(null);
77
+
78
+ onMounted(() => {
79
+ watch(() => startFirstScroll.value, async () => {
80
+ if (finishedFirstScroll.value) {
81
+ return;
82
+ }
83
+
84
+ if (!startFirstScroll.value) {
85
+ return;
86
+ }
87
+
88
+ if (resolverRef.value) {
89
+ const scrollHeight = resolverRef.value.scrollHeight;
90
+ const clientHeight = resolverRef.value.clientHeight;
91
+
92
+ gsap.to(resolverRef.value, {
93
+ duration: Math.round(resolver.value.teams.length * 0.5),
94
+ scrollTop: scrollHeight - clientHeight,
95
+ ease: "power1.inOut",
96
+ onComplete: () => {
97
+ finishedFirstScroll.value = true;
98
+ },
99
+ });
100
+ }
101
+ }, { immediate: true });
102
+
103
+ watch(() => resolver.value.currentIndex, async () => {
104
+ if (!finishedFirstScroll.value) {
105
+ return;
106
+ }
107
+
108
+ if (resolverRef.value && currentRowRef.value) {
109
+ const containerRect = resolverRef.value.getBoundingClientRect();
110
+ const containerHeight = containerRect.height;
111
+ const rowRect = currentRowRef.value.getBoundingClientRect();
112
+ const rowHeight = rowRect.height;
113
+
114
+ // 计算选中行应该在的位置(距离底部2行)
115
+ const targetPosition = containerHeight - 3 * rowHeight;
116
+
117
+ // 计算当前选中行相对于容器顶部的位置
118
+ const currentPosition = rowRect.top - containerRect.top;
119
+
120
+ // 计算需要滚动的距离
121
+ const scrollDistance = (currentPosition - targetPosition);
122
+
123
+ gsap.to(resolverRef.value, {
124
+ duration: 2.5,
125
+ ease: "power1.out",
126
+ scrollTop: `+=${scrollDistance}`,
127
+ });
128
+ }
129
+ }, { flush: "post" });
130
+ });
131
+ </script>
132
+
133
+ <template>
134
+ <div
135
+ text-gray-200
136
+ w-screen h-screen
137
+ >
138
+ <div v-if="!firstLoaded">
139
+ <div
140
+ flex flex-col
141
+ justify-center items-center
142
+ w-screen h-screen
143
+ text-xl italic
144
+ class="bg-[#323443]"
145
+ >
146
+ <div>
147
+ {{ t("common.loading") }}...
148
+ </div>
149
+
150
+ <div v-if="isError">
151
+ {{ error }}
152
+ </div>
153
+ </div>
154
+ </div>
155
+
156
+ <div
157
+ v-else
158
+ >
159
+ <div>
160
+ <div
161
+ class="bg-resolver-bg-1"
162
+ flex flex-col justify-between
163
+ font-mono
164
+ w-screen h-screen
165
+ overflow-hidden
166
+ >
167
+ <div
168
+ ref="resolverRef"
169
+ h-full
170
+ overflow-y-auto
171
+ >
172
+ <TransitionGroup
173
+ name="resolver"
174
+ tag="ul"
175
+ >
176
+ <template
177
+ v-for="(team, index) in resolver.teams"
178
+ :key="team.id"
179
+ >
180
+ <div
181
+ :ref="(el) => { if (index === resolver.currentIndex) { currentRowRef = el as HTMLElement; } }"
182
+ :class="[team.id === resolver.currentTeamId ? 'z-999' : 'z-0']"
183
+ position-relative
184
+ >
185
+ <ResolverTeamRow
186
+ :index="index"
187
+ :team="team"
188
+ :resolver="resolver"
189
+ />
190
+ </div>
191
+ </template>
192
+ </TransitionGroup>
193
+ </div>
194
+ </div>
195
+ </div>
196
+ </div>
197
+ </div>
198
+ </template>
199
+
200
+ <style scoped>
201
+ .resolver-move,
202
+ .resolver-enter-active,
203
+ .resolver-leave-active {
204
+ transition: all 2s ease;
205
+ }
206
+
207
+ .resolver-enter-from,
208
+ .resolver-leave-to {
209
+ opacity: 0;
210
+ transform: translateX(30px);
211
+ }
212
+
213
+ .resolver-leave-active {
214
+ position: absolute;
215
+ }
216
+ </style>
@@ -0,0 +1,127 @@
1
+ <script setup lang="ts">
2
+ import type { ResolverVue, Team } from "@xcpcio/core";
3
+
4
+ const props = defineProps<{
5
+ index: number;
6
+ team: Team;
7
+ resolver: ResolverVue;
8
+ }>();
9
+
10
+ const index = computed(() => props.index);
11
+ const team = computed(() => props.team);
12
+ const resolver = computed(() => props.resolver);
13
+ const el = ref(null);
14
+
15
+ // TODO(Dup4): Optimizing performance with useElementVisibility
16
+ // const isVisible = useElementVisibility(el);
17
+ const isVisible = true;
18
+
19
+ function showTeamName(team: Team) {
20
+ const sections = [team.organization, team.name];
21
+ return sections.filter(s => s).join(" - ");
22
+ }
23
+ </script>
24
+
25
+ <template>
26
+ <div
27
+ ref="el"
28
+ h-24
29
+ >
30
+ <div
31
+ v-if="isVisible"
32
+ h-24
33
+ flex flex-row gap-x-4
34
+ font-mono text-4xl
35
+ :class="[index % 2 === 0 ? 'bg-resolver-bg-zero' : 'bg-resolver-bg-one',
36
+ resolver.duringAnimation && resolver.currentTeamId === team.id ? 'bg-resolver-selected' : '',
37
+ !resolver.duringAnimation && index === resolver.currentIndex ? 'bg-resolver-selected' : '',
38
+ ]"
39
+ >
40
+ <div
41
+ w-20
42
+ flex flex-shrink-0 justify-center items-center
43
+ >
44
+ <div>
45
+ {{ team.rank }}
46
+ </div>
47
+ </div>
48
+
49
+ <div
50
+ flex flex-1 flex-col justify-center items-start gap-y-3
51
+ >
52
+ <Tooltip>
53
+ <div
54
+ class="resolver-team-name"
55
+ truncate overflow-hidden
56
+ >
57
+ {{ showTeamName(team) }}
58
+ </div>
59
+ <template #popper>
60
+ <div>
61
+ {{ showTeamName(team) }}
62
+ </div>
63
+ </template>
64
+ </Tooltip>
65
+
66
+ <div
67
+ flex flex-row text-sm items-start gap-x-2
68
+ >
69
+ <template
70
+ v-for="(p, pIndex) in team.problemStatistics"
71
+ :key="p.problem.id"
72
+ >
73
+ <div
74
+ class="rounded w-22 h-7 flex justify-center items-center"
75
+ :class="[p.isAccepted ? 'bg-resolver-ac' : '',
76
+ p.isWrongAnswer ? 'bg-resolver-wa' : '',
77
+ p.isPending ? 'bg-resolver-pending' : '',
78
+ p.isUnSubmitted ? 'bg-resolver-untouched' : '',
79
+ resolver.problemFlashingEnded === false
80
+ && index === resolver.currentIndex
81
+ && resolver.currentProblemIndex === pIndex
82
+ ? 'resolver-uncover'
83
+ : '',
84
+ ]"
85
+ >
86
+ <template v-if="p.isAccepted">
87
+ {{ `${p.failedCount + Number(p.isAccepted)}/${Math.floor(p.lastSubmitTimestamp / 60)}` }}
88
+ </template>
89
+ <template v-if="p.isWrongAnswer">
90
+ {{ `${p.failedCount}/${Math.floor(p.lastSubmitTimestamp / 60)}` }}
91
+ </template>
92
+ <template v-if="p.isPending">
93
+ {{ `${p.failedCount} + ${p.pendingCount}` }}
94
+ </template>
95
+ <template v-if="p.isUnSubmitted">
96
+ {{ p.problem.label }}
97
+ </template>
98
+ </div>
99
+ </template>
100
+ </div>
101
+ </div>
102
+
103
+ <div
104
+ w-48
105
+ flex flex-shrink-0 flex-row justify-start items-center
106
+ >
107
+ <div class="w-1/3">
108
+ {{ team.solvedProblemNum }}
109
+ </div>
110
+ <div class="w-2/3">
111
+ {{ team.penaltyToMinute }}
112
+ </div>
113
+ </div>
114
+ </div>
115
+ </div>
116
+ </template>
117
+
118
+ <style scoped>
119
+ .resolver-uncover {
120
+ animation: flashing 300ms infinite;
121
+ -webkit-animation: flashing 30ms infinite; /*Safari and Chrome*/
122
+ }
123
+
124
+ .resolver-team-name {
125
+ max-width: calc(100vw - 80px - 192px - 112px);
126
+ }
127
+ </style>
@@ -113,7 +113,7 @@ watch(data, async () => {
113
113
  reBuildRank();
114
114
 
115
115
  firstLoaded.value = true;
116
- });
116
+ }, { immediate: true });
117
117
 
118
118
  function dynamicReBuildRank() {
119
119
  if (firstLoaded.value === false) {
@@ -1,5 +1,7 @@
1
1
  <template>
2
- <div class="flex items-center justify-center dark:text-black">
2
+ <div
3
+ flex items-center justify-center dark:text-black
4
+ >
3
5
  <table>
4
6
  <tbody>
5
7
  <tr>
@@ -25,7 +27,7 @@
25
27
  Attempted problem
26
28
  </td>
27
29
  <td class="pending">
28
- Pending judgement / Frozen
30
+ Pending judgement/Frozen
29
31
  </td>
30
32
  </tr>
31
33
  </tbody>
@@ -1,16 +1,12 @@
1
1
  <script setup lang="ts">
2
- // const props = defineProps<{
3
- // rank: Rank,
4
- // }>();
5
-
6
2
  const { t } = useI18n();
7
3
 
8
4
  const route = useRoute();
9
5
  const router = useRouter();
10
6
 
11
- const resolverUrl = computed(() => {
12
- return `https://resolver.xcpcio.com/resolver?xcpcio-data-source=${route.path}`;
13
- });
7
+ function goResolver() {
8
+ router.push(`/resolver/?data-source=${route.path}`);
9
+ }
14
10
 
15
11
  function goBalloon() {
16
12
  router.push(`/balloon/?data-source=${route.path}`);
@@ -47,14 +43,13 @@ function goCountdown() {
47
43
  w-full
48
44
  flex mt-4 gap-4
49
45
  >
50
- <a
46
+ <button
51
47
  btn
52
- :href="resolverUrl"
53
- target="_blank"
54
48
  title="Resolver"
49
+ @click="goResolver"
55
50
  >
56
- {{ t("type_menu.resolver") }}
57
- </a>
51
+ {{ t('type_menu.resolver') }}
52
+ </button>
58
53
 
59
54
  <button
60
55
  btn
@@ -21,6 +21,7 @@ declare module 'vue' {
21
21
  CustomBalloon: typeof import('./components/CustomBalloon.vue')['default']
22
22
  CustomBoard: typeof import('./components/CustomBoard.vue')['default']
23
23
  CustomCountdown: typeof import('./components/CustomCountdown.vue')['default']
24
+ CustomResolver: typeof import('./components/CustomResolver.vue')['default']
24
25
  DataSourceInput: typeof import('./components/DataSourceInput.vue')['default']
25
26
  Export: typeof import('./components/board/Export.vue')['default']
26
27
  Footer: typeof import('./components/Footer.vue')['default']
@@ -42,6 +43,8 @@ declare module 'vue' {
42
43
  RatingTable: typeof import('./components/rating/RatingTable.vue')['default']
43
44
  RatingUserUI: typeof import('./components/rating/RatingUserUI.vue')['default']
44
45
  ReactionVideoModal: typeof import('./components/board/ReactionVideoModal.vue')['default']
46
+ Resolver: typeof import('./components/Resolver.vue')['default']
47
+ ResolverTeamRow: typeof import('./components/ResolverTeamRow.vue')['default']
45
48
  RightArrowIcon: typeof import('./components/icon/RightArrowIcon.vue')['default']
46
49
  RouterLink: typeof import('vue-router')['RouterLink']
47
50
  RouterView: typeof import('vue-router')['RouterView']