#include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_map>
#include<list>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef pair<int,int> pi;
typedef pair<double,double> pd;
typedef pair<double,ll> pdl;
#define F first
#define S second
#define MK make_pair
const ll E=1e18+7;
const ll MOD=1000000007;

template<typename T> //double or long long
class Geometry{
private:
    typedef pair<T,T> point;
    typedef point Vector;
    typedef pair<point,point> line;
    vector<point> P;
    
public:
    Geometry(vector<point> P={}):P(P){}
    
    void add_point(point p){P.push_back(p);}
    
    void Sort(){
        sort(P.begin(),P.end());
    }
    
    //from first,to second
    Vector line_Vector(line a){
        return {a.S.F-a.F.F,a.S.S-a.F.S};
    }
    
    T dot(line a,line b){
        return dot(line_Vector(a),line_Vector(b));
    }
    
    T dot(Vector a,Vector b){
        return a.F*b.F+a.S*b.S;
    }
    
    T cross(line a,line b){
        return cross(line_Vector(a),line_Vector(b));
    }
    
    T cross(Vector a,Vector b){
        return a.F*b.S-a.S*b.F;
    }
    
    T norm(line a){
        return dot(a,a);
    }
    
    T norm(Vector a){
        return dot(a,a);
    }
    
    double abs(line a){
        return sqrt(norm(a));
    }
    
    double abs(Vector a){
        return sqrt(norm(a));
    }
    
    vector<point> convex_hull(){
        assert(P.size()>=3);
        vector<point> a=P;
        sort(a.begin(),a.end());
        vector<point> up;
        up.push_back(a[0]);
        up.push_back(a[1]);
        for(int i=2;i<a.size();i++){
            point p=a[i];
            while(up.size()>=2 && cross({up[up.size()-2],up[up.size()-1]},{up[up.size()-1],p})>=0){
                up.pop_back();
            }
            up.push_back(p);
        }
        reverse(a.begin(),a.end());
        vector<point> down;
        down.push_back(a[0]);
        down.push_back(a[1]);
        for(int i=2;i<a.size();i++){
            point p=a[i];
            while(down.size()>=2 && cross({down[down.size()-2],down[down.size()-1]},{down[down.size()-1],p})>=0){
                down.pop_back();
            }
            down.push_back(p);
        }
        vector<point> ret;
        for(int i=0;i<up.size();i++){
            ret.push_back(up[i]);
        }
        for(int i=1;i<down.size()-1;i++){
            ret.push_back(down[i]);
        }
        return ret;
    }
    
    double max_dist(){
        vector<point> P=convex_hull();
        T mx=0;
        ll where=0;
        for(int i=0;i<P.size();i++){
            if(norm({P[0],P[i]})>=mx){mx=norm({P[0],P[i]}); where=i;}
        }
        mx=0;
        for(int i=0;i<P.size();i++){
            while(norm({P[i],P[where]})<=norm({P[i],P[(where+1)%P.size()]})){
                where=(where+1)%P.size();
            }
            mx=max(mx,norm({P[i],P[where]}));
        }
        return sqrt(mx);
    }
};



int main(){
    Geometry<ll> G;
    ll q;
    cin>>q;
    while(q--){
    ll x,y;
    ll xd,yd;
    cin>>x>>y>>xd>>yd;
    x-=xd;
    y-=yd;
    ll x2,y2;
    cin>>x2>>y2>>xd>>yd;
    x2-=xd;
    y2-=yd;
    if(G.dot({x,y},{x2,y2})==0){cout<<1<<endl;}
    else if(G.cross({x,y},{x2,y2})==0){cout<<2<<endl;}
    else{cout<<0<<endl;}
    }
    
    return 0;
}


Measured memory_bytes: 3124