!function(e){var t={};function n(a){if(t[a])return t[a].exports;var r=t[a]={i:a,l:!1,exports:{}};return e[a].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,a){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:a})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var a=Object.create(null);if(n.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(a,r,function(t){return e[t]}.bind(null,r));return a},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=10)}([function(e,t){e.exports=React},function(e,t){e.exports=ReactBootstrap},function(e,t,n){var a; /*! Copyright (c) 2017 Jed Watson. Licensed under the MIT License (MIT), see http://jedwatson.github.io/classnames */!function(){"use strict";var n={}.hasOwnProperty;function r(){for(var e=[],t=0;te.split("="))):{}}function m(){return!!u().loginas}function d(){return(d=Object.assign||function(e){for(var t=1;t=0||(r[n]=e[n]);return r}var p=n(2),h=n.n(p),E=r.a.createContext({});E.Consumer,E.Provider;function v(e,t){var n=Object(a.useContext)(E);return e||n[t]||t}var b=function(){for(var e=arguments.length,t=new Array(e),n=0;nt(!1)},"Back to Exam")))}class C extends r.a.Component{constructor(e){super(e),this.state={hasError:!1}}static getDerivedStateFromError(){return{hasError:!0}}render(){return this.state.hasError?null:this.props.children}}var k=n(7);function j({name:e}){return r.a.createElement("a",{style:{display:"block",position:"relative",top:-70,visibility:"hidden"},name:e})}var T=Object(a.createContext)({exam:"",savedAnswers:{},onInternetError:()=>null,recordUnsaved:()=>null,recordSaved:()=>null,recordSolved:()=>null,recordUnsolved:()=>null,setStarred:()=>null,unsavedQuestions:new Set,solvedQuestions:new Map,starredQuestions:new Map});function N({points:e}){return null!==e&&r.a.createElement("small",null,"Points: ",e)}async function M(e,t,n){const a=fetch(e,{method:"POST",cache:"no-cache",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});return n?a:function(e,t){return new Promise((n,a)=>{const r=setTimeout(()=>{a(new Error("promise timeout"))},e);t.then(e=>{clearTimeout(r),n(e)},e=>{clearTimeout(r),a(e)})})}(1e4,a)}function _({text:e,suffixType:t}){return r.a.createElement("div",{style:{color:"red"}},e," ",e&&{exam:"If this error persists, contact your course staff or use the alternative exam medium.",alerts:""}[t||"exam"])}function P({children:e,loading:t,disabled:n,onClick:a,style:o,variant:s="primary",size:c}){return r.a.createElement(l.Button,{variant:s,onClick:()=>a(),disabled:n,style:o,size:c},t&&r.a.createElement(l.Spinner,{as:"span",animation:"border",size:"sm",role:"status","aria-hidden":"true",style:{marginRight:10}}),e)}function R(e){return{historyPrefix:e+"|history:|",answerPrefix:e+"|answerPrefix:|"}}async function I(e){try{const t={},n={},{historyPrefix:a,answerPrefix:r}=R(e);for(const[e,o]of Object.entries(localStorage))e.startsWith(a)?(t[e.slice(a.length)]=o,localStorage.removeItem(e)):e.startsWith(r)&&(n[e.slice(r.length)]=o);M("backup_all",{exam:e,history:t,snapshot:n,...i()})}catch(e){console.error(e)}}window.synchronize=I;const F=(e,t)=>{if("short_answer"!==e.type&&"short_code_answer"!==e.type)return null;const n=`^(${e.options})$`;try{if(e.options&&t&&"string"==typeof t){if(!t.match(n))return r.a.createElement(r.a.Fragment,null,"Input does not match regular expression ",r.a.createElement("code",null,n))}return null}catch(e){return r.a.createElement(r.a.Fragment,null,"Internal error: regular expression ",r.a.createElement("code",null,n)," is invalid")}};function L({question:e,number:t}){const n=Object(a.useContext)(T),o=n.savedAnswers[e.id]||e.template||"",[s,c]=Object(a.useState)(o),[u,m]=Object(a.useState)(o),[d,f]=Object(a.useState)(!1),[p,h]=Object(a.useState)(""),E=t=>{n.locked||(c(t),function(e,t,n){try{const{historyPrefix:a,answerPrefix:r}=R(e);localStorage.setItem(`${a}${t}|${Date.now()}`,n),localStorage.setItem(`${r}${t}`,n)}catch(e){console.error(e)}}(n.exam,e.id,t),t[0]&&t!==e.template&&!F(e,t)?n.recordSolved(e.id):n.recordUnsolved(e.id))};Object(a.useEffect)(()=>{E(o)},[]),Object(a.useEffect)(()=>{u===s?n.recordSaved(e.id):n.recordUnsaved(e.id)},[s!==u]);const v=Object(a.useRef)(null);let b;if(Object(a.useLayoutEffect)(()=>{if(null!==v.current){const{target:e,pos:t}=v.current;e.selectionStart=t,e.selectionEnd=t,v.current=null}},[v.current]),"multiple_choice"===e.type)b=r.a.createElement("div",{style:{marginBottom:10}},e.options.map(t=>r.a.createElement(l.Form.Check,{key:t.text,custom:!0,checked:s===t.text,name:e.id,type:"radio",label:r.a.createElement("span",{dangerouslySetInnerHTML:{__html:t.html}}),value:t.text,id:`${e.id}|${t.text}`,onChange:e=>{E(e.target.value)}})));else if("select_all"===e.type)b=r.a.createElement("div",{style:{marginBottom:10}},e.options.map(t=>r.a.createElement(l.Form.Check,{key:t.text,custom:!0,checked:s.includes(t.text),name:e.id,type:"checkbox",label:r.a.createElement("span",{dangerouslySetInnerHTML:{__html:t.html}}),value:t.text,id:`${e.id}|${t.text}`,onChange:e=>{E((Array.isArray(s)?s:[]).filter(t=>t!==e.target.value).concat(e.target.checked?[e.target.value]:[]))}})));else if("short_answer"===e.type||"short_code_answer"===e.type){const t=F(e,s);b=r.a.createElement(l.InputGroup,{className:"mb-3"},r.a.createElement(l.FormControl,{isInvalid:!!t,style:"short_code_answer"===e.type?{fontFamily:"monospace"}:null,value:s,onChange:e=>{E(e.target.value)}}),t&&r.a.createElement(l.Form.Control.Feedback,{type:"invalid"},t))}else if("long_answer"===e.type)b=r.a.createElement(l.InputGroup,{className:"mb-3"},r.a.createElement(l.FormControl,{as:"textarea",value:s,rows:e.options,onChange:e=>{E(e.target.value)}}));else if("long_code_answer"===e.type){const t=e=>{if(9===e.keyCode){e.preventDefault();const{target:t}=e,n=t.selectionStart,a=t.selectionEnd;E(`${s.substring(0,n)}\t${s.substring(a)}`),v.current={target:t,pos:t.selectionStart+1}}};b=r.a.createElement(l.InputGroup,{className:"mb-3"},r.a.createElement(l.FormControl,{as:"textarea",style:{fontFamily:'"Lucida Console", Monaco, monospace',tabSize:4},value:s,onKeyDown:t,rows:e.options,onChange:e=>{E(e.target.value)}}))}const g=async(t,a)=>{if(t!==a&&!d){f(!0);try{const a=await M("submit_question",{id:e.id,value:t,sentTime:(new Date).getTime(),exam:n.exam,...i()});if(f(!1),!a.ok)return h("Server failed to respond, please try again."),void n.onInternetError();try{(await a.json()).success?(m(t),h("")):(h("Server responded but failed to save, please refresh and try again."),n.onInternetError())}catch{m(null),h("Server returned invalid JSON. Please try again."),n.onInternetError()}}catch{m(null),f(!1),h("Unable to reach server, your network may have issues."),n.onInternetError()}}},y=()=>g(s,u),x=Object(a.useCallback)(function(e,t){let n;return(...a)=>{clearTimeout(n),n=setTimeout(()=>e(...a),t)}}(g,3e3),[]);Object(a.useEffect)(()=>(x(s,u),()=>x(s,u)),[s,u]);const w=n.starredQuestions.get(e.id),O=w?"orange":"black",S=w?r.a.createElement(r.a.Fragment,null,"★"):r.a.createElement(r.a.Fragment,null,"☆");return r.a.createElement(r.a.Fragment,null,r.a.createElement(l.Form,{onSubmit:e=>{e.preventDefault(),y()}},r.a.createElement(l.Form.Label,{style:{width:"100%"}},r.a.createElement(j,{name:t}),r.a.createElement("h5",{style:{marginTop:8,marginBottom:0}},"Q",t,r.a.createElement("a",{href:"#",onClick:t=>{t.preventDefault(),n.setStarred(e.id,!w)},className:"badge badge-light",style:{float:"right",fontSize:"100%",color:O}},S))," ",r.a.createElement(N,{points:e.points}),r.a.createElement("div",{style:{marginTop:8},dangerouslySetInnerHTML:{__html:e.html}})),b,r.a.createElement(P,{loading:d,disabled:d||s===u,onClick:y},s===u?"Saved":d?"Saving...":"Save"),r.a.createElement(_,{text:p})),r.a.createElement("br",null))}const D=r.a.createElement("span",{style:{color:"orange"}}," ★"),B=r.a.createElement("span",null," ✓");function A({groups:e}){const t=Object(a.useContext)(T);return r.a.createElement(l.Nav,{defaultActiveKey:"/home",className:"flex-column"},e.map((e,n)=>{const a=r.a.createElement(l.Nav.Link,{href:"#"+(n+1)},n+1,". ",e.name,H(e,t).completed&&B);return r.a.createElement("div",{key:n},a,function(e){const t=[],n=(e,a)=>{t.push({element:e,name:a}),e.elements&&e.elements.forEach((e,t)=>n(e,`${a}.${t+1}`))};return n(e,""),t}(e).filter(({element:{id:e},name:n})=>2===n.split(".").length||t.starredQuestions.get(e)).map(({element:e,name:t},a)=>r.a.createElement($,{key:a,question:e,name:`${n+1}${t}`})))}))}function $({question:e,name:t}){const n=Object(a.useContext)(T),{completed:o,starred:s}=H(e,n),c=r.a.createElement(l.Nav.Link,{style:{paddingLeft:20},href:"#"+t},"Q",t,s&&D,o&&!s&&B);return s?r.a.createElement("b",null,c):o?r.a.createElement(r.a.Fragment,null,c):c}function H(e,t){let n=!0;const a=t.starredQuestions.get(e.id),r=e=>{if(e.id&&(!t.solvedQuestions.get(e.id)||t.unsavedQuestions.has(e.id)||t.starredQuestions.get(e.id)))n=!1;else if(e.elements)for(const t of e.elements)r(t)};return r(e),{completed:n,starred:a}}function Q(e,t){const n=Object(a.useRef)();Object(a.useEffect)(()=>{n.current=e},[e]),Object(a.useEffect)(()=>{const e=setInterval((function(){n.current()}),t);return()=>clearInterval(e)},[t])}function q({groups:e,publicGroup:t,watermark:n,ended:o}){const{exam:s}=Object(a.useContext)(T),c=Object(a.useRef)();var d,f,p;Object(a.useEffect)(()=>function(e){for(const t of e.getElementsByTagName("a"))t.getAttribute("href")&&t.hostname!==window.location.hostname&&(t.target="_blank");for(const t of e.getElementsByTagName("table"))t.classList.add("table","table-bordered");for(const t of e.getElementsByTagName("blockquote"))t.classList.add("blockquote");Object(k.typeset)([e])}(c.current),[c.current,e,t]),d=c,f=()=>{n&&(M("/log_event",{exam:s,event:"style_edited",...i()}),alert("You must not edit the DOM during the exam. This is considered academic dishonesty. This event has been logged. We will follow up with you after the exam regarding this event."))},p=[n],Object(a.useEffect)(()=>{if(!d.current)return()=>null;const e=new MutationObserver(f);return e.observe(d.current,{attributes:!0,attributeFilter:["style"]}),()=>e.disconnect()},[d.current,...p]);Q(()=>{s&&!u().loginas&&I(s)},3e4);const h=!o||m();return r.a.createElement("div",{className:"exam",ref:c,style:n?{backgroundImage:`url("/watermark.svg?seed=${n.value}&brightness=${n.brightness}")`,backgroundRepeat:"repeat-xy",textShadow:"0px 0px 2px white"}:{}},r.a.createElement(l.Row,null,r.a.createElement(l.Col,{md:9,sm:12},h&&t&&r.a.createElement(U,{group:t,number:0}),h&&e&&e.map((e,t)=>r.a.createElement(U,{key:t,group:e,number:t+1})),e&&r.a.createElement(l.Jumbotron,null,r.a.createElement("h1",null,"🎉Congratulations!🎉"),r.a.createElement("p",null,"You have reached the end of the exam! Your answers will all be automatically saved."))),h&&e&&!!e.length&&r.a.createElement(l.Col,{md:3,className:"d-none d-md-block",style:{position:"sticky",top:"5em",height:"85vh",overflowY:"auto"}},r.a.createElement(A,{groups:e}))))}function U({group:e,number:t,small:n}){const a=e=>n?r.a.createElement("h4",e):r.a.createElement("h3",e);return r.a.createElement(r.a.Fragment,null,r.a.createElement("br",null),r.a.createElement("div",null,r.a.createElement(j,{name:t}),r.a.createElement(a,{style:{marginBottom:0}},r.a.createElement("b",null,"Q",t)," ",e.name),r.a.createElement(N,{points:e.points}),r.a.createElement("div",{dangerouslySetInnerHTML:{__html:e.html}}),e.elements.map((e,n)=>"group"===e.type?r.a.createElement(U,{key:n,group:e,number:`${t}.${n+1}`,small:!0}):r.a.createElement(L,{key:n,question:e,number:`${t}.${n+1}`}))),!n&&r.a.createElement("hr",null))}function G(e){var t,n,r=(t=e,(n=Object(a.useRef)(t)).current=t,n);Object(a.useEffect)((function(){return function(){return r.current()}}),[])}var z=Math.pow(2,31)-1;function Y(){var e=function(){var e=Object(a.useRef)(!0),t=Object(a.useRef)((function(){return e.current}));return Object(a.useEffect)((function(){return function(){e.current=!1}}),[]),t.current}(),t=Object(a.useRef)();return G((function(){return clearTimeout(t.current)})),Object(a.useMemo)((function(){var n=function(){return clearTimeout(t.current)};return{set:function(a,r){void 0===r&&(r=0),e()&&(n(),r<=z?t.current=setTimeout(a,r):function e(t,n,a){var r=a-Date.now();t.current=r<=z?setTimeout(n,r):setTimeout((function(){return e(t,n,a)}),z)}(t,a,Date.now()+r))},clear:n}}),[])}function J(e){var t=function(e){return e&&e.ownerDocument||document}(e);return t&&t.defaultView||window}var W=/([A-Z])/g;var K=/^ms-/;function V(e){return function(e){return e.replace(W,"-$1").toLowerCase()}(e).replace(K,"-ms-")}var X=/^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i;var Z=function(e,t){var n="",a="";if("string"==typeof t)return e.style.getPropertyValue(V(t))||function(e,t){return J(e).getComputedStyle(e,t)}(e).getPropertyValue(V(t));Object.keys(t).forEach((function(r){var o=t[r];o||0===o?!function(e){return!(!e||!X.test(e))}(r)?n+=V(r)+": "+o+";":a+=r+"("+o+") ":e.style.removeProperty(V(r))})),a&&(n+="transform: "+a+";"),e.style.cssText+=";"+n},ee=!("undefined"==typeof window||!window.document||!window.document.createElement),te=!1,ne=!1;try{var ae={get passive(){return te=!0},get once(){return ne=te=!0}};ee&&(window.addEventListener("test",ae,ae),window.removeEventListener("test",ae,!0))}catch(e){}var re=function(e,t,n,a){if(a&&"boolean"!=typeof a&&!ne){var r=a.once,o=a.capture,s=n;!ne&&r&&(s=n.__once||function e(a){this.removeEventListener(t,e,o),n.call(this,a)},n.__once=s),e.addEventListener(t,s,te?a:o)}e.addEventListener(t,n,a)};var oe=function(e,t,n,a){var r=a&&"boolean"!=typeof a?a.capture:a;e.removeEventListener(t,n,r),n.__once&&e.removeEventListener(t,n.__once,r)};var se=function(e,t,n,a){return re(e,t,n,a),function(){oe(e,t,n,a)}};function le(e,t,n){void 0===n&&(n=5);var a=!1,r=setTimeout((function(){a||function(e){var t=document.createEvent("HTMLEvents");t.initEvent("transitionend",!0,!0),e.dispatchEvent(t)}(e)}),t+n),o=se(e,"transitionend",(function(){a=!0}),{once:!0});return function(){clearTimeout(r),o()}}function ce(e,t,n,a){var r,o;null==n&&(r=Z(e,"transitionDuration")||"",o=-1===r.indexOf("ms")?1e3:1,n=parseFloat(r)*o||0);var s=le(e,n,a),l=se(e,"transitionend",t);return function(){s(),l()}}var ie=n(5),ue=n.n(ie),me=!1,de=r.a.createContext(null),fe=function(e){var t,n;function a(t,n){var a;a=e.call(this,t,n)||this;var r,o=n&&!n.isMounting?t.enter:t.appear;return a.appearStatus=null,t.in?o?(r="exited",a.appearStatus="entering"):r="entered":r=t.unmountOnExit||t.mountOnEnter?"unmounted":"exited",a.state={status:r},a.nextCallback=null,a}n=e,(t=a).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n,a.getDerivedStateFromProps=function(e,t){return e.in&&"unmounted"===t.status?{status:"exited"}:null};var o=a.prototype;return o.componentDidMount=function(){this.updateStatus(!0,this.appearStatus)},o.componentDidUpdate=function(e){var t=null;if(e!==this.props){var n=this.state.status;this.props.in?"entering"!==n&&"entered"!==n&&(t="entering"):"entering"!==n&&"entered"!==n||(t="exiting")}this.updateStatus(!1,t)},o.componentWillUnmount=function(){this.cancelNextCallback()},o.getTimeouts=function(){var e,t,n,a=this.props.timeout;return e=t=n=a,null!=a&&"number"!=typeof a&&(e=a.exit,t=a.enter,n=void 0!==a.appear?a.appear:t),{exit:e,enter:t,appear:n}},o.updateStatus=function(e,t){void 0===e&&(e=!1),null!==t?(this.cancelNextCallback(),"entering"===t?this.performEnter(e):this.performExit()):this.props.unmountOnExit&&"exited"===this.state.status&&this.setState({status:"unmounted"})},o.performEnter=function(e){var t=this,n=this.props.enter,a=this.context?this.context.isMounting:e,r=this.props.nodeRef?[a]:[s.a.findDOMNode(this),a],o=r[0],l=r[1],c=this.getTimeouts(),i=a?c.appear:c.enter;!e&&!n||me?this.safeSetState({status:"entered"},(function(){t.props.onEntered(o)})):(this.props.onEnter(o,l),this.safeSetState({status:"entering"},(function(){t.props.onEntering(o,l),t.onTransitionEnd(i,(function(){t.safeSetState({status:"entered"},(function(){t.props.onEntered(o,l)}))}))})))},o.performExit=function(){var e=this,t=this.props.exit,n=this.getTimeouts(),a=this.props.nodeRef?void 0:s.a.findDOMNode(this);t&&!me?(this.props.onExit(a),this.safeSetState({status:"exiting"},(function(){e.props.onExiting(a),e.onTransitionEnd(n.exit,(function(){e.safeSetState({status:"exited"},(function(){e.props.onExited(a)}))}))}))):this.safeSetState({status:"exited"},(function(){e.props.onExited(a)}))},o.cancelNextCallback=function(){null!==this.nextCallback&&(this.nextCallback.cancel(),this.nextCallback=null)},o.safeSetState=function(e,t){t=this.setNextCallback(t),this.setState(e,t)},o.setNextCallback=function(e){var t=this,n=!0;return this.nextCallback=function(a){n&&(n=!1,t.nextCallback=null,e(a))},this.nextCallback.cancel=function(){n=!1},this.nextCallback},o.onTransitionEnd=function(e,t){this.setNextCallback(t);var n=this.props.nodeRef?this.props.nodeRef.current:s.a.findDOMNode(this),a=null==e&&!this.props.addEndListener;if(n&&!a){if(this.props.addEndListener){var r=this.props.nodeRef?[this.nextCallback]:[n,this.nextCallback],o=r[0],l=r[1];this.props.addEndListener(o,l)}null!=e&&setTimeout(this.nextCallback,e)}else setTimeout(this.nextCallback,0)},o.render=function(){var e=this.state.status;if("unmounted"===e)return null;var t=this.props,n=t.children,a=(t.in,t.mountOnEnter,t.unmountOnExit,t.appear,t.enter,t.exit,t.timeout,t.addEndListener,t.onEnter,t.onEntering,t.onEntered,t.onExit,t.onExiting,t.onExited,t.nodeRef,f(t,["children","in","mountOnEnter","unmountOnExit","appear","enter","exit","timeout","addEndListener","onEnter","onEntering","onEntered","onExit","onExiting","onExited","nodeRef"]));return r.a.createElement(de.Provider,{value:null},"function"==typeof n?n(e,a):r.a.cloneElement(r.a.Children.only(n),a))},a}(r.a.Component);function pe(){}fe.contextType=de,fe.propTypes={},fe.defaultProps={in:!1,mountOnEnter:!1,unmountOnExit:!1,appear:!1,enter:!0,exit:!0,onEnter:pe,onEntering:pe,onEntered:pe,onExit:pe,onExiting:pe,onExited:pe},fe.UNMOUNTED="unmounted",fe.EXITED="exited",fe.ENTERING="entering",fe.ENTERED="entered",fe.EXITING="exiting";var he,Ee=fe;var ve=((he={}).entering="show",he.entered="show",he),be=r.a.forwardRef((function(e,t){var n=e.className,o=e.children,s=f(e,["className","children"]),l=Object(a.useCallback)((function(e){!function(e){e.offsetHeight}(e),s.onEnter&&s.onEnter(e)}),[s]);return r.a.createElement(Ee,d({ref:t,addEndListener:ce},s,{onEnter:l}),(function(e,t){return r.a.cloneElement(o,d({},t,{className:h()("fade",n,o.props.className,ve[e])}))}))}));be.defaultProps={in:!1,timeout:300,mountOnEnter:!1,unmountOnExit:!1,appear:!1},be.displayName="Fade";var ge=be;var ye=function(e){var t=Object(a.useRef)(e);return Object(a.useEffect)((function(){t.current=e}),[e]),t};var xe={label:ue.a.string.isRequired,onClick:ue.a.func},we=r.a.forwardRef((function(e,t){var n=e.label,a=e.onClick,o=e.className,s=f(e,["label","onClick","className"]);return r.a.createElement("button",d({ref:t,type:"button",className:h()("close",o),onClick:a},s),r.a.createElement("span",{"aria-hidden":"true"},"×"),r.a.createElement("span",{className:"sr-only"},n))}));we.displayName="CloseButton",we.propTypes=xe,we.defaultProps={label:"Close"};var Oe=we,Se=r.a.createContext({onClose:function(){}}),Ce=r.a.forwardRef((function(e,t){var n=e.bsPrefix,o=e.closeLabel,s=e.closeButton,l=e.className,c=e.children,i=f(e,["bsPrefix","closeLabel","closeButton","className","children"]);n=v(n,"toast-header");var u=Object(a.useContext)(Se),m=function(e){var t=ye(e);return Object(a.useCallback)((function(){return t.current&&t.current.apply(t,arguments)}),[t])}((function(e){u&&u.onClose&&u.onClose(e)}));return r.a.createElement("div",d({ref:t},i,{className:h()(n,l)}),c,s&&r.a.createElement(Oe,{label:o,onClick:m,className:"ml-2 mb-1","data-dismiss":"toast"}))}));Ce.displayName="ToastHeader",Ce.defaultProps={closeLabel:"Close",closeButton:!0};var ke=Ce,je=/-(.)/g;var Te=function(e){return e[0].toUpperCase()+(t=e,t.replace(je,(function(e,t){return t.toUpperCase()}))).slice(1);var t};var Ne,Me,_e,Pe,Re,Ie,Fe,Le,De=(Ne="toast-body",Pe=(_e=void 0===Me?{}:Me).displayName,Re=void 0===Pe?Te(Ne):Pe,Ie=_e.Component,Fe=_e.defaultProps,(Le=r.a.forwardRef((function(e,t){var n=e.className,a=e.bsPrefix,o=e.as,s=void 0===o?Ie||"div":o,l=f(e,["className","bsPrefix","as"]),c=v(a,Ne);return r.a.createElement(s,d({ref:t,className:h()(n,c)},l))}))).defaultProps=Fe,Le.displayName=Re,Le),Be=r.a.forwardRef((function(e,t){var n=e.bsPrefix,o=e.className,s=e.children,l=e.transition,c=void 0===l?ge:l,i=e.show,u=void 0===i||i,m=e.animation,p=void 0===m||m,E=e.delay,b=void 0===E?3e3:E,g=e.autohide,y=void 0!==g&&g,x=e.onClose,w=f(e,["bsPrefix","className","children","transition","show","animation","delay","autohide","onClose"]);n=v(n,"toast");var O=Object(a.useRef)(b),S=Object(a.useRef)(x);Object(a.useEffect)((function(){O.current=b,S.current=x}),[b,x]);var C=Y(),k=!(!y||!u),j=Object(a.useCallback)((function(){k&&(null==S.current||S.current())}),[k]);Object(a.useEffect)((function(){C.set(j,O.current)}),[C,j]);var T=Object(a.useMemo)((function(){return{onClose:x}}),[x]),N=!(!c||!p),M=r.a.createElement("div",d({},w,{ref:t,className:h()(n,o,!N&&(u?"show":"hide")),role:"alert","aria-live":"assertive","aria-atomic":"true"}),s);return r.a.createElement(Se.Provider,{value:T},N&&c?r.a.createElement(c,{in:u,unmountOnExit:!0},M):M)}));Be.displayName="Toast";var Ae=Object.assign(Be,{Body:De,Header:ke});const $e=Object(a.createContext)({time:0,examData:{questions:[]},stale:!1});var He=$e;function Qe(){return Object(a.useContext)($e).time}function qe(){return Object(a.useContext)($e).examData}function Ue({send:e}){const t=qe(),[n,o]=Object(a.useState)(""),[s,c]=Object(a.useState)("Overall Exam"),[i,u]=Object(a.useState)(!1),[m,d]=Object(a.useState)("");return r.a.createElement(l.Row,null,r.a.createElement(l.Col,null,r.a.createElement(l.Card,null,r.a.createElement(l.Card.Header,null,"Request Clarification"),r.a.createElement(l.Card.Body,null,r.a.createElement(l.Form,null,r.a.createElement(l.Form.Group,null,r.a.createElement(l.Form.Control,{as:"textarea",rows:3,value:n,placeholder:"Send a private message to staff.",onChange:e=>o(e.target.value)})),r.a.createElement(l.Form.Group,null,r.a.createElement(l.Form.Control,{as:"select",value:s,onChange:e=>c(e.target.value),custom:!0},r.a.createElement("option",{value:null},"Overall Exam"),t.questions.map(e=>r.a.createElement("option",{key:e},e)))),r.a.createElement(l.Form.Group,null,r.a.createElement(P,{loading:i,disabled:i,onClick:async()=>{u(!0);const t=await e("ask_question",{question:"Overall Exam"===s?null:s,message:n});t?d(t):o(""),u(!1)}},"Send"),r.a.createElement(_,{text:m,suffixType:"alerts"}))))),r.a.createElement("br",null)))}function Ge(e){return Math.floor(e/60)+" minutes ago"}function ze(){const e=Qe(),t=qe();return 0===t.messages.length?null:r.a.createElement(l.Row,null,r.a.createElement(l.Col,null,t.messages.map(({id:t,message:n,question:a,timestamp:o,responses:s})=>r.a.createElement("div",{key:t},r.a.createElement(l.Card,null,r.a.createElement(l.Card.Header,null,r.a.createElement("b",null,0===s.length?"Unresolved Thread":"Resolved Thread")," ","[",a,"]"),r.a.createElement(l.ListGroup,{variant:"flush"},r.a.createElement(l.ListGroup.Item,{key:t,style:{whiteSpace:"pre-wrap"}},r.a.createElement("b",null,"You: "),n," (",Ge(e-o),")"),s.map(({id:t,message:n,timestamp:a})=>r.a.createElement(l.ListGroup.Item,{key:t,style:{whiteSpace:"pre-wrap"}},r.a.createElement("b",null,"Staff: "),n," (",Ge(e-a),")")))),r.a.createElement("br",null)))))}function Ye({exam:e,setDeadline:t}){const[n,o]=Object(a.useState)(!1),[s,c]=Object(a.useState)(!0),[u,m]=Object(a.useState)(!1),d=Object(a.useRef)(),[f,p,h,E]=function(e,t,n,r){const[o,s]=Object(a.useState)(null),[l,c]=Object(a.useState)(!1),[u,m]=Object(a.useState)([]),[d,f]=Object(a.useState)(!1);Object(a.useEffect)(()=>{if(u.length>0&&!d){const e=u[0],t=new Audio("data:audio/mp3;base64,"+e);f(!0),t.play(),t.addEventListener("ended",()=>{m(e=>e.slice(1)),f(!1)})}},[u,d]);const p=e=>{c(!1);const a={};for(const[t,n]of Object.entries(e))if("messages"===t){const t=new Map;for(const e of o.messages)t.set(e.id,e);const n=[];for(const a of e.messages)if(t.has(a.id)){const e=t.get(a.id),n=e.responses.map(({id:e})=>e);t.set(a.id,{...a,responses:e.responses.concat(a.responses.filter(({id:e})=>!n.includes(e)))})}else n.push(a);for(const e of o.messages)n.push(t.get(e.id));a.messages=n}else if("announcements"===t){const t=new Map;for(const e of o.announcements)e.private&&t.set(e.id,e);for(const n of e.announcements)t.set(n.id,n);a.announcements=Array.from(t.values()).sort(({timestamp:e},{timestamp:t})=>t-e)}else a[t]=n;if(s(a),!t){const t=[];for(const{audio:n}of e.announcements)n&&(t.push(n),r&&r());t.reverse(),m(e=>e.concat(t))}n&&n(e.endTime-Math.round(e.timestamp)+Math.round((new Date).getTime()/1e3)-2)};return Q(async()=>{if(o)try{const n=await M(t?"alerts/fetch_staff_data":"alerts/fetch_data",{...i(),exam:e,receivedAudio:o?o.announcements.map(e=>e.id):null,latestTimestamp:o.latestTimestamp});if(n.ok){const e=await n.json();e.success&&p(e)}}catch(e){console.error(e),c(!0)}},1e4),[o,l,async()=>{try{const n=await M(t?"alerts/fetch_staff_data":"alerts/fetch_data",{...i(),exam:e,latestTimestamp:0});if(!n.ok)return`The exam server failed with error ${n.status}. Please try again.`;try{const e=await n.json();if(!e.success)return"The exam server responded but did not produce valid data. Please try again.";s(e)}catch{return"The web server returned invalid JSON. Please try again."}}catch{return"Unable to reach server, your network may have issues."}return null},async(t,n)=>{try{const a=await M("alerts/"+t,{...i(),exam:e,latestTimestamp:o.latestTimestamp,...n}),r=await a.json();if(!r.success)throw Error();p(r)}catch(e){return console.error(e),"Something went wrong. Please try again, or reload the page."}return null}]}(e,!1,t,()=>{c(!0),d.current.scrollTop=d.current.scrollHeight}),v=function(){const[e,t]=Object(a.useState)(Math.round((new Date).getTime()/1e3));return Q(()=>t(Math.round((new Date).getTime()/1e3))),e}();return Object(a.useEffect)(()=>{h().then(e=>!e||o(!0))},[]),r.a.createElement(He.Provider,{value:{time:v,examData:f,stale:p}},r.a.createElement("div",{ref:d,style:{position:"fixed",overflow:"auto",bottom:80,right:32,width:350,maxHeight:"80%"}},s&&f&&f.announcements.slice().reverse().map(({id:e,message:t,question:n,timestamp:a,private:o})=>r.a.createElement(Ae,{key:e},r.a.createElement(Ae.Header,{closeButton:!1},r.a.createElement("strong",{className:"mr-auto"},o?"Staff Reply":r.a.createElement(r.a.Fragment,null,"Announcement for ",n)),r.a.createElement("small",null,Ge(v-a))),r.a.createElement(Ae.Body,null,r.a.createElement("div",{style:{whiteSpace:"pre-wrap"}},t))))),r.a.createElement("div",{style:{position:"fixed",bottom:32,right:32,width:350,background:"white"}},r.a.createElement(O,{block:!0,onClick:()=>c(e=>!e),variant:"outline-secondary"},s?"Hide Announcements":"Show Announcements",p?" (Offline)":"",f?"":" (Loading...)")),f&&f.enableClarifications&&r.a.createElement("div",{style:{position:"fixed",bottom:32,left:32,width:200,background:"white"}},r.a.createElement(O,{block:!0,onClick:()=>m(!0),variant:"outline-secondary"},"Clarifications")),n&&r.a.createElement(l.Modal,{show:!0},r.a.createElement(l.Modal.Header,{closeButton:!0},r.a.createElement(l.Modal.Title,null,"Network Connection Lost!")),r.a.createElement(l.Modal.Body,null,"The tool was unable to fetch announcements from the server. Please refresh and try again. If this error persists, contact your course staff.")),f&&f.enableClarifications&&r.a.createElement(l.Modal,{show:u,onHide:()=>m(!1),size:"lg"},r.a.createElement(l.Modal.Header,null,"Ask a question"),r.a.createElement(l.Modal.Body,null,r.a.createElement(Ue,{exam:e,send:E}),r.a.createElement(ze,null))))}function Je({onHide:e}){return r.a.createElement(l.Modal,{show:!0},r.a.createElement(l.Modal.Header,{closeButton:!0},r.a.createElement(l.Modal.Title,null,"Network Connection Lost!")),r.a.createElement(l.Modal.Body,null,"The tool was unable to save due to a network error. Please try saving again. If this error persists, refresh the page and try again, or submit your answers by email. Note that if the exam has ended, you should not refresh, but instead just send us your answers by email directly."),r.a.createElement(l.Modal.Footer,null,r.a.createElement(O,{variant:"danger",onClick:e},"I know connection is lost. I am still going back to the exam")))}function We({unsavedQuestions:e,solvedQuestions:t}){if(0===t.size)return null;const n=+Array.from(t.values()).reduce((e,t)=>e+t),a=t.size,o={cursor:"inherit",opacity:1};return r.a.createElement(r.a.Fragment,null,e.size?r.a.createElement("div",{className:"ml-auto btn btn-danger disabled",style:o},e.size," unsaved question",1!==e.size&&"s"):r.a.createElement("div",{className:"ml-auto btn btn-outline-light disabled",style:o},n," / ",a," questions solved"))}var Ke=n(6);function Ve({encryptedExam:e,onDecrypt:t}){const[n,o]=Object(a.useState)(""),[s,c]=Object(a.useState)("");return r.a.createElement(r.a.Fragment,null,r.a.createElement(l.InputGroup,{className:"mb-3"},r.a.createElement(l.FormControl,{value:n,onChange:e=>o(e.target.value)})),r.a.createElement(l.Button,{variant:"primary",type:"submit",onClick:()=>{try{const a=new Ke.Secret(n.trim()),r=new Ke.Token({secret:a,token:e,ttl:0});t(JSON.parse(r.decode()))}catch(e){console.error(e),c("Wrong password! (or other decryption error)")}}},"Decrypt"),r.a.createElement(_,{text:s}))}function Xe({exam:e,onReceive:t}){const[n,o]=Object(a.useState)(!1),[s,l]=Object(a.useState)("");return r.a.createElement(r.a.Fragment,null,r.a.createElement(P,{onClick:async()=>{o(!0),l("");try{const n=await M("get_exam",{...i(),exam:e});n.ok||l(`\n The exam server failed with error ${n.status}. Please try again. \n `);try{const e=await n.json();e.success?t(e):l("\n The exam server responded but did not produce a valid exam. Please try again. \n ")}catch{l("The web server returned invalid JSON. Please try again.")}}catch{l("Unable to reach server, your network may have issues.")}o(!1)},disabled:n,loading:n},"Generate Exam"),r.a.createElement(_,{text:s}))}function Ze({onSuccess:e}){const[t,n]=Object(a.useState)("localhost"===window.location.hostname?"exam-test@berkeley.edu":""),o=e=>{e.preventDefault(),n(""),c.auth2.getAuthInstance().signOut(),window.location.reload()};return Object(a.useEffect)(()=>{t?e(t):Object(c.load)("auth2",()=>{c.signin2.render("signInButton",{width:200,longtitle:!0,onsuccess:t=>{n(t.getBasicProfile().getEmail()),e(t.getBasicProfile().getEmail())}})})},[]),t?r.a.createElement(r.a.Fragment,null,"You have signed in as ",r.a.createElement("b",null,u().loginas||t),"."," ",r.a.createElement("a",{href:"#",onClick:o},"Log out")," ","if this is not the right account."):r.a.createElement(r.a.Fragment,null,"First, sign into Google using your CalNet account.",r.a.createElement("div",{id:"signInButton",className:"g-signin2","data-onsuccess":"onSignIn","data-theme":"dark"}))}function et({target:e,onLock:t,onEnd:n}){const[o,s]=Object(a.useState)(!1),[c,i]=Object(a.useState)(!1),[u,m]=Object(a.useState)(""),d=()=>{const a=Math.round((new Date).getTime()/1e3),r=Math.max(e-a,0),o=Math.floor(r/3600),s=Math.floor(r%3600/60),l=r%60;m(`${o.toString().padStart(2,"0")}:${s.toString().padStart(2,"0")}:${l.toString().padStart(2,"0")}`),e-a<0&&e-a>=-60&&(t(),m(60+e-a+"s")),e-a<-60&&n()};return Q(d,1e3),u||d(),r.a.createElement(l.Button,{style:{minWidth:80},onClick:()=>s(!o),variant:"outline-light",className:"ml-auto",onMouseEnter:()=>i(!0),onMouseLeave:()=>i(!1)},o?c?"Click to hide timer":u:"Click to show timer")}function tt(){const[e,t]=Object(a.useState)(""),[n,o]=Object(a.useState)([]),s=decodeURIComponent(window.location.pathname).replace("/","").trim(),[c,u]=Object(a.useState)(s),[d,f]=Object(a.useState)(null),[p,h]=Object(a.useState)(null),[E,v]=Object(a.useState)(null),[b,g]=Object(a.useState)(null),[y,x]=Object(a.useState)(null),[w,O]=Object(a.useState)(null),[k,j]=Object(a.useState)(!1),[N,_]=Object(a.useState)(!1),[P,R]=Object(a.useState)(!1),[I,F]=Object(a.useState)(new Set),[L,D]=Object(a.useState)(new Map),[B,A]=Object(a.useState)(new Map);Object(a.useEffect)(()=>{try{A(new Map(JSON.parse(localStorage.getItem("starredQs"))))}catch{}},[]),Object(a.useEffect)(()=>{e&&(async()=>{o(await(await M("list_exams",i())).json())})()},[e]);return r.a.createElement(r.a.Fragment,null,r.a.createElement(l.Navbar,{bg:m()?"danger":"dark",variant:"dark",sticky:"top"},r.a.createElement(l.Navbar.Brand,{href:"#"},"CS 61A Exam Runner"),r.a.createElement(We,{unsavedQuestions:I,solvedQuestions:L}),y&&r.a.createElement(et,{target:y,onLock:()=>j(!0),onEnd:()=>_(!0)})),r.a.createElement(l.Container,null,r.a.createElement("br",null),r.a.createElement(l.Row,null,r.a.createElement(l.Col,null,r.a.createElement("h1",null,"Exam"))),r.a.createElement(l.Row,null,r.a.createElement(l.Col,null,r.a.createElement(Ze,{onSuccess:t}))),r.a.createElement("br",null),e&&!p&&!s&&r.a.createElement(r.a.Fragment,null,r.a.createElement(l.Row,null,r.a.createElement(l.Col,null,r.a.createElement(l.Form,null,r.a.createElement(l.Form.Group,{controlId:"exampleForm.SelectCustom"},r.a.createElement(l.Form.Label,null,"Now, choose your exam:"),r.a.createElement(l.Form.Control,{as:"select",value:c,onChange:e=>{u(e.target.value),h(null)},custom:!0},r.a.createElement("option",{hidden:!0,disabled:!0,selected:!0,value:""},"Select an exam"),n.map(e=>r.a.createElement("option",null,e)))))))),e&&c&&!p&&r.a.createElement(l.Row,null,r.a.createElement(l.Col,null,r.a.createElement("p",null,"You have selected the exam ",r.a.createElement("b",null,c),"."," ",!s&&r.a.createElement(r.a.Fragment,null," ","If this does not look correct, please re-select your exam.")),r.a.createElement("p",null,"Click the button to generate your exam. You can do this before the exam starts."),r.a.createElement(Xe,{exam:c,onReceive:({exam:e,publicGroup:t,privateGroups:n,watermark:a,answers:r,deadline:o,timestamp:s})=>{g(r),u(e),f(t),h(n),v(a),x(o-Math.round(s)+Math.round((new Date).getTime()/1e3)-2)}}))),p&&!w&&r.a.createElement(r.a.Fragment,null,r.a.createElement("br",null),r.a.createElement(l.Row,null,r.a.createElement(l.Col,null,r.a.createElement("p",null,"The ",r.a.createElement("b",null,c)," exam has successfully been downloaded! Enter the password distributed by course staff to decrypt it and start the exam."),r.a.createElement(Ve,{encryptedExam:p,onDecrypt:O})))),r.a.createElement("br",null),r.a.createElement(T.Provider,{value:{exam:c,savedAnswers:b,locked:k,onInternetError:()=>R(!0),recordUnsaved:e=>{I.add(e),F(new Set(I))},recordSaved:e=>{I.delete(e),F(new Set(I))},recordSolved:e=>{L.get(e)||(L.set(e,!0),D(new Map(L)))},recordUnsolved:e=>{L.has(e)&&!L.get(e)||(L.set(e,!1),D(new Map(L)))},unsavedQuestions:I,solvedQuestions:L,setStarred:(e,t)=>{B.set(e,t),A(new Map(B));try{localStorage.setItem("starredQs",JSON.stringify(Array.from(B.entries())))}catch{}},starredQuestions:B}},r.a.createElement(q,{publicGroup:d,groups:w,watermark:E,ended:N}),r.a.createElement(C,null,p&&r.a.createElement(Ye,{exam:c,setDeadline:x}))),k&&r.a.createElement(S,null),P&&r.a.createElement(Je,{onHide:()=>R(!1)})))}Object(o.render)(r.a.createElement(tt,null),document.querySelector("#root"))}]);