forked from gregoryfenton/other-life
/
trade_log.cpp
executable file
·205 lines (177 loc) · 6.07 KB
/
trade_log.cpp
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*
Log trades.
If enabled, logs all successful trades. Any time you fully "Accept", the
items are recorded. Only after GET_TRADE_EXIT, followed by either
STORAGE_ITEMS or HERE_YOUR_INVENTORY is the trade confirmed and the
log entry written.
Author bluap/pjbroad February 2013
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <time.h>
#include <algorithm>
#include <functional>
#include "client_serv.h"
#include "elconfig.h"
#include "elloggingwrapper.h"
#include "loginwin.h"
#include "io/elpathwrapper.h"
#include "item_info.h"
#include "text.h"
#include "trade_log.h"
#include "translate.h"
/*
* TODO Write to Trade Log tab in one of the existing windows.
*/
namespace Trade_Log
{
// Class to hold trade details for one party
//
class List
{
public:
List(const char *name, const trade_item *stuff, size_t max_size);
~List(void) { delete [] the_stuff; }
const std::string &who(void) const { return trade_name; }
void get_details(std::ostream & out, const char* prefix) const;
private:
trade_item *the_stuff;
std::string trade_name;
size_t size;
};
// Copy the trade information to create the object
//
List::List(const char *name, const trade_item *stuff, size_t max_size)
: the_stuff(0), size(0)
{
size = max_size;
the_stuff = new trade_item[size];
memcpy(the_stuff, stuff, size*sizeof(trade_item));
trade_name = name;
}
// Write the trade information to the specified stream
//
void List::get_details(std::ostream & out, const char* prefix) const
{
for(size_t i=0;i<size;i++)
if (the_stuff[i].quantity > 0)
{
// if we have a description, and it is unique, use it
if (get_item_count(the_stuff[i].id, the_stuff[i].image_id)==1)
out << " " << prefix <<
" " << the_stuff[i].quantity <<
" " << get_item_description(the_stuff[i].id, the_stuff[i].image_id) <<
((the_stuff[i].type != 1) ?" (s)" :"") << std::endl;
// otherwise use the raw ids
else
out << " " << prefix <<
" " << the_stuff[i].quantity <<
" image_id=" << the_stuff[i].image_id <<
" id=" << the_stuff[i].id <<
((the_stuff[i].type != 1) ?" (s)" :"") << std::endl;
}
}
// Class to hold the state of current in-progress trade
//
class State
{
public:
State(void) : your_stuff(0), their_stuff(0), the_state(TLS_INIT) {}
void destroy(void);
void accepted(const char *name, const trade_item *yours, const trade_item *others, int max_items);
void completed(void);
void exit(void) { if (the_state == TLS_ACCEPT) the_state = TLS_EXIT; else init(); }
void aborted(void) { init(); }
private:
void init(void) { the_state = TLS_INIT; }
List *your_stuff;
List *their_stuff;
enum TRADE_LOG_STATE { TLS_INIT, TLS_ACCEPT, TLS_EXIT } the_state;
std::string filename;
};
// Make sure we free the memory.
//
void State::destroy(void)
{
if (your_stuff)
delete your_stuff;
if (their_stuff)
delete their_stuff;
}
// Each time we accept for the second time, store the current items in case we complete.
//
void State::accepted(const char *name, const trade_item *yours, const trade_item *others, int max_items)
{
if (your_stuff)
delete your_stuff;
if (their_stuff)
delete their_stuff;
your_stuff = new List(get_username(), yours, max_items);
their_stuff = new List(name, others, max_items);
the_state = TLS_ACCEPT;
}
// The trade completed so write the log text
//
void State::completed(void)
{
if ((trade_log_mode == TRADE_LOG_NONE) || (the_state != TLS_EXIT))
{
init();
return;
}
init();
item_info_help_if_needed();
char buf[80];
time_t now = time(0);
strftime(buf, sizeof(buf), "%Y-%m-%d %X", localtime(&now));
std::ostringstream message;
message << "Trade log (" << your_stuff->who() << " <-"
<< "-> " << their_stuff->who() << ") " << buf << std::endl;
if (your_stuff)
your_stuff->get_details(message, "-->");
if (their_stuff)
their_stuff->get_details(message, "<--");
// write to console
if ((trade_log_mode == TRADE_LOG_CONSOLE) || (trade_log_mode == TRADE_LOG_BOTH))
{
std::string message_str = message.str();
// inspired by https://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
message_str.erase(std::find_if(message_str.rbegin(), message_str.rend(),
[](unsigned char ch) { return !std::iscntrl(ch); }).base(), message_str.end());
LOG_TO_CONSOLE(c_green2, message_str.c_str()); // stripped of final newline
}
// and/or append to a log file
if ((trade_log_mode == TRADE_LOG_FILE) || (trade_log_mode == TRADE_LOG_BOTH))
{
if (filename.empty())
filename = std::string(get_path_config()) + "trade_" + std::string(get_lowercase_username()) + ".log";
std::ofstream out(filename.c_str(), std::ios_base::out | std::ios_base::binary | std::ios_base::app);
if (!out)
{
std::string error_str = std::string(file_write_error_str) + ' ' + filename;
LOG_TO_CONSOLE(c_red2, error_str.c_str());
LOG_ERROR("%s: %s \"%s\"\n", reg_error_str, file_write_error_str, filename.c_str());
}
else
out << message.str();
out.close();
}
}
} // end of Trade_Log namespace
// Hold all the current trade log state
static Trade_Log::State the_log;
// The external interface
extern "C"
{
static int enable_local_debug = 0;
int trade_log_mode = TRADE_LOG_NONE; // The config window option to enable the trade log
void trade_accepted(const char *name, const trade_item *yours, const trade_item *others, int max_items)
{ if (enable_local_debug) printf("%s\n", __FUNCTION__); the_log.accepted(name, yours, others, max_items); }
void trade_exit(void) { if (enable_local_debug) printf("%s\n", __FUNCTION__); the_log.exit(); }
void trade_aborted(const char *message) { if (enable_local_debug) printf("%s\n", __FUNCTION__); the_log.aborted(); }
void trade_post_storage(void) { if (enable_local_debug) printf("%s\n", __FUNCTION__); the_log.completed(); }
void trade_post_inventory(void) { if (enable_local_debug) printf("%s\n", __FUNCTION__); the_log.completed(); }
void destroy_trade_log(void) { if (enable_local_debug) printf("%s\n", __FUNCTION__); the_log.destroy(); }
}