- Project has been deployed on Heroku. Please have a look
heroku
branch has been used for deployment- No
CORS
and hardcoded urls inheroku
branch
The project serves as a test for Job Application for the position of Software Developer at Terribly Tiny Tales.
This document will serve as a guide to get better understanding of different components of the project. The document contains explanations of components of code, as well as some personal notes from my side. The notes are a version of my thought process at the time of coding a particular component and the reason behind it.
- The aim of the project was to create a fronted that accepts a number input N
- On click of submit button, a request is to be sent to the backend. The request will contain the user input N
- At backend, fetch a file hosted at http://terriblytinytales.com/test.txt
- The backed will process this file and return the top N most frequently used words in the file
- Finally, the backend will display these words in a serialized tabular format
The project can be divided into two parts: Backend
and Frontend
. Both of these will be explained in detail.
-
Framework: ExpressJs
-
Backend code is in the file named,
server.js
. -
Start the backend server:
node server.js
-
Run
node server.js
on CLI to run the backend node server. The server will run onhttp://localhost:8000/
and application will listen for requests on port 8000. -
Once the app receives a get request from frontend on
api/words/:userInput
, it'll call thereadTextFile
function. -
readTextFile
function will utilizenode-fetch
to fetch the text file hosted at (http://terriblytinytales.com/test.txt). The text will be extracted from the response and the text body will be fed to another functiontextToWords
. -
textToWords
is basically the first step in our process of frequency computation of words. The input to this function is a text which contains different types of spacing characters (single space, tab\t
, next line character\n
), various symbols (@
,:
,_
,?
etc.) and punctuations(.
,,
,"
etc.) and also numbers that we don't need. The idea is to remove all these from the text and store just the words in an array which can be used for frequency computation of words.split
helps us with this.
At first, I tried by splitting the text at some of these characters, but to do that for each and every character didn't seem like an efficient process. So, to find a better way I googled, and discovered with the help of
stackoverflow
thatsplit
command can work upon a regex. This made the process of splitting text over different characters an easy task.
- The
text
issplit
on this regex/[.,@:_;?\/\(\)\t\n"<>0-9– ]/
and the result is saved inwords
array.
Initially, I included hyphen(
-
) in the regex, but that caused an issue. If we include-
in the regex then the words like,t-shirts
ande-commerce
will split intot
shirts
ande
commerce
respectively. Now, the words array will haveshirts
andcommerce
elements which qualify as words but alsot
ande
which do not qualify as words in my opinion. Also, my opinion was that words like,t-shirts
ande-commerce
are words in their own right, so there is no need to split these. For this reason, I excluded-
from theregex
. But this caused another problem, in the text there are words like,terribly-tiny-tales
andterribly-tiny-test
that are combination of multiple words, and in my opinion should be split.
- To tackle the above issue, I wrote a separate function
hyphenSplit
. This function will check if the words in the array contain-
, and if the-
is in the first position (t-shirts
,e-commerce
); if the-
is not at the first position then theword
will besplit
over-
otherwise not. Thepros
of this is that now we can save words liket-shirts
and split words like,terribly-tiny-test
. Thecons
is that if the text contains a word likeco-passenger
, it'll be split inco
andpassenger
.
The final decision to implement this will be based upon the developer's discretion, and he or she can use it or not by commenting out or uncommenting the
words = hyphenSplit(words)
command in thetextToWords
function.
I've decided to use this function.
-
After the text is
split
and the result saved towords
array, the array is served as an input to frequency computation function. I wrote two such functions which differ slightly.-
simpleFrequencyComputation
: This is forabsolute match
. Example, wordtale
is present intale
as well as intales
. This will only match withtale
. -
frequencyComputation
: This will performabsolute match
for single letter words likea
andi
. But for words with length greater than 1, this function will perform an includes match. Example, worda
is present in worda
,tale
,tales
,talented
, but it'll match witha
only. Thus,frequency
ofa
will be1
. Now, if word in consideration istale
, in this function it'll match withtale
,tales
andtalented
, giving it's frequency as3
and not1
as was the case withsimpleFrequencyComputation
.
-
-
Both these functions,
simpleFrequencyComputation
andFrequencyComputation
have some common traits:-
Both check for empty elements
""
that are present in thewords
array due tosplit
, and both check if a word's frequency has been computed already. -
Both send the final
frequencyArray
for sorting indescending
order on the basis offrequency
.
-
This is again on developer's discretion which type of Frequency Computation, he or she wants.
- The following are the screenshots of the results displayed on frontend:
master
branch: CORS has been implemented inserver.js
to enableCross Origin Resource Sharing
.heroku
branch: No need for CORS
-
Framework: AngularJS
-
This project was generated with Angular CLI version 6.0.5.
-
src/app/
folder is where all frontendcomponents
andservices
are present -
Run
ng serve --open
on CLI for a dev server. Navigate tohttp://localhost:4200/
. The app will automatically reload if you change any of the source files. -
Run
ng generate component component-name
on CLI to generate a new component. -
Run
ng generate service service-name
on CLI to generate a new component. -
There are two components (
ask-user
anddisplay-words
) and one service (words
) created. One other defaultapp
component is present. -
The whole page is
app
component;ask-user
anddisplay-words
are called inside this component.
- When the user enters an input and presses submit
getWords
present inask-user.component
is called. The function first checks if theinput
is anumber greater than 0
or not. If not then functions present inwords.service
, which acts as a connection betweenask-user
anddisplay-words
are called upon to log an error on screen.
-
If the
input > 0
then,callDisplayWords
present inwords.service
is called upon, which in turn callsgetWords
function present indisplay-words
component. This function again uses thewords.service
to make aget
request to server with theuserInput
. -
If the request catches any error then again a error message is logged on screen.
- If everything goes right, the number of most frequently used words the user asked for are displayed on screen.
-
I've not updated the
favicon
because I couldn't decide, and went ahead with the default angular favicon -
I thought of adding a
check
forinternet-connectivity
to make sure app can fetch the text file hosted at remote server. But, decided against it at this moment. But, that can be done to enhance the user experience -
After submission, I'll be working to host this on
heroku
. I am not doing this now because I am not sure if you are still hiring and I don't want to delay the submission -
Whenever you see this, please let me know how close is this to your required solution; irrespective of whether I am hired or not