@@ -20,6 +20,7 @@ program. If not, see <https://www.gnu.org/licenses/>.
2020#include " random_price.h"
2121
2222#include < algorithm>
23+ #include < cassert>
2324#include < fstream>
2425#include < iostream>
2526
@@ -49,97 +50,92 @@ void Stock::save(const std::string & playerName, int i) {
4950 filesave = SAVE_FOLDER_PREFIX + playerName + " /" + std::to_string (i) + " " +
5051 SAVE_FILE_EXTENSION_TXT; // creating the file path
5152 fout.open (filesave.c_str ());
52- fout << category << std::endl; // literally load everything into class into file
53- fout << name << std::endl;
54- for (unsigned int index = 0 ; index < history.size (); index++) {
55- fout << history[index] << " " ;
56- }
57- fout << -1
58- << std::endl; // -1 is the stop code for vector<float> history in filesave
59- fout << quantity << std::endl;
60- fout << attributes[standard_deviation] << " " ;
61- fout << attributes[mean] << " " ;
62- fout << attributes[lower_limit] << " " ;
63- fout << attributes[upper_limit] << std::endl;
64- fout << split_count << std::endl << std::endl;
65-
66- // Save the ongoing events, separated by std::endl
67- std::list<Stock_event>::iterator event_itr = events.begin ();
68- while (event_itr != events.end ()) {
69- fout << *event_itr << std::endl;
70- event_itr++;
71- }
53+ fout << *this ; // use operator<< to save the Stock object
7254 fout.close ();
7355}
7456
7557void Stock::load (const std::string & playerName, int i) {
7658 std::string fileToBeLoaded;
77- float loadedPrice;
7859 std::ifstream fin;
7960 fileToBeLoaded = SAVE_FOLDER_PREFIX + playerName + " /" + std::to_string (i) + " " +
8061 SAVE_FILE_EXTENSION_TXT;
8162 std::cout << " Loading " << fileToBeLoaded << " ... " ;
8263 fin.open (fileToBeLoaded.c_str ());
8364 // get the first line, which is category
84- fin >> category;
85- // boundary check for category
86- if (category >= category_list_size) {
87- std::cerr << " Error: Invalid category loaded" << std::endl;
88- exit (1 );
65+ fin >> *this ; // use operator>> to load the Stock object
66+ fin.close ();
67+ // @todo Do not hardcode this limit, use a constant
68+ // STOCK_PRICE_LIMIT instead
69+ assert (price <= 1000 && " Price exceed the limit" );
70+ std::cout << " done" << std::endl;
71+ }
72+
73+ std::ostream & operator <<(std::ostream & fout, const Stock & stock) {
74+ fout << stock.category
75+ << std::endl; // literally load everything into class into file
76+ fout << stock.name << std::endl;
77+ for (unsigned int index = 0 ; index < stock.history .size (); index++) {
78+ fout << stock.history [index] << " " ;
8979 }
90- // the second line is entirely the stock name
91- std::getline (fin >> std::ws, name);
80+ fout << -1 << std::endl; // -1 is the stop code for vector<float> history in
81+ // filesave
82+ fout << stock.quantity << std::endl;
83+ fout << stock.attributes .at (standard_deviation) << " " ;
84+ fout << stock.attributes .at (mean) << " " ;
85+ fout << stock.attributes .at (lower_limit) << " " ;
86+ fout << stock.attributes .at (upper_limit) << std::endl;
87+ fout << stock.split_count << std::endl << std::endl;
88+
89+ // Save the ongoing events, separated by std::endl
90+ for (Stock_event event : stock.events ) {
91+ fout << event << std::endl;
92+ }
93+ return fout;
94+ }
95+
96+ std::istream & operator >>(std::istream & fin, Stock & stock) {
97+ fin >> stock.category ; // line 1
98+ assert (stock.category < category_list_size && " Invalid category" );
99+ // line 2 is entirely the stock name
100+ std::getline (fin >> std::ws, stock.name );
101+ float loadedPrice;
92102 fin >> loadedPrice;
93- // Erase the history vector, since we called the constructor already
94- history.clear ();
103+ // Erase the history vector and load the new history
104+ stock. history .clear ();
95105 while (loadedPrice != -1 ) {
96- history.emplace_back (loadedPrice);
97- fin >> loadedPrice;
106+ stock. history .emplace_back (loadedPrice);
107+ fin >> loadedPrice; // line 3
98108 }
99109 // Set the price
100- price = history[history.size () - 1 ];
101- fin >> quantity;
102- fin >> attributes[standard_deviation];
103- fin >> attributes[mean];
104- fin >> attributes[lower_limit];
105- fin >> attributes[upper_limit];
106- fin >> split_count;
107- // Manually reposition the file pointer to the sixth line
108- // by going to the beginning of the file and skipping the first five lines
109- fin.seekg (0 , std::ios::beg);
110- for (int lineCount = 0 ; lineCount < 7 ; lineCount++) {
111- std::string line;
112- std::getline (fin, line);
113- }
114-
115- // Load the ongoing events, separated by std::endl
110+ stock.price = stock.history .back ();
111+ fin >> stock.quantity ; // line 4
112+ fin >> stock.attributes [standard_deviation]; // line 5
113+ fin >> stock.attributes [mean];
114+ fin >> stock.attributes [lower_limit];
115+ fin >> stock.attributes [upper_limit];
116+ fin >> stock.split_count ; // line 6
117+ // Clear the events list
118+ stock.events .clear ();
119+ // Skip 2 empty lines
120+ std::string emptyLine;
121+ std::getline (fin >> std::ws, emptyLine);
122+ std::getline (fin >> std::ws, emptyLine);
116123 std::string loadedEventString;
117124 while (std::getline (fin, loadedEventString)) {
118125 Stock_event loadedEvent;
119126 std::istringstream (loadedEventString) >> loadedEvent;
120127 // Check the loaded event is valid
121- // Ignore the special case of event_id >= 65535
122- if (loadedEvent.event_id >= 65535 &&
123- loadedEvent.event_id < all_stock_events.size ()) {
124- add_event (loadedEvent);
128+ if (loadedEvent.event_id == STOCK_SPLIT_EVENT.event_id ) {
125129 continue ;
126130 }
131+ assert (
132+ loadedEvent.event_id < all_stock_events.size () && " Invalid event loaded" );
127133 Stock_event comparedEvent = all_stock_events[loadedEvent.event_id ];
128- if (loadedEvent == comparedEvent) {
129- add_event (loadedEvent);
130- }
131- else {
132- std::cerr << " Error: Invalid event loaded" << std::endl;
133- // Output the difference between the loaded event and the compared event
134- std::cerr << " Loaded event: " << loadedEvent << std::endl;
135- std::cerr << " Compared event: " << comparedEvent << std::endl;
136- exit (1 );
137- }
134+ assert (loadedEvent == comparedEvent && " Invalid event loaded" );
135+ stock.add_event (loadedEvent);
138136 }
139- fin.close ();
140- time::sleep (random_integer (sleepShort)); // optimize this
141- std::cout << " done" << std::endl;
142- }
137+ return fin;
138+ };
143139
144140float Stock::purchase (
145141 float & balance, unsigned int amount, float trading_fees_percent) {
@@ -271,33 +267,20 @@ float Stock::sum_attribute(stock_modifiers attribute) {
271267 return sum;
272268}
273269
270+ Stock_event Stock::setup_STOCK_SPLIT_EVENT (void ) {
271+ Stock_event event_copy = STOCK_SPLIT_EVENT;
272+ event_copy.text = name + event_copy.text ;
273+ event_copy.category = category;
274+ return event_copy;
275+ }
276+
274277void Stock::next_round (void ) {
275278 /* * Update the price of the stock.
276279 * If the price is less than 1000, the price will increase or decrease by a random
277280 * percentage. If the price is more than 1000, the price will be halved and the
278281 * quantity will be doubled.
279282 */
280283 float price_diff = percentage_change_price (*this ) / 100 ;
281- if (!(price * (1 + price_diff) > 999.9 )) {
282- price *= (1 + price_diff);
283- }
284- else {
285- price /= 2 ;
286- quantity *= 2 ;
287- split_count++;
288- add_event (Stock_event{// Stock split event
289- /* * event_id */ 65535 ,
290- /* * mutually_exclusive_events */ {},
291- /* * text */
292- name +
293- " has rised too high and the company has decide a stock split on it." ,
294- /* * duration */ 1 ,
295- /* * percentage_permille */ 0 ,
296- /* * type_of_event */ pick_random_stock,
297- /* * category */ category,
298- /* * modifiers*/
299- {{standard_deviation, 0 }, {mean, 0 }, {lower_limit, 0 }, {upper_limit, 0 }}});
300- }
301284 // Reduce all events duration by one.
302285 std::list<Stock_event>::iterator event_itr = events.begin ();
303286 while (event_itr != events.end ()) {
@@ -309,6 +292,15 @@ void Stock::next_round(void) {
309292 }
310293 event_itr++;
311294 }
295+ if (!(price * (1 + price_diff) >= STOCK_PRICE_LIMIT)) {
296+ price *= (1 + price_diff);
297+ }
298+ else {
299+ price /= 2 ;
300+ quantity *= 2 ;
301+ split_count++;
302+ add_event (setup_STOCK_SPLIT_EVENT ());
303+ }
312304 remove_obselete_event ();
313305 update_history ();
314306}
0 commit comments