A simple idea I came up with while working on something else. Seemed like a fun mini-project, so decided to package it xD
Installation
npm i -g time-taken-to
This installs the binary to PATH after which it can be accessed either using time-taken-to or ttt.
Alternatively, can be run using npx without local installation.
Usage
⚠️If your command is interactive (requires runtime input), time-taken-to will stall and not do anything. This case is currently not handled and will be fixed in a later patch.
🟢 Hence if interactive, hard-code your command.
time-taken-to [OPTIONS] <your_command>
Measures the time taken to execute <your_command>.
ttt [OPTIONS] <your_command>
Also does the same thing.
Using npx,
npx time-taken-to <your_command>
<your_command> must be specified as a string if it consists of more than one word.
$ ttt "ls -s"
is different from
$ ttt ls -s
Options
The various available options can be viewed by running
ttt -h
--round-to or -r – Rounds off the result to the number of digits provided as argument. The default value is 6.
--show-stdou or -s – If specified, ttt also displays the stdout produced by the command.
--iterations or -i – Runs the command for the specified number of times and returns the average for a more accurate result. Default is 1.
--version or -v – Displays current version of time-taken-to.
Android-TV + Phone: Application which locks down selected apps for a child, which can only be unlocked from a Parent’s device.
Phone (Redevelopment TODO): Application which sets a timer, within which the child is allowed to use a restricted set of Apps
… Why?
With the day-to-day work by parents, it becomes a difficulty to manage their child’s device usage. When given a device with the child assuring “I’ll play for 5 mins plsplspls”, it usually doesn’t happen that way, and the child ends up using for hours :laugh:.
Now, coming to Android TVs, popular App Lock solutions require to enter a PIN in the big picture. Let’s not underestimate a child’s image processing abilities to pick up the PIN.
Features
Android TV + Phone: Remotely Lock/Unlock Android TV device. No requirement to enter PIN in the TV.
Phone: Decide the time within which child can use restricted apps. Phone Locks once time’s over.
Issues / TODO
Let’s face the truth: Kids are intelligent enough to remove the app (Android TV doesn’t have Device Administrator Service, so we’re vulnerable to uninstallation)
PackageInstaller is blocked now, gotta make it operable (to allow user to uninstall if insisted)
Issue when the remote locker device is lost OR the the remote locker app is uninstalled
How to get back in the system? Something to think on
Authentication
[FEATURE] TV App listing in the remote control phone itself. It would remove need of a frontend for TV, we can just package the server, and a minimal UI to provide info and get things started.
Manage Disconnection Failures
See if LockService advertising forever can be tackled Current implementation works only when device is awake. Still, can look out for some more reduction.
Well, a TV is always awake 🤷…
Big TODO: Use Bluetooth/WiFi P2P based communication. Can eliminate the “overkill” requirement of a hosted function.– Suggestions are welcome for this. The issue is that neither of this communication methods can be kicked off in the background, easily.
Issue details:
Moved to Google Nearby Connections API
Pairing takes considerable time (5 seconds), is juice consuming, and is unreliable (connectivity time changes randomly)
Moved to Android NsdManager (for discovery of service) + TCP Sockets (for Server)
NsdManager’s interaction with mdns android daemon works very well (Device Logs and Wireshark Capture Logs say so). But the app isn’t informed about any such events at all.
simple calculator REPL, similar to bc(1), with syntax highlighting and persistent history
installation
Homebrew
$ brew install eva
crates.io
$ cargo install eva
manual
$ git clone https://github.com/nerdypepper/eva
$ cd eva
$ cargo run
usage
eva 0.3.1
NerdyPepper <akshayoppiliappan@gmail.com>
Calculator REPL similar to bc(1)
USAGE:
eva [OPTIONS] [INPUT]
ARGS:
<INPUT> Optional expression string to run eva incommand mode
OPTIONS:
-b, --base <RADIX> Radix of calculation output (1 - 36) [default: 10]
-f, --fix <FIX> Number of decimal places in output (1 - 64) [default: 10]
-h, --help Print help information
-r, --radian Use radian mode
-V, --version Print version information
some constants available in rust standard library.
e pi
examples:
pi * 5^2 # πr²
functions
all trigonometric functions expect input in degrees.
1 argument:
sin cos tan csc sec cot sinh cosh tanh
asin acos atan acsc asec acot ln log2 log10
sqrt ceil floor abs
2 arguments:
log nroot
deg(x) - convert x to degrees
rad(x) - convert x to radians
examples:
sqrt(sin(30)) # parentheses are mandatory for functions
log10100 # no
log10(100) # yes
log(1, 10) # function with two arguments
quality of life features
auto insertion of * operator
>12sin(45(2)) # 12 * sin(45 * (2))
12
auto balancing of parentheses
>ceil(sqrt(3^2 + 5^2 # ceil(sqrt(3^2 + 5^2))
6
use previous answer with _
> sin(pi)
0.0548036650
> _^2
0.0030034417
>
super neat error handling
> 1 + ln(-1)
Domain Error: Out of bounds!
syntax highlighting
todo
add support for variables (pi, e, _ (previous answer))
syntax highlighting
multiple arg functions
screenshots
create logo
unary operators (minus, plus)
add detailed error handler
add unit tests
lineditor with syntax highlighting
add more functions
contributors
the rust community has helped eva come a long way, but these devs deserve a
special mention for their contributions:
Web Toolbox is a deadsimple web app that is meant to provide an easy way for users to convert different types of data into different formats in order to ease stress about finding a tool online they could use. Since it just uses vanilla HTML, CSS and Javascript, it can be easily extended to support new and different type of conversions.
🧐 Features
Fully responsive
Supports PWA installation
Easily etendable
Simple and intuitive workflow
Lightning fast browsing speeds thanks to prefetching
Copy and paste that to the top of the array and use that as your starting point for creating your converter.
Afterwards, use simple HTML, CSS and Javascript to finish creating your page and make a Pull Request on Github where me, and possibly others, can review the code, add suggestion and eventually push it through into production.
Please read CONTRIBUTING for details on our CODE OF CONDUCT, and the process for submitting pull requests to us.
PWA and Extra Features
This website is almost 100% PWA ready and is almost ready to be shipped to the Progressive Web App Store, however I’m running into some issues with the cache not working after you close the app, which means no offline access, and help would be very much appreciated.
The web app also should be mostly mobile friendly, however I do not have any modern day devices to test out how it performs and looks on real hardware.
Nonsense is an esoteric programming language (or esolang) where pretty much any English sentence you could concoct is a valid program. The catch is, though, that most “useful” programs are usually nonsensical jumbles of words rather than coherent sentences. For example, here’s “Hello world!”:
72 ey 100 envoy nab 108 eyry em 111 entry 32 ey eon 87 ey try 114 ey my by nay
While reminiscent of a monkey picking words from a dictionary, Nonsense has some nice structure built around the phonetics and syntax of English itself. And, unlike some other languages which utilize English letters for commands, all Nonsense commands must be valid English words (or numbers or punctuation) where case does not matter, with the structure of word itself being critical (rather than just the order of the letters). It’s also Turing-complete since any BrainFuck program can be translated to Nonsense (see bf_convert.py).
Nonsense interprets words by splitting them into syllables, each containing consonants and vowels (where y is a vowel). Consonants correspond to variables, while vowels correspond to instructions. Integers (or chars; see interpreter.py) can be stored in consonant variables as well as the array (denoted S here), an arbitrarily long list of integers (initialized to zeroes) which is accessed by indexing (see the section on the letter e below). The zeroth entry in the array is called result, and is always updated with the value of the most recent command (think of it like Ans in TI-Basic).
To run Nonsense programs for yourself, simply download interpreter.py and the associated words_dictionary.json file into the same directory; the dictionary file is used to check that all words are valid English words, and is actually quite lenient for what does count as word. Run interpreter.py with your program (or as it is called, a paragraph) as the first argument. The interpreter will display any output and ask for any inputs during execution (these are prompted by a single :).
To aid debugging, a paragraph can be executed via interpreter.py with the -i or --inspect flag, which will display the current state of all consonants, the array, and the stack after each instruction execution. Note that the array is not enlarged until necessary, and only nonzero consonants are displayed.
Syllables
Words are decomposed into syllables which have consonants at either endpoint and vowels in-between. For example, the word candid is split into can, nd, and did; notice how syllables overlap at their endpoints. Each syllable is a single instruction, with the beginning consonant corresponding to a stored value (called the operand) and the ending consonant corresponding to a destination (called the location); the vowels in between are the instructions themselves, and can be compounded via diphthongs.
All words and syllables in Nonsense must start and end with a consonant, though, so when no constant begins or ends a syllable the interpreter creates the “invisible” consonant 0, a null value. When being accessed 0 always returns zero, while as a destination 0 corresponds to result.
Consonants
Consonants are easy. There are precisely twenty of them, b, c, d, ..., x, z, and each one can hold an integer value (all initialized to zero). A consonant in a word is either a retrieval of that consonant’s value (when at the beginning of a syllable, as the operand) or a specification of the destination of a result (when at the end of a syllable, as the location).
Vowels
These are the fun ones. Each vowel is a unique operation (either unary or binary), and some have some odd but useful edge cases when they begin or end syllables, or combine into diphthongs.
_: STORE
The STORE command is invoked whenever a syllable is composed of just consonants, and simply stores the operand at location.
nd : n->d
str : s->t; t->r
g : g (place g in result)
a: ADD
The ADD command is pretty straightforward; take the operand, add it to the value at location, and store it back at location. You can effectively replace any a with a “+” sign (in fact that is more-or-less what the interpreter does).
ban : b+n->n
band : b+n->n; n->d
baa : b+0 (the second a has no additional effect)
act : 0+c->c; c->t
e: INDEX
The INDEX command accesses the array either by designating the operand as the index at which to pull from the array for an instruction, or specifying that the location is actually an array entry (rather than a consonant variable).
bet : S[b]->t
beet : S[S[b]]->t
err : S[0]->r; r->r (due to the implicit 0)
cane : c+S[n]->S[n]; S[n] (here, the syllable must look ahead a letter to see if the location is an array entry, and always does)
aerate : S[0]+r->r; r+S[t]->S[t] (indexing “passes through” other vowels; ae behaves identically to ea)
i: MINUS
The MINUS command is precisely what you think it is: the inverse operation of ADD. Again, you could replace any i with a “-” sign and be totally correct.
wig : w-g->g
wing : w-n->n; n->g
skiing : s->k; k+n->n; n->g (since “–” makes a “+”)
ice : -S[c]->S[c] (easy negation!)
braid : b->r; r-d->d (since “+-” makes a “-“, as would “-+”)
icicle : -c->c; c-c->c; c->S[l] (easy zeroing!)
o: ONE
ONE is one. Just like, the number one. What more do you need?
But seriously, the ONE command will increment (or decrement, if subtracting) the operand by one and store it to the location. If a syllable ends with the implicit 0, in addition to storing to result, the ONE command does in-place increment/decrement.
row : r+1->w
roe : S[r]+1->S[r]
road : r+1->d (did you expect it to be different?)
avoid : 0+v->v; v-1->d
oat : 0+1->t (easy 1-ing!?)
toon : t+2->n (1+1=2)
moo : m+2->m
u: NULL
The NULL command is a bit unique, and is mostly a construct to make writing Nonsense programs easier. Basically, any letters following a u in a word (including the u itself) are struck from the word, as if they didn’t exist; the rules for adding implicit 0‘s still follow. This implement helps in ensuring commands are valid English words, even when certain consonant combinations are difficult to produce.
gruff : g->r
bus: b
undo : (literally nothing)
bleu : b->S[l]
caribou : c+r->r; r-b->b; b+1->b
y: I/O
The I/O command is for inputting integers and outputting text in a program. When at the start of a syllable, y calls for input from the user; all other instances output the result as an ASCII character.
my : print m
yam : input()+m->m
yes : S[input()]->s
you : input()+1
cyan : c+n->n; print n (note that printing always occurs after syllable execution using result)
Punctuation marks are used to construct simple loops and conditionals within a Nonsense paragraph. The four valid punctuation marks are the comma (,), question mark (?), period (.), and exclamation point (!). It is intended that they are written into a paragraph akin to usual English punctuation, being directly adjacent to a word and followed by whitespace.
, : Start of a while loop, which uses result as the loop condition; a result of zero will skip to the corresponding period.
? : Start of an if conditional, again using result; a result of zero will skip to the corresponding period.
. : End of a while loop or if conditional; the interpreter will always return to the corresponding , or ? upon arrival.
! : Break conditional, again using result; a nonzero result instantly terminates the program.
Numbers
Numbers can be used to insert direct values into result, so that incrementing a variable a hundred times can be done in one syllable. When a number appears in a Nonsense paragraph, it must appear without any letters adjacent to it.
The objective of this experiment is to discard the laborious task of manually turning on/off a
projector when delivering presentations on a Raspberry Pi. The approach undertaken to automate
this is to catch HDMI connect/disconnect events and send appropriate signals to the projector
through an IR Transmitter.
(Done as a part of VL 855 – Device Driver Development coursework at IIIT-B)
Preparation
Installed LIRC packages on Raspbian Buster with kernel 4.19.75-v7+
with a patch [1].
Issued IR Emitter (IR333-A) and GPIO Utility Board with IR Receiver
(TSOP1738).
Setup the IR Transmitter circuit; with a 5V source (in my case its
from the RaspberryPi itself), a 400ohm resistor, a NPN transistor
and an IR emitter (detailed schematic is given in
LIRC section).
Connect the RaspberryPi to a power source (in my case its a laptop)
with the loaded modules (‘ssh’ with Ethernet cable could be used for
debugging) and ensure the initial state of the whole setup is that
the projector is ON and the HDMI cable is connected.
Ensure the IR emitter is directed towards the projector and there’s
no obstruction in-between.
The expected output is that once we disconnect the HDMI connector
for the RaspberryPi, the IR emitter sends a POWER_OFF signal (can
be seen through a phone camera with no IR-filter) and the projector
turns off after 3-4 secs (depends on polling frequency) of the
disconnect event. In the case of plugging in the HDMI connector when
the projector is OFF (red light), the IR emitter should send
POWER_ON signal and the projector should turn on in 3-4 secs.
Experiments and Analysis
GPIO
“GPIO is half-baked hardware” – with this statement in my head, I set
out to discover how one can setup functions for a GPIO cell to act like
an IR receiver and a transmitter. I figured de-compiling the device-tree
(which is currently being used by the kernel) to check for overlays that
have defined the GPIO pin numbers for IR-rx and IR-tx could be a valid
approach.
$ sudo dtc -I fs /sys/firmware/devicetree/base -O dts -o loaded\_device\_tree.dts
saved my de-compiled device-tree in ‘loaded_device_tree.dts’. There I looked for ir-rx and ir-tx which gave me:
Here, we can see that receiver is to be connected to GPIO 17 (0x11) and
emitter at GPIO 18 (0x12). The same information is available in
/boot/overlay/README (under gpio-ir and
gpio-ir-tx). Although to enable infrared communication and for the
overlay to take reflect in the device-tree, one had to uncomment a few
lines in /boot/config.txt (and then reboot for the
new device-tree to be picked up by the kernel) as shown here:
I also examined the description of the device-tree bindings
[2][3] for more clarity on how the IR rx and tx
works before proceeding with the practical experiments.
LIRC
I, first, set up the initial circuitry composed of only the IR rx to
decode the 38KHz infrared signals from the CASIO projector’s remote
using lircd daemon. I noticed the device special file created by LIRC
driver: /dev/lirc0 (Tx) and
/dev/lirc1 (Rx) were exposed in devfs, as
discussed in the class. To see the receive raw (pulse-space) codes from
the remote, I used the command line utility provided by LIRC:
mode2. Although, that didn’t work as expected even
after numerous tries and re-reading the man pages. The output I was
getting were decoded keycodes which were also different everytime even
for the same button press, as shown here:
This diverted my attention towards other utilities provided by LIRC;
irrecord, after it directed me to a database of
remotes with their corresponding keycodes [4] to an unfruitful
search, also proved to be erroneous because after recording KEY_POWER
for the CASIO projector’s remote, my keycode didn’t match with my
colleagues’ keycodes for the same button! This threw me off to use
ir-ctl which after reading the man pages revealed
that it could be used to do both rx and tx but with raw IR codes! So,
the lircd daemon was no use in this case since I didn’t have to decode.
$ ir-ctl -1 - -receive=KEY\_POWER.txt -d/dev/lirc1
was used to receive the raw codes of the
POWER button and save it in the KEY_POWER.txt file.
After this, testing of the rx part was done successfully. Before delving
into the circuitry of the tx part, I was warned by my colleague Shivam
to use a transistor to amplify the current supplied to the IR emitter
such that its able to send the infrared signals to the projector with
high-enough amplitude. Keeping this in mind the schematic of the circuit
is given below:
$ ir-ctl - -send=KEY\_POWER.txt -d /dev/lirc0 was
used to emit the raw codes of the POWER button saved in the
key_power.txt file. This completes my testing of tx part as well. Now,
I just had to devise a solution to the question “When do I send the
POWER signal to the projector?”
Mailbox
Unaware of the presence of Broadcom VideoCore VI processor on my
Raspberry Pi Model 2B which handles the detection of HDMI instead of the
ARM Cortex-A7 processor, I hypothesised that the HDMI event detection
mechanism incorporated by my HP Pavilion 15 laptop should be the same in
case of the Raspberry Pi. With this assumption, I carried out some
unnecessary but enlightening experiments involving the ‘drm’ subsystem.
It had a device in sysfs named under
card0-HDMI-A-1 which had exposed attributes on the
state of HDMI connection, device-specific information in EDID (Extended
Display Identification Data) [5] format, etc (see figure
below).
This gave me an illusion on the complexity of the project in Raspberry
Pi. This illusion was erased once I re-read the problem statement and
discovered the absence of the ‘drm’ subsystem in RaspberryPi. But,
borrowing ideas from the above experiment, I used the EDID format to
detect the presence of an HDMI connect/disconnect event which I shall
discuss in the report later.
Mentioned in the hints, I turned my attention towards using ‘tvservice’
and investigated how it uses Mailbox, an inter-processor communication
mechanism between the ARM core and the VideoCore, to detect the state of
HDMI connection when one uses the command-line utility: $ tvservice -s or $ tvservice -M. Upon
reading the source code [6], I stumbled upon the different values
(bitmask) the state can take. This proved to be useful in deciphering
what the state code meant when one executed $ tvservice -s. Although, I wasn’t able to trace how
‘tvservice’ uses the Mailbox channels for the communication. Surfing
through the ‘userland’ repository, I found the source code for
‘vcmailbox’ [7] utility. This had evident traces of how it uses the
Mailbox1 (ARM to VC) to send request on channel 8 (search for
MBOX_CHAN_PROPERTY) with property tags and how the response is
received on Mailbox0 (VC to ARM) in the same buffer, which is in sync
with the documentation [8]. I even tried out a few examples by
using the command-line utility $ /opt/vc/bin/vcmailbox \[words\] and tried to exercise the same code as
this [9]. This was too tedious when I tried to request EDID blocks
with the property ‘Get EDID Block’ as mentioned here [10] as I
got confused on request format. This is when my colleague Vijay
suggested me to use Mailbox utility from kernel-modules [11]!
This seemed like a more reasonable approach as this would be a
kernel-space-based solution rather than a user-space one, where one
would ideally just write a ‘bash’ script to continuously poll over
tvservice’s utility.
Tracing the source code [12][13][14], the whole
communication interface between ARM and VC was much clearer. All I had
to do now was write a miscellaneous device module which exposes an
attribute called ‘status’ which, when read, sends a ‘Get EDID Block’
request to VC over the mailbox channel and with some further logic
(discussed later) tells us if HDMI is connected or not. I used this
approach (of exposing an attribute) for testing purposes and I soon
realised how an ‘uevent’ mechanism would be much structured in this
case.
uevents
On my colleague Mohana’s recommendation, I decided to look through the
source code for how one can generate ‘uevents’ from kernel modules
[15]. I devised a mechanism which generates a ‘uevent’ with CHANGE
action and under a defined “myHDMI” subsystem whenever there is a
change in state of HDMI connection; disconnected to connected and
connected to disconnected. A corresponding .rules file was implemented
which executes my previous findings on matching with my generated
‘uevent’; sending a POWER infrared signal using
ir-ctl.
hdmi_dev.c – Misc Device
Inspired by goonj.c and blinker.c, I wrote a misc_device module which
sets up a timer to send a ‘Get EDID Block’ request (with workqueues
because the requests are not atomic due to presence of locks [16]) to
VC through a mailbox channel at a pre-defined rate and detects state
change to generate an ‘uevent’ with some internal logic. The logic is
that, when no HDMI device is connected, the reponse by VC should not
contain any information to my request of ‘Get EDID Block’ and when some
HDMI device is connected, I get some device-related data. I encountered
a few errors involving devices which can send multiple blocks of data in
the request but those were cleared after a thorough read of the EDID
v1.3 (bytes 18 and 19 tell the EDID version) specification issued by
VESA [17][18] which said that the 127th byte tells us about
the remaining extension blocks to come. Once I received all the EDID
extensions correctly, I used edidparser to make
sense of the received data which reflected the flawlessly execution of
my module.
HPD in HDMI
The above approach of using a mailbox channel become obsolete when I
discovered that GPIO 46 is connected to pin 19 (Hot Plug Detect) of the
HDMI connector [19] in Raspberry Pi Model 2B. I even traced the
lines in the schematic (page 2) [20] just to confirm! Upon learning
more on about the detection process [21], it made a lot of sense for me
to take this approach rather than the EDID one because it’s much more
“cleaner” and that pin must be solely meant to do HDMI detection. With
this, I updated my hdmi_dev-w-edid.c to hdmi_dev-w-gpio.c which uses the
get\_gpio\_value() framework to read the level of
GPIO 46. The other logic remains the same. Note: It’s not necessary to
use workqueues in this case although it made sense for me that a
separate kernel-thread does the polling for me rather than the kernel
module itself.
Modes in CASIO projectors
After numerous experiments, Mohana and I realised that the projector
stays in STANDBY mode when the RED light is displayed. At this state,
even if the HDMI connector is plugged in, it’s not plausible to detect
if it has been plugged in (we are assuming the power is not let through
the connector). In response to this, I believe it’s not possible to
switch ON the projector when HDMI cable is plugged in; it must already
be in state ON for it to detect the connection. This behaviour is not
seen in cases of Monitors. I even explored other options apart from
POWER signal like BLANK signal (puts the projector in low-power mode by
switching off the display) but then I realised I was diverting away from
the original problem statement.
Conclusion
The output matched the expectation in the case of HDMI disconnect event
but not for the HDMI connect event because it does not seem possible to
know if the HDMI is connected when the CASIO projector is OFF. Although,
when the projector is ON and we plug in the HDMI connector, we can
detect it. Below is the output:\
This project educated me on how to look through source code to interpret
the author’s intentions. It also enabled me to question my design
choices through-out the process for example: kernel-space-based solution
vs. user-space-based solution, misc_device vs. platform_device, the
polling time, etc.
Welcome to the Voting Application Project repository! This repository contains all the information and code you need to understand, contribute to, and develop an innovative voting application using Laravel and React JS. This application is designed to facilitate efficient and secure voting processes, providing a seamless experience for users.
About the Project
The Voting Application Project is our endeavor to develop a modern solution for conducting voting. By harnessing the power of the Laravel and React JS frameworks, along with other advanced features, this application aims to address challenges in traditional voting systems. Utilizing cutting-edge technology, we aim to ensure vote integrity and enhance participation in the democratic process.
Key Features
Online Voting: Enables voters to cast their votes online, saving time and effort.
Ensured Security: Incorporates a robust security system to protect voter data and prevent vote manipulation.
Intuitive Interface: Built with React JS, providing a user-friendly interface that caters to users from various backgrounds.
Real-time Monitoring: Monitors real-time voting results and generates accurate statistical reports.
We highly value contributions from all parties. If you wish to contribute to the development of the Voting Application Project, follow these steps:
Fork the Repository: Begin by forking this repository.
Clone the Repository: Clone the forked repository to your local machine.
Create a Branch: Before making any changes, create a new branch with a clear description of the changes you intend to make.
Make Changes: Implement changes and enhancements aligned with your goals, using Laravel and React JS technologies.
Testing: Thoroughly test all your changes to ensure they do not disrupt overall functionality.
Create a Pull Request: Submit a pull request with detailed information about the changes you’ve made and their purpose.
We hope that this application will be a valuable contribution in advancing the democratic process and facilitating better voting experiences. If you have questions, suggestions, or wish to participate, feel free to raise issues or submit pull requests. Thank you for joining us in this project!
Stack Overflow Assistant Telegram Chatbot, based on templates from Potapenko et al, HSE, Russia.
Accessing the bot:
Simply go to t.me/prannerta100_bot and start chatting!
The bot has been hosted on a Google Cloud VM, so you might face some server-side latency.
Here is a sample conversation with the bot:
Dependencies:
nltk
chatterbot corpus
sklearn
Description:
Here is how the bot works:
read the message, use a classifier to classify its intent as non-programming or programming
If non-programming, then invoke a pre-trained, off-the-shelf chatbot (here I used Ron Obvious from the chatterbot module)
If programming, then show the relevant Stack Overflow link that matches the question description the best
Training data:
The first classifier (programming versus non-programming) was trained by mixing 2 datasets:
tagged_posts.tsv — StackOverflow posts, tagged with one programming language (positive samples).
dialogues.tsv — dialogue phrases from movie subtitles (negative samples).
The second classifier (given a programming question, find the relevant Stack Overflow link) works by finding the closest StarSpace embedding.
Relevant files:
The most relevant file here is nlp-chatbot/nlp-chatbot-main/dialogue_manager.py.
The entered question is transformed into a TF-IDF feature vector.
A model is trained to identify the most relevant question and tag.
DISCLAIMER: This software is for educational purposes only. Your account might be suspended because of script usage. USE THE SOFTWARE AT YOUR OWN RISK. THE AUTHORS ASSUME NO RESPONSIBILITY FOR RESULTS.
NOTE: It works with the old registration system, I didn’t try it with new BUIS system. But BUIS pages are similar to old registration pages, I think it needs small changes.
Usage
fromregistrationimportRegistration# Create instancereg=Registration(STUDENT_ID, STUDENT_PASSWORD)
# Set debug true for printing logs to consolereg.set_debug(True)
# Get quota for HUM102.01reg.get_quota("HUM", "102", 11)
# If login your account is successfulifreg.login():
# Take CMPE493.01 coursereg.take_course("CMPE", "493", 1)
# Take CMPE49J.01 course non-creditreg.take_course("CMPE", "49J", 1, non_credit=True)
# Take HTR312.01 course credit and with-repeatreg.take_course("HTR", "312", 11, non_credit=False, repeat_with="HTR 312 DD")
# Try to change HTR312 section 11 to 14forsectioninrange(11, 15):
reg.change_section("HTR", "312", section)