// Arup Guha
// 4/27/2205
// Solution to COP 4516 Final Team Contest Problem: Geode Slices

import java.util.*;
import java.io.*;

public class geode {

	public static void main(String[] args) throws Exception {

		Scanner stdin = new Scanner(System.in);
		int nC = stdin.nextInt();
		
		// Process cases.
		for (int loop=0; loop<nC; loop++) {
		
			// Read in the points.
			int n = stdin.nextInt();
			pt[] pts = new pt[n];
			for (int i=0; i<n; i++) {
				long x = stdin.nextLong();
				long y = stdin.nextLong();
				pts[i] = new pt(x, y, i);
			}		
			
			// Peel off layers until there are no more.
			int res = 0;
			while (pts.length >= 3) {
			
				// Set the reference point.
				int refIndex = getIndexMin(pts, pts.length);
				pt.refX = pts[refIndex].x;
				pt.refY = pts[refIndex].y;
				
				// Get hull.
				HashSet<Integer> hull = grahamScan(pts, pts.length);
				res++;
				
				// Copy over points not in hull.
				int j = 0;
				pt[] newpts = new pt[pts.length - hull.size()];
				for (int i=0; i<pts.length; i++) {
					if (hull.contains(pts[i].id)) continue;
					newpts[j++] = pts[i];
				}
				
				// Set for next iteration.
				pts = newpts;
			}
		
			// Ta da!
			System.out.println(res);
		}
	}

	// Returns the point in pts with minimum y breaking tie by minimum x.
	public static int getIndexMin(pt[] pts, int n) {
		int res = 0;
		for (int i=1; i<n; i++)
			if (pts[i].y < pts[res].y || (pts[i].y == pts[res].y && pts[i].x < pts[res].x))
				res = i;
		return res;
	}

	public static HashSet<Integer> grahamScan(pt[] pts, int n) {

		// Sort the points by angle with reference point.
		Arrays.sort(pts);

		// Push first two points on.
		Stack<pt> myStack = new Stack<pt>();
		myStack.push(pts[0]);
		myStack.push(pts[1]);

		// Go through the rest of the points.
		for (int i=2; i<n; i++) {

			// Get last three pts.
			pt cur = pts[i];
			pt mid = myStack.pop();
			pt prev = myStack.pop();

			// Pop off the left turns.
			while (!prev.isRightTurn(mid, cur)) {
				mid = prev;
				prev = myStack.pop();
			}

			// Push back the last right turn.
			myStack.push(prev);
			myStack.push(mid);
			myStack.push(cur);
		}

		// Add pts of hull.
		HashSet<Integer> res = new HashSet<Integer>();
		while (myStack.size() > 0) {
			res.add(myStack.pop().id);
		}

		// Return.
		return res;
	}
}

class pt implements Comparable<pt> {

	// Stores reference pt
	public static long refX;
	public static long refY;

	public long x;
	public long y;
	public int id;
	
	public pt(long myx, long myy, int myid) {
		x = myx;
		y = myy;
		id = myid;
	}

	// Returns the vector from this to other.
	public pt getVect(pt other) {
		return new pt(other.x-x, other.y-y, -1);
	}

	// Returns the distance between this and other.
	public double dist(pt other) {
		return Math.sqrt((other.x-x)*(other.x-x) + (other.y-y)*(other.y-y));
	}

	// Returns the magnitude ot this cross product other.
	public long crossProductMag(pt other) {
		return this.x*other.y - other.x*this.y;
	}

	// returns true iff this to mid to next is a right turn (180 degree is considered right turn).
	public boolean isRightTurn(pt mid, pt next) {
		pt v1 = getVect(mid);
		pt v2 = mid.getVect(next);
		return v1.crossProductMag(v2) >=0; /*** Change to > 0 to skip collinear points. ***/
	}

	// Returns true iff this pt is the origin.
	public boolean isZero() {
		return x == 0 && y == 0;
	}

	public int compareTo(pt other) {

		pt myRef = new pt(refX, refY, 1001);
		pt v1 = myRef.getVect(this);
		pt v2 = myRef.getVect(other);

		// To avoid 0 issues.
		if (v1.isZero()) return -1;
		if (v2.isZero()) return 1;

		// Angles are different, we are going counter-clockwise here.
		if (v1.crossProductMag(v2) < 0) return 1;
		if (v1.crossProductMag(v2) > 0) return -1;

		// This should work, smaller vectors come first.
		if (myRef.dist(v1) < myRef.dist(v2)) return -1;
		return 1;
	}
}