Commit 0e9c3790 authored by Pietro Saccardi's avatar Pietro Saccardi
Browse files

Added customizable konami background

parent e4b60c4a
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
<div id="knWrapper">
  <h4 class="d-konami m-2">Multidirectional Dijkstra background by Spak</h4>
  <button type="button" class="btn btn-light m-2 d-konami" data-toggle="modal" data-target="#knCustomizeModal">
    Customize
  </button>
  <button type="button" class="btn btn-light m-2 d-konami" data-kn-fn="redraw">
    Redraw
  </button>
  <svg class="w-100 h-100 position-fixed z-lowest" id="graph"></svg>
</div>
 No newline at end of file
+2 −1
Original line number Diff line number Diff line
@@ -6,11 +6,12 @@
{% block title %}{{ this.title }}{% endblock %}
{% block body %}
<body>
  {% include 'konami.html' %}
  <div class="container-fluid h-md-100 px-0">
    <div class="row h-md-100 mx-0">
      <div class="col-md-6 col-lg-5 order-md-2 inner-shadow px-0 h-100">
        <div class="scrollable-md">
          <svg class="w-100 h-100 position-fixed z-lowest" id="graph"></svg>
          {% include 'bg_graph.html' %}
          <header class="my-3 mx-3">
            <h1><img src="{{ '/images/logo.svg' | url}}" alt="Mittelab" class="logo d-block mx-auto"></h1>
            <p class="text-monospace text-center lead">

templates/konami.html

0 → 100644
+137 −0
Original line number Diff line number Diff line
<div class="modal fade" id="knCustomizeModal" tabindex="-1" role="dialog" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content bg-dark border-secondary outer-shadow">
      <div class="modal-header border-secondary">
        <h5 class="modal-title">Customize multi-directional Dijkstra</h5>
        <button type="button" class="close text-white" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <form>
          <div class="form-group form-row mb-1">
            <label for="knNSources" class="col text-right col-form-label col-form-label-sm">Num. of terminals</label>
            <div class="col-5">
              <input type="number" class="form-control-sm form-control" id="knNSources" value="10" min="2">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knGridUnit" class="col text-right col-form-label col-form-label-sm">Grid unit</label>
            <div class="input-group input-group-sm col-5">
              <input id="knGridUnit" type="number" class="form-control-sm form-control" aria-describedby="knPx" min="5" value="30">
                <div class="input-group-append">
                  <span class="input-group-text" id="knPx">px</span>
                </div>
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knCostNodeW" class="col text-right col-form-label col-form-label-sm">Edge cost node weight</label>
            <div class="col-5">
              <input type="number" class="form-control-sm form-control" id="knCostNodeW" value="5" min="0" step="0.1">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knCostRndFrac" class="col text-right col-form-label col-form-label-sm">Edge cost random fraction</label>
            <div class="col-5">
              <input type="range" class="form-control-sm form-control-range" id="knCostRndFrac" value="0.6" min="0.0" max="1.0" step="0.01">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knFeasCenterX" class="col text-right col-form-label col-form-label-sm">Node clearance center X</label>
            <div class="col-5">
              <input type="number" class="form-control-sm form-control" id="knFeasCenterX" value="0.5" step="0.01">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knFeasCenterY" class="col text-right col-form-label col-form-label-sm">Node clearance center Y</label>
            <div class="col-5">
              <input type="number" class="form-control-sm form-control" id="knFeasCenterY" value="0.3" step="0.01">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knFeasRad" class="col text-right col-form-label col-form-label-sm">Node clearance radius</label>
            <div class="col-5">
              <input type="number" class="form-control-sm form-control" id="knFeasRad" value="0.2" min="0" step="0.01">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knFeasFalloff" class="col text-right col-form-label col-form-label-sm">Node clearance falloff radius</label>
            <div class="col-5">
              <input type="number" class="form-control-sm form-control" id="knFeasFalloff" value="0.3" min="0" step="0.01">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knFeasFalloffExp" class="col text-right col-form-label col-form-label-sm">Node clearance falloff exponent</label>
            <div class="col-5">
              <input type="number" class="form-control-sm form-control" id="knFeasFalloffExp" value="0.8" step="0.01">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knFeasRndFrac" class="col text-right col-form-label col-form-label-sm">Node clearance random fraction</label>
            <div class="col-5">
              <input type="range" class="form-control-sm form-control-range" id="knFeasRndFrac" value="0.3" min="0.0" max="1.0" step="0.01">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knLblPcPerFrame" class="col text-right col-form-label col-form-label-sm">Max grid fraction labeled per frame</label>
            <div class="col-5">
              <input type="number" class="form-control-sm form-control" id="knLblPcPerFrame" min="0.0" max="1.0" value="0.004" step="0.0001">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knOpacity" class="col text-right col-form-label col-form-label-sm">Opacity</label>
            <div class="col-5">
              <input type="range" class="form-control-sm form-control-range" id="knOpacity" value="0.45" min="0.0" max="1.0" step="0.01">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knOpacityTempLbl" class="col text-right col-form-label col-form-label-sm">Temporary label opacity</label>
            <div class="col-5">
              <input type="range" class="form-control-sm form-control-range" id="knOpacityTempLbl" value="0.23" min="0.0" max="1.0" step="0.01">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knOpacityShortestPath" class="col text-right col-form-label col-form-label-sm">Shortest path opacity</label>
            <div class="col-5">
              <input type="range" class="form-control-sm form-control-range" id="knOpacityShortestPath" value="0.36" min="0.0" max="1.0" step="0.01">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knStrokeWShortestPath" class="col text-right col-form-label col-form-label-sm">Shortest path stroke width</label>
            <div class="col-5">
              <input type="number" class="form-control-sm form-control" id="knStrokeWShortestPath" min="0.0" value="5" step="0.1">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knTrunkCol" class="col text-right col-form-label col-form-label-sm">Steiner tree path color</label>
            <div class="col-5">
              <input type="text" class="form-control-sm form-control" id="knTrunkCol" value="#444">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knRayCol" class="col text-right col-form-label col-form-label-sm">Secondary path color</label>
            <div class="col-5">
              <input type="text" class="form-control-sm form-control" id="knRayCol" value="#fff">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knRootRad" class="col text-right col-form-label col-form-label-sm">Terminal radius</label>
            <div class="col-5">
              <input type="number" class="form-control-sm form-control" id="knRootRad" min="0.0" value="6" step="0.1">
            </div>
          </div>
          <div class="form-group form-row mb-1">
            <label for="knRootCol" class="col text-right col-form-label col-form-label-sm">Terminal color</label>
            <div class="col-5">
              <input type="text" class="form-control-sm form-control" id="knRootCol" value="#444">
            </div>
          </div>
        </form>
      </div>
      <div class="modal-footer border-secondary">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-light" data-kn-fn="redraw">Redraw</button>
      </div>
    </div>
  </div>
</div>
 No newline at end of file
+2 −1
Original line number Diff line number Diff line
@@ -2,7 +2,8 @@
{% block title %}{{ this.title }}{% endblock %}
{% block body %}
<body class="inner-shadow">
  <svg class="w-100 h-100 position-fixed z-lowest" id="graph"></svg>
  {% include 'bg_graph.html' %}
  {% include 'konami.html' %}
  <div class="container-fluid h-md-100">
    <div class="row h-100">
      <div class="col-md-5 col-lg-4 col-xl-3 col-xxl-2 px-0">
+63 −32
Original line number Diff line number Diff line
@@ -6,21 +6,43 @@ require('typeface-ubuntu');

import Konami from 'konami';

new Konami(function () {
    alert('Konami Code!')
});

const Snap = require( "imports-loader?this=>window,fix=>module.exports=0!snapsvg/dist/snap.svg.js" );
import {Dijkstra, GridGraph} from "./grid";
import $ from 'jquery';

function paintTree() {
    const GRID_UNIT = 30
    const N_SOURCES = 10
    const OPACITY = 0.45
    const TRUNK_COL = '#444' //'#7fc0c2'
    const RAY_COL = '#fff' //'#fff'
    const ROOT_COL = '#444' //'#222'
    function getSetting(camelId, defaultVal) {
        let settingInput = $(`#kn${camelId}`)
        let value = defaultVal
        if (settingInput.length == 1) {
            value = settingInput.val()
        }
        console.log(`Graph setting ${camelId}: ${value}`)
        return value
    }

    const GRID_UNIT = getSetting('GridUnit', 30)
    const N_SOURCES = getSetting('NSources', 10)

    const COST_NODE_W = getSetting('CostNodeW', 5.)
    const COST_RND_FRAC = getSetting('CostRndFrac', 0.6)

    const FEAS_CENTER = [getSetting('FeasCenterX', 0.5), getSetting('FeasCenterY', 0.3)]
    const FEAS_RAD = getSetting('FeasRad', 0.2)
    const FEAS_FALLOFF = getSetting('FeasFalloff', 0.3)
    const FEAS_FALLOFF_EXP = getSetting('FeasFalloffExp', 0.8)
    const FEAS_RND_FRAC = getSetting('FeasRndFrac', 0.3)

    const LBL_PC_PER_FRAME = getSetting('LblPcPerFrame', 1. / 250.)

    const OPACITY = getSetting('Opacity', 0.45)
    const OPACITY_TEMP_LBL = getSetting('OpacityTempLbl', 0.23)
    const OPACITY_SHORTEST_PATH = getSetting('OpacityShortestPath', 0.36)
    const STROKEW_SHORTEST_PATH = getSetting('StrokeWShortestPath', 5)
    const ROOT_RAD = getSetting('RootRad', 6)
    const TRUNK_COL = getSetting('TrunkCol', '#444')
    const RAY_COL = getSetting('RayCol', '#fff')
    const ROOT_COL = getSetting('RootCol', '#444')

    const graph = $('#graph')
    const W = graph.width()
@@ -30,7 +52,7 @@ function paintTree() {

    console.log(`Grid graph: ${N_X}×${N_Y}`)

    const LBLS_PER_FRAME = N_X * N_Y / 250
    const LBLS_PER_FRAME = N_X * N_Y * LBL_PC_PER_FRAME

    const embed = pos => [(W - N_X * GRID_UNIT) / 2 + pos[0] * GRID_UNIT, (H - N_Y * GRID_UNIT) / 2 + pos[1] * GRID_UNIT]

@@ -46,18 +68,13 @@ function paintTree() {
        let pos = grid.getNodeXY(node)
        pos[0] /= N_X
        pos[1] /= N_Y
        const center = [0.5, 0.3]
        const radius = 0.2
        const falloff = 0.3
        const exp = 0.8
        const rand_fraction = 0.3
        // Actual math:
        const dx = center[0] - pos[0]
        const dy = center[1] - pos[1]
        const dx = FEAS_CENTER[0] - pos[0]
        const dy = FEAS_CENTER[1] - pos[1]
        const l2 = Math.sqrt(dx * dx + dy * dy)
        const unit_l2 = Math.max(Math.min((l2 - radius) / falloff, 1.), 0.)
        const l2_pow_law = Math.pow(unit_l2, exp)
        const rand_lerp = l2_pow_law * (1. - rand_fraction) + rand_fraction * Math.random()
        const unit_l2 = Math.max(Math.min((l2 - FEAS_RAD) / FEAS_FALLOFF, 1.), 0.)
        const l2_pow_law = Math.pow(unit_l2, FEAS_FALLOFF_EXP)
        const rand_lerp = l2_pow_law * (1. - FEAS_RND_FRAC) + FEAS_RND_FRAC * Math.random()
        return rand_lerp
    }

@@ -85,17 +102,15 @@ function paintTree() {
        const dir = grid.getEdgeDirection(edge)
        // base l2 cost
        const l2 = dir_l2_len[dir2idx(dir)]
        const node_weight = 5.
        const rand_fraction = 0.6
        // Add a random component
        const artificial_cost = (1. + (Math.random() - 1.) * rand_fraction) * node_weight * (1. - node_feasibility(node))
        const artificial_cost = (1. + (Math.random() - 1.) * COST_RND_FRAC) * COST_NODE_W * (1. - node_feasibility(node))
        return l2 + artificial_cost
    }

    let algo = new Dijkstra(grid, edge_cost, {
        found_candidate: function (node, edge, other_node) {
            ensure_edge(edge)
            edges[edge].attr('opacity', 0.5 * OPACITY)
            edges[edge].attr('opacity', OPACITY_TEMP_LBL)
        },
        remove_candidate: function (node, edge, other_node) {
            edges[edge].attr('opacity', 0.)
@@ -105,16 +120,16 @@ function paintTree() {
            if (algo.labels[other_node].backlink != null) {
                edges[algo.labels[other_node].backlink].attr('opacity', 0.)
            }
            edges[edge].attr('opacity', 0.5 * OPACITY)
            edges[edge].attr('opacity', OPACITY_TEMP_LBL)
        },
        add_source: function(node, owner) {
            if (owner < N_SOURCES) {
                node_group.circle(...embed(grid.getNodeXY(node)), 6)
                node_group.circle(...embed(grid.getNodeXY(node)), ROOT_RAD)
                    .attr('stroke', TRUNK_COL)
                    .attr('strokeOpacity', 0.8 * OPACITY)
                    .attr('strokeWidth', 5)
                    .attr('strokeOpacity', OPACITY_SHORTEST_PATH)
                    .attr('strokeWidth', STROKEW_SHORTEST_PATH)
                    .attr('fill', ROOT_COL)
                    .attr('fillOpacity', 0.8 * OPACITY)
                    .attr('fillOpacity', OPACITY_SHORTEST_PATH)
            }
        }
    })
@@ -141,8 +156,8 @@ function paintTree() {
                    edges[edge]
                        .attr('opacity', 1.)
                        .attr('stroke', TRUNK_COL)
                        .attr('strokeOpacity', 0.8 * OPACITY)
                        .attr('strokeWidth', 5)
                        .attr('strokeOpacity', OPACITY_SHORTEST_PATH)
                        .attr('strokeWidth', STROKEW_SHORTEST_PATH)
                })
                if (algo.isRouted()) {
                    clearInterval(anim)
@@ -153,7 +168,21 @@ function paintTree() {
}

document.addEventListener('DOMContentLoaded', () => {
    $('[data-kn-fn="redraw"]').click(paintTree)
    paintTree()

    new Konami(function () {
        $('#knWrapper')
            .prependTo('body')
            .addClass('fixed-fill')
            .addClass('z-konami')
            .addClass('inner-shadow')
            .addClass('bg-dark')
        $('#graph')
            .removeClass('position-fixed')
            .addClass('fixed-fill')
        $('.d-konami').removeClass('d-konami')
    });
});

let resizeTimer = null
@@ -177,3 +206,5 @@ window.addEventListener('resize', () => {
        }
    }, 250)
});

Loading