<h3>Welcome to Neurochromohexonics</h3>

  <div id="bgdiv">
    The rain in spain falls mainly on the plains.
  </div>

  <div id="voting">
    Is the foreground text color good or bad for the background color?
    <ul>
      <li>
        Click to change color:
        <input type="color" id="fgpicker" alt="A color picker"></input>
      </li>
      <li>
        Color is good:
        <button id="next">Next</button>
      </li>
    </ul>
</div>
h3 {
  font-family: monospace;
}

#bgdiv {
  width: 300;
  height: 300;
  border: 1px solid;
}
    // Code parsing rgb codes to hex.
    // This section cribbed from StackOverflow. Source:
    //   https://stackoverflow.com/questions/1740700/how-to-get-hex-color-value-rather-than-rgb-value
    // Slightly modified the regex to also accept rgba.

    var hexDigits = new Array
          ("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");

    //Function to convert rgb color to hex format
    function rgb2hex(rgb) {
     rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+).*\)$/);
     return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
    }

    function hex(x) {
      return isNaN(x) ? "00" : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
    }

    // End section cribbed from StackOverflow

    function hexFromInts(r, g, b){
      return '#' + hex(r) + hex(g) + hex(b);
    }

    function intsFromHex(hex){
      return [
        parseInt(hex[1] + hex[2], 16),
        parseInt(hex[3] + hex[4], 16),
        parseInt(hex[5] + hex[6], 16),
      ];
    }

    class Color{
      // stores colors internally as 3 ints from 0 to 255 inclusive
      // externally, use Color.fromRgbInts instead of constructor
      constructor(red, green, blue){
        this.red = Math.floor(red);
        this.green = Math.floor(green);
        this.blue = Math.floor(blue);
      }

      toRgbInts(){
        return [this.red, this.green, this.blue];
      }

      toHex(){
        return hexFromInts(...this.toRgbInts());
      }

      toNeural(){
        return [
          this.red / 255,
          this.green / 255,
          this.blue / 255
        ]
      }

      static fromRgbInts(r, g, b){
        return new Color(r, g, b)
      }

      // string in format rgb(n, n, n) or rgba(n, n, n, n)
      // a (alpha) value is ignored
      static fromRgbString(str){
        return Color.fromHex(rgb2hex(str));
      }

      static fromHex(hex){
        return new Color(...intsFromHex(hex))
      }

      static fromNeural(r, g, b){
        let red = Math.round(r * 255)
        let green = Math.round(g * 255)
        let blue = Math.round(b * 255)

        return new Color(red, green, blue)
      }

      static newRandom(){
        return Color.fromRgbInts(
          Math.floor((Math.random() * 256)),
          Math.floor((Math.random() * 256)),
          Math.floor((Math.random() * 256)))
      }
    }

    const Trainer = synaptic.Trainer;
    const Architect = synaptic.Architect;

    const generatorNetwork = new Architect.Perceptron(3,27,3);
    const generatorNetworkTrainer = new Trainer(generatorNetwork);

    function regenerateColors(event=null){
      let bgcolor = Color.newRandom()
      let fgcolor = generateForegroundColor(bgcolor);

      $('#bgdiv').css({
        'background-color': bgcolor.toHex(),
        'color': fgcolor.toHex()
      })
      $('#fgpicker').val(fgcolor.toHex());
    }

    function trainOnCurrentColors(){
      let bgcolor = Color.fromRgbString($('#bgdiv').css('background-color'));
      let fgcolor = Color.fromRgbString($('#bgdiv').css('color'))

      generatorNetworkTrainer.train([{
        input: bgcolor.toNeural(),
        output: fgcolor.toNeural()
      }])
    }

    function generateForegroundColor(bgcolor){
      let input = bgcolor.toNeural()
      let output = generatorNetwork.activate(input)

      return Color.fromNeural(...output);
    }

    function initPage(){
      $('#next').on('click', function(event){
        trainOnCurrentColors();
        regenerateColors();
        event.preventDefault()
      });

      $('#fgpicker').on('input', function(){
        $('#bgdiv').css({'color': this.value})
      })

      generatorNetworkTrainer.train([
        {input: [0, 0, 0], output: [1, 1, 1]},
        {input: [1, 1, 1], output: [0, 0, 0]}
      ])

      regenerateColors();
    }

    $(initPage);
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/synaptic/1.1.4/synaptic.js
  3. https://cdnjs.cloudflare.com/ajax/libs/tinyColorPicker/1.1.1/jqColorPicker.min.js