-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.cpp
152 lines (127 loc) · 4.36 KB
/
main.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
// by wuwbobo2021 <https://github.com/wuwbobo2021>, <wuwbobo@outlook.com>
// If you have found bugs in this program, please pull an issue, or contact me.
#include "picker.h"
#include <iostream>
#include <sstream>
using namespace std;
RandomPicker::Table table;
RandomPicker::Picker picker(table);
void config(string& save_path);
void print_help();
unsigned int read_value(const string& str);
bool ask_yes_no();
int main(int argc, char** argv)
{
bool arg_help = false, arg_show_table = false, arg_config = false, arg_test = false;
unsigned int arg_amount = 0; string arg_path = "";
bool flag_opened = false;
string arg;
for (unsigned int i = 1; i < argc; i++) {
arg = argv[i];
if (arg[0] == '-' && arg.length() > 1) {
switch (arg[1]) {
case 'h': arg_help = true; break;
case 's': arg_show_table = true; break;
case 'c': arg_config = true; break;
case 't': arg_test = true; break;
default: break;
}
} else {
unsigned int val = read_value(arg);
if (val > 0 && (val <= table.count() || table.repetitive_picking))
arg_amount = val;
else {
arg_path = arg;
if (table.open(arg_path)) flag_opened = true;
}
}
}
if (arg_help || arg_path.length() == 0) {print_help(); return 0;}
if (arg_config) {config(arg_path); return 0;}
else if (!flag_opened || arg_amount == 0) {print_help(); return 0;}
if (arg_show_table) {
table.output(cout);
if (table.count() > 0 && arg_amount > 0) {
RandomPicker::Table cal; picker.calculate(arg_amount, cal);
cal.scale(100.0);
cout << "\nAbsolute values (%):\n";
cal.output(cout);
if (table.repetitive_picking)
cout << "Note: Probabilities in this table are for a picking operation of a single item, "
<< "you can calculate probability of <i>th item in a group of n items by: 1 - (1 - Pi)^m.\n";
}
return 0;
}
if (! arg_test) {
vector<string> result;
picker.pick(arg_amount, result);
for (unsigned int i = 0; i < result.size(); i++)
cout << result[i] << ' ';
cout << '\n';
} else {
std::random_device ran_dev;
cout << "entropy() returned by current standard library random_device: "
<< ran_dev.entropy() << ".\n";
RandomPicker::Table result;
picker.test(1000000, arg_amount, result);
if (! table.repetitive_picking) {
result.scale(1.0 / 10000.0);
cout << "Test result indicating probabilities (%) of occurence in a group of results:\n";
} else {
result.scale(1.0 / (10000.0*arg_amount));
cout << "Test result of frequencies (%):\n";
}
result.output(cout);
}
return 0;
}
void config(string& save_path)
{
if (! table.is_empty()) {
cout << "Existing items:\n";
table.output(cout); cout << '\n';
}
cout << "Is it allowed to pick items repetitively?";
table.repetitive_picking = ask_yes_no();
cout << "Should the power values of items be inversed to calculate their probability? "
<< "In this case the power value represents its prize, the higher the prize, "
<< "the lower the probability of being picked up.\n";
table.power_inversed = ask_yes_no();
cout << "Input items, seperate names and power values with spaces, "
<< "delete item with `delete <name>`, input end at last:\n";
if (! table.input(cin))
cout << "Sorry, part of your input is not recorded. Make sure your names consist of "
<< "letters, digits, or underline characters, without any space.\n";
cout << "Please check the recorded items below:\n";
table.output(cout);
if (table.is_empty()) return;
while (! table.save(save_path)) {
cout << "Sorry, failed to save file \"" << save_path << "\".\n"
<< "Enter file path: ";
save_path = ""; cin >> save_path;
}
}
void print_help()
{
cout << "random-picker <table_file> <amount>\n"
<< "Options:\n"
<< "-h\t\t\tShow this help\n"
<< "-c <file>\t\tDo configuration and save table file\n"
<< "-s <file> [amount]\tPrint current table, show table of absolute values if amount is given\n"
<< "-t <file> <amount>\tTest the random engine by statistics of 1,000,000 groups of results\n"
<< "Note: When repetitive mode is off, <amount> must not exceed amount of items in the table.\n";
}
unsigned int read_value(const string& str)
{
static stringstream sst;
sst.clear(); sst.str(str);
unsigned int val = 0;
sst >> val; return val;
}
bool ask_yes_no()
{
static char buf[4096];
cout << " (Y/n) ";
cin.getline(buf, 4096);
return buf[0] == 'Y' || buf[0] == 'y';
}