From 63669c5984503c151d202452ec2edb2cc3e0dfeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Rebelo?= Date: Tue, 18 Jul 2023 16:26:27 +0200 Subject: [PATCH] refactor: minor fixes on interface (cont.) #16 --- src/client/components/Interface.js | 4 ++-- src/public/app.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/client/components/Interface.js b/src/client/components/Interface.js index 914182e..9375df4 100644 --- a/src/client/components/Interface.js +++ b/src/client/components/Interface.js @@ -70,7 +70,7 @@ export class Interface extends LitElement { ${Divider.get()}
- - - + @@ -339,7 +339,7 @@ const ae=2;class le{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,r)
`:F}
- `}createRenderRoot(){return this}}customElements.define("header-section",je);var Se={solid:(e,t)=>{e.background(t)},gradient:(e,t,r)=>{push();const o=e.drawingContext;e.background(t);let s=e.height;const n=o.createLinearGradient(0,0,0,s);n.addColorStop(0,t),n.addColorStop(.25,t),n.addColorStop(.75,r),n.addColorStop(1,r),o.fillStyle=n,o.fillRect(0,0,e.width,s),pop()},triangle:(e,t,r)=>{push(),e.background(t),e.noStroke(),e.fill(r),e.triangle(0,0,0,e.height,e.width,e.height),pop()}};const Ee=(e,t,r,o,s)=>o+(e-t)/(r-t)*(s-o),Me=(e,t)=>Ee(e=(e=e>=0?0:e)<=-t?-t:e,-t,0,.5,0),Te=(e,t)=>(e=Math.abs(e),Ee(e=e>t?t:e,t,0,.5,0)),Ce=(e,t)=>Te(e=e>=0?e/3:e,t),Ae=(e=[],t,r="OVERSET",o=1)=>{let s=[],n=t*o;for(let o of e){let e=t-o,i=.5;switch(r){case"JUSTIFY":i=Te(e,n);break;case"ATTEMPT_JUSTIFY":i=Ce(e,n);break;default:i=Me(e,n)}s.push(i)}const i=(e=>{const t=e.reduce(((e,t)=>e+t),0);return t/e.length||0})([...s]);return i};class ke{#h=!1;#p=!1;constructor(e,t,r=null,o=null){this.id=`${t}-${e}`,this.n=e,this.generation=t,this.ready=!1,this.fitness=1,this.sentencesLenght=[],this.genotype=null===o?this.#f(r):o,this.#h=null===r||r.display.grid,this.phenotype=null,this.evaluate()}copy=()=>{const e=this.genotype.grid,t=new Le(JSON.parse(JSON.stringify(e.size)),JSON.parse(JSON.stringify(e.v)),JSON.parse(JSON.stringify(e.h)),JSON.parse(JSON.stringify(e.gwper)),JSON.parse(JSON.stringify(e.ghper))),r=JSON.parse(JSON.stringify(this.genotype.size)),o=JSON.parse(JSON.stringify(this.genotype.textboxes));for(let e in o)o[e].color=color(this.genotype.textboxes[e].color);const s=JSON.parse(JSON.stringify(this.genotype.background));s.colors[0]=color(this.genotype.background.colors[0]),s.colors[1]=color(this.genotype.background.colors[1]);let n=[];for(let e of this.genotype.images){const t={scale:e.scale,src:e.src,x:e.x,y:e.y};n.push(t)}const i={grid:t,textboxes:o,size:r,background:s,typography:JSON.parse(JSON.stringify(this.genotype.typography)),images:n};return new ke(this.n,this.generation,null,i)};#f=e=>{const t=new Le({width:e.size.width,height:e.size.height,margin:e.size.margin},2,e.sentences.length),r=[];for(let o of e.sentences){const s=Math.round(Math.random()*(e.typography.typefaces.length-1));let n=e.typography.typefaces[s].stretch.replaceAll("%","").split(" ").map((e=>(isNaN(e)&&(e=100),parseInt(e))));n.length<2&&n.push(100);let i=e.typography.typefaces[s].weight.split(" ").map((e=>parseInt(e))),a=e.typography.weight.min+Math.round(Math.random()*e.typography.weight.max);a=Math.max(i[0],Math.min(a,i[1]));let l=e.typography.stretch.min+Math.round(Math.random()*e.typography.stretch.max);l=Math.max(n[0],Math.min(l,n[1]));let c=Math.round(t.rows.l[0]);c+=Math.round(-c*se.typography.range+Math.random()*(c*se.typography.range)),c=Math.max(Math.round(e.size.height*se.typography.minSize),Math.min(Math.round(e.size.height*se.typography.maxSize),c));let u=0===e.typography.verticalAlignment?Math.round(Math.random()*(se.textAlignmentOptions.length-2)+1):e.typography.verticalAlignment;console.log("initial upper",e.typography.uppercase),r.push({content:o,weight:a,"font-stretch":l,alignment:u,size:c,typeface:e.typography.typefaces[s].family,color:e.typography.color.random?color(random(255),random(255),random(255)):color(e.typography.color.value),uppercase:e.typography.uppercase})}const o=[];for(let t of e.images){const r=t.src,s=loadImage(r,(async t=>{await t.resize(0,e.size.height),t.ready=!0}));o.push({x:Math.random(),y:Math.random(),scale:Math.random(),src:s})}return{grid:t,textboxes:r,size:{width:e.size.width,height:e.size.height,margin:e.size.margin},background:{style:0===e.background.style?Math.round(1+Math.random()*(se.background.availableStyles.length-2)):e.background.style,colors:[e.background.color.random?color(random(255),random(255),random(255)):color(e.background.color.valueA),e.background.color.random?color(random(255),random(255),random(255)):color(e.background.color.valueB)]},typography:{color:e.typography.color.random?color(random(255),random(255),random(255)):color(e.typography.color.value),verticalAlignment:0===e.typography.verticalAlignment?Math.round(Math.random()*se.textAlignmentTbOptions.length-2+1):e.typography.verticalAlignment},images:o}};draw=async()=>{this.ready=!0,this.phenotype=createGraphics(this.genotype.size.width,this.genotype.size.height),this.phenotype.id=this.n;const e=Object.keys(Se)[this.genotype.background.style-1];return(0,Se[e])(this.phenotype,this.genotype.background.colors[0],this.genotype.background.colors[1]),this.ready=await this.#m(this.phenotype),await this.typeset(this.phenotype),this.#p&&(pg.textSize(10),pg.fill(0),pg.text(`${this.id}+${this.genotype.typography.verticalAlignment}+style=${this.genotype.background.style}\nfitness=${this.fitness}`,20,20)),(this.#h||this.#p)&&this.genotype.grid.display(this.phenotype),this.phenotype};evaluate=async()=>{this.phenotype=await this.draw(),this.fitness=1;const e=Ae(this.sentencesLenght,this.genotype.grid.getAvailableWidth(),"JUSTIFY");this.fitness-=e};typeset=async e=>{this.sentencesLenght=[],e.push(),e.translate(e.width/2,e.height/2);const t=e.drawingContext;for(let r in this.genotype.textboxes){const o=this.genotype.textboxes[r];let s=o.alignment,n=LEFT;2===s?n=CENTER:3===s&&(n=RIGHT),e.textAlign(n,BASELINE);let i=this.genotype.grid.col(s-1,!1),a=this.genotype.grid.row(parseInt(r)+1,!1);e.fill(o.color),t.font=`${o.weight} ${Oe(o["font-stretch"])} ${o.size}px ${o.typeface}`,drawingContext.font=`${o.weight} ${Oe(o["font-stretch"])} ${o.size}px ${o.typeface}`;let l=!0===o.uppercase?o.content.toUpperCase():o.content;e.text(l,i,a);const c=t.measureText(l).width;this.sentencesLenght.push(c)}e.pop()};#m=async e=>{let t=!0;for(let r of this.genotype.images)if(void 0!==r.src&&r.src.hasOwnProperty("ready")){if(r.src.ready){let t=e.width*r.x,o=e.height*r.y;e.imageMode(CENTER),e.image(r.src,t,o,r.src.width*r.scale,r.src.height*r.scale)}}else t=!1;return t};toggleGrid=(e=null)=>{null===e&&(e=!this.#h),this.#h=e,this.draw()}}const Oe=e=>e>-10&&e<=50?"ultra-condensed":e>50&&e<=62.5?"extra-condensed":e>62.5&&e<=75?"condensed":e>75&&e<=87.5?"semi-condensed":e>87.5&&e<=100?"normal":e>100&&e<=112.5?"semi-expanded":e>112.5&&e<=125?"expanded":e>125&&e<=150?"extra-expanded":"ultra-expanded";class Le{constructor(e,t=12,r=24,o=.03,s=null){null===s&&(s=o),this.pos=createVector(e.width/2,e.height/2),this.size=e,this.v=t,this.h=r,this.gwper=o,this.ghper=s,this.gapw=this.size.width*this.gwper,this.gaph=this.size.height*this.ghper,this.regular=!0,this.verticalSpace=[],this.marginsPos={},this.columns={},this.columns.y={},this.columns.center={},this.columns.gap={},this.rows={},this.rows.x={},this.rows.center={},this.rows.gap={},this.def()}export=()=>({pos:[this.pos.x,this.pos.y,this.pos.z],size:this.size,v:this.v,h:this.h,gapw:this.gapw,gaph:this.gaph,marginsPos:this.marginsPos,columns:this.columns,rows:this.rows});copy=()=>new Le(JSON.parse(JSON.stringify(this.size)),JSON.parse(JSON.stringify(this.v)),JSON.parse(JSON.stringify(this.h)),JSON.parse(JSON.stringify(this.gwper)),JSON.parse(JSON.stringify(this.ghper)));updateMarginsBasedOnSize=(e=0,t=1,r,o=this.size.height)=>{const s=t*r;let n=this.size.height-s;0===e&&(n/=2),(0===e||1===e)&&this.size.margin[1]{0===e&&(t/=2),(0===e||1===e)&&this.size.margin[1]{this.#y(),this.#g(),this.#v()};update=(e=null,t=null)=>{null!==e&&e!==this.v&&console.log(`grid updated from ${this.v} to ${e}`)};defineRow=(e,t,r)=>{this.regular=!1;const o=this.rows.l[e];this.rows.l[e]=t;let s=this.rows.l[e]-o;s=2===r?s/2:s,this.marginsPos.bottom,this.size.height,r<=2&&(this.size.margin[3]=(this.marginsPos.bottom-s)/this.size.height),r>=2&&(this.size.margin[1]=(this.marginsPos.top-s)/this.size.height),this.def()};#y=()=>{this.marginsPos.left=this.size.margin[0]*this.size.width,this.marginsPos.top=this.size.margin[1]*this.size.height,this.marginsPos.right=this.size.margin[2]*this.size.width,this.marginsPos.bottom=this.size.margin[3]*this.size.height};getSpace=()=>{const e=this.rows.l.reduce(((e,t)=>e+t),0)/this.rows.l.length;return{centre:{col:this.columns.l,row:e},gap:{col:this.columns.l-this.gapw/2,row:e-this.gaph/2}}};#g=()=>{this.columns.y.top=-this.size.height/2+this.marginsPos.top,this.columns.y.bottom=this.size.height/2-this.marginsPos.bottom;const e=(this.size.width-(this.marginsPos.left+this.marginsPos.right))/this.v;this.columns.l=e;let t=-this.size.width/2+this.marginsPos.left;for(let r=0;r0&&r{this.rows.x.left=-this.size.width/2+this.marginsPos.left,this.rows.x.right=this.size.width/2-this.marginsPos.right;const t=e;this.rows.l=t;let r=-this.size.height/2+this.marginsPos.top;for(let e=0;e0&&e{this.rows.x.left=-this.size.width/2+this.marginsPos.left,this.rows.x.right=this.size.width/2-this.marginsPos.right;const e=(this.size.height-(this.marginsPos.top+this.marginsPos.bottom))/this.h;if(null===this.verticalSpace||this.verticalSpace.length!==this.h||this.regular){this.verticalSpace=[];for(let t=0;tthis.h?r+=parseInt(this.rows.l[e-1]):r+=parseInt(this.rows.l[e]),this.rows.gap[e]={},e>0&&ee=0?t?this.columns.center[e]:this.columns.gap[e].right:(console.error(`this col dod not exists in grid. requested number ${e}`),0);row=(e,t=!1)=>e=0?t?this.rows.center[e]:this.rows.gap[e].top:(console.error(`this row do not exists in grid. requested number ${e}`),0);getAvailableWidth=(e=!0)=>{if(e){return this.size.width-this.size.width*this.size.margin[0]-this.size.width*this.size.margin[2]}return this.size.width};width=(e,t=!1,r=!1)=>e0?t||e===this.v?this.columns.l*e:r?this.columns.l*e-this.gapw/2:this.columns.l*e-this.gapw:(console.error(`side bigger than grid. requested side ${e}`),0);height=(e,t=!1,r=!1)=>e0?t||e===this.h?this.rows.l*e:r?this.rows.l*e-this.gaph/2:this.rows.l*e-this.gaph:(console.error(`side bigger than row grid. requested side ${e}`),0);display=(e,t=!0,r=!0,o=!0)=>{e.push(),e.translate(this.size.width/2,this.size.height/2),r&&this.#b(e),o&&this.#_(e),t&&this.#w(e),e.pop()};#w=(e,t="#0000ff")=>{e.push(),e.stroke(t),e.rectMode(CORNER),e.noFill(),e.rect(this.rows.x.left,this.columns.y.top,this.size.width-(this.marginsPos.left+this.marginsPos.right),this.size.height-(this.marginsPos.top+this.marginsPos.bottom)),e.pop()};#b=(e,t="#ff00ff",r="#009800")=>{e.push(),e.stroke(t);for(let t of Object.keys(this.columns.center)){const r=this.columns.center[t];e.line(r,this.columns.y.top,r,this.columns.y.bottom)}e.stroke(r);for(let t of Object.keys(this.columns.gap)){const r=this.columns.gap[t];"0"!==t&&t!==""+this.v&&(e.line(r.left,this.columns.y.top,r.left,this.columns.y.bottom),e.line(r.right,this.columns.y.top,r.right,this.columns.y.bottom))}e.pop()};#_=(e,t="#ff00ff",r="#009800")=>{e.push(),e.stroke(t);for(let t of Object.keys(this.rows.center)){const r=this.rows.center[t];e.line(this.rows.x.left,r,this.rows.x.right,r)}e.stroke(r);for(let t of Object.keys(this.rows.gap)){t=parseInt(t);const r=this.rows.gap[t];0!==t&&t!==this.h&&(e.text(t,this.rows.x.left+this.rows.x.right/2,r.top),e.line(this.rows.x.left,r.top,this.rows.x.right,r.top),e.line(this.rows.x.left,r.bottom,this.rows.x.right,r.bottom))}e.pop()}}class Pe{#x;constructor(e){this.size=e.evo.popSize,this.params=e,this.population=[],this.generations=0,this.ready=!1,this.evolving=!1,this.pause=!1,this.#x=[],this.updated=!0,this.log={config:this.params,generations:[]}}initialisation=async()=>{this.updated=!0,this.generations=0,this.#j();for(let e=0;ee.typeface));for(const e of r)-1===this.#x.indexOf(e)&&this.#x.push(e)}this.evaluate(),this.updated=!0};evolve=async()=>{await this.#j(),document.getElementById("generation-number").textContent=this.generations;const e=[],t=parseInt(this.params.evo.eliteSize);for(let r=0;r{this.evolve()}),100)};uniformCrossover=(e,t)=>{const r=e.copy();t=t.copy(),Math.random()>.5&&(r.genotype.grid=t.genotype.grid,r.genotype.typography.verticalAlignment=t.genotype.background.verticalAlignment);for(const e in r.genotype.textboxes)Math.random()>.5&&(r.genotype.textboxes[e]=t.genotype.textboxes[e]);Math.random()>.5&&(r.genotype.background.style=t.genotype.background.style);for(let e in r.genotype.background.colors)Math.random()>.5&&(r.genotype.background.colors[e]=t.genotype.background.colors[e]);Math.random()>.5&&(r.genotype.typography.color=t.genotype.typography.color);for(const e in r.genotype.images)Math.random()>.5&&(r.genotype.images[e]=t.genotype.images[e]);return r};mutate=e=>{let t=this.params.evo.mutationProb;if(Math.random()1){const e=Math.round(Math.random()*(this.params.typography.typefaces.length-1));s=e,o.typeface=this.params.typography.typefaces[e].family}if(Math.random(){for(let t of this.population)t.toggleGrid(e);this.updated=!0};evaluate=async()=>{for(let e of this.population)await e.evaluate();this.population=this.population.sort(((e,t)=>t.fitness-e.fitness))};copy=e=>JSON.parse(JSON.stringify(e));tournament=(e=2)=>{let t=[];for(let r=0;rr.fitness&&(r=t[e]);return r};#S=()=>{for(let e of this.#x){if(!document.fonts.check(`12px ${e}`))return!1}return!0};#j=()=>{document.querySelectorAll("canvas:not(#defaultCanvas0)").forEach((e=>{e.remove()}))};draw=async()=>{this.updated=!1;const e=this.population.length{},window.setup=()=>{window.app=document.createElement("app-evo"),document.querySelector("main").appendChild(app),noCanvas(),noLoop(),frameRate(25)},window.draw=()=>{if(window.app.screen<3)return null;window.app.population.updated&&(push(),background(window.app.backgroundColor),window.app.population.draw(),pop(),console.log("draw"))},window.windowResized=()=>{if(window.app.screen<2)return null},window.keyPressed=()=>{};class Re extends re{static properties={screen:0,results:{},evolving:!1};constructor(){super(),this.results=null,this.screen=0,this.evolving=!1,this.config={evo:{popSize:se.evolution.popSize,noGen:se.evolution.noGen,crossoverProb:se.evolution.crossoverProb,mutationProb:se.evolution.mutationProb,eliteSize:se.evolution.eliteSize},size:{width:se.visualisationGrid.width,height:se.visualisationGrid.height,margin:se.visualisationGrid.posterMargins},images:[],sentences:null,background:{style:0,color:{random:!0,valueA:se.background.defaultColors[0],valueB:se.background.defaultColors[1]},lock:[!1,!1]},typography:{verticalAlignment:0,color:{random:!0,value:se.typography.defaultColor},textAlignment:0,typefaces:[],weight:null,stretch:null,uppercase:!1,texboxAlignment:0,lock:[!1,!1,!1,!1,!1,!1,!1,!1]},display:{grid:!0}},this.population=null,this.errorMessage=new he,this.resultsContainer=new de,this.inputForm=new ie(this.analyse,this.resultsContainer,this.errorMessage),this.header=new je,this.initPopForm=new xe(this.config,this.#E,this.population,this.errorMessage),document.getElementById("defaultCanvas0").style.visibility="visible",this.backgroundColor=getComputedStyle(document.documentElement).getPropertyValue("--main-bg-color")}analyse=async()=>{const e=this.inputForm.data();let t=`/${e.shouldDivide?"text":`lines/${e.delimiter}`}/${e.lang}/${e.textContent}`;fetch(t).then((e=>e.json())).then((e=>{this.results=e,!1===e.success&&this.errorMessage.set(e),this.resultsContainer.set(this.results),this.inputForm.dis(),this.screen=1})).catch((e=>{this.errorMessage.set(e)}))};setupEvolution=e=>{e.preventDefault(),this.screen=2,this.config.images=document.querySelectorAll("#input-images img"),this.#M(),this.#E()};#E=(e=!1)=>{e&&this.#M(),background(this.backgroundColor),null!==this.results?(null==this.config.sentences&&(this.config.sentences=this.results.sentences),this.population=new Pe(this.config),this.population.initialisation(),this.initPopForm.pop=this.population,this.screen=3,this.header.showControls()):this.errorMessage.set({msg:"text input not defined. Not possible to init population"})};#M=()=>{let e=se.visiblePosters,t=Math.ceil(e/Math.floor(windowWidth/this.config.size.width));t*=this.config.size.height+2*se.visualisationGrid.marginY,createCanvas(windowWidth,t),loop()};#T=()=>N` + `}createRenderRoot(){return this}}customElements.define("header-section",je);var Se={solid:(e,t)=>{e.background(t)},gradient:(e,t,r)=>{push();const o=e.drawingContext;e.background(t);let s=e.height;const n=o.createLinearGradient(0,0,0,s);n.addColorStop(0,t),n.addColorStop(.25,t),n.addColorStop(.75,r),n.addColorStop(1,r),o.fillStyle=n,o.fillRect(0,0,e.width,s),pop()},triangle:(e,t,r)=>{push(),e.background(t),e.noStroke(),e.fill(r),e.triangle(0,0,0,e.height,e.width,e.height),pop()}};const Ee=(e,t,r,o,s)=>o+(e-t)/(r-t)*(s-o),Me=(e,t)=>Ee(e=(e=e>=0?0:e)<=-t?-t:e,-t,0,.5,0),Te=(e,t)=>(e=Math.abs(e),Ee(e=e>t?t:e,t,0,.5,0)),Ce=(e,t)=>Te(e=e>=0?e/3:e,t),Ae=(e=[],t,r="OVERSET",o=1)=>{let s=[],n=t*o;for(let o of e){let e=t-o,i=.5;switch(r){case"JUSTIFY":i=Te(e,n);break;case"ATTEMPT_JUSTIFY":i=Ce(e,n);break;default:i=Me(e,n)}s.push(i)}const i=(e=>{const t=e.reduce(((e,t)=>e+t),0);return t/e.length||0})([...s]);return i};class ke{#h=!1;#p=!1;constructor(e,t,r=null,o=null){this.id=`${t}-${e}`,this.n=e,this.generation=t,this.ready=!1,this.fitness=1,this.sentencesLenght=[],this.genotype=null===o?this.#f(r):o,this.#h=null===r||r.display.grid,this.phenotype=null,this.evaluate()}copy=()=>{const e=this.genotype.grid,t=new Le(JSON.parse(JSON.stringify(e.size)),JSON.parse(JSON.stringify(e.v)),JSON.parse(JSON.stringify(e.h)),JSON.parse(JSON.stringify(e.gwper)),JSON.parse(JSON.stringify(e.ghper))),r=JSON.parse(JSON.stringify(this.genotype.size)),o=JSON.parse(JSON.stringify(this.genotype.textboxes));for(let e in o)o[e].color=color(this.genotype.textboxes[e].color);const s=JSON.parse(JSON.stringify(this.genotype.background));s.colors[0]=color(this.genotype.background.colors[0]),s.colors[1]=color(this.genotype.background.colors[1]);let n=[];for(let e of this.genotype.images){const t={scale:e.scale,src:e.src,x:e.x,y:e.y};n.push(t)}const i={grid:t,textboxes:o,size:r,background:s,typography:JSON.parse(JSON.stringify(this.genotype.typography)),images:n};return new ke(this.n,this.generation,null,i)};#f=e=>{const t=new Le({width:e.size.width,height:e.size.height,margin:e.size.margin},2,e.sentences.length),r=[];for(let o of e.sentences){const s=Math.round(Math.random()*(e.typography.typefaces.length-1));let n=e.typography.typefaces[s].stretch.replaceAll("%","").split(" ").map((e=>(isNaN(e)&&(e=100),parseInt(e))));n.length<2&&n.push(100);let i=e.typography.typefaces[s].weight.split(" ").map((e=>parseInt(e))),a=e.typography.weight.min+Math.round(Math.random()*e.typography.weight.max);a=Math.max(i[0],Math.min(a,i[1]));let l=e.typography.stretch.min+Math.round(Math.random()*e.typography.stretch.max);l=Math.max(n[0],Math.min(l,n[1]));let c=Math.round(t.rows.l[0]);c+=Math.round(-c*se.typography.range+Math.random()*(c*se.typography.range)),c=Math.max(Math.round(e.size.height*se.typography.minSize),Math.min(Math.round(e.size.height*se.typography.maxSize),c));let u=0===e.typography.verticalAlignment?Math.round(Math.random()*(se.textAlignmentOptions.length-2)+1):e.typography.verticalAlignment;r.push({content:o,weight:a,"font-stretch":l,alignment:u,size:c,typeface:e.typography.typefaces[s].family,color:e.typography.color.random?color(random(255),random(255),random(255)):color(e.typography.color.value),uppercase:e.typography.uppercase})}const o=[];for(let t of e.images){const r=t.src,s=loadImage(r,(async t=>{await t.resize(0,e.size.height),t.ready=!0}));o.push({x:Math.random(),y:Math.random(),scale:Math.random(),src:s})}return{grid:t,textboxes:r,size:{width:e.size.width,height:e.size.height,margin:e.size.margin},background:{style:0===e.background.style?Math.round(1+Math.random()*(se.background.availableStyles.length-2)):e.background.style,colors:[e.background.color.random?color(random(255),random(255),random(255)):color(e.background.color.valueA),e.background.color.random?color(random(255),random(255),random(255)):color(e.background.color.valueB)]},typography:{color:e.typography.color.random?color(random(255),random(255),random(255)):color(e.typography.color.value),verticalAlignment:0===e.typography.verticalAlignment?Math.round(Math.random()*se.textAlignmentTbOptions.length-2+1):e.typography.verticalAlignment},images:o}};draw=async()=>{this.ready=!0,this.phenotype=createGraphics(this.genotype.size.width,this.genotype.size.height),this.phenotype.id=this.n;const e=Object.keys(Se)[this.genotype.background.style-1];return(0,Se[e])(this.phenotype,this.genotype.background.colors[0],this.genotype.background.colors[1]),this.ready=await this.#m(this.phenotype),await this.typeset(this.phenotype),this.#p&&(pg.textSize(10),pg.fill(0),pg.text(`${this.id}+${this.genotype.typography.verticalAlignment}+style=${this.genotype.background.style}\nfitness=${this.fitness}`,20,20)),(this.#h||this.#p)&&this.genotype.grid.display(this.phenotype),this.phenotype};evaluate=async()=>{this.phenotype=await this.draw(),this.fitness=1;const e=Ae(this.sentencesLenght,this.genotype.grid.getAvailableWidth(),"JUSTIFY");this.fitness-=e};typeset=async e=>{this.sentencesLenght=[],e.push(),e.translate(e.width/2,e.height/2);const t=e.drawingContext;for(let r in this.genotype.textboxes){const o=this.genotype.textboxes[r];let s=o.alignment,n=LEFT;2===s?n=CENTER:3===s&&(n=RIGHT),e.textAlign(n,BASELINE);let i=this.genotype.grid.col(s-1,!1),a=this.genotype.grid.row(parseInt(r)+1,!1);e.fill(o.color),t.font=`${o.weight} ${Oe(o["font-stretch"])} ${o.size}px ${o.typeface}`,drawingContext.font=`${o.weight} ${Oe(o["font-stretch"])} ${o.size}px ${o.typeface}`;let l=!0===o.uppercase?o.content.toUpperCase():o.content;e.text(l,i,a);const c=t.measureText(l).width;this.sentencesLenght.push(c)}e.pop()};#m=async e=>{let t=!0;for(let r of this.genotype.images)if(void 0!==r.src&&r.src.hasOwnProperty("ready")){if(r.src.ready){let t=e.width*r.x,o=e.height*r.y;e.imageMode(CENTER),e.image(r.src,t,o,r.src.width*r.scale,r.src.height*r.scale)}}else t=!1;return t};toggleGrid=(e=null)=>{null===e&&(e=!this.#h),this.#h=e,this.draw()}}const Oe=e=>e>-10&&e<=50?"ultra-condensed":e>50&&e<=62.5?"extra-condensed":e>62.5&&e<=75?"condensed":e>75&&e<=87.5?"semi-condensed":e>87.5&&e<=100?"normal":e>100&&e<=112.5?"semi-expanded":e>112.5&&e<=125?"expanded":e>125&&e<=150?"extra-expanded":"ultra-expanded";class Le{constructor(e,t=12,r=24,o=.03,s=null){null===s&&(s=o),this.pos=createVector(e.width/2,e.height/2),this.size=e,this.v=t,this.h=r,this.gwper=o,this.ghper=s,this.gapw=this.size.width*this.gwper,this.gaph=this.size.height*this.ghper,this.regular=!0,this.verticalSpace=[],this.marginsPos={},this.columns={},this.columns.y={},this.columns.center={},this.columns.gap={},this.rows={},this.rows.x={},this.rows.center={},this.rows.gap={},this.def()}export=()=>({pos:[this.pos.x,this.pos.y,this.pos.z],size:this.size,v:this.v,h:this.h,gapw:this.gapw,gaph:this.gaph,marginsPos:this.marginsPos,columns:this.columns,rows:this.rows});copy=()=>new Le(JSON.parse(JSON.stringify(this.size)),JSON.parse(JSON.stringify(this.v)),JSON.parse(JSON.stringify(this.h)),JSON.parse(JSON.stringify(this.gwper)),JSON.parse(JSON.stringify(this.ghper)));updateMarginsBasedOnSize=(e=0,t=1,r,o=this.size.height)=>{const s=t*r;let n=this.size.height-s;0===e&&(n/=2),(0===e||1===e)&&this.size.margin[1]{0===e&&(t/=2),(0===e||1===e)&&this.size.margin[1]{this.#y(),this.#g(),this.#v()};update=(e=null,t=null)=>{null!==e&&e!==this.v&&console.log(`grid updated from ${this.v} to ${e}`)};defineRow=(e,t,r)=>{this.regular=!1;const o=this.rows.l[e];this.rows.l[e]=t;let s=this.rows.l[e]-o;s=2===r?s/2:s,this.marginsPos.bottom,this.size.height,r<=2&&(this.size.margin[3]=(this.marginsPos.bottom-s)/this.size.height),r>=2&&(this.size.margin[1]=(this.marginsPos.top-s)/this.size.height),this.def()};#y=()=>{this.marginsPos.left=this.size.margin[0]*this.size.width,this.marginsPos.top=this.size.margin[1]*this.size.height,this.marginsPos.right=this.size.margin[2]*this.size.width,this.marginsPos.bottom=this.size.margin[3]*this.size.height};getSpace=()=>{const e=this.rows.l.reduce(((e,t)=>e+t),0)/this.rows.l.length;return{centre:{col:this.columns.l,row:e},gap:{col:this.columns.l-this.gapw/2,row:e-this.gaph/2}}};#g=()=>{this.columns.y.top=-this.size.height/2+this.marginsPos.top,this.columns.y.bottom=this.size.height/2-this.marginsPos.bottom;const e=(this.size.width-(this.marginsPos.left+this.marginsPos.right))/this.v;this.columns.l=e;let t=-this.size.width/2+this.marginsPos.left;for(let r=0;r0&&r{this.rows.x.left=-this.size.width/2+this.marginsPos.left,this.rows.x.right=this.size.width/2-this.marginsPos.right;const t=e;this.rows.l=t;let r=-this.size.height/2+this.marginsPos.top;for(let e=0;e0&&e{this.rows.x.left=-this.size.width/2+this.marginsPos.left,this.rows.x.right=this.size.width/2-this.marginsPos.right;const e=(this.size.height-(this.marginsPos.top+this.marginsPos.bottom))/this.h;if(null===this.verticalSpace||this.verticalSpace.length!==this.h||this.regular){this.verticalSpace=[];for(let t=0;tthis.h?r+=parseInt(this.rows.l[e-1]):r+=parseInt(this.rows.l[e]),this.rows.gap[e]={},e>0&&ee=0?t?this.columns.center[e]:this.columns.gap[e].right:(console.error(`this col dod not exists in grid. requested number ${e}`),0);row=(e,t=!1)=>e=0?t?this.rows.center[e]:this.rows.gap[e].top:(console.error(`this row do not exists in grid. requested number ${e}`),0);getAvailableWidth=(e=!0)=>{if(e){return this.size.width-this.size.width*this.size.margin[0]-this.size.width*this.size.margin[2]}return this.size.width};width=(e,t=!1,r=!1)=>e0?t||e===this.v?this.columns.l*e:r?this.columns.l*e-this.gapw/2:this.columns.l*e-this.gapw:(console.error(`side bigger than grid. requested side ${e}`),0);height=(e,t=!1,r=!1)=>e0?t||e===this.h?this.rows.l*e:r?this.rows.l*e-this.gaph/2:this.rows.l*e-this.gaph:(console.error(`side bigger than row grid. requested side ${e}`),0);display=(e,t=!0,r=!0,o=!0)=>{e.push(),e.translate(this.size.width/2,this.size.height/2),r&&this.#b(e),o&&this.#_(e),t&&this.#w(e),e.pop()};#w=(e,t="#0000ff")=>{e.push(),e.stroke(t),e.rectMode(CORNER),e.noFill(),e.rect(this.rows.x.left,this.columns.y.top,this.size.width-(this.marginsPos.left+this.marginsPos.right),this.size.height-(this.marginsPos.top+this.marginsPos.bottom)),e.pop()};#b=(e,t="#ff00ff",r="#009800")=>{e.push(),e.stroke(t);for(let t of Object.keys(this.columns.center)){const r=this.columns.center[t];e.line(r,this.columns.y.top,r,this.columns.y.bottom)}e.stroke(r);for(let t of Object.keys(this.columns.gap)){const r=this.columns.gap[t];"0"!==t&&t!==""+this.v&&(e.line(r.left,this.columns.y.top,r.left,this.columns.y.bottom),e.line(r.right,this.columns.y.top,r.right,this.columns.y.bottom))}e.pop()};#_=(e,t="#ff00ff",r="#009800")=>{e.push(),e.stroke(t);for(let t of Object.keys(this.rows.center)){const r=this.rows.center[t];e.line(this.rows.x.left,r,this.rows.x.right,r)}e.stroke(r);for(let t of Object.keys(this.rows.gap)){t=parseInt(t);const r=this.rows.gap[t];0!==t&&t!==this.h&&(e.text(t,this.rows.x.left+this.rows.x.right/2,r.top),e.line(this.rows.x.left,r.top,this.rows.x.right,r.top),e.line(this.rows.x.left,r.bottom,this.rows.x.right,r.bottom))}e.pop()}}class Pe{#x;constructor(e){this.size=e.evo.popSize,this.params=e,this.population=[],this.generations=0,this.ready=!1,this.evolving=!1,this.pause=!1,this.#x=[],this.updated=!0,this.log={config:this.params,generations:[]}}initialisation=async()=>{this.updated=!0,this.generations=0,this.#j();for(let e=0;ee.typeface));for(const e of r)-1===this.#x.indexOf(e)&&this.#x.push(e)}this.evaluate(),this.updated=!0};evolve=async()=>{await this.#j(),document.getElementById("generation-number").textContent=this.generations;const e=[],t=parseInt(this.params.evo.eliteSize);for(let r=0;r{this.evolve()}),100)};uniformCrossover=(e,t)=>{const r=e.copy();t=t.copy(),Math.random()>.5&&(r.genotype.grid=t.genotype.grid,r.genotype.typography.verticalAlignment=t.genotype.background.verticalAlignment);for(const e in r.genotype.textboxes)Math.random()>.5&&(r.genotype.textboxes[e]=t.genotype.textboxes[e]);Math.random()>.5&&(r.genotype.background.style=t.genotype.background.style);for(let e in r.genotype.background.colors)Math.random()>.5&&(r.genotype.background.colors[e]=t.genotype.background.colors[e]);Math.random()>.5&&(r.genotype.typography.color=t.genotype.typography.color);for(const e in r.genotype.images)Math.random()>.5&&(r.genotype.images[e]=t.genotype.images[e]);return r};mutate=e=>{let t=this.params.evo.mutationProb;if(Math.random()1){const e=Math.round(Math.random()*(this.params.typography.typefaces.length-1));s=e,o.typeface=this.params.typography.typefaces[e].family}if(Math.random(){for(let t of this.population)t.toggleGrid(e);this.updated=!0};evaluate=async()=>{for(let e of this.population)await e.evaluate();this.population=this.population.sort(((e,t)=>t.fitness-e.fitness))};copy=e=>JSON.parse(JSON.stringify(e));tournament=(e=2)=>{let t=[];for(let r=0;rr.fitness&&(r=t[e]);return r};#S=()=>{for(let e of this.#x){if(!document.fonts.check(`12px ${e}`))return!1}return!0};#j=()=>{document.querySelectorAll("canvas:not(#defaultCanvas0)").forEach((e=>{e.remove()}))};draw=async()=>{this.updated=!1;const e=this.population.length{},window.setup=()=>{window.app=document.createElement("app-evo"),document.querySelector("main").appendChild(app),noCanvas(),noLoop(),frameRate(25)},window.draw=()=>{if(window.app.screen<3)return null;window.app.population.updated&&(push(),background(window.app.backgroundColor),window.app.population.draw(),pop(),console.log("draw"))},window.windowResized=()=>{if(window.app.screen<2)return null},window.keyPressed=()=>{};class Re extends re{static properties={screen:0,results:{},evolving:!1};constructor(){super(),this.results=null,this.screen=0,this.evolving=!1,this.config={evo:{popSize:se.evolution.popSize,noGen:se.evolution.noGen,crossoverProb:se.evolution.crossoverProb,mutationProb:se.evolution.mutationProb,eliteSize:se.evolution.eliteSize},size:{width:se.visualisationGrid.width,height:se.visualisationGrid.height,margin:se.visualisationGrid.posterMargins},images:[],sentences:null,background:{style:0,color:{random:!0,valueA:se.background.defaultColors[0],valueB:se.background.defaultColors[1]},lock:[!1,!1]},typography:{verticalAlignment:0,color:{random:!0,value:se.typography.defaultColor},textAlignment:0,typefaces:[],weight:null,stretch:null,uppercase:!1,texboxAlignment:0,lock:[!1,!1,!1,!1,!1,!1,!1,!1]},display:{grid:!0}},this.population=null,this.errorMessage=new he,this.resultsContainer=new de,this.inputForm=new ie(this.analyse,this.resultsContainer,this.errorMessage),this.header=new je,this.initPopForm=new xe(this.config,this.#E,this.population,this.errorMessage),document.getElementById("defaultCanvas0").style.visibility="visible",this.backgroundColor=getComputedStyle(document.documentElement).getPropertyValue("--main-bg-color")}analyse=async()=>{const e=this.inputForm.data();let t=`/${e.shouldDivide?"text":`lines/${e.delimiter}`}/${e.lang}/${e.textContent}`;fetch(t).then((e=>e.json())).then((e=>{this.results=e,!1===e.success&&this.errorMessage.set(e),this.resultsContainer.set(this.results),this.inputForm.dis(),this.screen=1})).catch((e=>{this.errorMessage.set(e)}))};setupEvolution=e=>{e.preventDefault(),this.screen=2,this.config.images=document.querySelectorAll("#input-images img"),this.#M(),this.#E()};#E=(e=!1)=>{e&&this.#M(),background(this.backgroundColor),null!==this.results?(null==this.config.sentences&&(this.config.sentences=this.results.sentences),this.population=new Pe(this.config),this.population.initialisation(),this.initPopForm.pop=this.population,this.screen=3,this.header.showControls()):this.errorMessage.set({msg:"text input not defined. Not possible to init population"})};#M=()=>{let e=se.visiblePosters,t=Math.ceil(e/Math.floor(windowWidth/this.config.size.width));t*=this.config.size.height+2*se.visualisationGrid.marginY,createCanvas(windowWidth,t),loop()};#T=()=>N`