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 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

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

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

- The tryit file will generate this result

## 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~~lt%%/title~~gt%%
    !md
        # Introduction
        This is a slightly more elaborate example

        ## 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
        # Another Page

        This is one more example in a new page. The is it my test.

        This is a example of optimization useful in certain modeling of estimating the cost of service for medical conditions.
        One simple model for a service, for example heart contition, is as follows:

        1. Average base cost
        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.
             a. ```Cost = Base * comp1 * comp2 * comp3```,  where comp1, comp2  percentage increase on the base cost.
             b. This can also be written in exponential form ```Cost = exp( b + c1 + c2 + c3 )``` where ```b = ln(Base)```, and ```c1 = ln(comp1)``` ...
        3. The values of **b, c1, c2...** (also refered to as cost factors) are unknown, but we have data for the cost of service fr thousands of patients. We will use the date to extimate the values of the cost factors.
        4. This becomes a regression problem

        ## 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 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

        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,
             a. All patients have the base factor ```b``` codes[0]
             b. The other factors have arelative probability of occuring, code[1] has (100-70) = 30% chance, codes[2] has (100-90)= 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 {
              this.factorFlag = Array.isArray(factorIndicators)? factorIndicators.slice() : factorIndicators();
              this.logReal = this.getRisk(realFactor)+Math.log(1 + normalSample()*1.5);
            }
            this.real = Math.exp(this.logReal);
            this.logCurrent = 0;
            this.current = 1;
          }

          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);
          }

          // 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
        ## Setup some constants

        1. EPI_COUNT - number of test episodes to create
        2. ITER - number of itteratins to compute the factors
        3. EPSILON - increment size for the gradient descent

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

    !tryit
        //           Base comp1 comp2 ...
        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 fill() {
          const prob =  [ 0,  0.70, 0.9,  0.95, 0.97, 0.98, 0.99];
          return prob.map(x =~~gt%% Math.random() ~~gt%% x ? 1 : 0);
        }

        var epiFlags = range(EPI_COUNT).map( () =~~gt%% fill())

        var episodes = epiFlags.map((fill) =~~gt%% new TreatmentCost(factorEstimates,fill, actualFactors));;
        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
    ## some space to inspect data
    !tryit
       $$.D(episodes.slice(0,3))

    !tryit

        //$$.D(dx(3)/total, total );
        let tcomp = factorEstimates;
        let scaleFunc = () =~~gt%%  total;
        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)]
        //var t = new C();
        //t.getRisk(actualFactors);
        //$$.D(actualFactors, t.getRisk(actualFactors));
        //t
    !md
    ## Display debug
    !tryit

         $$.D(episodes)

    @@include fast-epi.try
    !end

- The tryit file will generate this result

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%%

- The tryit file will generate this result

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

- See result

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
Executing previous dependent scripts
Waiting to execute