// File: /workspace/github_cpp_makefile_star2_O3/linuxnoodle[P]typer/main.cpp
// Function: main
int main(){
    // Clears screen when first ran.
    #ifdef _WIN32
        system("cls");
    #else
        cout << "\x1B[2J"; 
        cout << "\x1B[0;0H";
    #endif

    cout << "Enter the amount of words you want to type: (type \"quotes\" for quotes)\n";
    string s = "bruh";
    
    // Makes sure user input is valid.
    while (s != "quotes" && (!(s.find_first_not_of("0123456789") == string::npos) || s == "0")){
        #ifdef _WIN32
            cout << "Please enter a positive non-zero integer.\n";
        #else
            cout << "\033[0;32mPlease enter a positive non-zero integer.\033[0m\n";
        #endif
        getline(cin, s, '\n');
    }

    ifstream wordsFile;
    
    #ifdef _WIN32
        char *path = getenv("appdata");
        if (s == "quotes"){
            strcat(path, "\\quotes.txt"); 
        } else {
            strcat(getenv("appdata"), "\\words.txt"); 
        }   
    #else
        struct passwd *pw = getpwuid(getuid());
        char *path = pw->pw_dir;
        if (s == "quotes"){
            strcat(path, "/.local/share/quotes.txt");
        } else {
            strcat(path, "/.local/share/words.txt");
        } 
    #endif

    // Reads file into the vector "words".
    wordsFile = ifstream(path);

    if (!wordsFile){
        if (s == "quotes"){
            wordsFile = ifstream("quotes.txt");
        } else {
            wordsFile = ifstream("words.txt");
        }
        if (!wordsFile){
            #ifdef _WIN32
                cerr << "Error: quotes and/or words file is missing. Put \"words.txt\" and \"quotes.txt\" in \%appdata\%\\Roaming\\\n";
            #else
                cerr << "Error: quotes and/or words file is missing. Put \"words.txt\" and \"quotes.txt\" in ~/.local/share/\n";
            #endif
            return -1;
        } else {
            #ifdef _WIN32
                // Moving the files in windows doesn't appear to work, but at the very least, 
                // there is no reason to move them in windows
                if (s == "quotes"){
                    MoveFile("quotes.txt", path);
                } else {
                    MoveFile("words.txt", path);
                }
            #else
                if (s == "quotes"){
                    filesystem::rename("quotes.txt", path);
                } else {
                    filesystem::rename("words.txt", path);
                }
            #endif
        }
    }
    if (wordsFile.is_open()){
        string line;
        while (getline(wordsFile, line)){
            words.push_back(line);
        }
    }
    // Initializes random distribution, as before this the bounds are not decided.
    distribution = uniform_int_distribution<mt19937::result_type>(0, words.size() - 1);

    while (true){
        // Grabs the next phrase, and loads it.
        string phrase;
        if (s == "quotes"){
            phrase = words[distribution(generator)];
        } else {
            phrase = generateString(stoi(s));
        }

        // Clears screen, then displays text in green. 
        // (\033 is the escape character, 0;32 means green.)
        #ifdef _WIN32
            system("cls");
            cout << phrase << "\n";
        #else
            cout << "\x1B[2J";
            cout << "\x1B[0;0H";
            cout << "\033[0;32m" << phrase << "\033[0m\n";
        #endif
        // Splits phrase delimited by space, and finds wordcount. (Will be used to rework new typing system)
        vector<string> splitPhrase;
        istringstream iss(phrase);
        
        string word;
        while (getline(iss, word, ' ')){
            splitPhrase.push_back(word);
        }
        
        int wordCount = splitPhrase.size();
        
        // Starts timer to calculate WPM.
        auto startTime = chrono::system_clock::now();
        
        string userInput;
        getline(cin, userInput, '\n');
        
        float timeTaken = (chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now() - startTime).count());
        
        cout << "Time taken: " << timeTaken/1000 << "s\n";
        cout << "Raw WPM: " << wordCount/(timeTaken/60000) << "wpm\n";
        
        // Calculates the amount of mistyped characters.
        // First, it checks if the size of the phrase typed and the actual phrase are the same, as if they aren't,
        // checking each character would segfault due to an out of bounds exception.
        // If it is, it adds the difference to the error count, and only check for differences up to the shorter length.
        // If it isn't, it just checks each character with the same indicies.
        
        int errors = 0;
        if (userInput.size() != phrase.size()){
            errors += abs((int)userInput.size() - (int)phrase.size());
            for (int i = 0; i <= abs((int)userInput.size() - (int)phrase.size()); ++i){
                if (phrase[i] != userInput[i]){
                    ++errors;
                }
            }
        } else {
            for (int i = 0; i < (int)phrase.size(); ++i){
                if (phrase[i] != userInput[i]){
                    ++errors;
                }
            }
        }
        
        cout << "Mistyped characters: " << errors << "\n";
        errors = 0;
        
        // Waits for one second so that the user can actually read the output.
        #ifdef _WIN32
            Sleep(1000);
        #else
            usleep(1000000);
        #endif
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x4c8, %rsp            # imm = 0x4C8
movq 0x3a09(%rip), %rbx      # 0x5fc8
leaq 0x1a8a(%rip), %rsi      # 0x4050
movl $0x4, %edx
movq %rbx, %rdi
callq 0x21f0
leaq 0x1a7b(%rip), %rsi      # 0x4055
movl $0x6, %edx
movq %rbx, %rdi
callq 0x21f0
leaq 0x1a6e(%rip), %rsi      # 0x405c
movl $0x47, %edx
movq %rbx, %rdi
callq 0x21f0
leaq 0x70(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x1a99(%rip), %rsi      # 0x40a4
leaq 0x1a96(%rip), %rdx      # 0x40a8
leaq 0x60(%rsp), %r14
movq %r14, %rdi
callq 0x3222
leaq 0x1a83(%rip), %r15      # 0x40a9
leaq 0x1a83(%rip), %r12      # 0x40b0
leaq 0x1a89(%rip), %rbp      # 0x40bd
movq 0x399d(%rip), %r13      # 0x5fd8
movq %r14, %rdi
movq %r15, %rsi
callq 0x20a0
testl %eax, %eax
je 0x2697
movl $0xa, %ecx
movq %r14, %rdi
movq %r12, %rsi
xorl %edx, %edx
callq 0x22c0
cmpq $-0x1, %rax
jne 0x2675
movq %r14, %rdi
leaq 0x1a4f(%rip), %rsi      # 0x40bb
callq 0x20a0
testl %eax, %eax
jne 0x2697
movl $0x35, %edx
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x21f0
movq %r13, %rdi
movq %r14, %rsi
movl $0xa, %edx
callq 0x2310
jmp 0x263b
leaq 0x2c0(%rsp), %rdi
callq 0x21e0
callq 0x2100
movl %eax, %edi
callq 0x2200
movq 0x20(%rax), %rax
movq %rax, 0x30(%rsp)
leaq 0x19e9(%rip), %rsi      # 0x40a9
leaq 0x60(%rsp), %rdi
callq 0x20a0
movl %eax, %ebp
movq 0x30(%rsp), %rbx
movq %rbx, %rdi
callq 0x20f0
addq %rbx, %rax
testl %ebp, %ebp
je 0x26fa
movups 0x1a25(%rip), %xmm0     # 0x410c
movups %xmm0, (%rax)
movabsq $0x7478742e736472, %rcx # imm = 0x7478742E736472
movq %rcx, 0x10(%rax)
jmp 0x270f
movups 0x19fb(%rip), %xmm0     # 0x40fc
movups %xmm0, 0x9(%rax)
movups 0x19e7(%rip), %xmm0     # 0x40f3
movups %xmm0, (%rax)
leaq 0xb8(%rsp), %rdi
movq %rbx, %rsi
movl $0x8, %edx
callq 0x2300
leaq 0x2c0(%rsp), %rbx
leaq 0xb8(%rsp), %rsi
movq %rbx, %rdi
callq 0x2290
leaq 0xb8(%rsp), %rdi
callq 0x2060
movq 0x2c0(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x2e0(%rsp,%rax)
je 0x28fd
leaq 0x193f(%rip), %rsi      # 0x40a9
leaq 0x60(%rsp), %rdi
callq 0x20a0
testl %eax, %eax
je 0x27a8
leaq 0x199b(%rip), %rsi      # 0x411a
leaq 0xb8(%rsp), %rdi
movl $0x8, %edx
callq 0x2300
leaq 0x2c0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x2290
jmp 0x27d6
leaq 0x1952(%rip), %rsi      # 0x4101
leaq 0xb8(%rsp), %rdi
movl $0x8, %edx
callq 0x2300
leaq 0x2c0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x2290
leaq 0xb8(%rsp), %rdi
callq 0x2060
movq 0x2c0(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x2e0(%rsp,%rax)
je 0x2851
movq 0x37f0(%rip), %rdi      # 0x5ff0
leaq 0x191d(%rip), %rsi      # 0x4124
movl $0x60, %edx
callq 0x21f0
leaq 0x2c0(%rsp), %rdi
callq 0x2060
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0x283a
movq 0x70(%rsp), %rsi
incq %rsi
callq 0x21d0
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x4c8, %rsp            # imm = 0x4C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1851(%rip), %rsi      # 0x40a9
leaq 0x60(%rsp), %rdi
callq 0x20a0
testl %eax, %eax
jne 0x28a7
leaq 0x1894(%rip), %rsi      # 0x4101
leaq 0xb8(%rsp), %rdi
movl $0x2, %edx
callq 0x2f78
leaq 0x8(%rsp), %rdi
leaq 0x30(%rsp), %rsi
movl $0x2, %edx
callq 0x3000
leaq 0xb8(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x2140
jmp 0x28e6
leaq 0x186c(%rip), %rsi      # 0x411a
leaq 0xb8(%rsp), %rdi
movl $0x2, %edx
callq 0x30c0
leaq 0x8(%rsp), %rdi
leaq 0x30(%rsp), %rsi
movl $0x2, %edx
callq 0x3000
leaq 0xb8(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x2140
leaq 0x8(%rsp), %rdi
callq 0x3088
leaq 0xb8(%rsp), %rdi
callq 0x3088
leaq 0x338(%rsp), %rdi
callq 0x2050
testb %al, %al
je 0x29a0
leaq 0xb8(%rsp), %r14
leaq 0xc8(%rsp), %rax
movq %rax, (%r14)
movq $0x0, 0x8(%r14)
movb $0x0, 0x10(%r14)
leaq 0x3887(%rip), %r15      # 0x61c0
movq 0x2c0(%rsp), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x21b0
movsbl %al, %edx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2310
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x297b
movq %r15, %rdi
movq %r14, %rsi
callq 0x3148
jmp 0x2939
movq 0xb8(%rsp), %rdi
leaq 0xc8(%rsp), %rax
cmpq %rax, %rdi
je 0x29a0
movq 0xc8(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x3821(%rip), %rax      # 0x61c8
subq 0x3812(%rip), %rax      # 0x61c0
sarq $0x5, %rax
decq %rax
movq $0x0, 0x4ba0(%rip) # 0x7560
movq %rax, 0x4ba1(%rip)      # 0x7568
movq 0x35fa(%rip), %r12      # 0x5fc8
leaq 0xb8(%rsp), %rbx
leaq 0x80(%rsp), %r14
leaq 0xa0(%rsp), %r13
leaq 0x18(%rsp), %rax
movq %rax, 0x8(%rsp)
movq $0x0, 0x10(%rsp)
movb $0x0, 0x18(%rsp)
leaq 0x60(%rsp), %r15
movq %r15, %rdi
leaq 0x169c(%rip), %rsi      # 0x40a9
callq 0x20a0
testl %eax, %eax
je 0x2a63
movq %r15, %rdi
xorl %esi, %esi
movl $0xa, %edx
callq 0x3185
movq %rbx, %rdi
movl %eax, %esi
callq 0x24fc
leaq 0x8(%rsp), %rdi
movq %rbx, %rsi
callq 0x2210
movq 0xb8(%rsp), %rdi
leaq 0xc8(%rsp), %rax
cmpq %rax, %rdi
je 0x2a91
movq 0xc8(%rsp), %rsi
incq %rsi
callq 0x21d0
jmp 0x2a91
leaq 0x4af6(%rip), %rdi      # 0x7560
leaq 0x3767(%rip), %rsi      # 0x61d8
movq %rdi, %rdx
callq 0x32b8
shlq $0x5, %rax
addq 0x373c(%rip), %rax      # 0x61c0
leaq 0x8(%rsp), %rdi
movq %rax, %rsi
callq 0x2120
movl $0x4, %edx
movq %r12, %rdi
leaq 0x15b0(%rip), %rsi      # 0x4050
callq 0x21f0
movl $0x6, %edx
movq %r12, %rdi
leaq 0x15a1(%rip), %rsi      # 0x4055
callq 0x21f0
movl $0x7, %edx
movq %r12, %rdi
leaq 0x16bd(%rip), %rsi      # 0x4185
callq 0x21f0
movq 0x8(%rsp), %rsi
movq 0x10(%rsp), %rdx
movq %r12, %rdi
callq 0x21f0
movl $0x5, %edx
movq %rax, %rdi
leaq 0x15ff(%rip), %rsi      # 0x40ed
callq 0x21f0
xorps %xmm0, %xmm0
movaps %xmm0, 0xa0(%rsp)
movq $0x0, 0xb0(%rsp)
movq %rbx, %rdi
leaq 0x8(%rsp), %rsi
movl $0x8, %edx
callq 0x22b0
leaq 0x90(%rsp), %rax
movq %rax, 0x80(%rsp)
movq $0x0, 0x88(%rsp)
movb $0x0, 0x90(%rsp)
movq %rbx, %rdi
movq %r14, %rsi
movl $0x20, %edx
callq 0x2310
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x2b6b
movq %r13, %rdi
movq %r14, %rsi
callq 0x3148
jmp 0x2b40
movq 0xa8(%rsp), %rbp
subq 0xa0(%rsp), %rbp
callq 0x2040
movq %rax, %r15
leaq 0x50(%rsp), %rax
movq %rax, 0x40(%rsp)
movq $0x0, 0x48(%rsp)
movb $0x0, 0x50(%rsp)
movq 0x3436(%rip), %rdi      # 0x5fd8
leaq 0x40(%rsp), %rsi
movl $0xa, %edx
callq 0x2310
callq 0x2040
subq %r15, %rax
movabsq $0x431bde82d7b634db, %rcx # imm = 0x431BDE82D7B634DB
imulq %rcx
movq %rdx, %r15
movl $0xc, %edx
movq %r12, %rdi
leaq 0x15b5(%rip), %rsi      # 0x418d
callq 0x21f0
movq %r15, %rax
shrq $0x3f, %rax
sarq $0x12, %r15
addq %rax, %r15
xorps %xmm0, %xmm0
cvtsi2ss %r15, %xmm0
movss %xmm0, 0x3c(%rsp)
divss 0x1403(%rip), %xmm0     # 0x4004
cvtss2sd %xmm0, %xmm0
movq %r12, %rdi
callq 0x2280
movl $0x2, %edx
movq %rax, %rdi
leaq 0x157e(%rip), %rsi      # 0x419a
callq 0x21f0
movl $0x9, %edx
movq %r12, %rdi
leaq 0x156d(%rip), %rsi      # 0x419d
callq 0x21f0
shrq $0x5, %rbp
xorps %xmm0, %xmm0
cvtsi2ss %ebp, %xmm0
movss 0x3c(%rsp), %xmm1
divss 0x13ba(%rip), %xmm1     # 0x4008
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movq %r12, %rdi
callq 0x2280
movl $0x4, %edx
movq %rax, %rdi
leaq 0x153a(%rip), %rsi      # 0x41a7
callq 0x21f0
movq 0x48(%rsp), %rax
movq 0x10(%rsp), %rcx
cmpq %rcx, %rax
jne 0x2cb5
testl %eax, %eax
jle 0x2ced
movq 0x8(%rsp), %rcx
movq 0x40(%rsp), %rdx
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
xorl %esi, %esi
xorl %r15d, %r15d
movb (%rcx,%rsi), %dil
xorl %r8d, %r8d
cmpb (%rdx,%rsi), %dil
setne %r8b
addl %r8d, %r15d
incq %rsi
cmpq %rsi, %rax
jne 0x2c99
jmp 0x2cf0
subl %ecx, %eax
movl %eax, %r15d
negl %r15d
cmovsl %eax, %r15d
movq 0x8(%rsp), %rax
movq 0x40(%rsp), %rcx
leal 0x1(%r15), %edx
xorl %esi, %esi
movb (%rax,%rsi), %dil
xorl %r8d, %r8d
cmpb (%rcx,%rsi), %dil
setne %r8b
addl %r8d, %r15d
incq %rsi
cmpq %rsi, %rdx
jne 0x2cd1
jmp 0x2cf0
xorl %r15d, %r15d
movl $0x15, %edx
movq %r12, %rdi
leaq 0x14ad(%rip), %rsi      # 0x41ac
callq 0x21f0
movq %r12, %rdi
movl %r15d, %esi
callq 0x22d0
movl $0x1, %edx
movq %rax, %rdi
leaq 0x1384(%rip), %rsi      # 0x40a2
callq 0x21f0
movl $0xf4240, %edi          # imm = 0xF4240
callq 0x2230
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x2d49
movq 0x50(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x80(%rsp), %rdi
leaq 0x90(%rsp), %rax
cmpq %rax, %rdi
je 0x2d6e
movq 0x90(%rsp), %rsi
incq %rsi
callq 0x21d0
movq %rbx, %rdi
movq 0x3248(%rip), %rsi      # 0x5fc0
callq 0x2240
leaq 0x130(%rsp), %rdi
callq 0x20c0
movq %r13, %rdi
callq 0x2f1a
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rdi
je 0x29e6
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x21d0
jmp 0x29e6
jmp 0x2dcd
movq %rax, %rbx
jmp 0x2e99
jmp 0x2dc5
jmp 0x2dcd
movq %rax, %rbx
jmp 0x2ea6
movq %rax, %rbx
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x2e53
movq 0x50(%rsp), %rsi
incq %rsi
callq 0x21d0
jmp 0x2e53
jmp 0x2df0
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x3088
jmp 0x2e04
jmp 0x2e01
movq %rax, %rbx
leaq 0xb8(%rsp), %rdi
callq 0x3088
jmp 0x2ee1
jmp 0x2ede
jmp 0x2ede
jmp 0x2eca
jmp 0x2ede
movq %rax, %rbx
movq 0xb8(%rsp), %rdi
leaq 0xc8(%rsp), %rax
cmpq %rax, %rdi
je 0x2ee1
movq 0xc8(%rsp), %rsi
jmp 0x2eba
movq %rax, %rbx
movq 0x80(%rsp), %rdi
leaq 0x90(%rsp), %rax
cmpq %rax, %rdi
je 0x2e78
movq 0x90(%rsp), %rsi
incq %rsi
callq 0x21d0
movq 0x3141(%rip), %rsi      # 0x5fc0
leaq 0xb8(%rsp), %rdi
callq 0x2240
leaq 0x130(%rsp), %rdi
callq 0x20c0
leaq 0xa0(%rsp), %rdi
callq 0x2f1a
movq 0x8(%rsp), %rdi
leaq 0x18(%rsp), %rax
cmpq %rax, %rdi
je 0x2ee1
movq 0x18(%rsp), %rsi
incq %rsi
callq 0x21d0
jmp 0x2ee1
jmp 0x2eca
jmp 0x2ede
jmp 0x2ede
movq %rax, %rbx
leaq 0xb8(%rsp), %rdi
callq 0x2060
jmp 0x2ee1
jmp 0x2ede
movq %rax, %rbx
leaq 0x2c0(%rsp), %rdi
callq 0x2060
jmp 0x2ef5
jmp 0x2ef2
movq %rax, %rbx
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0x2f11
movq 0x70(%rsp), %rsi
incq %rsi
callq 0x21d0
movq %rbx, %rdi
callq 0x22e0
nop