"use strict"; var questionState = new Map(); var globalLevel; var globalId; function randomId() { return works[randomInt(0, works.length-1)]; } var queryTypes = [ { modes: new Set(["novice", "intermediate", "expert"]), type: "hue", inputType: "range", generateInputAttrs: function(attrs) { return new Map([["min", "0"], ["max", "359"], ["value", "180"]]); }, changeEvents: ["input"], calculateScore: function(attrs) { var hue = attrs.get("hue"); return Math.min(360 - hue, hue); }, imgAttrsModifier: function(evt) { var imgAttrs = questionState.get(globalId); var hueRandomness = imgAttrs.get("hueRandomness"); var newHue = Number(evt.target.value); imgAttrs.set("hue", mod(newHue + (hueRandomness - 180), 360)); redraw(); }, filterStyleString: function(attrs) { return 'hue-rotate(' + attrs.get("hue") + 'deg)' }, generateDefaultAttrs: function() { var r = randomInt(0, 359); return new Map([["hueRandomness", r], ["hue", r]]); }, generateInputId: function(id) { return `hue-input-${id}`; } }, { modes: new Set(["intermediate", "expert"]), type: "contrast", inputType: "range", generateInputAttrs: function(attrs) { return new Map([["min", attrs.get("contrastLowerBound")], ["max", attrs.get("contrastUpperBound")], ["value", attrs.get("contrast")]]); }, changeEvents: ["input"], calculateScore: function(attrs) { var contrast = attrs.get("contrast"); return abs(100 - contrast); }, imgAttrsModifier: function(evt) { var imgAttrs = questionState.get(globalId); imgAttrs.set("contrast", Number(evt.target.value)); redraw(); }, filterStyleString: function(attrs) { return 'contrast(' + attrs.get("contrast") + '%)' }, generateDefaultAttrs: function() { var r = randomInt(50, 100); var mid = r + 50; var lowerBound = r; var upperBound = r + 100; return new Map([["contrast", mid], ["contrastLowerBound", lowerBound], ["contrastUpperBound", upperBound]]); }, generateInputId: function(id) { return `contrast-input-${id}`; } }, { modes: new Set(["expert"]), type: "saturation", inputType: "range", generateInputAttrs: function(attrs) { return new Map([["min", attrs.get("saturationLowerBound")], ["max", attrs.get("saturationUpperBound")], ["value", attrs.get("saturation")]]); }, changeEvents: ["input"], calculateScore: function(attrs) { var saturation = attrs.get("saturation"); return abs(100 - saturation); }, imgAttrsModifier: function(evt) { var imgAttrs = questionState.get(globalId); imgAttrs.set("saturation", Number(evt.target.value)); redraw(); }, filterStyleString: function(attrs) { return 'saturate(' + attrs.get("saturation") + '%)' }, generateDefaultAttrs: function() { var r = randomInt(50, 100); var mid = r + 50; var lowerBound = r; var upperBound = r + 100; return new Map([["saturation", mid], ["saturationLowerBound", lowerBound], ["saturationUpperBound", upperBound]]); }, generateInputId: function(id) { return `saturation-input-${id}`; } } ]; function load() { var urlParams = new URLSearchParams(window.location.search); var id = urlParams.get('id') var level = urlParams.get('level') if (!id) { id = randomId(); level = "novice"; } startGame(id, level); } function renderArtist(s) { return s.split('-').map(capitalize).join(' '); } function getArtist(id) { var info = artists[id] var artist = manifest.features[1].type.names[info] return renderArtist(artist); } function startGame(id, level) { document.getElementById('answer').innerHTML = ''; document.getElementById('scoring').innerHTML = ''; document.getElementById('sliders').innerHTML = ''; document.getElementById('question').innerHTML = ''; globalId = id; globalLevel = level; addQuestion(id, level); finalizeQuestion(id, level); redraw(); document.getElementById('copy').addEventListener('click', function() { navigator.clipboard.writeText(`${location.origin}/countervisual?id=${id}&level=${level}`) }); } function redraw() { var el = document.getElementById('img'); var styleString = '' for (var queryType of queryTypes) { if (queryType.modes.has(globalLevel)) { var attrs = questionState.get(globalId); styleString += ` ${queryType.filterStyleString(attrs)} ` } } el.setAttribute("style", 'filter: ' + styleString); } function addQuestion(id, level) { var attrs = new Map(); for (var queryType of queryTypes) { if (queryType.modes.has(level)) { attrs = new Map([...attrs, ...queryType.generateDefaultAttrs()]); } } document.getElementById('question').innerHTML = `
Countervisual #${id}
` + generateImgDom(id, "img"); document.getElementById('sliders').innerHTML = generateAttrDOM(id, level, attrs) questionState.set(id, attrs); } function getImgUrl(id) { return `/countervisual/static/data/${id}.jpg` } function generateImgDom(id, htmlId) { return `` } function finalizeQuestion(id, level) { for (var queryType of queryTypes) { var inputId = queryType.generateInputId(id); var input = document.getElementById(inputId); if (queryType.modes.has(level)) { for (var changeEvent of queryType.changeEvents) { input.addEventListener(changeEvent, queryType.imgAttrsModifier); } } } } function generateAttrDOM(id, level, attrs) { var dom = ``; for (var queryType of queryTypes) { if (queryType.modes.has(level)) { var attrString = generateAttrString(queryType.generateInputAttrs(attrs)); dom += `

`; } } dom += ``; return dom; } document.onload = load(); document.getElementById('score-game').addEventListener('click', function(evt) { var s = score(); var imageUrl = location.protocol + '//' + location.host + location.pathname + getImgUrl(globalId) var lensUrl = `https://www.google.com/searchbyimage?image_url=${imageUrl}&client=app` document.getElementById('scoring').innerHTML = `

You were ${s} points away from zero.

This work is by ${getArtist(globalId)}.

` document.getElementById('answer').innerHTML = `
Solution
` + generateImgDom(globalId, "ans"); evt.preventDefault(); }) document.getElementById('reset').addEventListener('click', function(evt) { startGame(globalId, globalLevel); }); document.getElementById('random-novice').addEventListener('click', function(evt) { startGame(randomId(), "novice"); }); document.getElementById('random-intermediate').addEventListener('click', function(evt) { startGame(randomId(), "intermediate"); }); document.getElementById('random-expert').addEventListener('click', function(evt) { startGame(randomId(), "expert"); }); function generateAttrString(attrs) { var attrString = ""; for (var [attr, val] of attrs) { attrString += ` ${attr}=${val}` } return attrString; } // Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random function randomInt(min, max) { var min = Math.ceil(min); var max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; } function score() { var total = 0; for (var queryType of queryTypes) { if (queryType.modes.has(globalLevel)) { total += queryType.calculateScore(questionState.get(globalId)); } } return total; } function mod(p, n) { var z = (p % n); if (z >= 0) { return z; } else { return z + n; } } function abs(a) { return Math.max(a, -a); } function capitalize(s) { return s.substr(0,1).toUpperCase() + s.substr(1); }