Home > Code > calc.tcl

calc.tcl

#### calc.tcl v1.0.1 ###########################################################
################################################################################
## Written by:                                                                ##
##   KuNgFo0  (http://www.eggfaq.com/).              ##
##                                                                            ##
## Modified by:                                                               ##
##   Brian Schmidt aka. brianMan.                                             ##
################################################################################

#### Readme / Help #############################################################
################################################################################
## This script is ripped from KuNgFoO's ib.tcl v3.19 (infobot) script.        ##
##                                                                            ##
## Script that can calculate just about anything ;)                           ##
##                                                                            ##
## Usage:                                                                     ##
##   To have the .calc[ulate] commands available on a channel you need to set ##
##   the channel flag +calculator from the console/partyline .                ##
##   ``.chanset #channel +calculator´´                                        ##
##                                                                            ##
## Channel Commands (available only if channel is +convert):                  ##
##   .calc[ulate]                                                 ##
## Example:                                                                   ##
##   ``.calc 15*20+3´´                                                        ##
################################################################################

#### Changelog #################################################################
################################################################################
## v1.0.1                                                                     ##
## * Minor code cleanup                                                       ##
##                                                                            ##
## v1.0.0                                                                     ##
## + Initial release.                                                         ##
## * Changed the default trigger ``botname, calc[ulate]´´ to ``.calc[ulate]´´ ##
## + Added the possibility to control which channels could use the commands   ##
##   with the channel flag ``+/-calculator´´                                  ##
################################################################################

bind pub - .calc pub_calc
bind pub - .calculate pub_calc
bind msg - calc msg_calc
bind msg - calculate msg_calc

setudef flag calculator

# You shouldn't change these, however you may add additional variables
# These are used via %varname in the 'calculate' command
# Example: Mybot, calculate %pi / 2
set calc_const(pi) 3.14159265358979323846 ; # PI
set calc_const(e)  2.7182818284590452354  ; # E
set calc_const(n)  6.0221367e23           ; # Avogadro's number [1/mol]
set calc_const(R)  8.314510               ; # Universal gas constant [J/(mol*K)]
set calc_const(k)  1.380658e-23           ; # Boltzmann's constant [J/K]
set calc_const(G)  6.67259e-11            ; # Universal gravitational constant [N*m^2/kg^2]
set calc_const(h)  6.62606891e-34         ; # Planck's constant [J*s]
set calc_const(c)  2.99792458e8           ; # Speed of light [m/s]

# No more editing required

proc xrange {xr xr1 xr2} {
    return [join [lrange [split $xr] $xr1 $xr2]]
}

proc xindex {xr xr1} {
    return [join [lrange [split $xr] $xr1 $xr1]]
}

proc calc_fixdata {arg output} {
    global botnick
    if {[string index $output 0] != "#"} {
        regsub -all -nocase {$output's} $arg "your" arg
    }
    regsub -all -nocase {$botnick'
s} $arg "my" arg
    return $arg
}

proc calc_msg {targets arg} {
    foreach target $targets { puthelp "PRIVMSG $target :[calc_fixdata $arg $target]" }
}

proc calc_fixtopic {arg} {
    regsub -all {[\\\{\}\[\]\"]} $arg {}   arg ; # Bad characters
    regsub -all {(\s)+}          $arg {\1} arg ; # Double whitespace
    regsub -all {^\s*|\s*$}      $arg {}   arg ; # Whitespace at ends
    return $arg
}

# Begin 'calc' code
proc calc_fixexpr {exp} {
    global calc_const
    set exp [calc_fixtopic $exp]
    foreach i [array names calc_const] {
        regsub -all "
\%$i" $exp $calc_const($i) exp
    }
    return $exp
}
# End 'calc' code

# Begin Public binds code
proc msg_calc {nick uhost hand arg} {
    global botnick
    pub_calc $nick $uhost $hand "
" $arg
}

proc pub_calc {nick uhost hand chan arg} {
    global botnick calc_flag
    if {(![isbotnick $nick]) && (![matchattr $hand +b])} {
        if {(![string match "
$chan" ""]) && (![channel get $chan calculator])} {
            return 0 ; # If command comes from a channel, and that channel doesn't have +calculator then ignore
        }
        set isuser [expr {[matchattr $hand - $chan] || [matchattr $hand -]}] ; # Note that $chan might be "
", so we must handle both cases
        if {([validchan $chan]) && ($isuser)} {
            set output1 $chan ; # The bot sends the text to the channel for users
        } else {
            set output1 $nick ; # Non-users get privmsg'd
        }
        if {[set i [string last "
>" $arg]] == -1} {
            set output2 $output1 ; # By default, output2 (~stdout~) goes to output1 (~stderr~)
        } else {
            # Output has been redirected
            if {(!$isuser) || ([set output2 [string trim [string range $arg [expr $i + 1] end] "
"]] == "")} {
                set output2 $output1 ; # Error (User doesn't have access, or output was "
"), so we go back to the default
            }
            set arg [string trim [string range $arg 0 [expr $i - 1]] "
"]
        }
        set remainder [xrange $arg 0 end]

        if {$remainder == "
"} {
            calc_msg $output1 "
error parsing sentence"
        } elseif {[catch {expr [calc_fixexpr $remainder]} output]} {
            calc_msg $output1 "
error calculating '$remainder' ($output)"
        } else {
            calc_msg $output2 "
$remainder = $output"
        }
    }
}
# End Public binds code

# Init stuff
if {[catch {package require Tcl 8.2} error]} {
    putlog "
error TCL v8.2 or higher is required to run this script"
    return 0
}

putlog "
*** LOADED: calc.tcl"
Categories: Code Tags: , , , ,