Can merge the dictionary
[FreeRecite.git] / src / ui / Cui.cpp
blob4365867a462a775cab5fc3fae3ebf6d838296888
1 #include <set>
2 #include <fstream>
3 #include <cstdlib>
4 #include <iostream>
5 #include <cstdio>
6 #include <string>
7 #include <sstream>
8 #include <cstring>
9 #include <Manager.h>
10 #include <Dict.h>
11 #include <Task.h>
12 #include <Reciter.h>
13 #include <Tester.h>
14 #include <ConfigHolder.h>
15 #include <iomanip>
16 #include "Cui.h"
18 namespace freeRecite {
20 CUI::CUI()
22 if(!manager.load()) {
23 std::cerr << "Can't load " << configHolder.mgrFile() << ".\n";
24 std::cerr << "You should use command \'frt-init\' to initialize.\n";
25 exit(EXIT_FAILURE);
27 if(!dictionary.load()) {
28 std::cerr << "Can't load the dictionary.\n";
29 std::cerr << "You should use command \'frt-init\' to initialize.\n";
30 exit(EXIT_FAILURE);
34 CUI::~CUI()
38 void CUI::run(int argc, char *argv[]) {
39 if(argc == 1) {
40 help();
41 return;
42 }else if(argc == 2){
43 if(!strcmp(argv[1],"--help")) {
44 help();
45 return;
46 }else if(!strcmp(argv[1],"--version")) {
47 std::cout << "Free Recite version 1.0" << std::endl;
48 return;
49 }else if(!strcmp(argv[1],"all")) {
50 showAll();
51 return;
52 }else if(!strcmp(argv[1],"cls")) {
53 cleanStress();
54 return;
55 }else if(!strcmp(argv[1],"done")) {
56 exportDone();
57 return;
58 }else if(!strcmp(argv[1],"ls")) {
59 showActive();
60 return;
61 }else if(!strcmp(argv[1],"modify")) {
62 modify(std::string(""));
63 return;
64 }else if(!strcmp(argv[1],"stress")) {
65 exportStress();
66 return;
68 }else if(argc == 3) {
69 time_t taskID;
70 if(!strcmp(argv[1],"export")) { //frt export <taskID>
71 if( ( taskID = atoid(argv[2]) ) != 0 ) {
72 exportTask(taskID);
73 return;
74 } else { //frt export <filename>
75 exportFromFile(argv[2]);
76 return;
78 }else if(!strcmp(argv[1],"new")) {
79 createNew(argv[2]);
80 return;
81 }else if(!strcmp(argv[1],"merge")) {
82 merge(argv[2]);
83 return;
84 }else if(!strcmp(argv[1],"modify")) {
85 modify(std::string(argv[2]));
86 return;
87 }else if(!strcmp(argv[1],"recite")) { //frt recite <taskID>
88 if( ( taskID = atoid(argv[2]) ) != 0 ) {
89 recite(taskID);
90 return;
91 }else { //frt recite <fileName>
92 recite(argv[2]);
93 return;
95 }else if(!strcmp(argv[1],"remove")) {
96 if( ( taskID = atoid(argv[2]) ) != 0 ){
97 remove(taskID);
98 return;
100 }else if(!strcmp(argv[1],"test")) {
101 if( ( taskID = atoid(argv[2]) ) != 0 ) {
102 test(taskID);
103 return;
106 } //else if(argc == 3)
108 std::cout << "frt: \'" << argv[argc-1] << "\' is not a frt-command. "
109 << "See \'frt --help\'." << std::endl;
110 } //End of run().
112 time_t CUI::atoid(const char *argv) {
113 std::istringstream ssm(argv);
114 unsigned tid;
115 if((ssm >> tid))
116 return static_cast<time_t>(tid);
117 else
118 return static_cast<time_t>(0);
121 void CUI::cleanStress() {
122 ::remove(configHolder.keyFile().c_str());
125 void CUI::clear() {
126 for(int i = 0; i < 10; ++i)
127 std::cerr << std::endl;
130 void CUI::createNew(const char *fileName) {
131 std::string taskName;
132 std::ifstream ifs(fileName);
133 if(!ifs.is_open()) {
134 std::cout << "Can't find the file." << std::endl;
135 return;
137 std::set<std::string> wordSet;
138 std::string word, name, cmd;
139 std::cout << "Give a task name for it?" << std::endl;
140 std::cout << "(Press Enter will give a default name): ";
141 std::getline(std::cin,name);
142 while(ifs.good()) {
143 std::getline(ifs,word);
144 while(!dictionary.lookUp(word) && !word.empty()) {
145 std::cout << '\"' << word << '\"'
146 << " can't be fond in your dictionary"<<std::endl
147 << "Remove(R),Modify(M) or Add to dictionary(A)? (R/m/a)"
148 << std::endl;
149 std::getline(std::cin,cmd);
151 if(cmd == "A" || cmd == "a")
152 while(!modify(word)) /* An empty sentance. */;
153 else if(cmd == "M" || cmd == "m") {
154 std::cout << "Input the new word: ";
155 std::getline(std::cin,word); //Get a new word from the user.
156 continue;
157 } else
158 std::getline(ifs,word); //Read a new word from file.
161 wordSet.insert(word);
163 if(manager.createTask(wordSet,name.c_str(),30)) {
164 std::cout << "Creat a task SUCCESS!" << std::endl;
165 manager.refresh();
166 }else
167 std::cerr << "Can't creat a task :}" << std::endl;
171 void CUI::exportFromFile(const char *fileName) {
172 std::ifstream ifs(fileName);
173 std::string tmpWord;
174 std::set<std::string> wdSet;
175 if(!ifs.is_open()) {
176 return;
178 while(ifs.good()) {
179 std::getline(ifs, tmpWord);
180 if(!tmpWord.empty())
181 wdSet.insert(tmpWord);
183 ifs.close();
184 std::set<std::string>::const_iterator itr = wdSet.begin();
185 while(itr != wdSet.end()) {
186 if(dictionary.lookUp(*itr)) {
187 std::cout << std::setw(12) << std::setfill(' ') << std::left
188 << dictionary.word() << ' ';
189 if(!dictionary.phonetics().empty())
190 std::cout << '[' << dictionary.phonetics() << ']';
191 std::cout << ' ' << dictionary.translation() << std::endl;
192 }else {
193 std::cout << *itr << " *** " << std::endl;
195 ++itr;
199 void CUI::exportDone() {
200 exportFromFile(configHolder.doneFile().c_str());
203 void CUI::exportTask(time_t taskID) {
204 if(!manager.hasTask(taskID)) {
205 std::cout << "There's no this task!" << std::endl;
206 return;
208 std::string fileName = Scanner::getTaskFileName(taskID);
209 exportFromFile(fileName.c_str());
212 void CUI::exportStress(){
213 exportFromFile(configHolder.keyFile().c_str());
216 void CUI:: merge(const char *fileName) {
217 if(!dictionary.merge(fileName))
218 std::cerr << "FAIL" << std::endl;
219 else
220 std::cerr << "SUCCESS" << std::endl;
224 void CUI::test(time_t taskID) {
225 Tester tester;
226 if(!manager.hasTask(taskID)) {
227 std::cout << "There's no this task!" << std::endl;
228 return;
230 if(!tester.load(taskID)) {
231 std::cerr << "error when load words!" << std::endl;
232 return;
234 time_t startTime = 0;
235 time_t endTime = 0;
236 time(&startTime);
238 scanProcess(tester);
240 time(&endTime);
241 startTime = endTime - startTime;
242 std::cout << std::endl << "Used Time: "
243 << startTime/60 << "minutes" << std::endl;
244 int testResult = manager.test(taskID,tester.getScore());
245 if(testResult == 0) {
246 std::cout<<"Your score is " << tester.getScore() << std::endl;
247 std::cout<<"You passed it!"<<std::endl;
248 time_t nextTime = manager.getNextTime(taskID);
249 struct tm * timeinfo;
250 char buffer[30];
251 timeinfo = localtime(&nextTime);
252 strftime(buffer,30,"%Y.%m.%d %H:%M:%S",timeinfo);
253 std::cout << "Then next reviewing time is: " << buffer
254 << std::endl;
255 }else if(testResult == -1){
256 std::cout<<"Your score is " << tester.getScore() << std::endl
257 <<"You haven't passed it :} "<<std::endl;
258 }else { // testResult == 1
259 std::cout << "Congratulations! You have complish this task!"
260 << std::endl;
264 void CUI::recite(const char *fileName) {
265 Reciter reciter;
266 if(!reciter.load(fileName)) {
267 std::cerr << "Can't open this file!" << std::endl;
268 return;
270 time_t startTime = 0;
271 time_t endTime = 0;
272 time(&startTime);
273 scanProcess(reciter);
274 time(&endTime);
275 startTime = (endTime - startTime)/60;
276 time_t usedTime = startTime > 0 ? startTime : 1;
277 std::cout << std::endl << "Used Time: "
278 << usedTime << " minutes" << std::endl;
279 float r_num = reciter.capability() - reciter.getScore();
280 std::cout << "There're " << reciter.capability() << " words in this task. "
281 << reciter.getScore() << " of them you have known before."
282 << std::endl << "Your Reciting Rate is: "
283 << r_num / usedTime
284 << " word(s)/min" << std::endl;
287 void CUI::recite(time_t taskID) {
288 if(!manager.hasTask(taskID)) {
289 std::cerr<< "There's no this task!" << std::endl;
290 return;
293 Reciter reciter;
294 if(!reciter.load(taskID)) {
295 std::cerr << "error when load words!" << std::endl;
296 return;
298 time_t startTime = 0;
299 time_t endTime = 0;
300 time(&startTime);
301 scanProcess(reciter);
302 time(&endTime);
303 startTime = (endTime - startTime)/60;
304 time_t usedTime = startTime > 0 ? startTime : 1;
305 std::cout << std::endl << "Used Time: "
306 << usedTime << " minutes" << std::endl;
307 float r_num = reciter.capability() - reciter.getScore();
308 std::cout << "There're " << reciter.capability() << " words in this task. "
309 << reciter.getScore() << " of them you have known before."
310 << std::endl << "Your Reciting Rate is: "
311 << r_num / usedTime
312 << " word(s)/min" << std::endl;
315 void CUI::remove(time_t taskID) {
316 if(!manager.hasTask(taskID)) {
317 std::cerr<< "There's no this task!" << std::endl;
318 return;
320 manager.removeTask(taskID);
323 bool CUI::modify(const std::string &word) {
324 std::string newItem,inputStr;
325 if(word.empty()) {
326 std::cout<<"[W]: ";
327 std::getline(std::cin,inputStr);
328 newItem.append("[W]"+inputStr);
329 }else
330 newItem.append("[W]"+word);
332 std::cout<<"θ_ɑ_ʌ_ә_є_æ_ɔ_ʃ_ð_ŋ_ʒ"<<std::endl;
333 std::cout<<"0_1_2_3_4_5_6_7_8_9_="<<std::endl;
334 std::cout<<"[T]: ";
335 std::getline(std::cin,inputStr);
336 newItem.append("[T]"+inputStr);
337 std::cout<<"[M]: ";
338 std::getline(std::cin,inputStr);
339 newItem.append("[M]"+inputStr);
341 if(!dictionary.modify(newItem)) {
342 std::cout<<"ERROR!" << std::endl;
343 return false;
345 std::cout<<"SUCCESS!"<<std::endl;
346 return true;
349 void CUI::showActive() {
350 if(!manager.refresh()) {
351 std::cout << "The configure file is broken!" << std::endl;
352 exit(EXIT_FAILURE);
354 if(manager.getActiveTaskNum() == 0) {
356 std::cout << "There's no new task should be review,type \"new\" to creat one."
357 << std::endl;
359 if(manager.getNextTime() != 0) {
360 time_t nextTime = manager.getNextTime();
361 struct tm * timeinfo;
362 char buffer[30];
363 timeinfo = localtime(&nextTime);
364 strftime(buffer,30,"%Y.%m.%d %H:%M:%S",timeinfo);
365 std::cout << "The nearest reviewing time is at " << buffer
366 << std::endl
367 << "Please use FreeRecite at that time!"
368 << std::endl;
371 else {
372 std::cout << std::setw(5) << std::setfill(' ') << std::left << "N"
373 << std::setw(25) << std::setfill(' ') << std::left << "Name"
374 << std::setw(5) << std::setfill(' ') << std::left << "Step"
375 << std::setw(10) << std::setfill(' ') << std::left << " ID"
376 <<std::endl;
378 for(int i = 0; i < manager.getActiveTaskNum(); ++i) {
379 std::cout << std::setw(5) << std::setfill(' ') << std::left << i+1
380 << std::setw(25) << std::setfill(' ') << std::left
381 << manager.getTaskName(manager.getActiveTasks().at(i)) << ' '
382 << std::setw(5) << std::setfill(' ') << std::left
383 << manager.getTaskStep(manager.getActiveTasks().at(i))
384 << std::setw(10) << std::setfill(' ') << std::right
385 << manager.getActiveTasks().at(i)
386 << std::endl;
391 void CUI::showAll() {
392 if(!manager.refresh()) {
393 std::cout << "The configure file is broken!" << std::endl;
394 exit(EXIT_FAILURE);
396 if(manager.getAllTasks().empty()) {
397 std::cout << "There's no new task should be review,type \"new\" to creat one."
398 << std::endl;
400 else {
401 std::cout << "There's " << manager.getAllTasks().size()
402 << " tasks should review." << std::endl;
403 std::cout << std::setw(5) << std::setfill(' ') << std::left << "N"
404 << std::setw(20) << std::setfill(' ') << std::left << "Name"
405 << std::setw(5) << std::setfill(' ') << std::left << "Step"
406 << std::setw(12) << std::setfill(' ') << std::left << " ID"
407 << std::setw(12) << std::setfill(' ') << std::left << " Review Time"
408 <<std::endl;
410 std::map<time_t,Task>::const_iterator itr = manager.getAllTasks().begin();
411 unsigned i = 0;
412 while(++i,itr != manager.getAllTasks().end()) {
413 std::cout << std::setw(5) << std::setfill(' ') << std::left << i
414 << std::setw(20) << std::setfill(' ') << std::left
415 << manager.getTaskName(itr->first) << ' '
416 << std::setw(5) << std::setfill(' ') << std::left
417 << manager.getTaskStep(itr->first)
418 << std::setw(12) << std::setfill(' ') << std::right
419 << itr->first << " ";
420 time_t nextTime = manager.getNextTime(itr->first);
421 struct tm * timeinfo;
422 char buffer[30];
423 timeinfo = localtime(&nextTime);
424 strftime(buffer,30,"%Y.%m.%d %H:%M:%S",timeinfo);
425 std::cout << std::setw(12) << std::setfill(' ') << std::left
426 << buffer << std::endl;
427 ++itr;
432 void CUI::showResult(bool result) {
433 if(result) {
434 std::cout<<" ** * * "<<std::endl;
435 std::cout<<" * * * * "<<std::endl;
436 std::cout<<" * * ** "<<std::endl;
437 std::cout<<" * * * * "<<std::endl;
438 std::cout<<" ** * * "<<std::endl;
440 else {
441 std::cout<<"##### #### #### "<<std::endl;
442 std::cout<<"# # # # # "<<std::endl;
443 std::cout<<"##### #### #### "<<std::endl;
444 std::cout<<"# # # # # "<<std::endl;
445 std::cout<<"##### # # # # "<<std::endl;
449 void CUI::scanProcess(Scanner &scanner) {
450 bool result;
451 std::string inputStr;
452 while(scanner.isValid()) {
453 if(dictionary.lookUp(scanner.getWord())){
454 std::cout <<" Type \'\\help\' to show the implicit command!"
455 << std::endl;
456 std::cout <<" Amount: "<< scanner.capability()
457 <<" R_Num: " << scanner.size()
458 <<" R_Times: "<< scanner.times()<<std::endl;
459 std::cout<<"[M]: "<<dictionary.translation()<<std::endl;
460 std::cout <<"**********************************************" << std::endl;
461 std::cout<<"*Input : ";
462 std::getline(std::cin,inputStr);
464 if(inputStr == "\\hint") {
465 std::cout << "*Hint : " << dictionary.word().at(0);
466 for(unsigned i = 1; i < dictionary.word().size(); ++i)
467 std::cout << '_';
468 if( !dictionary.phonetics().empty() )
469 std::cout << " /" << dictionary.phonetics() << "/";
470 std::cout << std::endl <<"*Input : ";
471 std::getline(std::cin,inputStr);
474 if(inputStr == "\\help"){
475 scanProHelp();
476 continue;
477 } else if(inputStr == "\\modify"){
478 modify(scanner.getWord());
479 continue;
480 } else if(inputStr == "\\add"){
481 std::cout << "Input new word: ";
482 std::getline(std::cin,inputStr);
483 scanner.add(inputStr);
484 std::cout << "SUCCESS!" << std::endl;
485 continue;
486 } else if(inputStr == "\\rm"){
487 inputStr = scanner.getWord();
488 scanner.remove(inputStr);
489 std::cout << "SUCCESS!" << std::endl;
490 continue;
491 } else if(inputStr == "\\stop") {
492 exit(EXIT_SUCCESS);
494 result = ( inputStr == scanner.getWord() ? true : false );
495 std::cout << "*Answer: " << dictionary.word();
496 if( !dictionary.phonetics().empty() )
497 std::cout << " /" << dictionary.phonetics() << "/";
498 std::cout << std::endl;
499 std::cout <<"**********************************************" << std::endl;
500 showResult(result);
501 clear();
502 scanner.test(result);
503 } else { //If the dictionary can't look up the current word
504 std::cout << '\"' << scanner.getWord() << '\"'
505 << " can't be found in your dictionary."
506 << "\n Modify Or Remove it from task(M/r) ";
507 std::string m_r;
508 std::getline(std::cin,m_r);
509 if(m_r == "R" || m_r == "r") {
510 inputStr = scanner.getWord();
511 scanner.remove(inputStr);
512 std::cout << "SUCCESS!" << std::endl;
513 } else {
514 modify(scanner.getWord());
517 } //End of while()
521 void CUI::scanProHelp() {
522 std::cout << std::endl << "usage: \\command " << std::endl
523 << "\\help Show this help information" << std::endl
524 << "\\add Add new word to this task" << std::endl
525 << "\\rm Remove the current word from this task" << std::endl
526 << "\\modify Modify the current word in the dictionary" << std::endl
527 << "\\hint Get the hint of current word" << std::endl
528 << "\\stop Stop Free Recite at once" << std::endl;
531 void CUI::help() {
532 std::cout << "usage: frt [--version] [--help] COMMAND [ARGS]" << std::endl
533 << "The most commonly used git commands are:" << std::endl
534 << " all Show the detail of all the tasks"
535 << std::endl
536 << " cls Clean the strees' words in the system"
537 << std::endl
538 << " done Export the words which you have remembered"
539 <<std::endl
540 << " export <taskID> Export a tasks' words to the screen"
541 << std::endl
542 << " export <filename> Export the words in the file as it is a task"
543 << std::endl
544 << " ls List the tasks that should be reviewed"
545 << std::endl
546 << " new <filename> Creat new tasks with the words in the file"
547 << std::endl
548 << " merge <filename> Merge the dictionary into file" << std::endl
549 << " modify [word] Modify the word in the dictionary"
550 << std::endl
551 << " recite <taskID> Recite the task whose ID is taskID"
552 <<std::endl
553 << " recite <filename> Recite the words in the specified file"
554 <<std::endl
555 << " remove <taskID> Remove a task which you don't want to recite"
556 << std::endl
557 << " stress Show some words which may be difficult for you"
558 << std::endl
559 << " test <taskID> Test the task whose ID is taskID"
560 << std::endl
561 << " --help Show this help information"
562 << std::endl
563 << " --version Show the current version"
564 << std::endl;
567 } // namespace freeRecite End.