From f1a6aa08ba827a8720a7f62d0f9b434ae24c8f06 Mon Sep 17 00:00:00 2001 From: zilvinas Date: Wed, 16 Oct 2024 02:13:37 +0300 Subject: [PATCH] .. --- dist/assets/index-Cp6D6t7L.js | 13 ---- dist/assets/index-RO_tAo3e.js | 12 ++++ dist/index.html | 61 ++++++++----------- index.html | 61 ++++++++----------- index.html.old | 40 ++++++++++++ src/game-15-reconstruction/ConsoleUtils.ts | 20 ------ src/game-15-reconstruction/EpisodeRunner.ts | 18 +++--- src/game-15-reconstruction/G15EntryPoint.ts | 23 +++++++ src/game-15-reconstruction/GameUtils.ts | 2 +- src/game-15-reconstruction/Main.ts | 12 ---- src/game-15-reconstruction/QTableGenerator.ts | 20 +++--- src/game-15-reconstruction/QTableRow.ts | 5 +- src/game-15-reconstruction/Trainer.ts | 20 +++--- .../utils/ConsoleUtils.ts | 51 ++++++++++++++++ src/game-15-reconstruction/utils/Utils.ts | 43 +++++++------ src/main.ts | 20 ++++-- 16 files changed, 252 insertions(+), 169 deletions(-) delete mode 100644 dist/assets/index-Cp6D6t7L.js create mode 100644 dist/assets/index-RO_tAo3e.js create mode 100644 index.html.old delete mode 100644 src/game-15-reconstruction/ConsoleUtils.ts create mode 100644 src/game-15-reconstruction/G15EntryPoint.ts delete mode 100644 src/game-15-reconstruction/Main.ts create mode 100644 src/game-15-reconstruction/utils/ConsoleUtils.ts diff --git a/dist/assets/index-Cp6D6t7L.js b/dist/assets/index-Cp6D6t7L.js deleted file mode 100644 index bf8a885..0000000 --- a/dist/assets/index-Cp6D6t7L.js +++ /dev/null @@ -1,13 +0,0 @@ -var P=Object.defineProperty;var X=(d,t,e)=>t in d?P(d,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):d[t]=e;var c=(d,t,e)=>X(d,typeof t!="symbol"?t+"":t,e);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))s(n);new MutationObserver(n=>{for(const i of n)if(i.type==="childList")for(const l of i.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&s(l)}).observe(document,{childList:!0,subtree:!0});function e(n){const i={};return n.integrity&&(i.integrity=n.integrity),n.referrerPolicy&&(i.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?i.credentials="include":n.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function s(n){if(n.ep)return;n.ep=!0;const i=e(n);fetch(n.href,i)}})();const H=class H{static prnt(t){console.log(t)}static str(t,e){const s=t.toString();if(s.length>=e)return s;const n=e-s.length;return s+H.emptyString.substring(0,n)}static sum(t){return!t||(t=t.filter(e=>e!==0),t.length===0)?0:t.reduce((e,s)=>e+s,0)}static toString(t){return`[${Array.from(t).map(String).join(", ")}]`}static px(){return(t,e)=>t}static equalArrays(t,e){if(t.length!==e.length)return!1;for(let s=0;sMath.random()-.5)}};c(H,"emptyString"," ");let u=H;class G{static save(t,e){u.prnt(t),u.prnt(e)}}var r=(d=>(d.L="L",d.R="R",d.U="U",d.D="D",d))(r||{});class k{constructor(t,e){this.key=t,this.value=e}getKey(){return this.key}getValue(){return this.value}static P(t,e){return new k(t,e)}}class b{static blue(t){return`\x1B[34m${t}\x1B[0m`}static green(t){return`\x1B[32m${t}\x1B[0m`}static color(t,e){return`\x1B[${e}m${t}\x1B[0m`}static clearScreen(){console.log("clearScrn ... ")}}class p{static makeMove(t,e){const n=t.indexOf(-1),i=this.getXY(n);let l=i.getKey(),o=i.getValue();e===r.L&&(l-=1),e===r.R&&(l+=1),e===r.U&&(o-=1),e===r.D&&(o+=1);const h=this.getIndex(l,o),g=[...t],f=g[h];return g[n]=f,g[h]=-1,g}static getXY(t){const e=t%4,s=Math.floor(t/4);return k.P(e,s)}static getIndex(t,e){return e*4+t}static _getValidMoves(t){const e=this.getXY(t),s=Object.values(r).slice();return e.getKey()===0&&s.splice(s.indexOf(r.L),1),e.getKey()===3&&s.splice(s.indexOf(r.R),1),e.getValue()===0&&s.splice(s.indexOf(r.U),1),e.getValue()===3&&s.splice(s.indexOf(r.D),1),s}static getValidMoves(t,e){const s=this._getValidMoves(t),n=this.getXY(t);return this.contains(e,n.getKey()-1,n.getValue())&&s.splice(s.indexOf(r.L),1),this.contains(e,n.getKey()+1,n.getValue())&&s.splice(s.indexOf(r.R),1),this.contains(e,n.getKey(),n.getValue()-1)&&s.splice(s.indexOf(r.U),1),this.contains(e,n.getKey(),n.getValue()+1)&&s.splice(s.indexOf(r.D),1),s}static contains(t,e,s){return t.includes(this.getIndex(e,s))}static stateAsString(t,e){return Array.from({length:16},(s,n)=>{let i;const l=t[n];return l===-1?i=b.blue("*"):e.includes(l)?i=b.color(l.toString(),100):e.includes(n+1)?i=b.green(l.toString()):i=l.toString(),i+=" ",n!==0&&(n+1)%4===0&&(i+=` -`),i}).join("")}static getReverseAction(t){return t===r.D?r.U:t===r.U?r.D:t===r.L?r.R:t===r.R?r.L:null}}class x{static main(){const t=E.generateLessons()[0];let e=[...t.getState()];const s=[...t.getGoals()];x.prntState(e,s),e=x.shuffle(e,t.getLockedStateElements(),1e3),x.prntState(e,s)}static shuffle(t,e,s){const n=e.map(l=>l-1);let i=0;for(;ii+1),s.state=[...a.stateDone],s.episodesToTrain=100,a.shuffle(s,s.lockedStateElements),s}static moveHole(t,e){const s=u.shuffleArray(e)[0],n=t.state.indexOf(-1),i=t.state[s];return t.state[s]=-1,t.state[n]=i,t}static state7_8(t){const e=new a(t);return e.goals=[7,8],e.lockedStateElements=[1,2,3,4,5,6],e.state=[...a.stateDone],e.episodesToTrain=100,a.shuffle(e,[1,2,3,4,5,6,7]),e}static state9_13(t){const e=new a(t);return e.goals=[9,13],e.lockedStateElements=[1,2,3,4,5,6,7,8],e.state=[...a.stateDone],e.episodesToTrain=100,a.shuffle(e,e.lockedStateElements),e}static state10_15(t){const e=new a(t);return e.goals=[10,11,14,15],e.lockedStateElements=[1,2,3,4,5,6,7,8,9,13],e.state=x.shuffle([...a.stateDone],e.lockedStateElements,500),e.episodesToTrain=100,e}static state12(t){const e=new a(t);return e.goals=[12],e.lockedStateElements=[1,2,3,4,5,6,7,8,9,10,11,13,14,15],e.state=x.shuffle([...a.stateDone],e.lockedStateElements,500),e.episodesToTrain=10,e}isLockedIndex(t){return this.lockedStateElements.includes(t+1)}shuffleState(){this.state=x.shuffle(this.state,this.lockedStateElements,500)}static shuffle(t,e){let s=t.state.filter(n=>!e.includes(n));s=u.shuffleArray(s),t.state=[...e,...s]}resetState(){const t=a.generateLessons()[this.lessonNb];this.goals=[...t.goals],this.lockedStateElements=[...t.lockedStateElements],this.state=[...t.state]}};c(a,"stateDone",[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,-1]);let E=a;class v{constructor(t,e){c(this,"state");c(this,"goals");c(this,"fixedElements");t instanceof v?(this.state=[...t.getState()],this.goals=[...t.getGoals()],this.fixedElements=[...t.getFixedElements()]):(this.state=[...t],this.goals=[...(e==null?void 0:e.getGoals())??[]],this.fixedElements=[...(e==null?void 0:e.getLockedStateElements())??[]])}getState(){return this.state}setState(t){this.state=t}getGoals(){return this.goals}setGoals(t){this.goals=t}getFixedElements(){return this.fixedElements}setFixedElements(t){this.fixedElements=t}getHashCodeV2(){const t=this.getHashCodeV3__();return this.hashString(t)}getHashCodeV3__(){return Array.from({length:16},(t,e)=>{let s;const n=this.state[e];return n===-1?s="*":this.goals.includes(n)?s=String(n):this.goals.includes(e+1)?s="o":s=" ",s=s+" ",e!==0&&(e+1)%4===0&&(s=s+` -`),s}).join("")}getHashCode(){const t=this.state.map(String).join(",");return this.hashString(t)}hashString(t){let e=0;for(let s=0;sn-1);return p.getValidMoves(e,s)}executeAction(t,e){const s=p.makeMove(t.getState(),e),n=new v(s,m.stateProducer);let i=m._isTerminalSuccess(s,this.goals);this.state=new v(s,m.stateProducer);let l=NaN;this.reverseAction=p.getReverseAction(e),this.circleAction.push(e),this.circleAction.length>8&&this.circleAction.shift(),(u.equalArrays(this.circleAction,this.bigCircleAction1)||u.equalArrays(this.circleAction,this.bigCircleAction2)||u.equalArrays(this.circleAction,this.smallCircleAction1)||u.equalArrays(this.circleAction,this.smallCircleAction2))&&(i=!0);const o=this.state.getState().indexOf(-1);return m.stateProducer.isLockedIndex(o)&&(i=!0,l=-1),isNaN(l)&&(l=this.getReward(s,this.goals)),new $(n,e,l,i)}static _isTerminalSuccess(t,e){if(t.length!==16)throw new Error("newState.size() != 16");return e.filter(s=>t[s-1]===s).length===e.length}prntInfo(){u.prnt(` - -================================================ -`);const t=this.state.getState(),e=t.indexOf(-1),s=p.getXY(e);u.prnt(s);const n=p.getIndex(s.getKey(),s.getValue());u.prnt(`${e} - ${n}`);const i=p._getValidMoves(e);u.prnt(i);const l=this.getReward(t,this.goals);u.prnt(l);const o=p.stateAsString(t,this.goals);u.prnt(o)}getReward(t,e){const s=t.indexOf(-1),n=p.getXY(s),l=e.map(h=>this.getDistance(p.getXY(t.indexOf(h)),p.getXY(h-1))).reduce((h,g)=>h+g,0);if(l===0)return 100.5;const o=e.reduce((h,g)=>h+this.getDistance(p.getXY(t.indexOf(g)),n),0);return u.prnt(`d0Sum: ${l}`),u.prnt(`d1Sum: ${o}`),1/(l+o)}getDistance(t,e){const s=Math.pow(e.getKey()-t.getKey(),2),n=Math.pow(e.getValue()-t.getValue(),2);return Math.sqrt(s+n)}};c(m,"stateProducer");let w=m;class O{constructor(t,e,s,n,i){c(this,"state");c(this,"action");c(this,"reward");c(this,"done");c(this,"newState");this.state=new v(t),this.action=e,this.reward=s,this.done=n,this.newState=new v(i)}getState(){return this.state}getAction(){return this.action}getReward(){return this.reward}isDone(){return this.done}getNewState(){return this.newState}equals(t){return t instanceof O?this.hashCode()===t.hashCode():!1}hashCode(){return this.state.getHashCodeV2()^this.newState.getHashCodeV2()}}class B{constructor(t){c(this,"state");c(this,"qValues");this.state=t,this.qValues=new Map}setValue(t,e){const s=w.getPossibleActions(this.state);if(this.qValues.size===0&&s.forEach(n=>this.qValues.set(n,0)),!s.includes(t)){console.warn("WARNING: !moves.includes(action)");return}this.qValues.set(t,e)}getValue(t){return this.qValues.get(t)||0}getActionWithMaxValue(t){const e=w.getPossibleActions(this.state).filter(n=>n!==t),s=t===null?null:this.getAction(t);return s??(console.warn("WARNING: no action found"),e.length>0?e[0]:r.D)}getAction(t){const s=Array.from(this.qValues.entries()).filter(([n])=>n!==t).reduce((n,i)=>i[1]>n[1]?i:n,[t,-1/0]);return s[1]>-1/0?s[0]:void 0}getMaxValue(){return this.qValues.size===0?0:Math.max(...Array.from(this.qValues.values()))}}class Q{static updateQTable(t,e,s,n,i,l,o,h){let g;if(l)g=i;else{const f=this.getQValue(t,e,s),T=this.getMaxQValue(t,n);g=this.calcQValue(i,f,T,h,o)}this.addStateWithZeroValuesToQTableIfStateNotExist(t,e),this.updateQTableEntry(t,e.getHashCodeV2(),s,g)}static updateQTableEntry(t,e,s,n){var i;(i=t.get(e))==null||i.setValue(s,n)}static getMaxQValue(t,e){var n;const s=e.getHashCodeV2();return this.addStateWithZeroValuesToQTableIfStateNotExist(t,e),((n=t.get(s))==null?void 0:n.getMaxValue())??0}static getQValue(t,e,s){var i;const n=e.getHashCodeV2();return this.addStateWithZeroValuesToQTableIfStateNotExist(t,e),((i=t.get(n))==null?void 0:i.getValue(s))??0}static addStateWithZeroValuesToQTableIfStateNotExist(t,e){t.has(e.getHashCodeV2())||this.addStateWithZeroValuesToQTable(t,e)}static addStateWithZeroValuesToQTable(t,e){const s=e.getHashCodeV2(),n=new B(e);t.set(s,n)}static calcQValue(t,e,s,n,i){return e+i*(t+n*s-e)}}const y=class y{static runEpisode(t,e,s,n,i){const l=new U,o=new w(t);o.reset();let h=o.getInitState();o.prntInfo();const g=.5;let f=!1,T=0;for(;!f&&T<50;){T++;let S;const A=w.getPossibleActions(h);if(o.reverseAction!==null){const q=A.indexOf(o.reverseAction);A.splice(q,1)}l.nextDouble()S+A.qValues.size,0),L=`Episode ${i} done, states count: ${D}, experience size: ${y.experience.size}`;console.log(L),console.log("")}static replayExperience(t,e,s,n,i){Array.from(t).sort(()=>Math.random()-.5).slice(0,i).forEach(o=>{Q.updateQTable(e,o.getState(),o.getAction(),o.getNewState(),o.getReward(),o.isDone(),s,n)})}};c(y,"experience",new Set);let R=y;class U{nextDouble(){return Math.random()}}class K{static train(t,e,s){const l=E.generateLessons(),o=(g,f)=>{R.runEpisode(g,t,.9,.1,f)},h=g=>{for(let f=0;fArray.from(o.qValues.values())),s=e.reduce((o,h)=>o+h,0),n=e.length,i=n?s/n:0,l=new W;return l.count=n,l.sum=s,l.average=i,l}static testQTable(t){u.prnt("********************* test q table **********************"),u.prnt("********************* test q table **********************"),u.prnt("********************* test q table **********************");let e=0;const s=E.generateLessons(),n=s.length;let i=s[e],l=x.shuffle(E.stateDone,[],1e3),o=new v(l,i),h=i.getGoals();this.prntState(o);let g=!1,f=0,T=null;for(;!g&&f<200;){this.sleep(1e3/2).then(),b.clearScreen(),f++;const L=o.getHashCodeV2();Q.addStateWithZeroValuesToQTableIfStateNotExist(t,o);const S=t.get(L),A=S?S.getActionWithMaxValue(T):r.D;T=p.getReverseAction(A);const V=p.makeMove(o.getState(),A),M=w._isTerminalSuccess(V,h);o=new v(V,i),g=u.equalArrays(o.getState(),E.stateDone),u.prnt(`${f} ----- -`),this.prntState(o),M&&!g&&eo!==s),t.has(n)?((l=t.get(n))==null?void 0:l.getActionWithMaxValue(s))||r.D:this.getRandomAction(i)}static getRandomAction(t){return t.length>0?t[Math.floor(Math.random()*t.length)]:r.D}static sleep(t){return new Promise(e=>setTimeout(e,t))}}class W{constructor(){c(this,"count",0);c(this,"sum",0);c(this,"average",0)}}class Y{static main(){u.prnt("kuku"),C.train(),C.test()}}function j(d){var n,i,l;let t=0;const e=o=>o>=100?o-100:o<=-100?o+100:o,s=o=>{t=e(o);const h=`${t}`;d.innerHTML=h};(n=document.getElementById("increaseByOne"))==null||n.addEventListener("click",()=>s(t+1)),(i=document.getElementById("decreaseByOne"))==null||i.addEventListener("click",()=>s(t-1)),(l=document.getElementById("increaseByTwo"))==null||l.addEventListener("click",()=>s(t+2)),document.getElementById("decreaseByTwo"),s(0)}j(document.getElementById("counter-value"));Y.main(); diff --git a/dist/assets/index-RO_tAo3e.js b/dist/assets/index-RO_tAo3e.js new file mode 100644 index 0000000..9b83f2c --- /dev/null +++ b/dist/assets/index-RO_tAo3e.js @@ -0,0 +1,12 @@ +var N=Object.defineProperty;var X=(g,t,e)=>t in g?N(g,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):g[t]=e;var u=(g,t,e)=>X(g,typeof t!="symbol"?t+"":t,e);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))s(n);new MutationObserver(n=>{for(const i of n)if(i.type==="childList")for(const c of i.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&s(c)}).observe(document,{childList:!0,subtree:!0});function e(n){const i={};return n.integrity&&(i.integrity=n.integrity),n.referrerPolicy&&(i.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?i.credentials="include":n.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function s(n){if(n.ep)return;n.ep=!0;const i=e(n);fetch(n.href,i)}})();class E{static blue(t){return`\x1B[34m${t}\x1B[0m`}static green(t){return`\x1B[32m${t}\x1B[0m`}static color(t,e){return`\x1B[${e}m${t}\x1B[0m`}static clearScreen(){this.prnt("clearScrn ... ","color: orange;")}static prnt(t,e=""){const s=document.getElementById("console");if(s){const n=document.createElement("div");n.textContent=t,e&&(n.style.cssText=e),s.appendChild(n),s.scrollTop=s.scrollHeight}}static warn(t){this.prnt(t,"color: orange;")}static testPrint(){this.prnt("Hello, World!"),this.prnt("Error: Something went wrong!","color: red;"),this.prnt("Info: This is some information.","color: #00ff00;"),this.prnt("Warning: Be careful!","color: orange;")}}const H=class H{static prnt(t,e="color: black;"){E.prnt(t,e)}static str(t,e){const s=t.toString();if(s.length>=e)return s;const n=e-s.length;return s+H.emptyString.substring(0,n)}static sum(t){return!t||(t=t.filter(e=>e!==0),t.length===0)?0:t.reduce((e,s)=>e+s,0)}static toString(t){return`[${Array.from(t).map(String).join(", ")}]`}static px(){return(t,e)=>t}static equalArrays(t,e){if(t.length!==e.length)return!1;for(let s=0;sMath.random()-.5)}static _sleep(t){return new Promise(e=>setTimeout(e,t))}static async sleep(t){await this._sleep(t)}};u(H,"emptyString"," ");let r=H;var o=(g=>(g.L="L",g.R="R",g.U="U",g.D="D",g))(o||{});class k{constructor(t,e){this.key=t,this.value=e}getKey(){return this.key}getValue(){return this.value}static P(t,e){return new k(t,e)}}class m{static makeMove(t,e){const n=t.indexOf(-1),i=this.getXY(n);let c=i.getKey(),l=i.getValue();e===o.L&&(c-=1),e===o.R&&(c+=1),e===o.U&&(l-=1),e===o.D&&(l+=1);const h=this.getIndex(c,l),d=[...t],p=d[h];return d[n]=p,d[h]=-1,d}static getXY(t){const e=t%4,s=Math.floor(t/4);return k.P(e,s)}static getIndex(t,e){return e*4+t}static _getValidMoves(t){const e=this.getXY(t),s=Object.values(o).slice();return e.getKey()===0&&s.splice(s.indexOf(o.L),1),e.getKey()===3&&s.splice(s.indexOf(o.R),1),e.getValue()===0&&s.splice(s.indexOf(o.U),1),e.getValue()===3&&s.splice(s.indexOf(o.D),1),s}static getValidMoves(t,e){const s=this._getValidMoves(t),n=this.getXY(t);return this.contains(e,n.getKey()-1,n.getValue())&&s.splice(s.indexOf(o.L),1),this.contains(e,n.getKey()+1,n.getValue())&&s.splice(s.indexOf(o.R),1),this.contains(e,n.getKey(),n.getValue()-1)&&s.splice(s.indexOf(o.U),1),this.contains(e,n.getKey(),n.getValue()+1)&&s.splice(s.indexOf(o.D),1),s}static contains(t,e,s){return t.includes(this.getIndex(e,s))}static stateAsString(t,e){return Array.from({length:16},(s,n)=>{let i;const c=t[n];return c===-1?i=E.blue("*"):e.includes(c)?i=E.color(c.toString(),100):e.includes(n+1)?i=E.green(c.toString()):i=c.toString(),i+=" ",n!==0&&(n+1)%4===0&&(i+=` +`),i}).join("")}static getReverseAction(t){return t===o.D?o.U:t===o.U?o.D:t===o.L?o.R:t===o.R?o.L:null}}class v{static main(){const t=b.generateLessons()[0];let e=[...t.getState()];const s=[...t.getGoals()];v.prntState(e,s),e=v.shuffle(e,t.getLockedStateElements(),1e3),v.prntState(e,s)}static shuffle(t,e,s){const n=e.map(c=>c-1);let i=0;for(;ii+1),s.state=[...a.stateDone],s.episodesToTrain=100,a.shuffle(s,s.lockedStateElements),s}static moveHole(t,e){const s=r.shuffleArray(e)[0],n=t.state.indexOf(-1),i=t.state[s];return t.state[s]=-1,t.state[n]=i,t}static state7_8(t){const e=new a(t);return e.goals=[7,8],e.lockedStateElements=[1,2,3,4,5,6],e.state=[...a.stateDone],e.episodesToTrain=100,a.shuffle(e,[1,2,3,4,5,6,7]),e}static state9_13(t){const e=new a(t);return e.goals=[9,13],e.lockedStateElements=[1,2,3,4,5,6,7,8],e.state=[...a.stateDone],e.episodesToTrain=100,a.shuffle(e,e.lockedStateElements),e}static state10_15(t){const e=new a(t);return e.goals=[10,11,14,15],e.lockedStateElements=[1,2,3,4,5,6,7,8,9,13],e.state=v.shuffle([...a.stateDone],e.lockedStateElements,500),e.episodesToTrain=100,e}static state12(t){const e=new a(t);return e.goals=[12],e.lockedStateElements=[1,2,3,4,5,6,7,8,9,10,11,13,14,15],e.state=v.shuffle([...a.stateDone],e.lockedStateElements,500),e.episodesToTrain=10,e}isLockedIndex(t){return this.lockedStateElements.includes(t+1)}shuffleState(){this.state=v.shuffle(this.state,this.lockedStateElements,500)}static shuffle(t,e){let s=t.state.filter(n=>!e.includes(n));s=r.shuffleArray(s),t.state=[...e,...s]}resetState(){const t=a.generateLessons()[this.lessonNb];this.goals=[...t.goals],this.lockedStateElements=[...t.lockedStateElements],this.state=[...t.state]}};u(a,"stateDone",[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,-1]);let b=a;class w{constructor(t,e){u(this,"state");u(this,"goals");u(this,"fixedElements");t instanceof w?(this.state=[...t.getState()],this.goals=[...t.getGoals()],this.fixedElements=[...t.getFixedElements()]):(this.state=[...t],this.goals=[...(e==null?void 0:e.getGoals())??[]],this.fixedElements=[...(e==null?void 0:e.getLockedStateElements())??[]])}getState(){return this.state}setState(t){this.state=t}getGoals(){return this.goals}setGoals(t){this.goals=t}getFixedElements(){return this.fixedElements}setFixedElements(t){this.fixedElements=t}getHashCodeV2(){const t=this.getHashCodeV3__();return this.hashString(t)}getHashCodeV3__(){return Array.from({length:16},(t,e)=>{let s;const n=this.state[e];return n===-1?s="*":this.goals.includes(n)?s=String(n):this.goals.includes(e+1)?s="o":s=" ",s=s+" ",e!==0&&(e+1)%4===0&&(s=s+` +`),s}).join("")}getHashCode(){const t=this.state.map(String).join(",");return this.hashString(t)}hashString(t){let e=0;for(let s=0;sn-1);return m.getValidMoves(e,s)}executeAction(t,e){const s=m.makeMove(t.getState(),e),n=new w(s,f.stateProducer);let i=f._isTerminalSuccess(s,this.goals);this.state=new w(s,f.stateProducer);let c=NaN;this.reverseAction=m.getReverseAction(e),this.circleAction.push(e),this.circleAction.length>8&&this.circleAction.shift(),(r.equalArrays(this.circleAction,this.bigCircleAction1)||r.equalArrays(this.circleAction,this.bigCircleAction2)||r.equalArrays(this.circleAction,this.smallCircleAction1)||r.equalArrays(this.circleAction,this.smallCircleAction2))&&(i=!0);const l=this.state.getState().indexOf(-1);return f.stateProducer.isLockedIndex(l)&&(i=!0,c=-1),isNaN(c)&&(c=this.getReward(s,this.goals)),new G(n,e,c,i)}static _isTerminalSuccess(t,e){if(t.length!==16)throw new Error("newState.size() != 16");return e.filter(s=>t[s-1]===s).length===e.length}prntInfo(){r.prnt(` + +================================================ +`);const t=this.state.getState(),e=t.indexOf(-1),s=m.getXY(e);r.prnt(s);const n=m.getIndex(s.getKey(),s.getValue());r.prnt(`${e} - ${n}`);const i=m._getValidMoves(e);r.prnt(i);const c=this.getReward(t,this.goals);r.prnt(c);const l=m.stateAsString(t,this.goals);r.prnt(l)}getReward(t,e){const s=t.indexOf(-1),n=m.getXY(s),c=e.map(h=>this.getDistance(m.getXY(t.indexOf(h)),m.getXY(h-1))).reduce((h,d)=>h+d,0);if(c===0)return 100.5;const l=e.reduce((h,d)=>h+this.getDistance(m.getXY(t.indexOf(d)),n),0);return r.prnt(`d0Sum: ${c}`),r.prnt(`d1Sum: ${l}`),1/(c+l)}getDistance(t,e){const s=Math.pow(e.getKey()-t.getKey(),2),n=Math.pow(e.getValue()-t.getValue(),2);return Math.sqrt(s+n)}};u(f,"stateProducer");let x=f;class O{constructor(t,e,s,n,i){u(this,"state");u(this,"action");u(this,"reward");u(this,"done");u(this,"newState");this.state=new w(t),this.action=e,this.reward=s,this.done=n,this.newState=new w(i)}getState(){return this.state}getAction(){return this.action}getReward(){return this.reward}isDone(){return this.done}getNewState(){return this.newState}equals(t){return t instanceof O?this.hashCode()===t.hashCode():!1}hashCode(){return this.state.getHashCodeV2()^this.newState.getHashCodeV2()}}class ${constructor(t){u(this,"state");u(this,"qValues");this.state=t,this.qValues=new Map}setValue(t,e){const s=x.getPossibleActions(this.state);if(this.qValues.size===0&&s.forEach(n=>this.qValues.set(n,0)),!s.includes(t)){E.warn("WARNING: !moves.includes(action)");return}this.qValues.set(t,e)}getValue(t){return this.qValues.get(t)||0}getActionWithMaxValue(t){const e=x.getPossibleActions(this.state).filter(n=>n!==t),s=t===null?null:this.getAction(t);return s??(E.warn("WARNING: no action found"),e.length>0?e[0]:o.D)}getAction(t){const s=Array.from(this.qValues.entries()).filter(([n])=>n!==t).reduce((n,i)=>i[1]>n[1]?i:n,[t,-1/0]);return s[1]>-1/0?s[0]:void 0}getMaxValue(){return this.qValues.size===0?0:Math.max(...Array.from(this.qValues.values()))}}class Q{static updateQTable(t,e,s,n,i,c,l,h){let d;if(c)d=i;else{const p=this.getQValue(t,e,s),y=this.getMaxQValue(t,n);d=this.calcQValue(i,p,y,h,l)}this.addStateWithZeroValuesToQTableIfStateNotExist(t,e),this.updateQTableEntry(t,e.getHashCodeV2(),s,d)}static updateQTableEntry(t,e,s,n){var i;(i=t.get(e))==null||i.setValue(s,n)}static getMaxQValue(t,e){var n;const s=e.getHashCodeV2();return this.addStateWithZeroValuesToQTableIfStateNotExist(t,e),((n=t.get(s))==null?void 0:n.getMaxValue())??0}static getQValue(t,e,s){var i;const n=e.getHashCodeV2();return this.addStateWithZeroValuesToQTableIfStateNotExist(t,e),((i=t.get(n))==null?void 0:i.getValue(s))??0}static addStateWithZeroValuesToQTableIfStateNotExist(t,e){t.has(e.getHashCodeV2())||this.addStateWithZeroValuesToQTable(t,e)}static addStateWithZeroValuesToQTable(t,e){const s=e.getHashCodeV2(),n=new $(e);t.set(s,n)}static calcQValue(t,e,s,n,i){return e+i*(t+n*s-e)}}const V=class V{static async runEpisode(t,e,s,n,i){const c=new U,l=new x(t);l.reset();let h=l.getInitState();l.prntInfo();const d=.5;let p=!1,y=0;for(;!p&&y<50;){y++;let S;const A=x.getPossibleActions(h);if(l.reverseAction!==null){const I=A.indexOf(l.reverseAction);A.splice(I,1)}c.nextDouble()S+A.qValues.size,0),R=`Episode ${i} done, states count: ${D}, experience size: ${V.experience.size}`;r.prnt(R),r.prnt(""),await r.sleep(1e3)}static replayExperience(t,e,s,n,i){Array.from(t).sort(()=>Math.random()-.5).slice(0,i).forEach(l=>{Q.updateQTable(e,l.getState(),l.getAction(),l.getNewState(),l.getReward(),l.isDone(),s,n)})}};u(V,"experience",new Set);let L=V;class U{nextDouble(){return Math.random()}}class W{static async train(t,e){const i=b.generateLessons(),c=async(h,d)=>{await L.runEpisode(h,t,.9,.1,d)},l=async h=>{for(let d=0;dArray.from(l.qValues.values())),s=e.reduce((l,h)=>l+h,0),n=e.length,i=n?s/n:0,c=new K;return c.count=n,c.sum=s,c.average=i,c}static async testQTable(t){r.prnt("********************* test q table **********************"),r.prnt("********************* test q table **********************"),r.prnt("********************* test q table **********************");let e=0;const s=b.generateLessons(),n=s.length;let i=s[e],c=v.shuffle(b.stateDone,[],1e3),l=new w(c,i),h=i.getGoals();this.prntState(l);let d=!1,p=0,y=null;for(;!d&&p<200;){await r.sleep(1e3/2),E.clearScreen(),p++;const R=l.getHashCodeV2();Q.addStateWithZeroValuesToQTableIfStateNotExist(t,l);const S=t.get(R),A=S?S.getActionWithMaxValue(y):o.D;y=m.getReverseAction(A);const T=m.makeMove(l.getState(),A),M=x._isTerminalSuccess(T,h);l=new w(T,i),d=r.equalArrays(l.getState(),b.stateDone),r.prnt(`${p} +---- +`),this.prntState(l),M&&!d&&el!==s),t.has(n)?((c=t.get(n))==null?void 0:c.getActionWithMaxValue(s))||o.D:this.getRandomAction(i)}static getRandomAction(t){return t.length>0?t[Math.floor(Math.random()*t.length)]:o.D}}class K{constructor(){u(this,"count",0);u(this,"sum",0);u(this,"average",0)}}class Y{static async main(){r.prnt("tarining starts in:");for(let t=0;t<3;t++)r.prnt(t),await r.sleep(500);r.prnt("tarining .. "),await r.sleep(1e3),await C.train(),await r.sleep(1e3),r.prnt("testing .. "),await r.sleep(1e3),await C.test()}}Y.main().then(()=>{console.log("G15EntryPoint has completed execution.")}).catch(g=>{console.error("An error occurred:",g)}); diff --git a/dist/index.html b/dist/index.html index db78f51..1db0055 100644 --- a/dist/index.html +++ b/dist/index.html @@ -1,40 +1,31 @@ - + + - - - - WS playground - - + + + console-like Output + + + - -
-

- Thank you for trying it out.
Your first project is up and running - now. -

-
-
-

Counter is

-

-
-
- - - - -
-
-
-
- List of supported technologies -
+
+
+
+ - + + \ No newline at end of file diff --git a/index.html b/index.html index f982cbe..376477d 100644 --- a/index.html +++ b/index.html @@ -1,40 +1,31 @@ - + + - - - - WS playground - + + + console-like Output + + - -
-

- Thank you for trying it out.
Your first project is up and running - now. -

-
-
-

Counter is

-

-
-
- - - - -
-
-
-
- List of supported technologies -
- +
+
+
+ + - + + \ No newline at end of file diff --git a/index.html.old b/index.html.old new file mode 100644 index 0000000..f982cbe --- /dev/null +++ b/index.html.old @@ -0,0 +1,40 @@ + + + + + + + WS playground + + + + +
+

+ Thank you for trying it out.
Your first project is up and running + now. +

+
+
+

Counter is

+

+
+
+ + + + +
+
+
+
+ List of supported technologies +
+ + + diff --git a/src/game-15-reconstruction/ConsoleUtils.ts b/src/game-15-reconstruction/ConsoleUtils.ts deleted file mode 100644 index 0b03f54..0000000 --- a/src/game-15-reconstruction/ConsoleUtils.ts +++ /dev/null @@ -1,20 +0,0 @@ -// utils/ConsoleUtils.ts -export class ConsoleUtils { - public static blue(text: string): string { - return `\x1b[34m${text}\x1b[0m`; // Blue text - } - - public static green(text: string): string { - return `\x1b[32m${text}\x1b[0m`; // Green text - } - - public static color(text: string, colorCode: number): string { - return `\x1b[${colorCode}m${text}\x1b[0m`; // Color by code - } - - public static clearScreen() { - console.log("clearScrn ... "); - } - - -} \ No newline at end of file diff --git a/src/game-15-reconstruction/EpisodeRunner.ts b/src/game-15-reconstruction/EpisodeRunner.ts index c4f7e3a..42bbb74 100644 --- a/src/game-15-reconstruction/EpisodeRunner.ts +++ b/src/game-15-reconstruction/EpisodeRunner.ts @@ -6,18 +6,19 @@ import { QTableGenerator } from './QTableGenerator'; import { QTableUpdater } from './QTableUpdater'; import { Action } from './Action'; import { EnvironmentActionResult } from './EnvironmentActionResult'; +import { Utils } from './utils/Utils'; export class EpisodeRunner { private static experience: Set = new Set(); - public static runEpisode( + public static async runEpisode( stateProducer: StateProducer, qTable: Map, // random: Random, discount: number, learningRate: number, episode: number - ): void { + ) { const random = new Random(); const environment = new Environment(stateProducer); environment.reset(); @@ -39,10 +40,10 @@ export class EpisodeRunner { } if (random.nextDouble() < epsilon) { // Explore - console.log("\nrndm move"); + Utils.prnt("\nrndm move"); action = QTableGenerator.getRandomAction(possibleActions); } else { // Exploit - console.log("\nqTable move"); + Utils.prnt("\nqTable move"); action = QTableGenerator.getAction(qTable, state0, environment.reverseAction); if (!possibleActions.includes(action)) { @@ -50,8 +51,8 @@ export class EpisodeRunner { } } - console.log("\n--------------------------------------------------------"); - console.log("\naction: " + action); + Utils.prnt("\n--------------------------------------------------------"); + Utils.prnt("\naction: " + action); if (!possibleActions.includes(action)) { // throw new Error("!possibleActions.contains(action)"); @@ -77,8 +78,9 @@ export class EpisodeRunner { const count = Array.from(qTable.values()).reduce((acc, e) => acc + e.qValues.size, 0); const message = `Episode ${episode} done, states count: ${count}, experience size: ${EpisodeRunner.experience.size}`; - console.log(message); - console.log(""); + Utils.prnt(message); + Utils.prnt(""); + await Utils.sleep(1000); } public static replayExperience( diff --git a/src/game-15-reconstruction/G15EntryPoint.ts b/src/game-15-reconstruction/G15EntryPoint.ts new file mode 100644 index 0000000..f76ea2c --- /dev/null +++ b/src/game-15-reconstruction/G15EntryPoint.ts @@ -0,0 +1,23 @@ +import { QTableGenerator } from './QTableGenerator'; +import { Utils } from './utils/Utils'; +// import { ConsoleUtils } from './utils/ConsoleUtils'; + +export class G15EntryPoint { + + public static async main() { + // ConsoleUtils.testPrint(); + Utils.prnt("tarining starts in:"); + for (let i = 0; i < 3; i++) { + Utils.prnt(i); + await Utils.sleep(500); + } + + Utils.prnt("tarining .. "); + await Utils.sleep(1000); + await QTableGenerator.train(); + await Utils.sleep(1000); + Utils.prnt("testing .. "); + await Utils.sleep(1000); + await QTableGenerator.test(); + } +} diff --git a/src/game-15-reconstruction/GameUtils.ts b/src/game-15-reconstruction/GameUtils.ts index 82a897b..9441b27 100644 --- a/src/game-15-reconstruction/GameUtils.ts +++ b/src/game-15-reconstruction/GameUtils.ts @@ -3,7 +3,7 @@ // utils/GameUtils.ts import { Action } from './Action'; import { Pair } from './utils/Pair'; -import { ConsoleUtils } from './ConsoleUtils'; +import { ConsoleUtils } from './utils/ConsoleUtils'; export class GameUtils { diff --git a/src/game-15-reconstruction/Main.ts b/src/game-15-reconstruction/Main.ts deleted file mode 100644 index e9edf11..0000000 --- a/src/game-15-reconstruction/Main.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { QTableGenerator } from './QTableGenerator'; -import { Utils } from './utils/Utils'; - -export class Main { - - public static main() { - - Utils.prnt("kuku"); - QTableGenerator.train(); - QTableGenerator.test(); - } -} diff --git a/src/game-15-reconstruction/QTableGenerator.ts b/src/game-15-reconstruction/QTableGenerator.ts index 9584a73..0b06809 100644 --- a/src/game-15-reconstruction/QTableGenerator.ts +++ b/src/game-15-reconstruction/QTableGenerator.ts @@ -6,24 +6,24 @@ import { StateShuffle } from './StateShuffle'; import { Environment } from './Environment'; import { EnvironmentState } from './EnvironmentState'; import { Action } from './Action'; -import { ConsoleUtils } from './ConsoleUtils'; import { GameUtils } from './GameUtils'; import { QTableUpdater } from './QTableUpdater'; import { Utils } from './utils/Utils'; +import { ConsoleUtils } from './utils/ConsoleUtils'; export class QTableGenerator { - public static train(): void { + public static async train() { const filePath = "qTable.ser"; const qTable = this.loadQTable(filePath); - Trainer.train(qTable, filePath, 10); + await Trainer.train(qTable, 10); } - public static test(): void { + public static async test() { const filePath = "qTable.ser"; const qTable = this.loadQTable(filePath); while (true) { - this.testQTable(qTable); + await this.testQTable(qTable); } } @@ -55,7 +55,7 @@ export class QTableGenerator { return stats; } - public static testQTable(qTable: Map): void { + public static async testQTable(qTable: Map) { Utils.prnt("********************* test q table **********************"); Utils.prnt("********************* test q table **********************"); Utils.prnt("********************* test q table **********************"); @@ -75,7 +75,7 @@ export class QTableGenerator { let reverseAction: Action | null = null; while (!gameOver && step < 200) { - this.sleep(1000 / 2).then(); + await Utils.sleep(1000 / 2); ConsoleUtils.clearScreen(); step++; @@ -109,7 +109,7 @@ export class QTableGenerator { const isTerminalSuccess = Environment.isTerminalSuccess(state); Utils.prnt(`success: ${isTerminalSuccess}`); - this.sleep(3000).then(); + await Utils.sleep(3000); } private static prntState(state: EnvironmentState): void { @@ -132,9 +132,7 @@ export class QTableGenerator { : Action.D; } - private static sleep(ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)); - } + } class Stats { diff --git a/src/game-15-reconstruction/QTableRow.ts b/src/game-15-reconstruction/QTableRow.ts index 9e0f66a..a5f862a 100644 --- a/src/game-15-reconstruction/QTableRow.ts +++ b/src/game-15-reconstruction/QTableRow.ts @@ -1,6 +1,7 @@ import { Action } from './Action'; import { Environment } from './Environment'; import { EnvironmentState } from './EnvironmentState'; +import { ConsoleUtils } from './utils/ConsoleUtils'; export class QTableRow { private state: EnvironmentState; @@ -17,7 +18,7 @@ export class QTableRow { moves.forEach(e => this.qValues.set(e, 0)); } if (!moves.includes(action)) { - console.warn("WARNING: !moves.includes(action)"); + ConsoleUtils.warn("WARNING: !moves.includes(action)"); return; } this.qValues.set(action, qValue); @@ -32,7 +33,7 @@ export class QTableRow { const actionOption = lastAction === null ? null : this.getAction(lastAction); if (actionOption === null || actionOption === undefined) { - console.warn("WARNING: no action found"); + ConsoleUtils.warn("WARNING: no action found"); return possibleActions.length > 0 ? possibleActions[0] : Action.D; // Default action } else { return actionOption; diff --git a/src/game-15-reconstruction/Trainer.ts b/src/game-15-reconstruction/Trainer.ts index a1ce7f8..f22cbdf 100644 --- a/src/game-15-reconstruction/Trainer.ts +++ b/src/game-15-reconstruction/Trainer.ts @@ -1,30 +1,30 @@ import { QTableRow } from './QTableRow'; // Adjust the import according to your project structure -import { SerializedObjectSaver } from './utils/SerializedObjectSaver'; // Adjust the import according to your project structure +// import { SerializedObjectSaver } from './utils/SerializedObjectSaver'; // Adjust the import according to your project structure import { StateProducer } from './StateProducer'; // Adjust the import according to your project structure import { EpisodeRunner } from './EpisodeRunner'; // Adjust the import according to your project structure +import { Utils } from './utils/Utils'; export class Trainer { - public static train(qTable: Map, filePath: string, n: number): void { + public static async train(qTable: Map, n: number) { const discount = 0.9; const learningRate = 0.1; const lessons = StateProducer.generateLessons(); - const episodeRunner = (stateProducer: StateProducer, episode: number): void => { - EpisodeRunner.runEpisode(stateProducer, qTable, discount, learningRate, episode); + const episodeRunner = async (stateProducer: StateProducer, episode: number): Promise => { + await EpisodeRunner.runEpisode(stateProducer, qTable, discount, learningRate, episode); }; - const stateProducerConsumer = (stateProducer: StateProducer): void => { + const stateProducerConsumer = async (stateProducer: StateProducer): Promise => { for (let episode = 0; episode < stateProducer.getEpisodesToTrain(); episode++) { - episodeRunner(stateProducer, episode); + await episodeRunner(stateProducer, episode); } }; for (let i = 0; i < n; i++) { - lessons.forEach(stateProducerConsumer); + await Promise.all(lessons.map(stateProducerConsumer)); } - console.log("\ntraining done"); - SerializedObjectSaver.save(filePath, qTable); + Utils.prnt("training done"); } -} \ No newline at end of file +} diff --git a/src/game-15-reconstruction/utils/ConsoleUtils.ts b/src/game-15-reconstruction/utils/ConsoleUtils.ts new file mode 100644 index 0000000..a332934 --- /dev/null +++ b/src/game-15-reconstruction/utils/ConsoleUtils.ts @@ -0,0 +1,51 @@ +export class ConsoleUtils { + + public static blue(text: string): string { + return `\x1b[34m${text}\x1b[0m`; // Blue text + } + + public static green(text: string): string { + return `\x1b[32m${text}\x1b[0m`; // Green text + } + + public static color(text: string, colorCode: number): string { + return `\x1b[${colorCode}m${text}\x1b[0m`; // Color by code + } + + public static clearScreen() { + this.prnt("clearScrn ... ", "color: orange;"); + } + + public static prnt(message: string, style: string = ""): void { + const consoleDiv = document.getElementById('console'); + if (consoleDiv) { + // Create a new div element for each message + const messageElement = document.createElement('div'); + messageElement.textContent = message; + + // Apply custom styles if provided + if (style) { + messageElement.style.cssText = style; + } + + // Append the message to the custom Utils.prnt + consoleDiv.appendChild(messageElement); + + // Scroll to the bottom of the Utils.prnt to show the latest message + consoleDiv.scrollTop = consoleDiv.scrollHeight; + } + } + + public static warn(message: string) { + this.prnt(message, "color: orange;"); + } + + public static testPrint() { + // Example usage of the printToUtils.prnt function + this.prnt("Hello, World!"); + this.prnt("Error: Something went wrong!", "color: red;"); + this.prnt("Info: This is some information.", "color: #00ff00;"); + this.prnt("Warning: Be careful!", "color: orange;"); + } +} + diff --git a/src/game-15-reconstruction/utils/Utils.ts b/src/game-15-reconstruction/utils/Utils.ts index 0feab83..191aeff 100644 --- a/src/game-15-reconstruction/utils/Utils.ts +++ b/src/game-15-reconstruction/utils/Utils.ts @@ -1,10 +1,10 @@ -// import * as fs from 'fs'; +import { ConsoleUtils } from './ConsoleUtils'; export class Utils { private static emptyString = ' '; - public static prnt(o: any): void { - console.log(o); + public static prnt(o: any, color = 'color: black;'): void { + ConsoleUtils.prnt(o, color); } public static str(o: any, len: number): string { @@ -39,20 +39,6 @@ export class Utils { return (t: T, _: T) => t; } - // public static writeTextToFile(fileName: string, content: string): void { - // try { - // fs.writeFileSync(fileName, content, 'utf8'); - // } catch (error) { - // console.error('Error writing to file:', error); - // } - // } - - // public static _prnt(o: any): void { - // process.stdout.write(String(o)); - // } - - - public static equalArrays(array: T[], array2: T[]): boolean { // First, check if the lengths of both arrays are equal if (array.length !== array2.length) { @@ -72,6 +58,29 @@ export class Utils { public static shuffleArray(array: T[]): T[] { return array.sort(() => Math.random() - 0.5); } + + private static _sleep(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + public static async sleep(ms: number) { + // Utils.prnt('Start'); + await this._sleep(ms); // Pauses for 2 seconds + // Utils.prnt('End after 2 seconds'); + } + + + + // public static _sleep(ms: number): Promise { + // return new Promise(resolve => setTimeout(resolve, ms)); + // } + + // public static async sleep(ms: number) { + // Utils.prnt('Start'); + // this._sleep(ms).then(() => { + // Utils.prnt('End after 2 seconds'); + // }); + // } } // Helper type for collections (similar to Java's Collection interface) diff --git a/src/main.ts b/src/main.ts index be0e329..6046270 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,11 +1,12 @@ -import { Main } from './game-15-reconstruction/Main'; +import { G15EntryPoint } from './game-15-reconstruction/G15EntryPoint'; +// import { Utils.prntUtil } from './game-15-reconstruction/utils/Utils.prntUtil'; //TIP With Search Everywhere, you can find any action, file, or symbol in your project. Press , type in terminal, and press . Then run in the terminal and click the link in its output to open the app in the browser. export function setupCounter(element: HTMLElement) { //TIP Try on to see its usages. You can also use this shortcut to jump to a declaration – try it on on line 13. let counter = 0; - const adjustCounterValue = (value: number) => { + const adjustCounterValue = (value: number) => { if (value >= 100) return value - 100; if (value <= -100) return value + 100; return value; @@ -23,14 +24,23 @@ export function setupCounter(element: HTMLElement) { document.getElementById('increaseByTwo')?.addEventListener('click', () => setCounter(counter + 2)); //TIP In the app running in the browser, you’ll find that clicking -2 doesn't work. To fix that, rewrite it using the code from lines 19 - 21 as examples of the logic. - document.getElementById('decreaseByTwo') + document.getElementById('decreaseByTwo')?.addEventListener('click', () => G15EntryPoint.main()); + + //TIP Let’s see how to review and commit your changes. Press and look for commit. Try checking the diff for a file – double-click main.ts to do that. setCounter(0); } //TIP To find text strings in your project, you can use the shortcut. Press it and type in counter – you’ll get all matches in one place. -setupCounter(document.getElementById('counter-value') as HTMLElement); -Main.main(); +// setupCounter(document.getElementById('counter-value') as HTMLElement); //TIP There's much more in WebStorm to help you be more productive. Press and search for Learn WebStorm to open our learning hub with more things for you to try. +// Utils.prntUtil.testPrint(); +// await G15EntryPoint.main(); + +G15EntryPoint.main().then(() => { + console.log('G15EntryPoint has completed execution.'); +}).catch(error => { + console.error('An error occurred:', error); +}); \ No newline at end of file