/*
@title Macro
@category template
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
#define Yes "Yes"
#define No "No"
#define YES "YES"
#define NO "NO"
typedef long long ll;

template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;

const double PI = acos(-1.0);

const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";


#line 1 "/Users/knaga/programming/procon_library/geometory/template.cpp"


#line 5 "/Users/knaga/programming/procon_library/geometory/template.cpp"
/*
@title Geometory/template.cpp
@category Geometory
*/

typedef complex<double> Point;
typedef pair<Point, Point> Segment;
#define EPS (1e-10)
#define EQ(a, b) (abs((a) - (b)) < EPS)
Point operator*(const Point &p, const double &d) {
  return Point(real(p) * d, imag(p) * d);
}
// 内積
double dot(Point a, Point b){
    return (a.real() * b.real() + a.imag() * b.imag());
}
//外積
double cross(const Point &a, const Point &b){
    return (a.real() * b.imag() - a.imag() * b.real());
}

/*
"https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/2/CGL_1_A"
直線 l に p から引いた交点を求める
*/
Point projection(const Segment &l, const Point &p){
    double t = dot(p - l.first, l.second - l.first) / norm(l.second - l.first);
    return l.first + t * (l.second - l.first);
}
/*
直線 l に関して線対称な点を求める
*/
Point reflection(const Segment &l, const Point &p){
    return p + (projection(l,p)-p)*2.0;
}
/*
https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/1/CGL_1_C
crockwise
*/
int ccw(const Point &a, const Point &b, const Point &c){
    Point x = b - a;
    Point y = c - a;
    if(cross(x,y) > EPS)return 1;   //時計回り
    if(cross(x,y) < -EPS)return -1; //反時計回り
    if(dot(x,y) < -EPS)return +2;   //後ろ
    if(norm(x) < norm(y))return -2; //前
    return 0;                       //中
}
bool is_intersected_ls(Point a1, Point a2, Point b1, Point b2){
    return (cross(a2-a1, b1-a1)*cross(a2-a1, b2-b1) < EPS) && (cross(b2-b1, a1-b1)*cross(b2-b1, a2-b1) < EPS);
}


#line 4 "CGL_2_A.test.cpp"

int main(){
    int q;
    cin >> q;
    while(q--){
        int x[4],y[4];
        rep(i,4)cin >> x[i] >> y[i];
        Point p1(x[1]-x[0], y[1]-y[0]);
        Point p2(x[3]-x[2], y[3]-y[2]);
        if(dot(p1,p2)==0)cout<<1<<endl;
        else if(cross(p1,p2)==0)cout<<2<<endl;
        else cout << 0 << endl;
    }
}


Measured memory_bytes: 3212