import std.algorithm;
import std.array;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

int readint() { return readln.chomp.to!int; }
int[] readints() { return readln.split.map!(to!int).array; }

bool isParallel(Vec2 a, Vec2 b, Vec2 c, Vec2 d) {
    auto ab = b - a;
    auto cd = d - c;
    return ab.cross(cd) == 0;
}

bool isOrthogonal(Vec2 a, Vec2 b, Vec2 c, Vec2 d) {
    auto ab = b - a;
    auto cd = d - c;
    return ab.dot(cd) == 0;
}

int calc(Vec2 a, Vec2 b, Vec2 c, Vec2 d) {
    if (isParallel(a, b, c, d)) return 2;
    if (isOrthogonal(a, b, c, d)) return 1;
    return 0;
}

void main() {
    int n = readint();
    for (int i = 0; i < n; i++) {
        auto ps = readints();
        auto a = Vec2(ps[0], ps[1]);
        auto b = Vec2(ps[2], ps[3]);
        auto c = Vec2(ps[4], ps[5]);
        auto d = Vec2(ps[6], ps[7]);

        writeln(calc(a, b, c, d));
    }
}

struct Vec2 {
    immutable double x;
    immutable double y;

    this(double x, double y) {
        this.x = x;
        this.y = y;
    }

    Vec2 opNeg() { return Vec2(-this.x, -this.y); }
    Vec2 opAdd(Vec2 other) { return Vec2(this.x + other.x, this.y + other.y); }
    Vec2 opSub(Vec2 other) { return Vec2(this.x - other.x, this.y - other.y); }
    Vec2 opMul(double d) { return Vec2(this.x * d, this.y * d); }

    double dot(Vec2 other) { return this.x * other.x + this.y * other.y; }
    double cross(Vec2 other) { return this.x * other.y - other.x * this.y; }
    double mag() { return sqrt(magSq()); }
    double magSq() { return this.x * this.x + this.y * this.y; }

    Vec2 normalized() {
        auto m = mag();
        if (m != 0 && m != 1)
            return Vec2(this.x / m, this.y / m);
        return this;
    }

    static double distance(Vec2 a, Vec2 b) {
        return (a - b).mag();
    }
}

