fork download
  1. #include <cmath>
  2. #include <initializer_list>
  3.  
  4. #include <vector>
  5. #include <string>
  6. #include <iostream>
  7. #include <functional>
  8. #include <cstdlib>
  9. #include <map>
  10. using namespace std;
  11.  
  12. class CycledIndexer{
  13. using Number = int;
  14. public:
  15. CycledIndexer(Number max_val, Number val):
  16. max_value(max_val), value(fixed(val)){}
  17. public:
  18. Number max() const{ return max_value; }
  19. void update_max(Number max){
  20. max_value = max;
  21. value = fixed(value);
  22. }
  23.  
  24. void add(int val){ value = fixed(value + val); }
  25. void sub(int val){ add(-val); }
  26.  
  27. void set(int val){ value = fixed(val); }
  28.  
  29. CycledIndexer operator+(Number num){ return CycledIndexer(max_value, value + num); }
  30. CycledIndexer operator-(Number num){ return CycledIndexer(max_value, value - num); }
  31.  
  32. CycledIndexer &operator=(Number num){
  33. set(num);
  34. return *this;
  35. }
  36.  
  37. CycledIndexer &operator+=(Number num){
  38. add(num);
  39. return *this;
  40. }
  41. CycledIndexer &operator-=(Number num){
  42. sub(num);
  43. return *this;
  44. }
  45.  
  46. CycledIndexer &operator++(){
  47. add(1);
  48. return *this;
  49. }
  50. CycledIndexer &operator--(){
  51. sub(1);
  52. return *this;
  53. }
  54.  
  55. CycledIndexer operator++(int){
  56. auto result = *this;
  57. add(1);
  58. return result;
  59. }
  60. CycledIndexer operator--(int){
  61. auto result = *this;
  62. sub(1);
  63. return result;
  64. }
  65.  
  66. operator Number() const
  67. { return value; }
  68. private:
  69. Number fixed(Number val){
  70. auto mod = val%max_value;
  71. return mod<0 ? max_value + mod : mod;
  72. }
  73. private:
  74. Number max_value, value;
  75. };
  76.  
  77. struct MenuItem{
  78. using Text = string;
  79. using Action = function<void()>;
  80.  
  81. Text text;
  82. Action callback;
  83. };
  84.  
  85. template<typename MenuType>
  86. class MenuSelectionProxyTemplate{
  87. public:
  88. using Menu = MenuType;
  89. public:
  90. MenuSelectionProxyTemplate(Menu &menu): menu(menu){}
  91. public:
  92. operator MenuItem&()
  93. { return menu.items[menu.indexer]; }
  94. operator const MenuItem&() const
  95. { return menu.items[menu.indexer]; }
  96.  
  97. void call()
  98. { static_cast<MenuItem&>(*this).callback(); }
  99.  
  100. auto &text()
  101. { return static_cast<MenuItem&>(*this).text; }
  102. const auto &text() const
  103. { return static_cast<const MenuItem&>(*this).text; }
  104.  
  105. void move_up()
  106. { --menu.indexer; }
  107. void move_down()
  108. { ++menu.indexer; }
  109. private:
  110. Menu &menu;
  111. };
  112.  
  113. class Menu{
  114. using Items = vector<MenuItem>;
  115. using MenuSelectionProxy = MenuSelectionProxyTemplate<Menu>;
  116. friend MenuSelectionProxy;
  117. public:
  118. Menu(): indexer(0, 0){}
  119. Menu(initializer_list<MenuItem> items_list):
  120. items(items_list), indexer(items.size(), 0){}
  121. public:
  122. void add_item(const MenuItem &item){
  123. items.push_back(item);
  124. update_indexer();
  125. }
  126. void add_item(MenuItem &&item){
  127. items.push_back(item);
  128. update_indexer();
  129. }
  130.  
  131. Items &all_items()
  132. { return items; }
  133. const Items &all_items() const
  134. { return items; }
  135.  
  136. MenuSelectionProxy selection()
  137. { return MenuSelectionProxy(*this); }
  138. const MenuSelectionProxy selection() const
  139. { return MenuSelectionProxy(const_cast<Menu&>(*this)); }
  140. private:
  141. void update_indexer(){
  142. indexer.update_max(items.size());
  143. }
  144. private:
  145. Items items;
  146. CycledIndexer indexer;
  147. };
  148.  
  149. int main(){
  150. Menu menu{
  151. {"Hello, World!", [&]{ cout << "I have just said hello to World." << endl; }},
  152. {"Hello, Fred!", [&]{ cout << "I have just said hello to Fred." << endl; }},
  153. {"Start game!", [&]{ cout << "I have just stared the game(?)." << endl; }},
  154. {"exit program!", [&]{ cout << "Ciao!"; exit(EXIT_SUCCESS); }}
  155. };
  156.  
  157. using Action = function<void()>;
  158. using ActionsMap = map<string, Action>;
  159. ActionsMap actions_map{
  160. {"up", [&]{ menu.selection().move_up(); }},
  161. {"down", [&]{menu.selection().move_down(); }},
  162. {"call", [&]{menu.selection().call(); }},
  163. {"wait", []{}}
  164.  
  165. };
  166.  
  167. string command;
  168. while(cin>>command){
  169. cout << "#--Woobly, woobly, the next step--#" << endl;
  170. cout << "#<<" << command << endl;
  171. if(actions_map.count(command) == false){
  172. cout << "STOP PASSING WRONG COMMANDS!" << endl;
  173. continue;
  174. }
  175. actions_map[command]();
  176.  
  177. for(const auto &item : menu.all_items()){
  178. cout << item.text;
  179. if(item.text == menu.selection().text())
  180. cout << " <-- (thats our selected buddy)";
  181. cout << endl;
  182. }
  183. }
  184. return 0;
  185. }
Success #stdin #stdout 0s 3472KB
stdin
wait
call
down
call
down
call
down
down
down
down
up
down
down
foobar
call
stdout
#--Woobly, woobly, the next step--#
#<<wait
Hello, World! <-- (thats our selected buddy)
Hello, Fred!
Start game!
exit program!
#--Woobly, woobly, the next step--#
#<<call
I have just said hello to World.
Hello, World! <-- (thats our selected buddy)
Hello, Fred!
Start game!
exit program!
#--Woobly, woobly, the next step--#
#<<down
Hello, World!
Hello, Fred! <-- (thats our selected buddy)
Start game!
exit program!
#--Woobly, woobly, the next step--#
#<<call
I have just said hello to Fred.
Hello, World!
Hello, Fred! <-- (thats our selected buddy)
Start game!
exit program!
#--Woobly, woobly, the next step--#
#<<down
Hello, World!
Hello, Fred!
Start game! <-- (thats our selected buddy)
exit program!
#--Woobly, woobly, the next step--#
#<<call
I have just stared the game(?).
Hello, World!
Hello, Fred!
Start game! <-- (thats our selected buddy)
exit program!
#--Woobly, woobly, the next step--#
#<<down
Hello, World!
Hello, Fred!
Start game!
exit program! <-- (thats our selected buddy)
#--Woobly, woobly, the next step--#
#<<down
Hello, World! <-- (thats our selected buddy)
Hello, Fred!
Start game!
exit program!
#--Woobly, woobly, the next step--#
#<<down
Hello, World!
Hello, Fred! <-- (thats our selected buddy)
Start game!
exit program!
#--Woobly, woobly, the next step--#
#<<down
Hello, World!
Hello, Fred!
Start game! <-- (thats our selected buddy)
exit program!
#--Woobly, woobly, the next step--#
#<<up
Hello, World!
Hello, Fred! <-- (thats our selected buddy)
Start game!
exit program!
#--Woobly, woobly, the next step--#
#<<down
Hello, World!
Hello, Fred!
Start game! <-- (thats our selected buddy)
exit program!
#--Woobly, woobly, the next step--#
#<<down
Hello, World!
Hello, Fred!
Start game!
exit program! <-- (thats our selected buddy)
#--Woobly, woobly, the next step--#
#<<foobar
STOP PASSING WRONG COMMANDS!
#--Woobly, woobly, the next step--#
#<<call
Ciao!