summaryrefslogtreecommitdiff
path: root/Homework/cs3460/typeahead/main.cpp
blob: 4c1a71429af32588b0cd8df1db465008586aab7c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "WordTree.hpp"
#include "rlutil.h"

#include <algorithm>
#include <fstream>
#include <iterator>
#include <memory>
#include <sstream>
#include <string>

template <typename Out>
void split(const std::string& s, char delim, Out result)
{
    std::istringstream iss(s);
    std::string item;
    while (std::getline(iss, item, delim))
    {
        *result++ = item;
    }
}

std::vector<std::string> split(const std::string& s, char delim)
{
    std::vector<std::string> elems;
    split(s, delim, std::back_inserter(elems));
    return elems;
}

class TypeAhead
{
    std::string m_sentence;
    std::shared_ptr<WordTree> m_wordTree;

  public:
    TypeAhead() :
        m_sentence(""), m_wordTree(std::make_shared<WordTree>()) {}

    void constructWordTreeFromFile(std::string filename)
    {
        std::ifstream inFile = std::ifstream(filename, std::ios::in);

        while (!inFile.eof())
        {
            std::string word;
            std::getline(inFile, word);
            // Need to consume the carriage return character for some systems, if it exists
            if (!word.empty() && word[word.size() - 1] == '\r')
            {
                word.erase(word.end() - 1);
            }
            // Keep only if everything is an alphabetic character -- Have to send isalpha an unsigned char or
            // it will throw exception on negative values; e.g., characters with accent marks.
            if (std::all_of(word.begin(), word.end(), [](unsigned char c)
                            { return std::isalpha(c); }))
            {
                std::transform(word.begin(), word.end(), word.begin(), [](char c)
                               { return static_cast<char>(std::tolower(c)); });
                m_wordTree->add(word);
            }
        }
    }

    bool update()
    {
        char input = rlutil::getkey();

        if (input == rlutil::KEY_ESCAPE)
            return false;

        if (input == rlutil::KEY_BACKSPACE)
        {
            if (m_sentence.length() > 0)
                m_sentence.pop_back();
            return true;
        }

        m_sentence += input;

        return true;
    }

    void draw()
    {
        rlutil::cls();
        std::uint32_t cursorY = m_sentence.size() / rlutil::tcols() + 1;
        std::uint32_t cursorX = m_sentence.length() % rlutil::tcols();

        std::cout << m_sentence << std::endl;

        std::cout << " --- predictions ---" << std::endl;

        if (m_sentence.size() > 0 && m_sentence.back() != ' ')
        {
            std::vector<std::string> words = split(m_sentence, ' ');
            std::string currentWord = words.back();
            std::transform(currentWord.begin(), currentWord.end(), currentWord.begin(), ::tolower);
            std::vector<std::string> predictions = m_wordTree->predict(currentWord, rlutil::trows() - cursorY - 2);

            for (std::string prediction : predictions)
                std::cout << prediction << std::endl;
        }

        rlutil::locate(cursorX + 1, cursorY);
    }
};

int main()
{
    rlutil::cls();

    TypeAhead program;
    program.constructWordTreeFromFile("dictionary.txt");

    do
    {
        program.draw();
    } while (program.update());

    return 0;
}