11#include " dbman.h"
2+ #include < functional>
23#include < iostream>
34#include < sstream>
4- #include < thread>
55
6- // Input: dk_curr
7- // whitespace-separated list of card numbers
6+ // Input: dk_curr <mode> [<start time> <end time>]
7+ // <cardnums>
8+ // ...
9+ // <cardnum n> <time str n>
810// Output: none
911
1012// [currmin, currmax): the range of ID for a DK session
@@ -25,14 +27,94 @@ int get_op_lock(int currmin, int currmax, Spirit::Connection& conn) {
2527 return row->get <int >(0 );
2628}
2729
30+ // Given a string of 'xx:xx:xx', returns the second it is in a day
31+ // For example, '07:00:00' -> 3600 * 7
32+ int str2time (const std::string& timestr) {
33+ if (timestr.length () != 8 || timestr[2 ] != ' :' || timestr[5 ] != ' :' )
34+ throw std::logic_error (" Time string format incorrect" );
35+ auto toint = [×tr](int pos) {
36+ return 10 * (timestr[pos] - ' 0' ) + (timestr[pos + 1 ] - ' 0' );
37+ };
38+ return 3600 * toint (0 ) + 60 * toint (3 ) + toint (6 );
39+ }
40+
41+ class RandomTimeGetter {
42+ private:
43+ // mGen: [0, 9]
44+ std::function<int ()> mGen ;
45+ // Used with start and end
46+ std::function<int ()> mRandTime ;
47+ public:
48+ RandomTimeGetter (int start, int end) {
49+ std::mt19937 mt (std::chrono::system_clock::now ().time_since_epoch ().count ());
50+ std::uniform_int_distribution dist (0 , 9 );
51+ mGen = std::bind (dist, mt);
52+ std::uniform_int_distribution dist2 (start + 5 , end - 5 );
53+ mRandTime = std::bind (dist2, mt);
54+ }
55+
56+ [[nodiscard]] std::string operator () () {
57+ std::string res;
58+ // Let's do the random part first
59+ do {
60+ res = " 0123-56-89 12:45:78.0123456" ;
61+ for (std::size_t pos = 20 ; pos <= 26 ; pos++)
62+ res[pos] = mGen () + ' 0' ;
63+ while (res.back () == ' 0' )
64+ res.pop_back ();
65+ } while (res.back () == ' .' ); // Turn back if only . is left
66+ const auto ct = []{
67+ auto t = std::time (nullptr );
68+ return std::localtime (&t);
69+ }();
70+ // Year constituent
71+ const int year = ct->tm_year + 1900 ;
72+ res[0 ] = ' 0' + year / 1000 ;
73+ res[1 ] = ' 0' + year / 100 % 10 ;
74+ res[2 ] = ' 0' + year / 10 % 10 ;
75+ res[3 ] = ' 0' + year % 10 ;
76+ auto fill = [&res](int num, int pos) {
77+ res[pos] = ' 0' + num / 10 ;
78+ res[pos + 1 ] = ' 0' + num % 10 ;
79+ };
80+ // Fill in month, date, hms
81+ fill (ct->tm_mon + 1 , 5 );
82+ fill (ct->tm_mday , 8 );
83+ int rand_time = mRandTime ();
84+ fill (rand_time / 3600 , 11 );
85+ fill (rand_time / 60 % 60 , 14 );
86+ fill (rand_time % 60 , 17 );
87+ return res;
88+ }
89+ };
90+
2891int main () {
2992 // Reads in the card number of people who need to sign in
3093 // and writes to the database.
31- std::string card;
3294 Spirit::Connection conn (Spirit::dbname, Spirit::passwd);
3395 int dk_tot = 3 , dk_curr;
3496 std::cin >> dk_curr;
3597 const auto [currmin, currmax] = Spirit::get_id_range (dk_tot, dk_curr, conn);
98+ char mode;
99+ std::function<std::string ()> get_time;
100+ std::cin >> mode;
101+ switch (mode) {
102+ case ' c' : // current
103+ // no input
104+ get_time = Spirit::get_current_time;
105+ break ;
106+ case ' r' : {
107+ // random, read in
108+ std::string start_time, end_time;
109+ std::cin >> start_time >> end_time;
110+ get_time = RandomTimeGetter (str2time (start_time), str2time (end_time));
111+ break ;
112+ }
113+ default :
114+ std::cerr << " Unrecognized mode" << std::endl;
115+ return 1 ;
116+ }
117+ std::string card;
36118 while (std::cin) {
37119 std::cin >> card;
38120 // Do not explicitly check the card number to be valid,
@@ -42,7 +124,7 @@ int main() {
42124 query << " update 上课考勤 set OptimisticLockField="
43125 << get_op_lock (currmin, currmax, conn)
44126 << " , 打卡时间='"
45- << Spirit::get_current_time ()
127+ << get_time ()
46128 << " ' where "
47129 << currmin
48130 << " <= ID and ID < "
@@ -56,8 +138,5 @@ int main() {
56138 if (!row)
57139 break ;
58140 }
59- // Wait for 0.7s to simulate the real scenario
60- using namespace std ::chrono_literals;
61- std::this_thread::sleep_for (700ms);
62141 }
63142}
0 commit comments