#include <iostream>
#include <iomanip>
#include <cmath>
#include <array>

using Number = double;

const Number EPS = 1e-10;
const Number INF = 1e10;
const Number PI = acos(-1.0);

inline int sign(Number x) { return (x < -EPS) ? -1 : (x > EPS) ? +1 : 0; }
inline bool equal(Number a, Number b) { return sign(a - b) == 0; }

// change between degree and radian
inline Number to_radian(const Number degree) { return degree * PI / 180.0; }
inline Number to_degree(const Number radian) { return radian * 180.0 / PI; }


/**
 * Point in two dimensional
 */
class Point {
public:
    Number x, y;

    Point() {}
    Point(Number x, Number y) : x(x), y(y) {}

    // Arithmetic operator between points
    Point operator+(const Point &rhs) const {
        return Point(this->x + rhs.x, this->y + rhs.y);
    }
    Point operator-(const Point &rhs) const {
        return Point(this->x - rhs.x, this->y - rhs.y);
    }
    Point operator*(const Point &rhs) const { // cross product between points
        return Point(this->x * rhs.x - this->y * rhs.y,
                     this->x * rhs.x + this->y * rhs.x);
    }

    // Unary operator and compound assignment operator
    Point operator-() const {
        return Point(-this->x, -this->y);
    }
    Point& operator+=(const Point &rhs) {
        return *this = *this + rhs;
    }
    Point& operator-=(const Point &rhs) {
        return *this = *this - rhs;
    }

    // Arithmetic operator between point and number
    Point operator*(Number rhs) const {
        return Point(this->x * rhs, this->y * rhs);
    }
    Point operator/(Number rhs) const {
        return Point(this->x / rhs, this->y / rhs);
    }

    // Comparison operation
    bool operator==(const Point &rhs) const {
        return sign(this->x - rhs.x) == 0 && sign(this->y - rhs.y) == 0;
    }
    bool operator<(const Point &rhs) const {
        return (this->x < rhs.x) || (this->x == rhs.x && this->y < rhs.y);
    }

    // Other operator
    Number abs(void) const {
        return sqrt(this->x * this->x + this->y * this->y);
    }
    Number abs2(void) const {
        return this->x * this->x + this->y * this->y;
    }
    Number arg(void) const {
        return atan2(this->y, this->x);
    }
    Number dot(const Point &rhs) {
        return this->x * rhs.x + this->y * rhs.y;
    }
    Point rotate90(void) const {
        return Point(-this->y, this->x);
    }
    Point rotate(double angle) const {
        return Point(cos(angle) * this->x - sin(angle) * this->y,
                     sin(angle) * this->x + cos(angle) * this->y);
    }

};
inline Number dot(const Point &p1, const Point &p2) {
    return p1.x * p2.x + p1.y * p2.y;
}
inline Number abs_cross(const Point &p1, const Point &p2) {
    return p1.x * p2.y - p1.y * p2.x;
}
// Output of a point
std::ostream& operator<<(std::ostream &os, const Point &p) {
    return os <<  p.x << ' ' << p.y;
}
// Input of a point
std::istream& operator>>(std::istream &is, Point &p) {
    return is >> p.x >> p.y;
}

// Counter-Clockwise predicate (a, b, c)
enum CCW {
    COUNTER_CLOCKWISE = 1,      // counter clockwise
    CLOCKWISE         = -1,     // clockwise
    ONLINE_FRONT      = 0,      // a--c--b on line
    ONLINE_BACK       = 2,      // c--a--b on line
    ON_SEGMENT        = -2,     // a--b--c on line
};
CCW ccw(const Point &a, Point b, Point c) {
    b -= a;  c -= a;
    if (abs_cross(b, c) > 0) return COUNTER_CLOCKWISE;
    if (abs_cross(b, c) < 0) return CLOCKWISE;
    if (dot(b, c) < 0)       return ONLINE_BACK;
    if (b.abs2() < c.abs2())   return ONLINE_FRONT;
    return ON_SEGMENT;
}


/**
 * Line or Segment in two dimensional
 */
class Line : public std::array<Point, 2> {
public:
    Line() {}
    Line(const Point &p1, const Point &p2) {
        (*this)[0] = p1;
        (*this)[1] = p2;
    }
};
using Segment = Line;
// Input of a line
std::istream& operator>>(std::istream &is, Line &l) {
    return is >> l[0] >> l[1];
}
inline CCW ccw(const Line &l, const Point &p) {
    return ccw(l[0], l[1], p);
}
inline bool IsOrthogonal(const Line &l1, const Line &l2) {
    return equal(dot(l1[0] - l1[1], l2[0] - l2[1]), 0.0);
}
inline bool IsParallel(const Line &l1, const Line &l2) {
    return equal(abs_cross(l1[0] - l1[1], l2[0] - l2[1]), 0.0);
}


/**
 * Circle in two dimensional
 */
class Circle : public Point {
public:
    Number r;
    Circle(const Point &p, Number r = 0.0) : Point(p), r(r) {}
};
// Input of a circle
std::istream& operator>>(std::istream &is, Circle &c) {
    return is >> c.x >> c.y >> c.r;
}



/**
 * Intersection testing
 */


/**
 * Intersection point and Distance
 */
Point Projection(const Line &l, const Point &p) {
    Point dir = l[1] - l[0];
    Number t = dot(p - l[0], dir) / dir.abs2();
    return l[0] + dir * t;
}
Point Reflection(const Line &l, const Point &p) {
    return Projection(l, p) * 2.0 - p;
}


int main()
{
    Line l1, l2;
    int q;

    std::cin >> q;

    while (q--) {
        std::cin >> l1 >> l2;

        if (IsOrthogonal(l1, l2))
            std::cout << "1\n";
        else if (IsParallel(l1, l2))
            std::cout << "2\n";
        else
            std::cout << "0\n";
    }

    return 0;
}

Measured memory_bytes: 3196