// This library gives hints to help you through a calculation. // These hints are mostly based on failed calculations that I've seen // performed through the web-based interface. use HTMLUtils.frink // Str should include the whole input program like "foot -> m" getHints[str, fromStr, toStr, results] := { h = "" c = str // Using "per" for division which is ambiguous. For example, when you // say "miles per hour" you want miles/hour, but when you say // "days per week" you want to see 7, which is actually "week/day" // Best not to let this ambiguous English bit slip in. if c =~ %r/\bper\b/i { c =~ %s/\bper\b/\//ig h = h + """
per
is currently not allowed as
a synonym for division (because it's ambiguous in some cases.)
For example, when you say "miles per hour" you want miles/hour, but when you say "days per week" you probably expect to get 7, which is actually "week/day" (the size of a week divided by the size of a day.) Since this is ambiguous in English, I don't try to guess what you mean.
Please use the /
character to indicate division.
""" + HTMLEncode[c] + "
\n"
}
// Frink uses square brackets for function calls, not parentheses.
// This is to preserve the implicit multiplication in standard mathematical
// notation like x(x+1)
if c =~ %r/([a-zA-Z][a-zA-Z]*)\((.*?)\)/ // Function calls with parens
{
c =~ %s/([a-zA-Z][a-zA-Z]*)\((.*?)\)/$1[$2]/g
h = h + """
[ ]
to indicate function calls, and parentheses to indicate
grouping.
Why?
For example,
sin[30 degrees]
If you intended to call a function, you might try to write it as something like:
""" + HTMLEncode[c] + "
\n"
}
// Ounces are mass. Fluid ounces are volume.
if c =~ %r/\b(oz|ounces?|fluid)\b/ // oz / floz confusion
{
c =~ %s/\b(fluid\s+(ounces?\b|(oz\.|oz\b)))/floz/gi
c =~ %s/\b(fl\.?\s+(ounces?\b|(oz\.|oz\b)))/floz/gi
c =~ %s/\b((oz\.|oz\b)|ounces?\b|fluid\b)/floz/gi
h = h + """
ounce
to describe two completely different units
of measure.
One is a unit of mass, the other a unit of volume.
When referring to volume, the term is properly called
"fluid ounce." In Frink, please use
fluidounce
or floz
to indicate the
fluid ounce and
ounce
or oz
to refer to mass.
If you meant the fluid ounce, your calculation becomes:
""" + HTMLEncode[c] + "
\n"
}
// Warn about the word "of." Frink doesn't try to parse sentences,
// because they're usually ambiguous.
if c =~ %r/\bof\b/i
{
[property, noun] = c =~ %r/(\w+)\s+of\s+(?:(?:a|an|the)\s+)?(\w+)/i
property = lc[property]
noun = lc[noun]
fallbackName = "$noun$property"
fallback = unit[fallbackName]
fallbackHelp = ""
if (fallback != undef)
{
c =~ %s/(\w+)\s+of\s+(?:(?:a|an|the)\s+)?(\w+)/$2 + $1/egi
fallbackHelp = """
In fact, Frink has a unit called
$fallbackName
which is equal to:
$fallbackName = """ + HTMLEncode["$fallback"] + """\n
If that's what you need, your calculation might look something like:
""" +
HTMLEncode[c] + "
\n";
} else
c =~ %s/\s+of\s+(?:(?:a|an|the)\s+)?/ /gi
h = h + """
$property of $noun
, it might
be called something like: $noun$property
or
${noun}_$property
.
$fallbackHelp
If you want to see all of the units that contain "$noun",
you should type part or all of "$noun" into the "Lookup"
field or, better yet, enter
??$noun
into the From: box and see what you get.
More about
integrated help.\n"""
}
// "the" is not used. Sentences are ambiguous.
if [useless] = c =~ %r/\bthe\b/i
{
c =~ %s/\bthe\b//ig
h = h + """
""" +
HTMLEncode[c] + "
\n"
}
// The Google calculator uses the word "in" where Frink uses ->
if c =~ %r/\bin\b/i
{
c =~ %s/\bin\b/->/i
h = h + """
->
operator to convert to different units. Your
calculation might become:""" +
HTMLEncode[c] + "
\n" +
"""
However, it's unnecessary to type this symbol. Just enter the units you're converting from in the "From:" box and the units you're converting to in the "To:" box above.\n (Hint: You can probably switch between these quickly using the tab key.)""" } // I sometimes see "kilo/kilos/k" used by itself. A thousand what? if [let] = c =~ %r/\b(kilos?|k)\b/ { h = h + """
If you meant the temperature scale kelvin, that's either written "kelvin" (with a small k) or simply "K" with a capital K.""" } // Temperature conversions. Fahrenheit and Celsius, apart from being // almost always misspelled, cannot be treated as normal multiplicative // units because they don't have a reasonable zero-point at absolute // zero. Point the user to the different meanings of the units. if c =~ %r/\b(deg|degC|degF|F|C|(?:degree|deg)?[cC]el[sc]ius|(?:degree|deg)?[fF]ah?renheit|rankine|Rankine|Kelvin)\b/ { h = h + """
Frink can do it all, but you need to be unambiguous as to which you mean, so you don't get a wrong answer. For more information, please see the Temperature Scales section of the documentation.""" if c =~ %r/\b[cC]elcius\b/ h = h + """
By the way, you spelled "Celsius" wrong. I see that a lot.
""" if c =~ %r/\b[fF]arenheit\b/ h = h + """By the way, you spelled "Fahrenheit" wrong. I see that a lot.
""" } // Look for attempted date calculations without surrounding pound // signs. if c =~ %r/\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)/ if ! (c =~ %r/#/) { h = h + """
# August 19, 1969 #
Frink recognizes lots of date/time formats, and can do a lot of calculations and conversions with dates. Please see the Date/Time Handling section of the documentation for more information.""" } // Provide suggestions for possible unparsed dates. if results =~ %r/#/ { h = h + """
# August 19, 1969 #
.
If the date you're entering is not
being parsed, please use one of the formats listed
in the official
formats. I know you've learned from the Y2K fiasco that
you must enter 4-digit years. (Most-significant digits
first are recommended.) See the
Date/Time
Handling section of the documentation
for more information."""
}
// Warn about standard mathematical precedence in things like
// 30 miles / 2 hours where the calculation may actually want to be:
// 30 miles / (2 hours)
if [quot] = c =~ %r/\/\s*(\d+(?:\.\d+)?\s*[[:alpha:]]\w*)/
{
c =~ %s/\/\s*(\d+(?:\.\d+)?\s*\w+)/\/ ($1) /g
h = h + """
""" + HTMLEncode[c] + """
See this section of the FAQ for more information.""" } // People use the date calculations from the manual and miss the // obvious and necessary brackets after the now[] function. if c =~ %r/\bnow\b\s*[^\[]/ { c =~ %s/\bnow\b/now\[\]/g h = h + """
now[]
?
That's a function, so you need the square brackets after it.
Your calculation might become:
""" + HTMLEncode[c] + "
"
}
// Check for capitalization
for [word] results =~ %r/(\w+)\s*\(undefined symbol\)/ig
{
printed = false
if (word =~ %r/^(of|the|per|a|an)$/i) or (length[word] <= 1)
next
array = array[select[units[], regex["^$word$", "i"]]]
len = length[array]
for cap = array
{
if ((cap == word) and (len == 1))
next
if (not printed)
{
h = h + "
$word
?\n$cap
= " + unit[cap] + "\n"
if len == 1
{
rep = subst["\\b$word\\b", cap, "g"]
c =~ rep
h = h + """If so, your calculation becomes:
""" + HTMLEncode[c] + "
$word
was not found.
Perhaps you meant one of the following units:\n$option
(currency)\n"
else
altstr = altstr + "$option
= $unit\n"
}
if (altstr != "")
{
h = h + altstr + "\n$pRight
". Under the rules of the
International System of Units, these names must not be
capitalized. See the
official
list of SI prefixes for more details. Your calculation might
become:""" + HTMLEncode[c] + """
(You may also want to verify the
correct
capitalization of SI units for
"$rest
" if you continue to have
problems.)"""
}
} else // Try fixing bad "K" prefix
if [prefix, rest] = word =~ %r/^(K)(.+)/
{
pRight = lc[prefix]
sub = subst[word, "$pRight$rest"]
c =~ sub
h = h + """
$pRight
". Under the rules of the
International System of Units, all prefix symbols have only one
correct capitalization. See the
official
list of SI prefixes for more details. Your calculation might
become:""" + HTMLEncode[c] + """
(You may also want to verify the
correct
capitalization of SI units for
"$rest
" if you continue to have
problems.)"""
}
}
// Note about undefined symbol
if [word] = results =~ %r/(\w+)\s*\(undefined symbol\)/i
{
// Remove plural ending if the word is >= 4 characters long
if ((word =~ %r/s$/i) and (length[word] >= 4))
word = substrLen[word, 0, length[word]-1]
h = h + """
??$word
For more information on looking up units, read the Integrated Help section of the documentation.
""" } // Frink currently uses h for Planck's constant, not hours. This may change // as hours are more common and h, while not officially defined as an SI // symbol, is commonly used. if str =~ %r/\bh\b/ { c =~ %s/\bh\b/hr/g h = h + """h
to stand for
Planck's constant. If you mean hour
, please use
hour
or hr
:""" +
HTMLEncode[c] + "
\n"
}
if h == ""
return h
else
return """
If you didn't get the answer you expected: