Click to show TOC

TryITJs Tutorials

©Nurul Choudhury - 2020

Introduction

This is an introduction to TryITJs, a tool to create tutorials to Javascript libraries. It used a simple markup language to create these tutorials with runable code examples that the user can edit and experiment. The editing is non-destructive and you can go back to the original state by refreshing the browser. To make life easier for someone who wants to keep the edits and experiments and come back to it later, you can save your changes by clicking on the the save button . When you save some changes, these are ctored locally in your browser local storage.

To learn more tou can go to Why TryITjs

Directory Structure

Click on the image above to see a more detailed view

What is a .try file

Top level files

Top level files are simply text file with the extension .try. The first line on a top level file must start the !head. The fillowing section is an example of a very simple try file.

Basic Example

The code below is the basic.try file for the example

!head
  ~~lt%%title~~gt%%First Tryit~~lt%%/title~~gt%%
  @@include tools/head.try

!md 
  # Introduction
  This is a very simple **TryITjs** file. It has only one page.

  ## Code example

  This is a simple code example to create a javascript array and display it.

  Press the RUN button to execute the code (you can eddit the code and run again if you like)


!tryit
  var array = [ 'a String', 1 , { name: 'tryit'} ]; // array with a `string`, `number`, and an `object`
  array // the last expression is always displayed (except if the value is undefined) 


!md
  **What just happened**, if you execute the code above it will display the array just created. 

  __Note: the last expression `array` is displayed.__




  ## Content of basic.try (generated this content)
  ### Showing a .try file

  Below you will find the contents of basic.try file use to generate this page


  ```tryit
     @@include ESCAPE basic.try
  ```
  ### Showing a .try file

  The code snippet below will render the contents of a try file. Note, the __@@include__ must be followed by the
  word __ESCAPE__ to let the processor know the contents of the file is for display (ESCAPE tells the system not to process the contents as .try instructions )

!html
  ~~lt%%pre style="color: blue; font-size: 1.5rem;"~~gt%%
  ```tryit
     \@@include ESCAPE basic.try
  ```
  ~~lt%%/pre~~gt%%

!md
  ## Files included

  Including a file using `@@include filePathOrURL` will copy the contents into the file. The basic.try file includes
  the __tools/head.try__, you can see it's content below.

  ```tryit
     @@include ESCAPE tools/head.try
  ```

Two Page Example

In this example we show you how to create a multi page try file. The way to create a new page is to use '#' heading h1 to create a new page.

The following is the .try file used for this example

!head
  ~~lt%%title~~gt%%Sligltly More elaborate example - Machine Learning~~lt%%/title~~gt%%
  ~~lt%%script src="https://cdn.plot.ly/plotly-latest.min.js"~~gt%%~~lt%%/script~~gt%%
@@include tools/d3.try
@@include tools/head.try

  ~~lt%%script~~gt%%
  window.MathJax = {
    loader: {
      load: ['input/asciimath', 'output/chtml', 'ui/menu'],

    },
    asciimath: { delimiters: [['`','`'], ['%','%']], inlineMath: [['%', '%']] } 
  };
  ~~lt%%/script~~gt%%
  ~~lt%%script type="text/javascript" id="MathJax-script" async
  src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/startup.js"~~gt%%
  ~~lt%%/script~~gt%%
@@include ASSETS/doPlot.try          

!md 
    # Introduction
    This is a slightly more elaborate example, in the following pages we will show you how to create
    a model for estimating the cost of medical treatment. How to display the data in charts using D3.
    Finally it is to show how powerful machine learning algrothims can be inplemented in the browser.

    There is some math in the example and are explained, but you can skip over those if you are not
    ready to read through it. Hopefully I have kept the explanation simple enough to understand.

    ## Code example

    This is a simple code example to create a javascript array and display it.

!tryit
    var array = [ 'a String', 1 , { name: 'tryit'} ]; // array with a `string`, `number`, and an `object`
    array


!md
    **What just happened**, if you execute the code above it will display the array just created. 

    _Note: the last expression `array` is displayed._

    ## Some simple notes

    * You can edit the example above and runit as may time as you want
    * The code changes its theme once you edit it to show you
    A variable created within a **!tryit** snippet  usin a ``let`` only exists in the snipped

!md
    # Introduction to medical cost modeling

    This is a example of optimization useful in certain modeling for estimating the cost of service.
    The cost we are trying to estimate is the treatment of a medical conditions. This is not using a
    real medical condition or real data as will be explained later.



    ## Some utility functions
    1. ```expL``` take the exponent of the elements of an array
    2. ```rect``` acts like a rectifier in electronic circuit if val is negetive return 0, otherwise return the value, ```clamp``` id similar, returns 0 for negetive values and 1 for positive calues
    3. ```max``` returns the max value of a list
    4. ```stdPdiv``` get standard deviation uning only the poisitve values of an array 
    5. ```range``` Create a array with elemenst [0, 1, 2, ... n-1]
    6. ```zip``` Takes 2 lists (list1, list2)  and returns a new array with length of list1, where element ```i``` is a 2 element array [ list1[i], list2[i]  ]

!tryit
    function rect(a) { return a~~lt%%0?0:a;}
    function clamp(a) { return a~~lt%%0?0:1;}

    // Array  processing functions
    function max(list) {
      if(!list || list.length === 0) return 0;
      return list.reduce((m,v) =~~gt%% m~~lt%%v?v:m, list[0]);
    }
    function expL(arr) { return arr.map(v =~~gt%% Math.exp(v)); }

    // Get standard deviation of an
    function stdDiv(list) {
      if(!list || list.length ~~lt%%= 1) return 0;
      let res = list.reduce((m,v) =~~gt%% ([m[0]+1, m[1]+v*v, m[2]+v]), [0,0,0]);
      let mean = m[2]/m[0];
      return Math.sqrt(m[1]/m[0] - mean*mean);
    }

    function stdPdiv(list) {
      if(!list || list.length === 0) return 0;
      let res = list.reduce((m,v) =~~gt%% (v~~lt%%0?m:[m[0]+1, m[1]+v*v]), [0,0]);
      return Math.sqrt(m[1]/m[0]);
    }

    // create a array with elemenst [0, 1, 2, ... n-1]
    function range(n) {
      let res = []
      for(let i=0; i~~lt%%n; i++) res.push(i);
      return res;
    }

    // return an array with length of list1, where element ```i``` is a 2 element array [ list1[i], list2[i]  ] 
    function zip(list1, list2) {
       return list1.map((v,i) =~~gt%% [v,  list2[i] ])
    }

    function unzip(list) {
      return [ list.map(([x,y]) =~~gt%% x),  list.map(([x,y]) =~~gt%% y) ];
    }

    // Add elements of an array
    function sum(list,add) { 
        if(!add) add = (a,b) =~~gt%% a+b;
        return list.reduce(add,0); 
    }

    // function to create a normally distributed random number (see. mean value theorem)
    function normalSample(n=12) {
      let v = 0;
      if(n===0) return 0;
      for(let i=0; i~~lt%%n; i++) v += (Math.random()-0.5);
      return v/n;
    }

!md
    # Modeling Medical treatment

    This more elaborate example will investigate a data science problem; the modeling of metical treatment for a
    particular medical condition. For this example we will be creating some synthetic data rauther than 
    using actual medical claims data. The model assumes that all patients are not the same, some have other underlying
    medical issues that make the treatment more expensive. We will call these risk factors. Examples of risk factors
    might be age, older than 65, or younger than 5. Other factors might be pregnency, or high blood pressure. These risk
    factors increase the cost of treating the condition. The problem is that we only have the raw cost of treatment
    data and knowledge of the underlying condition. What we do not have is how they affect the cost of treatment.

    The purpose of the remaining section is model the cost of treatment and discover how these factors change the cost 
    of treatment model.

    1. Average base cost, the cost incured by most patients
    2. Number of additional complications that increase the cost of treatment. Example of thos those may be age, if you are older or very young. A simple model is to assume that each condition increases the cost by a certain percent.
        - ```Cost = Base * factor1 * factor2 * factor3...```,  where factor1, factor2  percentage 
        increase on the cost of treating a patient with thouse aditional factors.
        - This can also be written in exponential form   
        - __Cost = exp( b + f1 + f2 + f3 )__   where __b = log(Base)__ , and __f1 = log(factor1)__ ...
    3. The values of **b, f1, f2...** (also refered to as cost factors) are unknown, but we have data for 
    the cost of service for thousands of patients. We will use the data to estimate the values of the cost factors.
    4. This similar to a regression problem




    Object to model the cost of treatment, this has the following attributes
    1. ```real``` the actual cost of treatment
    2. ```factorFlag``` this is an array of 1 or 0 for each of the cost factors 1 = factor present for the patient, 0 = factor not present
    3. ```real``` holds the real cost. Since we do not actually have real data we will create some simulated data,
        * All patients have the base factor ```b``` in other words `factor0` (100% probablity)
        * The other factors have a relative probability of occuring, `factor1` has  30% chance, `factor2` has 10% chance and so on, this is allocodea using ```fillFactor()``` function. 
    4. ```current``` best estimate of cost prediction based on the factors estimates

!tryit

    var TreatmentCost = class { 
      constructor(factorEstimates, factorIndicators, realFactor) { 

        if(factorEstimates.factorFlag) {
            this.factorFlag = factorEstimates.factorFlag;
            this.logReal = factorEstimates.logReal; 
        } 
        else {
          // aray of flags 0 = patient has the risk factor, 0 = the patient does not have the risk factor
          this.factorFlag = Array.isArray(factorIndicators)? factorIndicators.slice() : factorIndicators();

          // create cost of treatment +/- 75% random fluctuations in the cost of treatment
          this.logReal = this.getRisk(realFactor)+Math.log(1 + normalSample()*1.5);
        }
        this.real = Math.exp(this.logReal);
        this.logCurrent = 0;
        this.current = 1;
      }


      get code() {
        // convert the factor flag bits to an integer
        // since each factor flag is 1 or 0, this can be used
        // to create an binary integer (each factor is a bit in the integer)
        // code = flag0*1 + flag1*2 + flag3*4 ...
        return this.factorFlag.reduceRight((s,v) =~~gt%% s*2+v, 0);
      }

      getRisk(factors) {
        let sumOfFactors = (total, v, i) =~~gt%% total+(v?factors[i]:0);
        return this.factorFlag.reduce(sumOfFactors, 0);
      }

      getCostIndex(factors) {
          return sum(this.factorFlag, ((s, v, i) =~~gt%% v?s+factor[i]:s));
      }

      hasRiskFactor(i) {
        return !!this.factorFlag[i];
      }

      setCurrent(factorEstimates) {
        this.logCurrent = this.getRisk(factorEstimates);
        this.current = Math.exp(this.logCurrent);
      }

      _setCurrent(cv) {
        this.current = cv;
        this.currentLog = Math.log(cv);
      }

      // derivitive of the factor with respect to factor[i], this is used to perform a gradient descent
      // search to the optimal value of the factors so that RMS difference of actual cost to computed cost based
      // on the factors is minimized.
      dx(i) {
        if(!this.hasRiskFactor(i)) return 0;
        return -(this.current-this.real)*this.current;
        //return -(this.logCurrent-this.logReal);
      }
    }
!md
    # Create synthetic treatment data

    This section we will create some synthetic data for our analysis. For this we will need to have an underlying
    model. A common model is to use what we call the multiplicative model, namely the fisk factor increases the cost
    of treatment by some percent. So we have a base cost of threatment, let us call this `factor0` and the other
    factors are `factor1`, `factor2` ...

    Every patient will have `factor0` and the total cost of treatment. Some patients will have `factor1` or not, and similarly
    for all the other factors. We choose which factors a patient has by rolling a dice, i.e. each factor has a probablity
    associated that it. 

    Finally we randomly increase or decrese the cost of treatment to reflect real treatment cost data.

    ## Setup some constants

    1. EPI_COUNT - number of test treatment data to create (we call each of those an episode)
    2. ITER - number of itteratins to compute the factors
    3. EPSILON - increment size for the gradient descent

!tryit
    var EPI_COUNT = 10000;
    var ITER = 1000;
    var EPSILON = 0.002;


!tryit
    // To create the data we will use(secret) underlying factor values,
    //                  Base factor1 factor2 ...
    var actualFactors = [300, 1.3,    1.05,  1.11, 1.80, 1.52, 1.01].map(x =~~gt%% Math.log(x)); // the actual values of the factors


    // factorEstimates represents the values we are trying to compute from the data 
    // (hopefully the values will be close to the values in ```actualFactors```)
    var factorEstimates =  [ 0,  0,    0,     0,    0, 0, 0];

    function createFactorFlags() {
      const prob =  [ 100,  30, 10,  5, 3, 2, 1]; // present chance of having the factor
      let factorFlag =  prob.map(x =~~gt%% Math.random()*100 ~~lt%%= x ? 1 : 0);
      return factorFlag;
    }


    var epiFlags = range(EPI_COUNT).map( () =~~gt%% createFactorFlags()); // an arry of risk factors, one for each patient

    var episodes = epiFlags.map((factorFlags) =~~gt%% new TreatmentCost(factorEstimates,factorFlags, actualFactors));;


!md
## Some space to inspect data
!tryit
   $$.D(episodes.slice(0,3))

!md
## Display Histogram

!tryit
    let x = episodes.map(v =~~gt%% v.real);

    let trace1 = {
      x: x,
      type: "histogram",
      opacity: 0.5,
      marker: {
         color: 'green',
      },
    };

    let data = [trace1];
    let layout = {
               barmode: "overlay", 
               yaxis: {type: 'log' }, // type: 'linear' or 'log' var layout = { yaxis: {type: 'log', title: 'Count' }, // type: 'linear' or 'log'
               xaxis: {title: 'Treatment Cost in $'}
             }; 
    newPlot( data, layout);     
!md
    # Predict factors (using gradient descent)


    We predict the factors iteratively using gradient desent. But before we do that, let a restate the problem 
    to make the math a bit more elegant and actually simpler. 

    ## Exponential function

    If we have the following expression (rule of exponentials)    
    ~~lt%%p~~gt%% %y = e^a * e^b% can be rewritten as %y = e^{a+b}% ~~lt%%/p~~gt%%

    ~~lt%%p~~gt%%Secondly, any value `x` can be rewritten as an exponential `x = e^{log x}` ~~lt%%/p~~gt%%    

    __Therefore:__

    ~~lt%%p~~gt%%%f1 = log("factor1")% and %f2 = log("factor2")% To learn more here is q quick video:  
    ~~lt%%a href="https://www.youtube.com/watch?v=m2MIpDrF7Es" target="_blank"~~gt%%Properties of Exponents~~lt%%/a~~gt%%~~lt%%/p~~gt%% 

    The technique is to minimize what is refered to a 
    loss function. The loss function we will use is called the __mean squared error__ **(MSE)**. "~~gt%%Video in exponents

    ~~lt%%p~~gt%%%MSE = 1/{2n} \sum _{i=1}^{n}(Real_{i} - P_{i})^2% where %n = "number of patients"%~~lt%%/p~~gt%%

    ~~lt%%p~~gt%%%P_{i}` is the predicted value for `"patient"_{i}`, `P_{i} = e^(F0_{i}+F1_{i}+F2_{i}...)%~~lt%%/p~~gt%%

    ~~lt%%p~~gt%%So we want to find the values of `{f0 ... fn}` to minimise `MSE`~~lt%%p~~gt%%

    ~~lt%%p~~gt%%%{del P_{i}}/{del f0} = P_{i}% is another beautiful property of exponentials, the same is true for %f1, f2 ...% ~~lt%%/p~~gt%%


    ~~lt%%p~~gt%% %F1_{i} = {(0,if text{factorFlag1} = 0),(f1,if text{factorFlag1} = 1):}% ~~amp%%nbsp; ~~amp%%nbsp;  for ~~amp%%\ \ "patient"_i% ~~lt%%/p~~gt%%

    Similarly for %F2_{i}, F3_{i} ...% __Note:__ Since all patients have %f0%, ~~amp%%nbsp;~~amp%%nbsp;~~amp%%nbsp; %:. F0_{i} = f0%

    The `MSE` is also known as the loss function. The purpose of a loss function is to give a way to quantify 
    how far the prediction is from the desired outcome. So out target is to adjust the values of the factors. 

    ~~lt%%p~~gt%%  % {del (MSE)}/{del f0} = 1/n \sum _{i=1}^{n}(Real_{i} - P_{i})*P_{i} % ~~amp%%nbsp;~~amp%%nbsp;~~amp%%nbsp; is the derivative of `MSE` ~~lt%%/p~~gt%%

    Gradient descent is an iterative algrothims for updating the factors %f0, f1, f2 ...%

    ~~gt%% %f0_{"new"} = f0 - {del (MSE)}/{del f0} * epsilon %, ~~amp%%nbsp;~~amp%%nbsp;~~amp%%nbsp; where %epsilon% is known as the learning rate and is usuall a
    small fraction ~~lt%%br~~gt%%
    ~~gt%% Similarly for,  %f1, f2 ...% we do the same as above. 
    ~~gt%% %f1_{"new"} = f1 - {del (MSE)}/{del f1} * epsilon %


    Checkout this youtube video 

    ~~lt%%iframe width="560" height="315" style="position: relative; top: 5px; left: 50px; padding: 5px;"
            src="https://www.youtube.com/embed/jc2IthslyzM" 
            title="Gradient Descent" frameborder="0" 
            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" 
            allowfullscreen~~gt%%
    ~~lt%%/iframe~~gt%%


!tryit
    var total=sum(episodes.map(t =~~gt%% t.real));;

    function getTotal(epi) {
      return sum(epi.map(t =~~gt%% t.real));
      //return sum(epi.map(t =~~gt%% t.logReal));
    }

    // sum the derivitives of factor 'i' 
    function dx(episodes,i) {
      return episodes.reduce((sum,t) =~~gt%% sum+t.dx(i), 0);
    }

    function computeUpdatedFactors(episodes, factorEstimates, ep, scale) {
      if(scale === undefined) scale = () =~~gt%% 1;
      let res =  factorEstimates.map( (c,i) =~~gt%% c+(dx(episodes,i)/scale(i)*ep));
      episodes.forEach(t =~~gt%% t.setCurrent(res));
      return res;
    }
!md 

    ## Gradient Descent


!tryit

    //$$.D(dx(3)/total, total );
    let tcomp = factorEstimates;
    let scaleFunc = () =~~gt%%  total;

    // perform gradient descent on factors
    for(let i=0; i~~lt%% ITER; i++) {
      tcomp = computeUpdatedFactors(episodes, tcomp, EPSILON, scaleFunc);
    }
    let costToMember = sum(episodes.map(t =~~gt%% rect(t.real-t.current)));
    let costSaved = sum(episodes.map(t =~~gt%% rect(t.current-t.real)));
    let outOfPocketMembers = sum(episodes.map(t =~~gt%% clamp(t.real-t.current)));
    // $$.D(sum(episodes.map(t =~~gt%% t.real-t.current)), costToMember/outOfPocketMembers, costToMember, total, costSaved, 
    //      outOfPocketMembers, max(episodes.map(t =~~gt%% t.real-t.current)));
    // [tcomp.map((v,i) =~~gt%% (Math.exp(v)-Math.exp(actualFactors[i]))/Math.exp(actualFactors[i])*100+'%'), expL(tcomp), expL(actualFactors)]
    $$.D( {
         "Real Cost - Projected Cost": sum(episodes.map(t =~~gt%% t.real-t.current)), 
         "Average Patient Out of Pocket": costToMember/outOfPocketMembers, 
         "Total cost to all Patients": costToMember, 
         "Total cost of treatment (All patients)": total, 
         "Savings for insurance company": costSaved, 
         "Total out of pocket": outOfPocketMembers, 
         "Highest out odf pocket": max(episodes.map(t =~~gt%% t.real-t.current))
        });
    ({ 
       "Computed Values": expL(tcomp), 
       "Actual Values": expL(actualFactors),
       "Difference Between Computed and Actual" : tcomp.map((v,i) =~~gt%% (Math.exp(v)-Math.exp(actualFactors[i]))/Math.exp(actualFactors[i])*100+'%'), 
    })



!md
    On the next page we will plot the treatment data to to show the predicted values and the coresponding
    real cost. 


!md

    # Visualize Factor Based Optimization Results

    We will use D3 to visualize the factors that have been computed. Where the x-axis represents the predicted cost
    and the y-axis shows the actual cost. The dashed line is the predicted cost line. Firstly remember this is using
    come synthetic data with random spred of cost from a prior risk factor values. The entire demo is that give this data
    the actual risk factors can be computed from the data itself.

!tryit
    function scatter(episodes, plotArea) {

    if(arguments.length ~~lt%%= 1) plotArea = genID($$.executeDiv);
    $$.lastly( () =~~gt%% {
        var id = document.getElementById(plotArea);
        id.innerHTML = '';
        var margin = {top: 10, right: 30, bottom: 30, left: 60},
           width = 1024 - margin.left - margin.right,
           height = 512 - margin.top - margin.bottom;
           // append the svg object to the body of the page
           var svg = d3.select(`#${plotArea}`)
             .append("svg")
               .attr("width", width + margin.left + margin.right)
               .attr("height", height + margin.top + margin.bottom)
             .append("g")
               .attr("transform",
                     "translate(" + margin.left + "," + margin.top + ")");

        //Read the data
        (function(epi) {
         // 
         // Add X axis
         var x = d3.scaleLog()
           .domain([1, 1])
           .range([ 0, 0 ]);
         svg.append("g")
           .attr("class", "myXaxis")   // Note that here we give a class to the X axis, to be able to call it later and modify it
           .attr("transform", "translate(0," + height + ")")
           .call(d3.axisBottom(x))
           .attr("opacity", "0")
         var [yLow, yHigh] = d3.extent(epi.map(d =~~gt%% d.real));
         // Add Y axis
         var y = d3.scaleLog()
           //.domain([1, 500000])
           .domain([yLow*0.8, yHigh*1.1])
           .range([ height, 0]);
         svg.append("g")
           .call(d3.axisLeft(y));

// Add Axis Labels
          svg.append("text")
              .attr("text-anchor", "end")
              .attr("x", width)
              .attr("y", height + margin.top + 20)
              .text("Predicted Cost in $");

          // Y axis label:
          svg.append("text")
              .attr("text-anchor", "end")
              .attr("transform", "rotate(-90)")
              .attr("y", -margin.left+20)
              .attr("x", -margin.top)
              .text("Real Cost in $")


         // Add dots
         svg.append('g')
           .selectAll("dot")
           //.data(data)
           .data(epi)
           .enter()
           .append("circle")
             // .attr("cx", function (d) { return x(d.GrLivArea); } )
             // .attr("cy", function (d) { return y(d.SalePrice); } )
             .attr("cx", function (d) { return x(d.current); } )
             .attr("cy", function (d) { return y(d.real); } )
             .attr("r", 5)
             .style("fill", "#69b3a2")

         var [xLow, xHigh] = d3.extent(epi.map(d =~~gt%% d.current));
               var xStart = xLow*0.9;
              // new X axis
              //x.domain([0, 4000])
              x.domain([xStart, xHigh *= 1.1])
               .range([ 0, width ]);

              svg
                .append("line")           // attach prediction line
                .style("stroke", "blue")  // colour the line
                .attr("x1", x(xStart))     // x position of the first end of the line
                .attr("y1", y(xStart))      // y position of the first end of the line
                .attr("x2", x(xHigh))     // x position of the second end of the line
                .attr("y2", y(xHigh))    // y position of the second end of the line
                .attr("opacity", "0.25")
                .attr("stroke-dasharray","5, 5");

         svg.select(".myXaxis")
           .transition()
           .duration(2000)
           .attr("opacity", "0.75")
           .call(d3.axisBottom(x));

         svg.selectAll("circle")
           .transition()
           .delay(function(d,i){return(i*1)})
           .duration(1000)
           .attr("cx", function (d) { return x(d.current); } )
           .attr("cy", function (d) { return y(d.real); } )
           .attr("opacity", "0.1")
        })(episodes);
      });

      $$.D($$.HTML(`~~lt%%div id="${plotArea}" /~~gt%%`));
      return plotArea;
  }
  scatter(episodes)        
!md

## A much faster Adjustment algorithm


!tryit

    //$$.D(episodes)
    function _reduce(i, max, fn,initial) {
      let b = 1
      let mask = 1 ~~lt%%~~lt%% i;
      for(j=0; j~~lt%%max; j++ ) {
        if(j~~amp%%mask) initial = fn(initial,j)
      }
      return initial;
    }


      let s = [];
       _reduce(1, 64,(s, i)=~~gt%% (s.push(i),s),s);
       $$.D(s.length);

       let bitsNeeded = actualFactors.length;
       let codeMax = 1 ~~lt%%~~lt%% bitsNeeded;
       let counts = episodes.reduce((res,e) =~~gt%% (res[e.code]++, res), range(codeMax).fill(0));
       let sums = episodes.reduce((res,e) =~~gt%% (res[e.code]+=e.real, res), range(codeMax).fill(0));
       let codeFactors = range(1 ~~lt%%~~lt%% bitsNeeded).fill(1);
       let computedFactors = actualFactors.slice().fill(0);
       let total = sum(sums);
      $$.D(counts.slice(20,64),sums.slice(20,64))

      function iterate(codeFactors, computedFactors, epsilon) {

        for(let i=0; i~~lt%% bitsNeeded; i++){
          let dx = adjustFactor(i)*epsilon;
          let expDx = Math.exp(dx);
          _reduce(i,codeMax, (s,ix)=~~gt%%(s[ix] *= expDx, s), codeFactors);
          computedFactors[i] += dx;
        }
        function adjustFactor(i) {
           let _dx = _reduce(i,codeMax, 
                             (delta, ix) =~~gt%% delta+(sums[ix]-counts[ix]*codeFactors[ix])*codeFactors[ix],
                     0 );
           return (_dx/total);
        }
      }

    for(let i=0; i~~lt%% ITER; i++) {
      iterate(codeFactors, computedFactors, EPSILON);
    }
    episodes.forEach(e =~~gt%% e._setCurrent(codeFactors[e.code]));


!md
## Render results using D3

!tryit
   scatter(episodes);    

!end




Page - 1




Modularizing a try file

Once you start creating a significant tutorial file it can start to become large and unwieldy. The tool that supports modularization is @@include file_name.try.

Try Fragments

This the file we are using to implement the page

!head
    ~~lt%%title~~gt%%Modular Tryit~~lt%%/title~~gt%%
    @@include tools/head.try

!md
    # Example of Modularizaion

    I am going to see how to modularize a try example into multiple files.

    While we are here we can demonstrate how to display data, amd show how to incorporate into a new file (in a sub directory __modular__)

    @@include modular/disp_data_simple.try

Internal file 1

The internal file is the following:

!md
    ## Displying data

    The simplest way of displaying data is to end the script with a expression that
    returns a value that is not __undefined__.

!tryit
    let arr = [0, 1, 2, 3, 4, 'hello'];
    arr.slice(2, 5);

!md
    ## Displaying and may values

    If we need to display display and other points of the script at ponts other than at the end, we need a display function, for example __console.log__

    * $$.D(exp1,exp2...) __Display Javascript expression results __
    * $$.HTML(str)  __Display string as HTML__
    * $$.json(expr) __Display data as JSON string__

    ### Displaying Javascript Data $$.D

    First we will use the __$$.D__ to display Javascript expressions. This function is
    very similar to __console.log(expr1, expr2)__

!tryit
    let name = "TryITjs"
    $$.D('Name: ', name); // display the naame and give it a description

    let jobTitle = "Developer";
    $$.D('Job Title', jobTitle);

    let arr = [0, 1, 2, 3, 4, 'hello'];
    $$.D(arr);

!md
    \
    ### Displaying HTML from string

    Here we will show how to render some HTML. In order to support remdering, TryITjs uses 
    ~~lt%%a href="https://semantic-ui.com/introduction/getting-started.html" target="_blank"~~gt%%Semantic-UI~~lt%%/a~~gt%%




Page - 2




Creating UI

Now we will create an example to a tutorial that shows you how to create UI. The expmplaw is kept intentionally simple so that we do not introduce too many complications all at once.

!head
  ~~lt%%title~~gt%%Modular Tryit~~lt%%/title~~gt%%
  @@include tools/head.try
  ~~lt%%script src="https://unpkg.com/react@16.12.0/umd/react.production.min.js" crossorigin="anonymous"~~gt%%~~lt%%/script~~gt%%
  ~~lt%%script src="https://unpkg.com/react-dom@16.12.0/umd/react-dom.production.min.js" ~~gt%%~~lt%%/script~~gt%%
  ~~lt%%script src="https://unpkg.com/semantic-ui-react/dist/umd/semantic-ui-react.min.js"~~gt%%~~lt%%/script~~gt%%
!md
   # Create UI

   There are several ways to create a UI using TryITjs. The simplest method is to create a string in Javascript with some HTML markup.
   The string is rendered in the output screen using the builtin TryITJs function ```$$.HTML(someHtmlString)```.


!md
  ## How to render some HTML

!tryit
  // Javascript - $$.HTML = builtin HTML
  $$.HTML(
     `~~lt%%h1~~gt%%Edit some HTML here~~lt%%/h1~~gt%%~~lt%%br~~gt%%~~lt%%br~~gt%%`
  );

!md
  ## More elaborate example

  In this example we will create a header with today's date and an image below it. The code for it is very simple as shown next.

!tryit
  // add some style
  $$.HTML(`
        ~~lt%%style~~gt%%
         .center {
          display: block;
          margin-left: auto;
          margin-right: auto;
        }
      ~~lt%%/style~~gt%%
  `)

  // Now render some html

  $$.HTML(`
    ~~lt%%div style="height: 30rem"~~gt%%
      ~~lt%%h1~~gt%%Hello World ${(new Date()).toLocaleDateString()}~~lt%%/h1~~gt%%
      ~~lt%%img class="center" src="https://www.w3schools.com/html/pic_trulli.jpg" /~~gt%%
    ~~lt%%/div~~gt%%
  `)


!md
    ## Semantic-UI example

    In this example we will create 3 button group, the first button is red, the second green, and the lat one the default color. After the
    button group we will plce an SVG image of a camera.


!tryit
  // The button group as a string
  var strHtml =   `
    ~~lt%%div style="width: 70%; margin-left: 10rem"~~gt%%
      ~~lt%%div class="ui three buttons"~~gt%%
        ~~lt%%button class="ui active button red"~~gt%%One~~lt%%/button~~gt%%
        ~~lt%%button class="ui button green"~~gt%%Two~~lt%%/button~~gt%%
        ~~lt%%button class="ui button"~~gt%%Three~~lt%%/button~~gt%%
      ~~lt%%/div~~gt%%
    ~~lt%%/div~~gt%%
  `;

  // Render the HTML in the output
  $$.HTML(
    `~~lt%%div id="ui-target"~~gt%%${strHtml}~~lt%%!-- html string to render --~~gt%%~~lt%%/div~~gt%%
    ~~lt%%div style="margin-left: 30rem; margin-top: 5rem"~~gt%%
     ~~lt%%img src="https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/AJ_Digital_Camera.svg" /~~gt%%
    ~~lt%%/div~~gt%%`
  )   

!md
  _Notes: the way the execution of the script works is, first the entire sceipt block is executed, all output is collected in a staging buffer. Once the execution of the script block has completed all the staged output is rendered in the output window.
  _


!md
  ### Using React JSX

It's easier to use inline JSX to render some UI. The code below will render some buttons 
in the output area.

!tryit
  // JSX - the system knows how to render JSX markup
  // Since the JSX obj is the last expression, it will be displayed in the output window
  (
  ~~lt%%div style={{width: "70%", marginLeft: '10rem'}}~~gt%%
    ~~lt%%div class="ui three buttons"~~gt%%
      ~~lt%%button class="ui active button red"~~gt%%One~~lt%%/button~~gt%%
      ~~lt%%button class="ui button green"~~gt%%Two~~lt%%/button~~gt%%
      ~~lt%%button class="ui button"~~gt%%Three~~lt%%/button~~gt%%
    ~~lt%%/div~~gt%%
    ~~lt%%div style={{marginLeft: "15rem", marginTop: "5rem"}}~~gt%%
      ~~lt%%img src="https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/AJ_Digital_Camera.svg" /~~gt%%
    ~~lt%%/div~~gt%%
  ~~lt%%/div~~gt%%
  )
!md      
  # UI using React

  This section will demonstrate we can use React and JSX to create some UI.

  * Ceate a function to create a div in JSX
       1. Display the current time
       2. Show an image


  _Notes: In a code block (the code block below) if you declare a variables ```let aVar``` the variable is local to the block, it is not visible 
  to any other block. On the other hand if the variable is declared as ```var aVar1``` then this variable and its content is available to 
  subsequent code block. In other words ```var``` declares a global variable, while ```let``` or ```const``` declares a local variable._

!tryit
// JSX example
var Clock= ({time}) =~~gt%% (
  ~~lt%%div style={{height: "30rem"}}~~gt%%
    ~~lt%%h1 class="center"~~gt%%~~lt%%b~~gt%%Hello World~~lt%%/b~~gt%% {(time||new Date()).toLocaleTimeString()}~~lt%%/h1~~gt%%
    ~~lt%%img class="center" src="https://www.w3schools.com/html/pic_trulli.jpg" /~~gt%%
  ~~lt%%/div~~gt%%
);

// Render the JSX by 
~~lt%%Clock time={new Date()}/~~gt%%

!md
    ## A simple running clock

    Using React to render a simple clock that updates the time. As explained earlier the rendering of the HTML is performed after the
  script has completely executed. This presents a challange since the script the HTML dom before the output has been rendered. To get
  around the problem we have another builtin function ```$$.lastly(aFunction)```. This delays the execution of the function until the output has been rendered.

!tryit
    // React JSX
    function JSXClock() {
      const clock = () =~~gt%% ReactDOM.render(~~lt%%Clock time={new Date()} /~~gt%%, document.getElementById('clock-id')); // function to render the React 'aClock'


      $$.HTML('~~lt%%div id="clock-id"~~gt%%~~lt%%/div~~gt%% ~~lt%%br /~~gt%%~~lt%%br /~~gt%%~~lt%%br /~~gt%%~~lt%%br /~~gt%%---------------'); // render HTML to create a div for the clock

      $$.lastly( () =~~gt%% setInterval(clock, 1000)); // execute after all rendering of output unsing the '$$.lastly( aFuncToExecute )'
    }    

    JSXClock();
!md
  ## Improved React Clock

  This is an example of an improved React implementation, using the new hooks API

!tryit
  let {useState, useEffect} = React;
  function BetterClock() {
      let [time, setTime] = useState(undefined);
      useEffect(() =~~gt%%{
        let timer = setInterval( () =~~gt%% setTime(new Date()), 1000);
        return ( () =~~gt%% clearInterval(timer));
      }, [])
      return ~~lt%%Clock time={time} /~~gt%%
  } 

  // Render the clock
  ~~lt%%BetterClock /~~gt%%


!end




Page - 3




Howto

This section explains how to apply all the facilities available to TryITJs.

Define a top level page

Add HTML

Add some markdown

Editable code example

Include the body of another try file

Include the content of URL

Display the content of a .try file

Display some TryITJs text




Page - 4