### Magic square ✨

This is a panmagic square:

- the sum of each horizontal rows is the same
- the sum of each vertical rows is the same
- the sum of each main diagonal row is the same

Each day there is a different magic square. Search for the magic constant value.
Use the choice slider to set/find it.

```const turtle = new Turtle();
const text = new Text();

const today = new Date();

const day = today.getDay();
const date = today.getDate();
const month = today.getMonth();
const year = today.getFullYear();

const seed = (today.getTime() / 1000 / 60 / 60 / 24) | 0;
const size = day % 2 === 0 ? 5 : 7;
//const seed = 0; // min=1, max=200, step=1
//const size = 5; // min=5, max=7, step=2
const random = new Random(seed);

function range(from,to, step=1) {
var arr = [];
for(let i = from; i < to; i += step) arr.push(i);
return arr;
}

function getValues(rnd = 0) {
const r1 = (rnd * random.next()) | 0;
const r2 = 1 + (rnd/2 * random.next())|0;
const values = range(0, size).map(a => (a+r1) * r2);
random.shuffle(values);
return values;
}

const values1 = getValues(4);
const values2 = getValues(4);

const grid1 = range(0, size).map((_, y) => range(0, size).map((v, x, arr) => values1[(x + 4 + y * 3 - 4) % arr.length]));
const grid2 = range(0, size).map((_, y) => range(0, size).map((v, x, arr) => values2[(x + 3 + y * 2 - 3) % arr.length]));
const grid = grid1.map((a, y) => a.map((b, x) => grid1[y][x] + grid2[y][x]));

const solveHorizontal = grid.map(a => a.reduce((acc,curr) => acc + curr));
const solveVertical = transpose(grid).map(a => a.reduce((acc,curr) => acc + curr));
const solveDiagonal1 = grid.map((a,idx, arr) => a[idx]).reduce((acc,curr) => acc + curr);
const solveDiagonal2 = grid.map((a,idx, arr) => a[arr.length - 1 - idx]).reduce((acc,curr) => acc + curr);
const validGrid = !solveHorizontal.find(v => v!==solveDiagonal1 && v!==solveDiagonal2) && !solveVertical.find(v => v!==solveDiagonal1 &&v!==solveDiagonal2);
// console.log(validGrid, [solveHorizontal, solveVertical, [solveDiagonal1], [solveDiagonal2]].toString());

const choice = 0; // min=5, max=200, step=1
Canvas.setpenopacity(-1);
} else {
Canvas.setpenopacity(1);
}

function walk(i) {
let offset = [size/2|0,size/2|0];
let scale = 175/size;
grid.forEach((a, y) => a.forEach((v, x) => {
turtle.jump(scl(sub([x,y], offset), scale));
text.print(turtle, `\${v}`, Math.max(1.25/size, .12));
}));
offset[0]-=0.1;
offset[1]-=0.1;
grid.forEach((a, y, yy) => a.forEach((v, x, xx) => {
if (x<xx.length-1) {
turtle.jump(scl(sub([x,y], offset), scale));
turtle.goto(scl(sub([x+1,y], offset), scale));
}
if (y<yy.length-1) {
turtle.jump(scl(sub([x,y], offset), scale));
turtle.goto(scl(sub([x,y+1], offset), scale));
}
if (x == 0 && y==0) {
turtle.jump(scl(sub([x,y], offset), scale));
turtle.goto(scl(sub([x+xx.length-1,y+yy.length-1], offset), scale));
}
if (x == xx.length-1 && y== 0) {
turtle.jump(scl(sub([x,y], offset), scale));
turtle.goto(scl(sub([0,yy.length-1], offset), scale));
}
}));
turtle.jump(0,-9999);
const label = `\${choice}!`;
text.print(turtle, label, 3);
const textX = -turtle.x() / 2
for(let i=0;i<10;i+=2) {
turtle.jump(textX+i, i);
text.print(turtle, label, 3);
}
}
return false;
}

// vec2 functions
function scl(a,b)   { return [a[0]*b, a[1]*b]; }
function add(a,b)   { return [a[0]+b[0], a[1]+b[1]]; }
function sub(a,b)   { return [a[0]-b[0], a[1]-b[1]]; }

// from: <https://stackoverflow.com/a/38518519>
function transpose(matrix) {
const len = matrix.length;
const result = [];
for (let i = 0; i < len; i++) { result.push([]); }
for (let i = 0; i < len; i++) {
for (let j = 0; j < matrix[i].length; j++) {
const temp = matrix[i][j];
result[j][i] = temp;
}
}
return result;
}

////////////////////////////////////////////////////////////////
// Text utility code. Created by Reinder Nijhoff 2019
// https://turtletoy.net/turtle/1713ddbe99
////////////////////////////////////////////////////////////////
function Text() {
class Text {
print (t, str, scale = 1, italic = -.075, kerning = 0.85) {
let pos = [t.x(), t.y()], h = t.h(), o = pos;
str.split('').map(c => {
const i = c.charCodeAt(0) - 32;
if (i < 0 ) {
pos = o = this.rotAdd([0, 48*scale], o, h);
} else if (i > 96 ) {
pos = this.rotAdd([16*scale, 0], o, h);
} else {
const d = dat[i], lt = d[0]*scale, rt = d[1]*scale, paths = d[2];
paths.map( p => {
t.up();
p.map( s=> {
t.goto(this.rotAdd([(s[0]-s[1]*italic)*scale - lt, s[1]*scale], pos, h));
t.down();
});
});
pos = this.rotAdd([(rt - lt)*kerning, 0], pos, h);
}
});
}
return [Math.cos(h)*a[0] - Math.sin(h)*a[1] + b[0],
Math.cos(h)*a[1] + Math.sin(h)*a[0] + b[1]];
}
}

const dat = ('br>eoj^jl<jqirjskrjq>brf^fe<n^ne>`ukZdz<qZjz<dgrg<cmqm>`thZhw<lZlw<qao_l^h^e_caccdeefg'+
'gmiojpkqmqporlshsercp>^vs^as<f^h`hbgdeeceacaab_d^f^h_k`n`q_s^<olmmlolqnspsrrspsnqlol>]wtgtfsereqfph'+
'nmlpjrhsdsbraq`o`makbjifjekckaj_h^f_eaecffhimporqssstrtq>eoj`i_j^k_kajcid>cqnZl\\j_hcghglhqjulxnz>c'+
'qfZh\\j_lcmhmllqjuhxfz>brjdjp<egom<ogem>]wjajs<ajsj>fnkojpiojnkokqis>]wajsj>fnjniojpkojn>_usZaz>`ti'+
'^f_dbcgcjdofrisksnrpoqjqgpbn_k^i^>`tfbhak^ks>`tdcdbe`f_h^l^n_o`pbpdofmicsqs>`te^p^jfmfogphqkqmppnrk'+
'shserdqco>`tm^clrl<m^ms>`to^e^dgefhekenfphqkqmppnrkshserdqco>`tpao_l^j^g_ebdgdlepgrjsksnrppqmqlping'+
'hcecddaf_i^j^m_oapepjoomrjshserdp>fnjgihjikhjg<jniojpkojn>fnjgihjikhjg<kojpiojnkokqis>^vrabjrs>]wag'+
'sg<amsm>^vbarjbs>asdcdbe`f_h^l^n_o`pbpdofngjijl<jqirjskrjq>]xofndlcicgdfeehekfmhnknmmnk<icgefhfkgmh'+
'q^qs<chqh>fnj^js>brn^nnmqlrjshsfreqdndl>_tc^cs<q^cl<hgqs>`qd^ds<dsps>^vb^bs<b^js<r^js<r^rs>_uc^cs<c'+
'^qs<q^qs>_uh^f_daccbfbkcndpfrhslsnrppqnrkrfqcpan_l^h^>_tc^cs<c^l^o_p`qbqepgohlici>_uh^f_daccbfbkcnd'+
'pfrhslsnrppqnrkrfqcpan_l^h^<koqu>_tc^cs<c^l^o_p`qbqdpfoglhch<jhqs>`tqao_l^h^e_caccdeefggmiojpkqmqpo'+
'rlshsercp>brj^js<c^q^>_uc^cmdpfrisksnrppqmq^>asb^js<r^js>^v`^es<j^es<j^os<t^os>`tc^qs<q^cs>asb^jhjs'+
'<r^jh>`tq^cs<c^q^<csqs>cqgZgz<hZhz<gZnZ<gznz>cqc^qv>cqlZlz<mZmz<fZmZ<fzmz>brj\\bj<j\\rj>asazsz>fnkc'+
'ieigjhkgjfig>atpeps<phnfleiegfehdkdmepgrislsnrpp>`sd^ds<dhffhekemfohpkpmopmrkshsfrdp>asphnfleiegfeh'+
'dkdmepgrislsnrpp>atp^ps<phnfleiegfehdkdmepgrislsnrpp>asdkpkpiognfleiegfehdkdmepgrislsnrpp>eqo^m^k_j'+
'bjs<gene>atpepuoxnylzizgy<phnfleiegfehdkdmepgrislsnrpp>ate^es<eihfjemeofpips>fni^j_k^j]i^<jejs>eoj^'+
'k_l^k]j^<kekvjyhzfz>are^es<oeeo<ikps>fnj^js>[y_e_s<_ibfdegeifjijs<jimfoeretfuius>ateees<eihfjemeofp'+
'ips>atiegfehdkdmepgrislsnrppqmqkphnfleie>`sdedz<dhffhekemfohpkpmopmrkshsfrdp>atpepz<phnfleiegfehdkd'+
'mepgrislsnrpp>cpgegs<gkhhjfleoe>bsphofleieffehfjhkmlompopporlsisfrep>eqj^jokrmsos<gene>ateeeofrhsks'+
'mrpo<peps>brdejs<pejs>_ubefs<jefs<jens<rens>bseeps<pees>brdejs<pejshwfydzcz>bspees<eepe<esps>cqlZj['+
'i\\h^h`ibjckekgii<j[i]i_jakbldlfkhgjkllnlpkrjsiuiwjy<ikkmkojqirhthvixjylz>fnjZjz>cqhZj[k\\l^l`kbjci'+
'eigki<j[k]k_jaibhdhfihmjilhnhpirjskukwjy<kkimiojqkrltlvkxjyhz>^vamakbhdgfghhlknlplrksi<akbidhfhhill'+
'nmpmrlsisg>brb^bscsc^d^dsese^f^fsgsg^h^hsisi^j^jsksk^l^lsmsm^n^nsoso^p^psqsq^r^rs').split('>').map(
r=> { return [r.charCodeAt(0)-106,r.charCodeAt(1)-106, r.substr(2).split('<').map(a => {const ret
= []; for (let i=0; i<a.length; i+=2) {ret.push(a.substr(i, 2).split('').map(b => b.charCodeAt(0)
-106));} return ret; })]; });

return new Text();
}

// Seeded random - Mulberry32
function Random(seed) {
class Random {
constructor(seed) {
this.seed = seed;
}
next() {
var t = this.seed += 0x6D2B79F5;
t = Math.imul(t ^ t >>> 15, t | 1);
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
return ((t ^ t >>> 14) >>> 0) / 4294967296;
}
shuffle(arr) {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(this.next() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
}
return new Random(seed);
}
```