// File: /workspace/github_cpp_makefile_star2_O2/NeoResearch[P]dbft3-spork-detect/main.cpp
// Function: verifyCommitSubset(std::vector<int, std::allocator<int>>, std::vector<int, std::allocator<int>>, std::vector<std::vector<std::pair<int, int>, std::allocator<std::pair<int, int>>>, std::allocator<std::vector<std::pair<int, int>, std::allocator<std::pair<int, int>>>>>, int*, int, int)
CommitStatus verifyCommitSubset(vector<int> cancels, vector<int> choices, vector<vector<pair<int, int>>> selections, int t[], int p, int k)
{
    int N = p;
    int f = (N - 1) / 3;
    //vector<pair<int, int>> pack; // pack all information
    std::set<pair<int, int>> pack;
    int count_cancel_zero = 0;
    int count_cancel_one = 0;
    //bool includes_primaryZero = false;
    for (unsigned c = 0; c < k; c++)
    {
        int e = t[c]; // get element from subset
        if (cancels[e] == -2)
            return CommitStatus{-4, false, true}; // dead node
        if (cancels[e] == 0)
            count_cancel_zero++;
        if (cancels[e] == 1)
            count_cancel_one++;
        /*
        if(e == 0)
        {
            includes_primaryZero = true;
            return 0; // very strong primary 0
        }
        */
        pack.insert(make_pair(choices[e], choices[e])); // first proposal (responded to)
        for (unsigned j = 0; j < selections[e].size(); j++)
            pack.insert(selections[e][j]); // responses (and possible more proposals)
    }

    cout << "PACK for p=N=" << p << " 2f+1=k=" << k << endl;
    /*
    sort(pack.begin(), pack.end(), [](const pair<int,int> & a, const pair<int,int> & b) -> bool
    { 
        return (a.first < b.first) && (a.second < b.second); 
    });
    unique(pack.begin(), pack.end());
    */
    //sort(pack.begin(), pack.end());
    //pack.erase(unique(pack.begin(), pack.end()));
    // remove repeated
    //for(unsigned i=0; i<int(pack.size())-1; i++)
    //    for(unsigned j=i+1; j<pack.size(); j++)

    //for(int j=0; j<pack.size(); j++)
    //    cout << pack[j].second << "(" << pack[j].first << ")" << "\t";
    int count_zero = 0;
    int count_one = 0;
    for (auto dp : pack)
    {
        cout << dp.second << "(" << dp.first << ")"
             << "\t";
        if (dp.second == 0)
            count_zero++;
        if (dp.second == 1)
            count_one++;
    }
    cout << endl;
    cout << "count_zero = " << count_zero << endl;
    cout << "count_one = " << count_one << endl;
    //if(count_zero >= 2) // f+1
    //    return 0;
    //if(count_zero >= k) // >=2f+1
    if (count_one >= 2 * f + 1) // >=2f+1 // this is correct one
                                //if (count_one >= f+1) // >=f+1 // NOT GOOD!! JUST TESTING (INTENDS TO FAIL AND CREATE FORKS!!)
        return 1;
    if (count_zero >= f + 1) // >=f+1  // this is correct one
        return 0;

    // THINK, WHAT ELSE?
    //return 0; // default zero (seems to cause problem, when all is 1, an intersection doesnt give 2f+1 ones...)
    // probably, voting.

    // VERY DUBIOUS CASE HERE... 0(0)    1(1)    1(3)
    /*
R_0 | 0(0) |    1(1)    1(3)    | Cancel 0
R_1 | 1(1) |    0(0)    1(3)    | Cancel 1
R_2 | 0(0) |    0(2)    1(1)    | Cancel 0
R_3 | 1(1) |    1(3)    0(0)    | Cancel 1
    */
    // but it should be zero.

    // try to vote by cancels.... desperate measure
    //if(count_cancel_zero > 0)
    //    return 0;
    //else
    //    return 1;
    // didn't work out...
    // all ones and only first is zero. No one answered it. So, it must go one.
    //if((count_one == 2) && (count_zero==1))
    //    return 1;
    // default
    //return 0;

    // cannot decide (THIS IS THE SOLUTION!!!)
    // sometimes, one should simply wait for more information...
    // ... and if really not possible, then Change View (rare cases, only 12.5% with permanent fault)
    return CommitStatus{-4, true};

    /*
    // didn't work out... dubious case:  0(0)    1(1)    1(3)
    if(count_one > count_zero)
        return 1;
    else
        return 0; // equality, still zero
        */
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movl %r9d, -0x2c(%rbp)
movq %rcx, -0x58(%rbp)
movq %rdx, %r13
movq %rsi, -0x48(%rbp)
movq %rdi, -0x50(%rbp)
movq %r8, -0x40(%rbp)
leal -0x1(%r8), %eax
pushq $0x3
popq %rcx
cltd
idivl %ecx
movq %rax, -0x38(%rbp)
leaq -0x88(%rbp), %rax
andl $0x0, (%rax)
andq $0x0, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
andq $0x0, 0x20(%rax)
xorl %ebx, %ebx
leaq -0x90(%rbp), %r14
cmpl -0x2c(%rbp), %ebx
je 0x1c26
movl %ebx, %eax
movq -0x58(%rbp), %rcx
movslq (%rcx,%rax,4), %r15
movq -0x50(%rbp), %rax
movq (%rax), %rax
cmpl $-0x2, (%rax,%r15,4)
je 0x1d58
movq -0x48(%rbp), %rax
movq (%rax), %rax
movl (%rax,%r15,4), %eax
movq %rax, %rcx
shlq $0x20, %rcx
orq %rax, %rcx
movq %rcx, -0x60(%rbp)
movq %r14, %rdi
leaq -0x60(%rbp), %rsi
callq 0x3846
xorl %r12d, %r12d
imulq $0x18, %r15, %r15
movl %r12d, %r12d
movq (%r13), %rcx
movq (%rcx,%r15), %rax
movq 0x8(%rcx,%r15), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
cmpq %r12, %rcx
jbe 0x1c22
leaq (%rax,%r12,8), %rsi
movq %r14, %rdi
callq 0x3a28
incl %r12d
jmp 0x1bf5
incl %ebx
jmp 0x1ba8
movq 0x53ab(%rip), %rdi      # 0x6fd8
leaq 0x246a(%rip), %rsi      # 0x409e
callq 0x1100
movq %rax, %rdi
movq -0x40(%rbp), %rsi
callq 0x11d0
leaq 0x2460(%rip), %rsi      # 0x40ac
movq %rax, %rdi
callq 0x1100
movq %rax, %rdi
movl -0x2c(%rbp), %esi
callq 0x11d0
movq %rax, %rdi
callq 0x1090
xorl %r14d, %r14d
movq -0x78(%rbp), %rbx
xorl %r15d, %r15d
leaq -0x88(%rbp), %rax
cmpq %rax, %rbx
je 0x1ced
movl 0x20(%rbx), %r12d
movl 0x24(%rbx), %r13d
movq 0x534c(%rip), %rdi      # 0x6fd8
movl %r13d, %esi
callq 0x11d0
movq %rax, %rdi
leaq 0x2393(%rip), %rsi      # 0x4031
callq 0x1100
movq %rax, %rdi
movl %r12d, %esi
callq 0x11d0
movq %rax, %rdi
leaq 0x2689(%rip), %rsi      # 0x4341
callq 0x1100
movq %rax, %rdi
leaq 0x23cb(%rip), %rsi      # 0x4092
callq 0x1100
cmpl $0x1, %r13d
adcl $0x0, %r14d
xorl %eax, %eax
cmpl $0x1, %r13d
sete %al
addl %eax, %r15d
movq %rbx, %rdi
callq 0x1140
movq %rax, %rbx
jmp 0x1c71
movq 0x52e4(%rip), %rdi      # 0x6fd8
callq 0x1090
movq 0x52d8(%rip), %rdi      # 0x6fd8
leaq 0x23ae(%rip), %rsi      # 0x40b5
callq 0x1100
movq %rax, %rdi
movl %r14d, %esi
callq 0x11d0
movq %rax, %rdi
callq 0x1090
movq 0x52b2(%rip), %rdi      # 0x6fd8
leaq 0x2396(%rip), %rsi      # 0x40c3
callq 0x1100
movq %rax, %rdi
movl %r15d, %esi
callq 0x11d0
movq %rax, %rdi
callq 0x1090
movq -0x38(%rbp), %rcx
leal (%rcx,%rcx), %eax
cmpl %eax, %r15d
jle 0x1d69
pushq $0x1
popq %rbx
xorl %eax, %eax
jmp 0x1d82
movabsq $0x10000000000, %rax    # imm = 0x10000000000
movl $0xfffffffc, %ebx       # imm = 0xFFFFFFFC
jmp 0x1d82
movq %rcx, %rdx
movl $0xfffffffc, %ebx       # imm = 0xFFFFFFFC
leaq 0x4(%rbx), %rax
xorl %ecx, %ecx
cmpl %edx, %r14d
cmovgq %rcx, %rbx
cmovgq %rcx, %rax
orq %rax, %rbx
leaq -0x90(%rbp), %rdi
callq 0x3196
pushq $-0x1
popq %rdx
movq %rbx, %rax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x1dae
jmp 0x1dae
jmp 0x1dae
jmp 0x1dae
movq %rax, %rbx
leaq -0x90(%rbp), %rdi
callq 0x3196
movq %rbx, %rdi
callq 0x11e0