solve.fsp - Frink Server Pages highlighter

[Try solve.fsp]

<!DOCTYPE html>
<HTML LANG="en">
 <HEAD>
  <TITLE>Frink Solver</TITLE>
  <META NAME="viewport" CONTENT="width=device-width, initial-scale=1.0">
  <META HTTP-EQUIV="Default-Style" CONTENT="Spaceship"> 
  <LINK REL="StyleSheet" HREF="/frinkdocs/spaceship.css"
        TYPE="text/css" TITLE="Spaceship">
  <LINK REL="Alternate StyleSheet" HREF="/frinkdocs/apeairy.css" 
        TYPE="text/css" TITLE="APE Airy"> 
  <LINK REL="Alternate StyleSheet" HREF="/frinkdocs/style.css" TYPE="text/css"
        TITLE="APE Classic">
  <LINK REL="Alternate StyleSheet" HREF="/frinkdocs/style2.css" TYPE="text/css"
        TITLE="Compact"> 
  <LINK REL="icon" HREF="/images/futureboyicon.png" TYPE="image/png">
  <LINK REL="canonical" HREF="https://frinklang.org/fsp/solve.fsp">
 </HEAD>
<% 
    use ../allTransforms.frink
    use ../HTMLUtils.frink
    use ../MathML.frink

    symbolicMode[true]

    if  ! isVariableDefined["equation"] && ! isVariableDefined["eq"]
        ev = "on"

    if ! isVariableDefined["equation"]
       if isVariableDefined["eq"]
          equation = eq  // Moving to use variable "eq" for shorter URLs.
 
/*    if (!equation)
    {
        equation = "h = h0 + Integrate[v0, t] + Integrate[-gravity, t, 2]"
        solveFor = "h"
    } */
    eqStr = HTMLEncodeQuoted[equation]
    solveFor = solveFor ? trim[solveFor] : ""
    solveStr = HTMLEncodeQuoted[solveFor]
    wchecked = w ? "CHECKED" : ""
    f = f ? f : ""
    fchecked = (f=="f" or f=="on") ? "CHECKED" : ""
    mchecked = f=="m" ? "CHECKED" : ""
    nchecked = f==""  ? "CHECKED" : ""
    evchecked = ev ? "CHECKED" : ""
    resultAsQuoted = resultAs ? HTMLEncodeQuoted[resultAs] : ""
    extra = """ class="big" """
%>

 <BODY>
  <H1>Frink Solver</H1>
  <FORM ACTION="solve.fsp" METHOD="GET">
  <DIV CLASS="back">
      <TABLE BORDER="0" SUMMARY="Equation input">
        <TR><TD CLASS="noborder"><LABEL FOR="eq">Equation:</LABEL>
        <INPUT TYPE="text" NAME="eq" 
         STYLE="width: 100%; box-sizing: border-box" SIZE="40" ID="eq"
         VALUE="$eqStr" autocapitalize="none" autocorrect="none" 
         oninput="document.getElementById('resultAs').value=''">
        <TR><TD CLASS="noborder"><LABEL FOR="solveFor">Solve&nbsp;for:&nbsp;</LABEL><INPUT TYPE="text" SIZE="15" autocapitalize="none" autocorrect="none" NAME="solveFor"
        ID="solveFor" VALUE="$solveStr" oninput="document.getElementById('resultAs').value=''">
        <TR><TD CLASS="noborder" COLSPAN="2"><INPUT TYPE="CHECKBOX" NAME="w" ID="w" $wchecked
        onChange="this.form.submit();"><LABEL FOR="w">Show work</LABEL>
            <TR><TD CLASS="noborder">Show output as:
              <INPUT TYPE="RADIO" NAME="f" ID="fnone" VALUE="" $nchecked onChange="this.form.submit();"><LABEL FOR="fnone">Default</LABEL>
              <INPUT TYPE="RADIO" NAME="f" ID="f" VALUE="f" $fchecked onChange="this.form.submit();"><LABEL FOR="f">Raw Frink notation</LABEL>
              <INPUT TYPE="RADIO" NAME="f" ID="m" VALUE="m" $mchecked onChange="this.form.submit();"><LABEL FOR="m">MathML</LABEL> 
        <TR><TD CLASS="noborder" COLSPAN="2"><INPUT TYPE="CHECKBOX" NAME="ev" ID="ev" $evchecked
    onChange="this.form.submit();"><LABEL FOR="ev">Evaluate result numerically</LABEL>
        <TR><TD CLASS="noborder" COLSPAN="2"><INPUT TYPE="Submit" VALUE="Solve">
      </TABLE>
  </DIV>        
<%
    if (equation)
    {
        if (equation =~ %r/=/)
        {
           equation =~ %s/=/===/
           if solveFor
              expr = parseToExpression["solve[$equation,$solveFor]"]
           else
           {
              // If there's no "solve for" specified but only 1 symbol in the
              // equation, use the one symbol.  This does not put it into the
              // text field, though.
              // TODO: Also, this code should be unified with
              // the code below that checks to see if the "solve for" symbol
              // even exists in the expression.
              expr = parseToExpression[equation]
              syms = getSymbols[expr]
              if length[syms] == 1
              {
                  solveFor = toArray[syms]@0
                  solveStr = HTMLEncodeQuoted[solveFor]
                  expr = parseToExpression["solve[$equation,$solveFor]"]
              } else
                 println["""<P CLASS="warning"><I>No "solve for" variable present.  Please select a variable to solve for.</I></P>"""]
           }
        } else
        {
           println["<P><I>No equals sign present.  Will not solve equation, but just evaluate the expression.</I></P>"]
           expr = parseToExpression[equation]
        }

        symbols = getSymbols[parseToExpression[equation]]
//        println["<P>symbols are: " + join[", ", symbols] + "</P>"]
        if solveFor && ! symbols.contains[solveFor]
           println["""<P CLASS="warning">The equation does not contain the "solve for" variable <CODE><B>$solveFor</B></CODE>.  Please choose a correct variable to solve for.</P>\n"""]
        println["<P><B>Solution:</B></P><P CLASS=\"code\"><CODE>"]
        last = undef
        if w  // Show work?
        {
           res = array[transformExpressionTrace[expr]]
           lastres = ""
           for resline = res
           {
               resline = HTMLEncode[toString[resline]]
               if resline != lastres
               {
                  if f=="f"
                    println[removeApproximations[resline] + "<BR><BR>\n"]
                  else
                    println[formatExpressionSymbolic[resline] + "<BR><BR>\n"]
                }
                lastres = resline
           }

           last = res@(length[res]-1)
        } else
        {  // Don't show work
           res = array[transformExpression[expr]]
           if f=="f"
              println[removeApproximations[join["<BR>",res]]]
           else
              if f=="m"
              {
                 for r1 = res
                    println[MathML.format[r1,true,0,extra]+"<BR>\n"]
              } else
                 println[formatExpressionSymbolic[join["<BR>",res]]]

           last = res
        }
        println["</CODE></P>"]

        /* All of the following code is to detect variable names in the 
           resulting solutions and create HTML forms to allow the user to 
           optionally plug in values for each variable (or leave them symbolic)
           and evaluate the result symbolically and numerically. */
        if ev  // Evaluate result?
        {
           println["""<DIV CLASS="back"><P><A NAME="Evaluated"><B>Evaluated result:</B></A></P>"""]

           symbols = getSymbols[last]
           symbols.remove[solveFor]
           repstr = ""
           repls = new array
  
           println["""<TABLE BORDER=1 STYLE="width: 100%"><TR><TH>Sym<TH>Symbolic?<TH>Value"""]
           for sym = symbols
           {
              selvar = "sel_$sym"
              varname = "val_$sym"
              sch = eval[selvar] == "S" ? "checked" : ""
              lch = eval[selvar] == "L" ? "checked" : ""
              if (! sch AND ! lch)
              sch = "checked"
              if sch
                 repstr = repstr + "$sym = noEval[$sym]\n"
              if lch
                 repls.push[ [constructExpression["Symbol",[sym]], eval[eval[varname]]]]
              val = eval[varname] ? eval[varname] : (unit[sym] != undef ?  eval[sym] : "")
              valstr = HTMLEncodeQuoted[isString[val] ? val : inputFormUnicode[val]]
              println[" <TR>"]
              println["""  <TD>$sym ="""]
              println["""  <TD><INPUT TYPE="RADIO" NAME="$selvar" ID="${selvar}_S"  VALUE="S" $sch><LABEL FOR="${selvar}_S">$sym</LABEL>"""]
              println["""  <TD><INPUT TYPE="RADIO" NAME="$selvar" ID="${selvar}_L" VALUE="L" $lch>"""]
              print["""    <INPUT TYPE="TEXT" autocapitalize="none" autocorrect="none" NAME="$varname" VALUE="$valstr" STYLE="width: 90%; box-sizing: border-box" oninput="document.getElementById('${selvar}_L').checked=true">"""]
           }
           println["</TABLE>"]
           println["""<BR>(Optional) Show result in units: <INPUT TYPE="TEXT" NAME="resultAs" ID="resultAs" VALUE="$resultAsQuoted" autocapitalize="none" autocorrect="none">"""]
           println["""<BR><INPUT TYPE="Submit" VALUE="Solve">"""]
           println["""<P CLASS="code"><CODE>"""]

           resultAs = resultAs ? trim[resultAs] : ""
 
           if isVariableDefined[resultAs] and resultAs != ""
           {
              // If resultAs has a comma like "ft, in" or "[ft, in]", or
              // with quoted terms such as ["ft", "in"], then just canonify
              // it to ["ft", "in"] or if it has a zero, leave that unquoted
              // like ["ft", "in", 0]
              // TODO:  Turn this into a function
              if resultAs =~ %r/,/
              {
                 // Remove square brackets and quotes
                 resultAs =~ %s/[\[\]"]//g
                 resultAsArray = new array
                 for resa = split[",", resultAs] // Split on commas
                 {
                    resa = trim[resa]
                    if resa == "0"   // Preserve literal 0 unquoted.
                       resultAsArray.push[0]
                    else
                       resultAsArray.push[resa]
                 }
                 resultAs = resultAsArray
              }
           }

           results = flatten[toArray[last]]
           for eqn = rangeOf[results]
           {
              eq1 = results@eqn
              varlen = 1
              // Evaluate right-hand sides of solved equations
              if structureEquals[_a === _b, eq1]
              {
                 print[getChild[eq1, 0] + " = "]
                 part = getChild[eq1, 1]
                 varlen = length[inputFormUnicode[getChild[eq1,0]]]
              }  else
                 part = eq1

              for [e1, e2] = repls
                 part = substituteExpression[part, e1, e2]
  
              repstr2 = repstr + inputFormUnicode[part]
              pe = eval[repstr2, false, true]
              if ! structureEquals[pe, part]
              if f
                  print[HTMLEncode[inputFormUnicode[part]] + "<BR>" + repeat["&nbsp;", varlen + 1]  + "= "]
              else
                 print[formatExpressionSymbolic[inputFormUnicode[part]] +
                 "<BR>" + repeat["&nbsp;", varlen + 1]  + "= "]

              if isVariableDefined[resultAs] and resultAs != "" and isUnit[pe]
              {
                 result = (pe -> resultAs)
                 result = HTMLEncode[result]
                 result = formatExpression[result]
                 result =~ %s/\n/<BR>\n/mg
                 result =~ %s/\s/&nbsp;/g
              } else
              {
                 if f
                    result = HTMLEncode[inputFormUnicode[pe]]
                 else
                    result = formatExpressionSymbolic[inputFormUnicode[pe]]
              }

              println[result + "<BR>"]
              if eqn < length[results]-1
                 println["<BR>"]
           }
           println["</CODE></P></DIV>"]
        }
     }
%>
  
  </FORM>
  <HR>
  <P>
   View source of <A HREF="highlight.fsp?f=solve.fsp">this FSP page</A>.  This
   is a program written in the programming language <A
   HREF="https://frinklang.org/">Frink</A>.
  </P>
  <P>
   <I>Contact <A HREF="mailto:eliasen@mindspring.com">Alan Eliasen</A></I>
  </P>

  <P>
   Back to <A HREF="/frinkdocs/fspdocs.html">Frink Server Pages
    documentation.</A>
  </P>  
 </BODY>
</HTML>

[Try solve.fsp]


Alan Eliasen was born 20203 days, 11 hours, 46 minutes ago.

Back to Frink Server Pages documentation.