~ciriarte/lakitu

d41924358db8d160a89e020380cb9af55ed9995c — Carlos Iriarte 1 year, 9 months ago 4c4fa35
Initial commit
6 files changed, 266 insertions(+), 21 deletions(-)

M public/index.html
M src/App.css
M src/App.tsx
A src/CidrInput.tsx
A src/Grid.tsx
M yarn.lock
M public/index.html => public/index.html +3 -2
@@ 5,6 5,7 @@
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css">
    <!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/


@@ 19,13 20,13 @@
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
    <title>Lakitu</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
    <div id="root" class="section"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

M src/App.css => src/App.css +4 -0
@@ 22,6 22,10 @@
  color: #61dafb;
}

input[type="pattern"] {
  width: 3em; 
}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);

M src/App.tsx => src/App.tsx +5 -15
@@ 1,25 1,15 @@
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import CidrInput from './CidrInput'
import Grid from './Grid'

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.tsx</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
        </header>
      <div className="container">
          <CidrInput value="10.0.0.0/16" />
          <Grid />
      </div>
    );
  }

A src/CidrInput.tsx => src/CidrInput.tsx +58 -0
@@ 0,0 1,58 @@
import React, { Component } from 'react';
import logo from './logo.svg';

type CidrInputProps = {
    value: string
}

class CidrInput extends Component<CidrInputProps, {}> {
    render() {
      const {a, b, c, d, suffix} = this.parse(this.props.value);

      return (
        <div className="field has-addons">
            <div className="field-body">
              <div className="control">
                  <input type="pattern" className="input is-large" defaultValue={String(a)} />
              </div>
              <div className="control">
                  <a className="button is-static is-large">.</a>
              </div>
              <div className="control">
                  <input type="pattern" className="input is-large" defaultValue={String(b)} />
              </div>
              <div className="control">
                  <a className="button is-static is-large">.</a>
              </div>
              <div className="control">
                  <input type="pattern" className="input is-large" defaultValue={String(c)} />
              </div>
              <div className="control">
                  <a className="button is-static is-large">.</a>
              </div>
              <div className="control">
                  <input type="pattern" className="input is-large" defaultValue={String(d)} />
              </div>
              <div className="control">
                  <a className="button is-static is-large">/</a>
              </div>
              <div className="control">
                  <input type="pattern" className="input is-large" defaultValue={String(suffix)} />
              </div>
            </div>
        </div>
    );
  }

  private parse(str: string): { a: number,  b: number, c: number, d: number, suffix: number} {
      return {
          a: 10,
          b: 0,
          c: 0,
          d: 0,
          suffix: 16
      };
  }
}

export default CidrInput;

A src/Grid.tsx => src/Grid.tsx +95 -0
@@ 0,0 1,95 @@
import * as React from 'react';


const styles: React.CSSProperties = {
    fill: "white",
        stroke: "grey", 
        strokeWidth: 0.7
    };

const textStyle = { styles, ...{ fill: "black", fontSize: 10 }};

class Grid extends React.Component {
   cells = 16;
   cellSize = 50;

   render() {
       const networks: any[] = [];
       const labels: any[] = [];
        for (let i=0; i < this.cells; i++) {
            for (let j=0; j < this.cells; j++) {
                const [ax, ay] = this.corner(1+i, j);
                const [bx, by] = this.corner(i, j);
                const [cx, cy] = this.corner(i, j+1);
                const [dx, dy] = this.corner(i+1, j+1);

                const network = `${ax},${ay} ${bx},${by} ${cx},${cy} ${dx},${dy}`;
                const dist = this.coordsToDistance(j, i);
                networks.push(<polygon key={dist} points={network}></polygon>);
                labels.push(<text key={dist} style={textStyle} x={bx + 2} y ={by + 10}>{dist}</text>);
            }            
        }


        return (
            <svg xmlns="http://www.w3.org/2000/svg" 
                 style={styles}
                 width={this.cells * this.cellSize} height={this.cells * this.cellSize}>
                 {networks}
                 {labels}
            </svg>
        );
    }

   corner(i: number, j: number): [number, number] {
        return [i*this.cellSize, j*this.cellSize];
   }

   coordsToDistance(i: number, j: number): number {
       let x: number, y: number, distance: number = 0;
       for (let s = this.cells; s >= 1; s = s / 2) {
           x = +((i & s) > 0);
           y = +((j & s) > 0);
           distance += s * s * ((3 * x) ^ y);
           console.log(`i, j, s, x, y => ${i} ${j} ${s} ${x} ${y}`);
           let res = this.rotate(s, i, j, x, y);
           i = res.x;
           j = res.y;
           console.log(`Rotated: ======> ${i} ${j} ${s} ${x} ${y}`);
       }
       return distance;
   }

   distanceToCoords(distance: number) {
       let x = 0, y = 0;
       let t = distance;
       for (let s = 1; s < this.cells / 2; s = s * 2) {
           let rx = 1 & (t / 2);
           let ry = 1 & (t ^ rx);
           let res = this.rotate(s, x, y, rx, ry);
           x = res.x;
           y = res.y;
           x += s * rx;
           y += s * ry;
           t = t / 4;
       }
       return {x, y};
   }

   rotate(n: number, x: number, y: number, rx: number, ry: number): {x: number, y: number} {
       if (ry === 0) {
           if (rx === 1) {
               x = n - 1 - x;
               y = n - 1 - y;
           }

           let temp = x;
           x = y;
           y = temp;
       }

       return {x, y};
   }
}

export default Grid;

M yarn.lock => yarn.lock +101 -4
@@ 1339,6 1339,11 @@ async@^2.1.4, async@^2.5.0:
  dependencies:
    lodash "^4.17.10"

async@~1.0.0:
  version "1.0.0"
  resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9"
  integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=

asynckit@^0.4.0:
  version "0.4.0"
  resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"


@@ 2225,6 2230,11 @@ color@^3.0.0:
    color-convert "^1.9.1"
    color-string "^1.5.2"

colors@1.0.x:
  version "1.0.3"
  resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
  integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=

colors@~1.1.2:
  version "1.1.2"
  resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"


@@ 2678,6 2688,11 @@ csstype@^2.2.0:
  resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.5.8.tgz#4ce5aa16ea0d562ef9105fa3ae2676f199586a35"
  integrity sha512-r4DbsyNJ7slwBSKoGesxDubRWJ71ghG8W2+1HcsDlAo12KGca9dDLv0u98tfdFw7ldBdoA7XmCnI6Q8LpAJXaQ==

cycle@1.0.x:
  version "1.0.3"
  resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2"
  integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI=

cyclist@~0.2.2:
  version "0.2.2"
  resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"


@@ 2961,6 2976,11 @@ dom-serializer@0:
    domelementtype "~1.1.1"
    entities "~1.1.1"

dom-walk@^0.1.0:
  version "0.1.1"
  resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
  integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=

domain-browser@^1.1.1:
  version "1.2.0"
  resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"


@@ 3368,6 3388,11 @@ etag@~1.8.1:
  resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
  integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=

event-lite@^0.1.1:
  version "0.1.2"
  resolved "https://registry.yarnpkg.com/event-lite/-/event-lite-0.1.2.tgz#838a3e0fdddef8cc90f128006c8e55a4e4e4c11b"
  integrity sha512-HnSYx1BsJ87/p6swwzv+2v6B4X+uxUteoDfRxsAb1S1BePzQqOLevVmkdA15GHJVd9A9Ok6wygUR18Hu0YeV9g==

eventemitter3@^3.0.0:
  version "3.1.0"
  resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163"


@@ 3573,6 3598,11 @@ extsprintf@^1.2.0:
  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
  integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=

eyes@0.1.x:
  version "0.1.8"
  resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0"
  integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=

fast-deep-equal@^1.0.0:
  version "1.1.0"
  resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"


@@ 4026,6 4056,14 @@ global-prefix@^1.0.1:
    is-windows "^1.0.1"
    which "^1.2.14"

global@^4.3.2:
  version "4.3.2"
  resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f"
  integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=
  dependencies:
    min-document "^2.19.0"
    process "~0.5.1"

globals@^11.1.0, globals@^11.7.0:
  version "11.8.0"
  resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d"


@@ 4456,7 4494,7 @@ identity-obj-proxy@3.0.0:
  dependencies:
    harmony-reflect "^1.4.6"

ieee754@^1.1.4:
ieee754@^1.1.4, ieee754@^1.1.8:
  version "1.1.12"
  resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b"
  integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==


@@ 4575,6 4613,11 @@ inquirer@6.2.0, inquirer@^6.1.0:
    strip-ansi "^4.0.0"
    through "^2.3.6"

int64-buffer@^0.1.9:
  version "0.1.10"
  resolved "https://registry.yarnpkg.com/int64-buffer/-/int64-buffer-0.1.10.tgz#277b228a87d95ad777d07c13832022406a473423"
  integrity sha1-J3siiofZWtd30HwTgyAiQGpHNCM=

internal-ip@^3.0.1:
  version "3.0.1"
  resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-3.0.1.tgz#df5c99876e1d2eb2ea2d74f520e3f669a00ece27"


@@ 4973,7 5016,7 @@ isobject@^3.0.0, isobject@^3.0.1:
  resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
  integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=

isstream@~0.1.2:
isstream@0.1.x, isstream@~0.1.2:
  version "0.1.2"
  resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
  integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=


@@ 5987,6 6030,13 @@ mimic-fn@^1.0.0:
  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
  integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==

min-document@^2.19.0:
  version "2.19.0"
  resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
  integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=
  dependencies:
    dom-walk "^0.1.0"

mini-css-extract-plugin@0.4.3:
  version "0.4.3"
  resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.3.tgz#98d60fcc5d228c3e36a9bd15a1d6816d6580beb8"


@@ 6120,6 6170,16 @@ ms@^2.1.1:
  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
  integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==

msgpack-lite@^0.1.26:
  version "0.1.26"
  resolved "https://registry.yarnpkg.com/msgpack-lite/-/msgpack-lite-0.1.26.tgz#dd3c50b26f059f25e7edee3644418358e2a9ad89"
  integrity sha1-3TxQsm8FnyXn7e42REGDWOKprYk=
  dependencies:
    event-lite "^0.1.1"
    ieee754 "^1.1.8"
    int64-buffer "^0.1.9"
    isarray "^1.0.0"

multicast-dns-service-types@^1.1.0:
  version "1.1.0"
  resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901"


@@ 6184,6 6244,16 @@ neo-async@^2.5.0:
  resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835"
  integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==

neovim@^4.2.1:
  version "4.2.1"
  resolved "https://registry.yarnpkg.com/neovim/-/neovim-4.2.1.tgz#25e99703831fafd9e26190feec15366bebfda8c0"
  integrity sha512-2Kto3HlBsFFtgyAmV8ecNtBBUrydoXp2EfIHwIvuhOIiVinCuKJaUmp1+1u5eGGu1TDZHUiHwvFv0T05eG8T+w==
  dependencies:
    lodash "^4.17.4"
    msgpack-lite "^0.1.26"
    traverse "^0.6.6"
    winston "^2.3.1"

nice-try@^1.0.4:
  version "1.0.5"
  resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"


@@ 7510,6 7580,11 @@ process@^0.11.10:
  resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
  integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=

process@~0.5.1:
  version "0.5.2"
  resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf"
  integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=

progress@^2.0.0:
  version "2.0.1"
  resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.1.tgz#c9242169342b1c29d275889c95734621b1952e31"


@@ 7740,7 7815,7 @@ react-dev-utils@^6.1.1:
    strip-ansi "4.0.0"
    text-table "0.2.0"

react-dom@16.6.3:
react-dom@^16.6.3:
  version "16.6.3"
  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.6.3.tgz#8fa7ba6883c85211b8da2d0efeffc9d3825cccc0"
  integrity sha512-8ugJWRCWLGXy+7PmNh8WJz3g1TaTUt1XyoIcFN+x0Zbkoz+KKdUyx1AQLYJdbFXjuF41Nmjn5+j//rxvhFjgSQ==


@@ 7810,7 7885,7 @@ react-scripts@2.1.1:
  optionalDependencies:
    fsevents "1.2.4"

react@16.6.3:
react@^16.6.3:
  version "16.6.3"
  resolved "https://registry.yarnpkg.com/react/-/react-16.6.3.tgz#25d77c91911d6bbdd23db41e70fb094cc1e0871c"
  integrity sha512-zCvmH2vbEolgKxtqXL2wmGCUxUyNheYn/C+PD1YAjfxHC54+MhdruyhO7QieQrYsYeTxrn93PM2y0jRH1zEExw==


@@ 8665,6 8740,11 @@ stable@~0.1.6:
  resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
  integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==

stack-trace@0.0.x:
  version "0.0.10"
  resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
  integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=

stack-utils@^1.0.1:
  version "1.0.1"
  resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620"


@@ 9054,6 9134,11 @@ tr46@^1.0.1:
  dependencies:
    punycode "^2.1.0"

traverse@^0.6.6:
  version "0.6.6"
  resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
  integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=

trim-right@^1.0.1:
  version "1.0.1"
  resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"


@@ 9567,6 9652,18 @@ wide-align@^1.1.0:
  dependencies:
    string-width "^1.0.2 || 2"

winston@^2.3.1:
  version "2.4.4"
  resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.4.tgz#a01e4d1d0a103cf4eada6fc1f886b3110d71c34b"
  integrity sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q==
  dependencies:
    async "~1.0.0"
    colors "1.0.x"
    cycle "1.0.x"
    eyes "0.1.x"
    isstream "0.1.x"
    stack-trace "0.0.x"

wordwrap@~0.0.2:
  version "0.0.3"
  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"