diff --git a/src/@evoposter/evaluator/src/index.mjs b/src/@evoposter/evaluator/src/index.mjs index aa385d3..4eaa962 100644 --- a/src/@evoposter/evaluator/src/index.mjs +++ b/src/@evoposter/evaluator/src/index.mjs @@ -10,6 +10,7 @@ import * as Legibility from "./metrics/Legibility.mjs"; import * as GridAppropriateSize from "./metrics/GridAppropriateSize.mjs"; import * as LayoutSemantics from "./metrics/LayoutSemantics.mjs"; +import * as VisualSemantics from "./metrics/VisualSemantics.mjs"; export const info = () => { console.log ("Evaluator working"); @@ -18,5 +19,6 @@ export const info = () => { export const legibility = Legibility.compute; export const gridAppropriateSize = GridAppropriateSize.compute; export const layoutSemantics = LayoutSemantics.compute; +export const visualSemantics = VisualSemantics.compute; export { info as default }; \ No newline at end of file diff --git a/src/@evoposter/evaluator/src/metrics/LayoutSemantics.mjs b/src/@evoposter/evaluator/src/metrics/LayoutSemantics.mjs index 7107523..626213d 100644 --- a/src/@evoposter/evaluator/src/metrics/LayoutSemantics.mjs +++ b/src/@evoposter/evaluator/src/metrics/LayoutSemantics.mjs @@ -22,7 +22,6 @@ */ import {arrMean, arrSum} from "../utils.js"; -import {sumArr} from "../../../../client/utils.js"; let dist = null; diff --git a/src/@evoposter/evaluator/src/metrics/VisualSemantics.mjs b/src/@evoposter/evaluator/src/metrics/VisualSemantics.mjs new file mode 100644 index 0000000..94abdb4 --- /dev/null +++ b/src/@evoposter/evaluator/src/metrics/VisualSemantics.mjs @@ -0,0 +1,102 @@ +/** + * Visual Semantics + * + * Measure the appropriate of the visual features + * based on the importance of the content + * it considers that most important parts of content + * are those have more emotions related + * + * return the mean of difference between all textboxes, + * a value between 1 (good) and 0 (bad) + * + * + * Sérgio M. Rebelo + * CDV lab. (CMS, CISUC, Portugal) + * srebelo[at]dei.uc.pt + * + * v1.0.0 November 2023 + */ +import {arrMax, arrMean, arrMin, map} from "../utils.js"; + +// by tradition, use more that a method to emphasize the text is considered typecrime +// this method enables turn on/off this, using the param allowMultiple +export const compute = (textboxes, dist, allowMultiple = false) => { + const fontWeight = 1-checkDifferenceVariableFeature(textboxes.map((b) => b["weight"]), dist.map((e) => e[3])); + const fontStretch = 1-checkDifferenceVariableFeature(textboxes.map((b) => b["font-stretch"]), dist.map((e) => e[3])); + + console.log (`fontWeight=`, fontWeight); + console.log (`fontStretch=`, fontStretch); + + // type design + + + // way of combine and only checks one + return [fontWeight, fontStretch]; +} + +const checkDifferenceVariableFeature = (currentFeatures, dist) => { + + // max feature range + const maxFeature = arrMax(currentFeatures); + const minFeature = arrMin(currentFeatures); + const range = Math.abs(maxFeature - minFeature); + + // semantic data range + const maxSemantic = arrMax(dist); + const minSemantic = arrMin(dist); + + // create target feature values + const target = dist.map((e) => { + // The most neutral sentence are the most regular + let v = map(e, minSemantic, maxSemantic, 0, range); + v = v > range ? range : v; + v = v < 0 ? 0 : v; + return v; + }); + + // distance to target + const current = []; + for (let i in currentFeatures) { + let w = currentFeatures[i]; + let currentDistance = Math.abs(w - minFeature); + let dif = Math.abs(currentDistance - target[i]); + current.push(dif); + } + + return arrMean(current)/range; +} + + +// check if the important part of text are typeset in a bolder typeface +const checkWeightFeature = (current, dist) => { + + // semantic data range + const maxSemantic = arrMax(dist); + const minSemantic = arrMin(dist); + + // max feature range + const maxFeature = arrMax(current); + const minFeature = arrMin(current); + + // create target feature values + const probs = dist.map((e) => { + let v = e[3]/maxSemantic * maxFeature; + if (e[3] === minSemantic) { + v = minFeature; + } + return v; + }); + + // calculate distance + let distance = []; + for (let i in current) { + let w = current[i] + let value = Math.abs(w-probs[i]); + distance.push(value); + } + + return arrMean(distance)/Math.abs(maxFeature-minFeature); +} + + +export { compute as default }; \ No newline at end of file diff --git a/src/@evoposter/evaluator/src/utils.js b/src/@evoposter/evaluator/src/utils.js index 8b3411f..7d0623e 100644 --- a/src/@evoposter/evaluator/src/utils.js +++ b/src/@evoposter/evaluator/src/utils.js @@ -10,3 +10,11 @@ export const arrMean = (arr) => { export const arrSum = (arr) => { return arr.reduce((partialSum, a) => partialSum + a, 0); } + +export const arrMax = (arr) => { + return Math.max(...arr); +} + +export const arrMin = (arr) => { + return Math.min(...arr); +} \ No newline at end of file diff --git a/src/client/controllers/Poster.js b/src/client/controllers/Poster.js index e728443..6b2dabc 100644 --- a/src/client/controllers/Poster.js +++ b/src/client/controllers/Poster.js @@ -226,6 +226,9 @@ class Poster { evaluate = async (dist) => { this.phenotype = await this.draw(); const layoutSemantics = evaluator.layoutSemantics(this.genotype["grid"]["rows"]["l"], dist, `RELATIVE`, this.genotype["size"]); + const visualSemantics = evaluator.visualSemantics(this.genotype["textboxes"], dist); + + console.log (`visualSemantics`, visualSemantics); this.fitness = layoutSemantics; diff --git a/src/public/app.js b/src/public/app.js index e1f5f70..85692c3 100644 --- a/src/public/app.js +++ b/src/public/app.js @@ -339,7 +339,7 @@ const ae=2;class le{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,r) `:U}