// File: 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
subq $0x1b0, %rsp            # imm = 0x1B0
movq %rdi, -0x110(%rbp)
movq %rsi, -0x108(%rbp)
movq %rdx, -0x100(%rbp)
movq %rdi, -0x18(%rbp)
movq %rsi, -0x20(%rbp)
movq %rdx, -0x28(%rbp)
movq %rcx, -0x30(%rbp)
movl %r8d, -0x34(%rbp)
movl %r9d, -0x38(%rbp)
movl -0x34(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
subl $0x1, %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl %eax, -0x40(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x4e20
movl $0x0, -0x74(%rbp)
movl $0x0, -0x78(%rbp)
movl $0x0, -0x7c(%rbp)
movl -0x7c(%rbp), %eax
cmpl -0x38(%rbp), %eax
jae 0x2720
movq -0x110(%rbp), %rdi
movq -0x30(%rbp), %rax
movl -0x7c(%rbp), %ecx
movl (%rax,%rcx,4), %eax
movl %eax, -0x80(%rbp)
movslq -0x80(%rbp), %rsi
callq 0x44d0
cmpl $-0x2, (%rax)
jne 0x25a7
leaq -0xc(%rbp), %rdi
movl $0xfffffffc, %esi       # imm = 0xFFFFFFFC
xorl %edx, %edx
movl $0x1, %ecx
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
callq 0x4e40
jmp 0x2578
movl $0x1, -0x90(%rbp)
jmp 0x2a19
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x5010
jmp 0x2a4c
movq -0x110(%rbp), %rdi
movslq -0x80(%rbp), %rsi
callq 0x44d0
cmpl $0x0, (%rax)
jne 0x25c5
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
movq -0x110(%rbp), %rdi
movslq -0x80(%rbp), %rsi
callq 0x44d0
cmpl $0x1, (%rax)
jne 0x25e3
movl -0x78(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x78(%rbp)
movq -0x108(%rbp), %rdi
movslq -0x80(%rbp), %rsi
callq 0x44d0
movq -0x108(%rbp), %rdi
movq %rax, -0x120(%rbp)
movslq -0x80(%rbp), %rsi
callq 0x44d0
movq -0x120(%rbp), %rdi
movq %rax, %rsi
callq 0x4d00
movq %rax, -0x118(%rbp)
jmp 0x2622
movq -0x118(%rbp), %rax
movq %rax, -0x98(%rbp)
leaq -0x70(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0x4e90
movb %dl, -0x129(%rbp)
movq %rax, -0x128(%rbp)
jmp 0x264f
movb -0x129(%rbp), %al
movq -0x128(%rbp), %rcx
movq %rcx, -0xa8(%rbp)
movb %al, -0xa0(%rbp)
movl $0x0, -0xac(%rbp)
movq -0x100(%rbp), %rdi
movl -0xac(%rbp), %eax
movq %rax, -0x138(%rbp)
movslq -0x80(%rbp), %rsi
callq 0x4d30
movq %rax, %rdi
callq 0x4da0
movq %rax, %rcx
movq -0x138(%rbp), %rax
cmpq %rcx, %rax
jae 0x2710
movq -0x100(%rbp), %rdi
movslq -0x80(%rbp), %rsi
callq 0x4d30
movq %rax, %rdi
movl -0xac(%rbp), %eax
movl %eax, %esi
callq 0x4d50
movq %rax, %rsi
leaq -0x70(%rbp), %rdi
callq 0x4ee0
movb %dl, -0x141(%rbp)
movq %rax, -0x140(%rbp)
jmp 0x26e2
movb -0x141(%rbp), %al
movq -0x140(%rbp), %rcx
movq %rcx, -0xc0(%rbp)
movb %al, -0xb8(%rbp)
movl -0xac(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xac(%rbp)
jmp 0x2673
jmp 0x2712
movl -0x7c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x7c(%rbp)
jmp 0x252d
movq 0xb8b1(%rip), %rdi      # 0xdfd8
leaq 0x6944(%rip), %rsi      # 0x9072
callq 0x10f0
movq %rax, -0x150(%rbp)
jmp 0x273c
movq -0x150(%rbp), %rdi
movl -0x34(%rbp), %esi
callq 0x11b0
movq %rax, -0x158(%rbp)
jmp 0x2754
movq -0x158(%rbp), %rdi
leaq 0x691e(%rip), %rsi      # 0x9080
callq 0x10f0
movq %rax, -0x160(%rbp)
jmp 0x2770
movq -0x160(%rbp), %rdi
movl -0x38(%rbp), %esi
callq 0x11b0
movq %rax, -0x168(%rbp)
jmp 0x2788
movq -0x168(%rbp), %rdi
movq 0xb832(%rip), %rsi      # 0xdfc8
callq 0x1130
jmp 0x279d
movl $0x0, -0xc4(%rbp)
movl $0x0, -0xc8(%rbp)
leaq -0x70(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rdi
callq 0x4f30
movq %rax, -0xd8(%rbp)
movq -0xd0(%rbp), %rdi
callq 0x4f60
movq %rax, -0xe0(%rbp)
leaq -0xd8(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x4f90
testb $0x1, %al
jne 0x27fe
jmp 0x28da
leaq -0xd8(%rbp), %rdi
callq 0x4fc0
movq (%rax), %rax
movq %rax, -0xe8(%rbp)
movl -0xe4(%rbp), %esi
movq 0xb7b7(%rip), %rdi      # 0xdfd8
callq 0x11b0
movq %rax, -0x170(%rbp)
jmp 0x282f
movq -0x170(%rbp), %rdi
leaq 0x67c8(%rip), %rsi      # 0x9005
callq 0x10f0
movq %rax, -0x178(%rbp)
jmp 0x284b
movq -0x178(%rbp), %rdi
movl -0xe8(%rbp), %esi
callq 0x11b0
movq %rax, -0x180(%rbp)
jmp 0x2866
movq -0x180(%rbp), %rdi
leaq 0x6aa3(%rip), %rsi      # 0x9317
callq 0x10f0
movq %rax, -0x188(%rbp)
jmp 0x2882
movq -0x188(%rbp), %rdi
leaq 0x67d6(%rip), %rsi      # 0x9066
callq 0x10f0
jmp 0x2897
cmpl $0x0, -0xe4(%rbp)
jne 0x28af
movl -0xc4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc4(%rbp)
cmpl $0x1, -0xe4(%rbp)
jne 0x28c7
movl -0xc8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc8(%rbp)
jmp 0x28c9
leaq -0xd8(%rbp), %rdi
callq 0x4fe0
jmp 0x27e2
movq 0xb6f7(%rip), %rdi      # 0xdfd8
movq 0xb6e0(%rip), %rsi      # 0xdfc8
callq 0x1130
jmp 0x28ef
movq 0xb6e2(%rip), %rdi      # 0xdfd8
leaq 0x678c(%rip), %rsi      # 0x9089
callq 0x10f0
movq %rax, -0x190(%rbp)
jmp 0x290b
movq -0x190(%rbp), %rdi
movl -0xc4(%rbp), %esi
callq 0x11b0
movq %rax, -0x198(%rbp)
jmp 0x2926
movq -0x198(%rbp), %rdi
movq 0xb694(%rip), %rsi      # 0xdfc8
callq 0x1130
jmp 0x293b
movq 0xb696(%rip), %rdi      # 0xdfd8
leaq 0x674e(%rip), %rsi      # 0x9097
callq 0x10f0
movq %rax, -0x1a0(%rbp)
jmp 0x2957
movq -0x1a0(%rbp), %rdi
movl -0xc8(%rbp), %esi
callq 0x11b0
movq %rax, -0x1a8(%rbp)
jmp 0x2972
movq -0x1a8(%rbp), %rdi
movq 0xb648(%rip), %rsi      # 0xdfc8
callq 0x1130
jmp 0x2987
movl -0xc8(%rbp), %eax
movl -0x40(%rbp), %ecx
shll %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jl 0x29bf
leaq -0xc(%rbp), %rdi
movl $0x1, %esi
xorl %ecx, %ecx
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
movl %ecx, %edx
callq 0x4e40
jmp 0x29b3
movl $0x1, -0x90(%rbp)
jmp 0x2a19
movl -0xc4(%rbp), %eax
movl -0x40(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jl 0x29f2
leaq -0xc(%rbp), %rdi
xorl %ecx, %ecx
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
movl %ecx, %esi
movl %ecx, %edx
callq 0x4e40
jmp 0x29e6
movl $0x1, -0x90(%rbp)
jmp 0x2a19
leaq -0xc(%rbp), %rdi
movl $0xfffffffc, %esi       # imm = 0xFFFFFFFC
movl $0x1, %edx
xorl %ecx, %ecx
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
callq 0x4e40
jmp 0x2a0f
movl $0x1, -0x90(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x5010
movl -0x4(%rbp), %eax
movl %eax, -0xf0(%rbp)
movq -0xc(%rbp), %rax
movq %rax, -0xf8(%rbp)
movq -0xf8(%rbp), %rax
movl -0xf0(%rbp), %edx
addq $0x1b0, %rsp            # imm = 0x1B0
popq %rbp
retq
movq -0x88(%rbp), %rdi
callq 0x11c0
nopl (%rax,%rax)