// File: zyLiu6707[P]Arknights-Pull-Simulation/simulation_sequential.cpp
// Function: main
int main(int argc, char* argv[]) {
  // On default, will calculate the probability of a limited banner (e.g.,
  // Nian, W and Rosmontis banner), which uses the following parameter:
  // 1. Pr(get a star6 operator): 2%
  // 2. Pr(get a on-banner star 6 operator | get a satr 6 operator): 70%
  // 3. Double rate up
  ProbabilityWrapper probability_wrapper(0.02, 0.7, 0.02, 2);

  // In Arknights, the pity system will come into effect after 50 pulls
  // if you did not get any star6 operator
  unsigned int pity_starting_point = 50;

  unsigned long long int total_pull_time = 100000000;
  unsigned long long int current_pull = 0;

  bool can_continue = process_cmd_input_and_set_corres_var(
      argc, argv, probability_wrapper, total_pull_time, pity_starting_point, current_pull);
  if (!can_continue) {
    // Exit the program here rather than exiting when argument format error is
    // found in order to avoid memory leak
    return 0;
  }

  display_simulation_settings(probability_wrapper, total_pull_time,
                              pity_starting_point, current_pull);

  auto seed = get_random_seed();
  std::mt19937_64 mt(seed);
  unsigned int dist_left_border = 0;
  unsigned int dist_right_border = 999;
  // Uniform distribution on [0, 999]
  std::uniform_int_distribution<unsigned int> dist(dist_left_border,
                                                   dist_right_border);

  // Count the times of getting a star 6 operator in total_pull_times pulling
  unsigned long long int star6_count = 0;
  // Count the times of getting the target star 6 operator in total_pull_times
  // pulling
  unsigned long long int target_star6_count = 0;
  // Count the times of countinuously getting a non-star-6 operator
  unsigned long long int pity_count = 0;
  // Count the times of pulling in a trial. Will be reset to 0 when get the
  // target star 6 operator. Theoretically, no matter how many bits used to
  // store the value of current_pull_count, there exists a non-zero probability
  // that it will overflow - but the probability will converge to zero when num
  // of bits grows to positive infinity
  unsigned long long int current_pull_count = 0;

  // The thresholds will be used to decide whether we got a star6/target star6
  // operator in a pull
  const unsigned long long int init_target_star6_threshold =
      probability_wrapper.calc_init_target_star6_threshold(dist_left_border,
                                                           dist_right_border);
  const unsigned long long int init_star6_threshold =
      probability_wrapper.calc_init_star6_threshold(dist_left_border,
                                                    dist_right_border);

  unsigned long long int target_star6_threshold = init_target_star6_threshold;
  unsigned long long int star6_threshold = init_star6_threshold;

  // The amount that the thresholds change after each failed pull when pity
  // system comes into effect
  unsigned int delta_star6_threshold =
      probability_wrapper.calc_star6_threshold_change_step(dist_left_border,
                                                           dist_right_border);
  unsigned int delta_target_star6_threshold =
      probability_wrapper.calc_target_star6_threshold_change_step(
          dist_left_border, dist_right_border);

  std::vector<unsigned long long int> result(1000);

  // Record the event that did not get a star 6 operator
  // untill pulling more than 1000 times
  std::unordered_map<unsigned long long int, unsigned long long int> rare_event;

  // To avoid the rare_event map recording too many items and consuming too
  // large memory.
  const size_t max_rare_event_map_size = 100000;  // you need to simulate
                                                  // approximately 10^13 times
                                                  // of pulling to reach this
                                                  // limit.

  std::cout << "Now will start the simulation...\n" << std::endl;

  struct timespec start;
  struct timespec end;

  clock_gettime(CLOCK_MONOTONIC, &start);

  // Start simulation
  for (unsigned long long int i = 0; i < total_pull_time; ++i) {
    unsigned int rand_num = dist(mt);
    current_pull_count++;  // leave the index 0 of result vector unused
    // Get a star-6 operator
    if (rand_num < star6_threshold) {
      star6_count++;
      pity_count = 0;
      // This star-6 operator is also your target operator
      if (rand_num < target_star6_threshold) {
        target_star6_count++;
        if (current_pull_count < result.size()) {
          result[current_pull_count]++;
        }
        else if (rare_event.size() < max_rare_event_map_size) {
          rare_event[current_pull_count]++;
        }
        current_pull_count = 0;
        // Finish currrent trial, reset the pity counter and start next trial
        pity_count = current_pull;
      }
      star6_threshold = init_star6_threshold;
      target_star6_threshold = init_target_star6_threshold;
    }
    else {
      pity_count++;
      if (pity_count >= pity_starting_point) {
        star6_threshold += delta_star6_threshold;
        target_star6_threshold += delta_target_star6_threshold;
      }
    }
  }

  clock_gettime(CLOCK_MONOTONIC, &end);

  // Print the result
  display_simulation_results(result, rare_event, star6_count,
                             target_star6_count, seed, start, end);

  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb60, %rsp            # imm = 0xB60
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x30(%rbp), %rdi
movsd 0x8ab3(%rip), %xmm2     # 0xf038
movsd 0x8a83(%rip), %xmm1     # 0xf010
movl $0x2, %esi
movaps %xmm2, %xmm0
callq 0x7690
movl $0x32, -0x34(%rbp)
movq $0x5f5e100, -0x40(%rbp) # imm = 0x5F5E100
movq $0x0, -0x48(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq -0x30(%rbp), %rdx
leaq -0x40(%rbp), %rcx
leaq -0x34(%rbp), %r8
leaq -0x48(%rbp), %r9
callq 0x2ab0
andb $0x1, %al
movb %al, -0x49(%rbp)
testb $0x1, -0x49(%rbp)
jne 0x65e4
movl $0x0, -0x4(%rbp)
jmp 0x6a2c
movq -0x40(%rbp), %rsi
movl -0x34(%rbp), %edx
movq -0x48(%rbp), %rcx
leaq -0x30(%rbp), %rdi
movq %rdi, -0xb28(%rbp)
callq 0x5b80
callq 0x2590
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rsi
leaq -0xa20(%rbp), %rdi
callq 0x6b10
movl $0x0, -0xa24(%rbp)
movl $0x3e7, -0xa28(%rbp)    # imm = 0x3E7
movl -0xa24(%rbp), %esi
movl -0xa28(%rbp), %edx
leaq -0xa30(%rbp), %rdi
callq 0x76e0
movq -0xb28(%rbp), %rdi
movq $0x0, -0xa38(%rbp)
movq $0x0, -0xa40(%rbp)
movq $0x0, -0xa48(%rbp)
movq $0x0, -0xa50(%rbp)
movl -0xa24(%rbp), %esi
movl -0xa28(%rbp), %edx
callq 0xe200
movq -0xb28(%rbp), %rdi
movq %rax, -0xa58(%rbp)
movl -0xa24(%rbp), %esi
movl -0xa28(%rbp), %edx
callq 0xe1a0
movq -0xb28(%rbp), %rdi
movq %rax, -0xa60(%rbp)
movq -0xa58(%rbp), %rax
movq %rax, -0xa68(%rbp)
movq -0xa60(%rbp), %rax
movq %rax, -0xa70(%rbp)
movl -0xa24(%rbp), %esi
movl -0xa28(%rbp), %edx
callq 0xe270
movq -0xb28(%rbp), %rdi
movl %eax, -0xa74(%rbp)
movl -0xa24(%rbp), %esi
movl -0xa28(%rbp), %edx
callq 0xe2b0
movl %eax, -0xa78(%rbp)
leaq -0xa91(%rbp), %rdi
movq %rdi, -0xb20(%rbp)
callq 0x7710
movq -0xb20(%rbp), %rdx
leaq -0xa90(%rbp), %rdi
movl $0x3e8, %esi            # imm = 0x3E8
callq 0x7730
jmp 0x6733
leaq -0xa91(%rbp), %rdi
callq 0x77a0
leaq -0xae0(%rbp), %rdi
callq 0x77c0
movq $0x186a0, -0xae8(%rbp) # imm = 0x186A0
movq 0x10873(%rip), %rdi     # 0x16fd0
leaq 0x9e78(%rip), %rsi      # 0x105dc
callq 0x2210
movq %rax, -0xb30(%rbp)
jmp 0x6772
movq -0xb30(%rbp), %rdi
movq 0x10840(%rip), %rsi     # 0x16fc0
callq 0x2240
jmp 0x6787
movl $0x1, %edi
leaq -0xaf8(%rbp), %rsi
callq 0x21e0
movq $0x0, -0xb10(%rbp)
movq -0xb10(%rbp), %rax
cmpq -0x40(%rbp), %rax
jae 0x69ba
leaq -0xa30(%rbp), %rdi
leaq -0xa20(%rbp), %rsi
callq 0x77e0
movl %eax, -0xb34(%rbp)
jmp 0x67cf
movl -0xb34(%rbp), %eax
movl %eax, -0xb14(%rbp)
movq -0xa50(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa50(%rbp)
movl -0xb14(%rbp), %eax
cmpq -0xa70(%rbp), %rax
jae 0x6956
movq -0xa38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa38(%rbp)
movq $0x0, -0xa48(%rbp)
movl -0xb14(%rbp), %eax
cmpq -0xa68(%rbp), %rax
jae 0x6938
movq -0xa40(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa40(%rbp)
movq -0xa50(%rbp), %rax
movq %rax, -0xb40(%rbp)
leaq -0xa90(%rbp), %rdi
callq 0x7670
movq %rax, %rcx
movq -0xb40(%rbp), %rax
cmpq %rcx, %rax
jae 0x68df
movq -0xa50(%rbp), %rsi
leaq -0xa90(%rbp), %rdi
callq 0x7810
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
jmp 0x6922
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xaa0(%rbp)
movl %eax, -0xaa4(%rbp)
leaq -0xa91(%rbp), %rdi
callq 0x77a0
jmp 0x6a38
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xaa0(%rbp)
movl %eax, -0xaa4(%rbp)
leaq -0xae0(%rbp), %rdi
callq 0x7860
leaq -0xa90(%rbp), %rdi
callq 0x7880
jmp 0x6a38
leaq -0xae0(%rbp), %rdi
callq 0x7520
cmpq $0x186a0, %rax          # imm = 0x186A0
jae 0x6920
leaq -0xae0(%rbp), %rdi
leaq -0xa50(%rbp), %rsi
callq 0x7830
movq %rax, -0xb48(%rbp)
jmp 0x690f
movq -0xb48(%rbp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
jmp 0x6922
movq $0x0, -0xa50(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0xa48(%rbp)
movq -0xa60(%rbp), %rax
movq %rax, -0xa70(%rbp)
movq -0xa58(%rbp), %rax
movq %rax, -0xa68(%rbp)
jmp 0x69a1
movq -0xa48(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa48(%rbp)
movq -0xa48(%rbp), %rax
movl -0x34(%rbp), %ecx
cmpq %rcx, %rax
jb 0x699f
movl -0xa74(%rbp), %eax
addq -0xa70(%rbp), %rax
movq %rax, -0xa70(%rbp)
movl -0xa78(%rbp), %eax
addq -0xa68(%rbp), %rax
movq %rax, -0xa68(%rbp)
jmp 0x69a1
jmp 0x69a3
movq -0xb10(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xb10(%rbp)
jmp 0x67a3
movl $0x1, %edi
leaq -0xb08(%rbp), %rsi
movq %rsi, -0xb50(%rbp)
callq 0x21e0
movq -0xb50(%rbp), %rsi
movq -0xa38(%rbp), %rdx
movq -0xa40(%rbp), %rcx
movl -0x58(%rbp), %r8d
movq %rsp, %rax
movq %rsi, (%rax)
leaq -0xa90(%rbp), %rdi
leaq -0xae0(%rbp), %rsi
leaq -0xaf8(%rbp), %r9
callq 0x5d20
jmp 0x6a0d
movl $0x0, -0x4(%rbp)
leaq -0xae0(%rbp), %rdi
callq 0x7860
leaq -0xa90(%rbp), %rdi
callq 0x7880
movl -0x4(%rbp), %eax
addq $0xb60, %rsp            # imm = 0xB60
popq %rbp
retq
movq -0xaa0(%rbp), %rdi
callq 0x2360
nopw %cs:(%rax,%rax)
nop