#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <numeric>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#include <unordered_map>
#include <unordered_set>

using namespace std;

#define ll long long
#define ull unsigned long long
#define INF (1 << 29)
#define LLINF (1LL << 61)
#define MOD7 1000000007
#define MOD9 1000000009
#define EPS 1e-9
#define P pair<int, int>
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pul pair<ull, ull>
#define all(a) (a).begin(), (a).end()
#define FOR(i,a,b) for (int i=(a);i<(b);++i)
#define RFOR(i,a,b) for (int i=(b)-1;i>=(a);--i)
#define REP(i,n) for (int i=0;i<(n);++i)
#define RREP(i,n) for (int i=(n)-1;i>=0;--i)
#define TO_STRING(VariableName) # VariableName

void YES() { cout << "YES" << endl; }
void NO() { cout << "NO" << endl; }
void Yes() { cout << "Yes" << endl; }
void No() { cout << "No" << endl; }
void yes() { cout << "yes" << endl; }
void no() { cout << "no" << endl; }

class Point;
class Segment;
class Circle;

using Vector = Point;
using Line = Segment;
using Polygon = vector<Point>;

class Point {
public:
	double x, y;

	Point(double x = 0, double y = 0) : x(x), y(y) {}

	Point operator+(Point p) { return Point(x + p.x, y + p.y); }
	Point operator-(Point p) { return Point(x - p.x, y - p.y); }
	Point operator*(double k) { return Point(x * k, y * k); }
	Point operator/(double k) { return Point(x / k, y / k); }

	bool operator<(const Point& p) const {
		return x != p.x ? x < p.x : y < p.y;
	}

	bool operator==(const Point& p) const {
		return fabs(x - p.x) < EPS && fabs(y - p.y) < EPS;
	}

	friend istream& operator>>(istream& stream, Point& p) {
		double x, y;
		stream >> x >> y;
		p.x = x;
		p.y = y;
		return stream;
	}

	friend ostream& operator<<(ostream& stream, const Point& p) {
		stream << fixed << setprecision(10) << p.x << " " << p.y;
		return stream;
	}

	double abs() { return sqrt(norm()); }
	double norm() { return x * x + y * y; }

	double dot(Vector v) {
		return x * v.x + y * v.y;
	}

	double cross(Vector v) {
		return x * v.y - y * v.x;
	}
};

#define CLOCKWISE 1
#define COUNTER_CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

class Segment {
public:
	Point p1, p2;

	Segment(Point p1 = Point(), Point p2 = Point()) : p1(p1), p2(p2) {}
	
	friend istream& operator>>(istream& stream, Segment& s) {
		Point p1, p2;
		stream >> p1 >> p2;
		s.p1 = p1;
		s.p2 = p2;
		return stream;
	}

	friend ostream& operator<<(ostream& stream, const Segment& s) {
		stream << fixed << setprecision(10) << s.p1.x << " " << s.p1.y << " ";
		stream << fixed << setprecision(10) << s.p2.x << " " << s.p2.y;
		return stream;
	}

	Point project(Point p) {
		Point base = p2 - p1;
		double r = (p - p1).dot(base) / base.norm();
		return p1 + base * r;
	}

	Point refrect(Point p) {
		return p + (project(p) - p) * 2;
	}

	int ccw(Point p) {
		Vector a = p2 - p1;
		Vector b = p - p1;
		if (a.cross(b) > EPS) return COUNTER_CLOCKWISE;
		if (a.cross(b) < -EPS) return CLOCKWISE;
		if (a.dot(b) < -EPS) return ONLINE_BACK;
		if (a.norm() < b.norm()) return ONLINE_FRONT;
		return ON_SEGMENT;
	}

	bool orthogonal(Segment s) {
		return fabs((p2 - p1).dot(s.p2 - s.p1)) < EPS;
	}

	bool parallel(Segment s) {
		return fabs((p2 - p1).cross(s.p2 - s.p1)) < EPS;
	}

	bool intersect(Segment s) {

	}
};

class Circle {
public:
	Point c;
	double r;
	Circle(Point c = Point(), double r = 0) : c(c), r(r) {}
};

int main() {
	Segment s1, s2;
	int q;
	cin >> q;
	while (q--) {
		cin >> s1 >> s2;
		if (s1.orthogonal(s2))
			cout << 1 << endl;
		else if (s1.parallel(s2))
			cout << 2 << endl;
		else
			cout << 0 << endl;
	}

	return 0;
}

Measured memory_bytes: 3228