From 1398cffc890a3984a39fa378f205f33ffdc5c817 Mon Sep 17 00:00:00 2001 From: Eyal Gruss Date: Thu, 25 Jan 2024 03:32:01 +0200 Subject: [PATCH] petri layout --- resen/petri/petri.json | 2 +- resen/petri/script.js | 84 +++++++++++++++++++++++------------------- resen/petri/style.css | 4 +- 3 files changed, 49 insertions(+), 41 deletions(-) diff --git a/resen/petri/petri.json b/resen/petri/petri.json index eba2d7b..f097bd4 100644 --- a/resen/petri/petri.json +++ b/resen/petri/petri.json @@ -52,7 +52,7 @@ "איבה עזה": 1 }, - "labels": {"בית עלמין ישראל": "ISRAEL CEMETERY", "פיגוע": "TERROR ATTACK", "כלא": "PRISON", "חילוף": "SWAP", "שבי": "CAPTIVITY", "פטירה_ישראל": "PASSING", "ישראל": "ISRAEL", "חטיפה": "ABDUCTION|ABDUCT", "ארגון טרור": "TERROR GROUP", "רבייה_עזה": "BREEDING|BREED", "איבה ישראל": "ISRAEL ENMITY", "רבייה_ישראל": "BREEDING|BREED", "איבה עזה": "GAZA ENMITY", "הסתה": "INCITEMENT|INCITE", "עזה": "GAZA", "שחרור": "DISCHARGE|DISCHAR", "צבא": "MILITARY", "מבצע": "OPERATION|OPERATE", "בית עלמין עזה": "GAZA CEMETERY", "פטירה_עזה": "PASSING"}, + "labels": {"בית עלמין ישראל": "ISRAEL CEMETERY", "פיגוע": "TERROR ATTACK", "כלא": "PRISON", "חילוף": "SWAP", "שבי": "CAPTIVITY", "פטירה_ישראל": "PASSING", "ישראל": "ISRAEL", "חטיפה": "ABDUCTION|ABDUCT", "ארגון טרור": "TERROR GROUP", "רבייה_עזה": "BREEDING", "איבה ישראל": "ISRAEL ENMITY", "רבייה_ישראל": "BREEDING", "איבה עזה": "GAZA ENMITY", "הסתה": "INCITEMENT|INCITE", "עזה": "GAZA", "שחרור": "DISCHARGE", "צבא": "MILITARY", "מבצע": "OPERATION|MIL OP", "בית עלמין עזה": "GAZA CEMETERY", "פטירה_עזה": "PASSING"}, "require": [ ["ישראל", "צבא"], diff --git a/resen/petri/script.js b/resen/petri/script.js index d8e448e..db62bc0 100644 --- a/resen/petri/script.js +++ b/resen/petri/script.js @@ -7,10 +7,12 @@ const fast = location.hash.slice(1) == 'fast' const auto_vertical = true const label_location = 'half' // Can be: 'half' (half above and half below, favoring the below), 'above', or anything else to indicate below const default_token_symbol = 'o' // Cannot be of 1-9 or capital A-N -const arrow_width = 6 +const arrow_width = 4 const arrow_height = 1 -const arrow_diagonal = 3 -const diagonal_offset = 19 +const arrow_short_diag = 3 +const short_diag_offset = 19 +const leaderline_factor1 = .17 +const leaderline_factor2 = .025 const comp_marking = 5 const lang = get_lang() @@ -44,10 +46,10 @@ function center(label, width, align_start=false) { return label.padEnd((width+sanitized_len(label)+align_start) / 2).padStart(width) } -function diagonal_arrows(ts, te, bs, be) { - let arrow_ts = arrow_te = arrow_bs = arrow_be = ' '.repeat(arrow_diagonal + 1) - const slashes = '/'.repeat(arrow_diagonal) - const backslashes = '\\'.repeat(arrow_diagonal) +function short_diag_arrows(ts, te, bs, be) { + let arrow_ts = arrow_te = arrow_bs = arrow_be = ' '.repeat(arrow_short_diag + 1) + const slashes = '/'.repeat(arrow_short_diag) + const backslashes = '\\'.repeat(arrow_short_diag) if (ts) arrow_ts = ts == 1 ? 'v' + slashes : slashes + '^' if (te) @@ -56,12 +58,12 @@ function diagonal_arrows(ts, te, bs, be) { arrow_bs = bs == 1 ? '^' + backslashes : backslashes + 'v' if (be) arrow_be = be == 1 ? '^' + slashes : slashes + 'v' - diagonals = Array(3).fill('') + short_diags = Array(3).fill('') for (const i in arrow_ts) { - const spaces = ' '.repeat(diagonal_offset + 2*i) - diagonals = [arrow_ts[i] + spaces + arrow_te[i] , ...diagonals, arrow_bs[i] + spaces + arrow_be[i]] + const spaces = ' '.repeat(short_diag_offset + 2*i) + short_diags = [arrow_ts[i] + spaces + arrow_te[i] , ...short_diags, arrow_bs[i] + spaces + arrow_be[i]] } - return diagonals.join('\n') + return short_diags.join('\n') } function trans_hor_symbol(label, len) { @@ -70,12 +72,20 @@ function trans_hor_symbol(label, len) { return `${shift}.${'-'.repeat(len)}.\n${shift}|${center(label, len, !!lang)}|\n${shift}'${'-'.repeat(len)}'` } +function fix_lang_align(string) { + return string.length == 1 || !lang ? string : string.match(/^( *)(.*?)( *)$/).slice(1).reverse().join('') +} + function trans_ver_symbol(label, len) { len = Math.max(len, place_lines.length - 2) - label = label.split(' ').map(l => center(l, len)) + if (label.length > len) + label = label.split(' ') + else + label = [label] + label = label.map(l => center(l, len)) const border = '-'.repeat(label.length * 3) const shift = ' '.repeat(label.length % 2 == 0) - const rows = [...label[0]].map((_, c) => label.map(row => row[c])).map(c => c.join(' ')).join(` |\n${shift}| `) + const rows = [...label[0]].map((_, c) => label.map(row => row[c])).map(c => fix_lang_align(c.join(' '))).join(` |\n${shift}| `) return `${len % 2 ? '' : '\n'}${shift}.${border}.\n${shift}| ${rows} |\n${shift}'${border}'` } @@ -121,7 +131,7 @@ function arrows(inside, outside, clue) { let arrow_body, inside_head, outside_head const is_hor = typeof clue == 'string' if (is_hor) { - arrow_body = '-'.repeat(arrow_width - clue.split(' ').length*1.5) + arrow_body = '-'.repeat(arrow_width + 2 - clue.split(' ').length*1.5) inside_head = '>' outside_head = '<' } else { @@ -221,7 +231,7 @@ function step(grid, json, steps=0, max_tokens={}, result_counter={}, reset_count missing_arrows.push([elem, pelem, inp, out]) }) if (ts || te || bs || be) - elem.firstChild.dataset.before = diagonal_arrows(ts, te, bs, be) + elem.firstChild.dataset.before = short_diag_arrows(ts, te, bs, be) } else { elem.firstChild.textContent = place_symbol(label, tokens[elem.dataset.id], elem.classList.contains('above')) if (!steps) { @@ -233,7 +243,7 @@ function step(grid, json, steps=0, max_tokens={}, result_counter={}, reset_count }) if (!comp && !grid.querySelector('.leader-line')) { - const leaderline_options = {color: getComputedStyle(grid.parentElement).getPropertyValue('--color'), dash: {len: 5, gap: 6}, endPlug: 'arrow2', endPlugSize: 2, path: 'straight', size: 1} + const leaderline_options = {color: getComputedStyle(grid.parentElement).getPropertyValue('--color'), dash: {len: 15, gap: 10}, endPlug: 'arrow2', endPlugSize: 2, path: 'straight', size: 1} missing_arrows.forEach(([telem, pelem, inp, out]) => { const tindex = elems.indexOf(telem) const pindex = elems.indexOf(pelem) @@ -241,14 +251,12 @@ function step(grid, json, steps=0, max_tokens={}, result_counter={}, reset_count const tcol = tindex % grid_columns const prow = pindex / grid_columns | 0 const pcol = pindex % grid_columns - const factor1 = 1/6 - const y1 = 50 + (trow-prow)*factor1*100 - const x1 = 50 + (pcol-tcol)*factor1*100 - const y2 = 50 + (prow-trow)*factor1*100 - const x2 = 50 + (tcol-pcol)*factor1*100 - const factor2 = 0.025 - const dy = Math.abs(pcol-tcol) * factor2 * 100 - const dx = (prow-trow) * Math.sign(pcol - tcol) * factor2 * 100 + const y1 = 50 + (trow-prow)*leaderline_factor1*100 + const x1 = 50 + (pcol-tcol)*leaderline_factor1*100 + const y2 = 50 + (prow-trow)*leaderline_factor1*100 + const x2 = 50 + (tcol-pcol)*leaderline_factor1*100 + const dy = Math.abs(pcol-tcol) * leaderline_factor2 * 100 + const dx = (prow-trow) * Math.sign(pcol - tcol) * leaderline_factor2 * 100 const c = (inp + out - 1) / 2 for (let i = 0; i < inp; i++) new LeaderLine(LeaderLine.pointAnchor(pelem, {x: x1 + (i-c)*dx + '%', y: y1 + (i-c)*dy + '%'}), LeaderLine.pointAnchor(telem, {x: x2 + (i-c)*dx + '%', y: y2 + (i-c)*dy + '%'}), leaderline_options) @@ -305,20 +313,20 @@ fetch(json_file).then(response => response.json()).then(json => { if (transitions.includes(label)) { if (json.vertical?.includes(label) || json.transitions[label][2] == 'vertical' || elem.id in json.transitions) pre.classList.add('vertical') - let hor = ver = outer = 0 - let top_arrows = bottom_arrows = false - json.transitions[label].slice(0, 2).flat().forEach(place => { - const is_hor = index % cols && labels[index - 1] == place || (index+1) % cols && labels[index + 1] == place - hor += is_hor - const top_arrow = labels[index - cols] == place - top_arrows |= top_arrow - const bottom_arrow = labels[index + cols] == place - bottom_arrows |= bottom_arrow - const is_ver = top_arrow || bottom_arrow - ver += is_ver - }) - if (auto_vertical && hor > ver) - pre.classList.add('vertical') + if (auto_vertical && !(elem.id in json.transitions)) { + let hor = ver = 0 + json.transitions[label].slice(0, 2).flat().forEach(place => { + const pindex = labels.indexOf(place) + const trow = index / cols | 0 + const tcol = index % cols + const prow = pindex / cols | 0 + const pcol = pindex % cols + hor += Math.abs(trow - prow) < Math.abs(tcol - pcol) + ver += Math.abs(trow - prow) > Math.abs(tcol - pcol) + }) + if (hor > ver) + pre.classList.add('vertical') + } if (json.labels[label].includes('|')) json.labels[label] = json.labels[label].split('|')[pre.classList.contains('vertical') | 0] } else { diff --git a/resen/petri/style.css b/resen/petri/style.css index f5b313f..ad65fdd 100644 --- a/resen/petri/style.css +++ b/resen/petri/style.css @@ -20,7 +20,7 @@ .petri > div { display: grid; - grid-template-columns: repeat(var(--cols), 23ch); + grid-template-columns: repeat(var(--cols), 25ch); font-family: 'IBM Plex Mono', 'Courier New', monospace; justify-self: stretch; letter-spacing: initial; @@ -29,7 +29,7 @@ position: relative; text-align: center; --hor_offset: -2ch; - --ver_offset: -1.5em; + --ver_offset: -.75em; } .petri pre {