Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Da Dict #16

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9728fb2
names added
Alex-Willenbrink Jul 18, 2017
0c3e344
Warmup!
thebopshoobop Jul 18, 2017
57ad2c5
Outline
thebopshoobop Jul 18, 2017
046ab41
Merge branch 'master' of https://github.com/thebopshoobop/assignment_…
Alex-Willenbrink Jul 18, 2017
e9db0aa
started
Alex-Willenbrink Jul 18, 2017
60cdb87
try again
Alex-Willenbrink Jul 18, 2017
b537f27
object based menu, started file loader
thebopshoobop Jul 18, 2017
219a8be
something
Alex-Willenbrink Jul 18, 2017
0d0e730
troubleshooting
thebopshoobop Jul 18, 2017
6135993
file loaded with word count
Alex-Willenbrink Jul 18, 2017
28080d3
Count letter frequency.
thebopshoobop Jul 18, 2017
94a81a8
Comments!
thebopshoobop Jul 18, 2017
e32965d
making more modular menus
Alex-Willenbrink Jul 18, 2017
40bf50e
Holy searches, batman!
thebopshoobop Jul 18, 2017
3ef68c1
added search modularity
Alex-Willenbrink Jul 18, 2017
ccb02f2
partial search
thebopshoobop Jul 18, 2017
6cd7802
ALL THE SEARCHING!
thebopshoobop Jul 18, 2017
74efaad
saveMenu
Alex-Willenbrink Jul 18, 2017
9f35b8f
Saving. Really. Somehow...
thebopshoobop Jul 18, 2017
decb8d5
finished anagram
Alex-Willenbrink Jul 18, 2017
3332727
Refactor menu to use prompt
thebopshoobop Jul 19, 2017
a566373
Refactor lib/search to use prompt
thebopshoobop Jul 19, 2017
a2c9139
Refactor searching for much less duplication!
thebopshoobop Jul 19, 2017
997ec7f
Simplify selectDict > load > info|search
thebopshoobop Jul 19, 2017
fb910b7
Refactor menus and loading
thebopshoobop Jul 19, 2017
72fe8cb
Load ALL THE DICTIONARIES
thebopshoobop Jul 19, 2017
21e127a
new io folder!
thebopshoobop Jul 19, 2017
e46823a
Saving is out of ui/search, and refactored to be much clearer
thebopshoobop Jul 19, 2017
3f8b607
Make the writeDict api more sensible
thebopshoobop Jul 19, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
# assignment_node_dictionary_reader
I CAN HAS SPELLZ IN "Node"? K THNX BYE


Will Thompson
Alex Willenbrink
3 changes: 3 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const dictionary = require('./lib');

dictionary();
17 changes: 17 additions & 0 deletions lib/frequency.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Return an object containing the frequency of words starting with each
// letter in a given dictionary

function countFrequency(data) {
let counts = {};
for (let word in data) {
if (counts[word[0]]) {
counts[word[0]] += 1;
} else {
counts[word[0]] = 1;
}
}

return counts;
}

module.exports = countFrequency;
5 changes: 5 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const ui = require('./ui');

function init(){ui();}

module.exports = init;
20 changes: 20 additions & 0 deletions lib/io/findDicts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Pass an object containing the available dictionary files
// into a given callback

const fs = require('fs');

function findDicts(callback) {
fs.readdir('./data', (err, files) => {
if (err) {
callback(err);
} else {
let dictionaries = {};
for (let i = 0; i < files.length; i++) {
dictionaries[i + 1] = './data/' + files[i];
}
callback(null, dictionaries);
}
});
}

module.exports = findDicts;
20 changes: 20 additions & 0 deletions lib/io/loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Load a given json file
// Display some pretty information about it
// Pass it into a given callback

const fs = require('fs');
const info = require('../ui/info');

function load(path, callback) {
fs.readFile(path, 'utf8', (err, data) => {
if (err || !data) {
callback(err);
} else {
data = JSON.parse(data);
info(path, data);
callback(null, path, data);
}
});
}

module.exports = load;
19 changes: 19 additions & 0 deletions lib/io/writeDict.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Given a file, subdictionary, dictionary, and callback
// Write the subdictionary into the file
// Pass the dictionary into the callback

const fs = require('fs');

function writeFile(filename, words, dictionary, callback) {
fs.writeFile(`./data/${filename}.json`, JSON.stringify(words), err => {
if (err) {
console.log(`Warning: ${err}`);
} else {
console.log('File successfully written.');
}

callback(dictionary);
});
}

module.exports = writeFile;
51 changes: 51 additions & 0 deletions lib/search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Search functions!

let searches = {
// Full Text Search
f: function(dictionary, searchText, matches, callback) {
if (dictionary[searchText]) {
matches[searchText] = dictionary[searchText];
}
callback(dictionary, searchText, matches);
},
// Partial Match
p: function(dictionary, searchText, matches, callback) {
for (let word in dictionary) {
if (word.indexOf(searchText) !== -1) {
matches[word] = dictionary[word];
}
}
callback(dictionary, searchText, matches);
},
// Word Begins With
b: function(dictionary, searchText, matches, callback) {
for (let word in dictionary) {
if (word.startsWith(searchText)) {
matches[word] = dictionary[word];
}
}
callback(dictionary, searchText, matches);
},
// Word Ends With
e: function(dictionary, searchText, matches, callback) {
for (let word in dictionary) {
if (word.endsWith(searchText)) {
matches[word] = dictionary[word];
}
}
callback(dictionary, searchText, matches);
},
// Anagrams
a: function(dictionary, searchText, matches, callback) {
let searchSorted = searchText.split('').sort().join('');
for (let word in dictionary) {
let wordSorted = word.split('').sort().join('');
if (wordSorted === searchSorted) {
matches[word] = dictionary[word];
}
}
callback(dictionary, searchText, matches);
}
};

module.exports = searches;
11 changes: 11 additions & 0 deletions lib/ui/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const menu = require('./menu');
const selectDict = require('./selectDict');
const search = require('./search');

function init() {
console.log('Welcome to the Node Dictionary Reader:');
console.log('======================================');
selectDict(search);
}

module.exports = init;
20 changes: 20 additions & 0 deletions lib/ui/info.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Given a file path and dictionary object
// Display some information about them

const selectDict = require('./selectDict');
const count = require('../frequency');

// Recieve results from a load
function displayInfo(path, result) {
// Display results
console.log(`Success!`);
console.log(`Loaded: ${path}`);
console.log(`Words: ${Object.keys(result).length}`);
console.log('Word frequency by starting letter:');
const counts = count(result);
for (let letter in counts) {
console.log(`${letter.toUpperCase()}: ${counts[letter]}`);
}
}

module.exports = displayInfo;
30 changes: 30 additions & 0 deletions lib/ui/menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Given a message, an object containing options, and a callback
// Present the message and options to the user repeatedly
// Until they enter one of the options
// Pass that option into the callback

const prompt = require('./prompt');

function menu(message, acceptable, callback) {
// Show message
console.log(message);

// Display options
for (let option in acceptable) {
console.log(`${option}. ${acceptable[option]}`);
}

// Handle input
prompt(null, selection => {
if (Object.keys(acceptable).includes(selection)) {
// The user unput an acceptable selection
callback(selection);
} else {
// Retry
console.log(`Sorry ${selection} is not a valid option.`);
menu(message, acceptable, callback);
}
});
}

module.exports = menu;
17 changes: 17 additions & 0 deletions lib/ui/prompt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Optionally display a message to the user
// Wait for some input and pass that input into a given callback

function prompt(message, callback) {
if (message) console.log(message);
process.stdin.resume();
process.stdin.setEncoding('utf8');
let onData = data => {
data = data.trim();
process.stdin.pause();
process.stdin.removeListener('data', onData);
callback(data);
};
process.stdin.on('data', onData);
}

module.exports = prompt;
36 changes: 36 additions & 0 deletions lib/ui/saveDict.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Given a dictionary, a subdictionary, and a callback
// Prompt the user for where they would like to save
// Check to see if that file exists
// If not, write the file
// If so, prompt the user to overwrite
// Either write or return to the menu

const fs = require('fs');
const writeDict = require('../io/writeDict');
const prompt = require('./prompt');
const menu = require('./menu');

function saveDict(dictionary, words, callback) {
prompt('What filepath should we write results to?', filename => {
fs.readdir('./data', (err, data) => {
if (err) throw err;
if (data.includes(filename + '.json')) {
promptExists(filename, words, dictionary, callback);
} else {
writeDict(filename, words, dictionary, callback);
}
});
});
}

function promptExists(filename, words, dictionary, callback) {
menu('File exists. Overwrite?', { y: 'Yes', n: 'No' }, choice => {
if (choice === 'y') {
writeDict(filename, words, dictionary, callback);
} else {
callback(dictionary);
}
});
}

module.exports = saveDict;
70 changes: 70 additions & 0 deletions lib/ui/search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const selectDict = require('./selectDict');
const search = require('../search');
const menu = require('./menu');
const prompt = require('./prompt');
const saveDict = require('./saveDict');

function displayResult(dictionary, term, words) {
if (!words || !Object.keys(words).length) {
console.log(`Sorry, I couldn't find ${term}`);
displayMenu(dictionary);
} else {
console.log('Results:');
for (let word in words) {
console.log(`${word}: ${words[word]}`);
}
// Promp for save
menu('Do you want to save results', { y: 'Yes', n: 'No' }, choice => {
if (choice === 'n') {
displayMenu(dictionary);
} else {
saveDict(dictionary, words, displayMenu);
}
});
}
}

function displayMenu(dictionary) {
menu(
'Search Menu',
{
f: 'Full Text Search',
p: 'Partial Matches',
b: 'Word Begins With..',
e: 'Word Ends With...',
a: 'Find anagrams',
l: 'Load another dictionary',
q: 'Quit'
},
result => {
switch (result) {
case 'q':
// The user want's out!
process.exit();
case 'l':
// Load the load menu
selectDict(recieveDict);
break;
default:
// The user wants to search
prompt('Enter search term:', searchText => {
let matches = {};
search[result](dictionary, searchText, matches, displayResult);
});
}
}
);
}

// Recieve results from a load
function recieveDict(err, path, result) {
if (err) {
// Prompt user again on error
console.log('Sorry, there was an error. Please try again.');
selectDict(recieveDict);
} else {
displayMenu(result);
}
}

module.exports = recieveDict;
22 changes: 22 additions & 0 deletions lib/ui/selectDict.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Given a callback
// Prompt the user to select a dictionary
// Pass that dictionary and callback into the loader

const menu = require('./menu');
const load = require('../io/loader');
const findDicts = require('../io/findDicts');

function init(callback) {
findDicts((err, options) => {
if (err) throw err;
options['q'] = 'Quit';
menu('Select a dictionary to load:', options, selection => {
if (selection === 'q') {
process.exit();
}
load(options[selection], callback);
});
});
}

module.exports = init;
Loading