#pragma GCC optimize ("O2")
#pragma GCC optimize ("tree-vectorize")
#pragma GCC target ("sse4")

#include <bits/stdc++.h>
#define FOR(i, a, b) for(int i=(a);i<(b);++i)
#define FFOR(i, a, b) FOR(i, a, b+1)
#define REP(i, n) FOR(i, 0, n)
#define RREP(i, n) FOR(i, 1, n+1)
#define ALL(v) (v).begin(), (v).end()
#define RALL(v) (v).rbegin(), (v).rend()
#define LEN(x) (int)(x).size()
#define DUMP(x) cerr<<__LINE__<<' '<<#x<<"="<<(x)<<endl;
#define pb push_back
#define eb emplace_back
#define mp make_pair

using namespace std;
using lint = long long;
using pii =  pair<int, int>;
using pll =  pair<lint, lint>;
template <typename T> using vc = vector<T>;
template <typename T> using vvc = vector<vector<T>>;
template <typename T> inline bool chmax(T &a, T b){if(a<b){a = b; return true;} return false;}
template <typename T> inline bool chmin(T &a, T b){if(a>b){a = b; return true;} return false;}

const double PI = acos(-1);
constexpr lint ten(int n) {return n==0 ? 1 : ten(n-1)*10;}

namespace Geometry{
    //TODO: REPLACE
    double eps = 1e-12;

    template <typename T>
    struct Vector{
    public:
        T x, y;

        explicit Vector(T x=0, T y=0) : x(x), y(y){}

        Vector& operator+=(const Vector v) {
            x += v.x; y += v.y;
            return *this;
        }
        Vector& operator-=(const Vector v) {
            x -= v.x; y -= v.y;
            return *this;
        }
        Vector& operator*=(const T a){
            x *= a; y *= a;
            return *this;
        }
        Vector& operator/=(const T a){
            x /= a; y /= a;
            return *this;
        }
        Vector operator+(const Vector v) const {
            Vector res(*this);
            return res += v;
        }
        Vector operator-(const Vector v) const {
            Vector res(*this);
            return res -= v;
        }
        Vector operator*(const T a) const {
            Vector res(*this);
            return res *= a;
        }
        Vector operator/(const T a) const {
            Vector res(*this);
            return res /= a;
        }
        bool operator==(const Vector p) const {
            return fabs(x-p.x) < eps and fabs(y-p.y) < eps;
        }
        bool operator!=(const Vector p) const {
            return not (fabs(x-p.x) < eps and fabs(y-p.y) < eps);
        }
        T norm() const {
            return x * x + y * y;
        }
        T args() const {
            return atan2(y, x);
        }
        T abs() const {
            return sqrt(norm());
        }
    };

    template <typename T>
    struct Segment{
    public:
        Vector<T> first, second;

        explicit Segment(Vector<T> first=Vector<T>(), Vector<T> second=Vector<T>()) : first(first), second(second){}
    };

    template <typename T>
    static T norm(const Vector<T> v) {
        return v.norm();
    }
    template <typename T>
    static T norm(const Segment<T> s){
        return (s.second-s.first).norm();
    }
    template <typename T>
    static T args(const Vector<T> v) {
        return v.args();
    }
    template <typename T>
    static T args(const Segment<T> s) {
        return (s.second-s.first).args();
    }
    template <typename T>
    static T abs(const Vector<T> v){
        return v.abs();
    }
    template <typename T>
    static T abs(const Segment<T> s){
        return (s.second-s.first).abs();
    }
    template <typename T>
    static T dot(const Vector<T> v1, const Vector<T> v2){
        return v1.x * v2.x + v1.y * v2.y;
    }
    template <typename T>
    static T dot(const Segment<T> s1, const Segment<T> s2){
        return dot(s1.second-s1.first, s2.second-s2.first);
    }
    template <typename T>
    static T cross(const Vector<T> v1, const Vector<T> v2){
        return v1.x * v2.y - v1.y * v2.x;
    }
    template <typename T>
    static T cross(const Segment<T> s1, const Segment<T> s2){
        return cross(s1.second-s1.first, s2.second-s2.first);
    }
    template <typename T>
    static bool isOrthogonal(const Vector<T> v1, const Vector<T> v2){
        return fabs(dot(v1, v2)-0.0) < eps;
    }
    template <typename T>
    static bool isOrthogonal(const Segment<T> s1, const Segment<T> s2){
        return fabs(dot(s1, s2)-0.0) < eps;
    }
    template <typename T>
    static bool isParallel(const Vector<T> v1, const Vector<T> v2){
        return fabs(cross(v1, v2)-0.0) < eps;
    }
    template <typename T>
    static bool isParallel(const Segment<T> s1, const Segment<T> s2){
        return fabs(cross(s1, s2)-0.0) < eps;
    }
}

using namespace Geometry;

class Task{
public:
    void solve(istream& in, ostream& out){
        int Q;
        in>>Q;
        while(Q--){
            int x0, y0, x1, y1, x2, y2, x3, y3;
            in>>x0>>y0>>x1>>y1>>x2>>y2>>x3>>y3;
            Segment<double> s1(Vector<double>(x0, y0), Vector<double>(x1, y1));
            Segment<double> s2(Vector<double>(x2, y2), Vector<double>(x3, y3));
            if(isOrthogonal(s1, s2)) out<<1<<'\n';
            else if(isParallel(s1, s2)) out<<2<<'\n';
            else out<<0<<'\n';
        }
    }
};

int main(){
    istream& in(cin);
    ostream& out(cout);
    ios_base::sync_with_stdio(false);
    in.tie(nullptr), out.tie(nullptr);
    Task solver;
    solver.solve(in, out);
    return 0;
}


Measured memory_bytes: 3212