import java.util.Scanner;
import java.io.File;
import java.io.PrintStream;

import java.util.Collection;
import java.util.Collections;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Comparator;
import java.util.Arrays;

import java.util.Locale;

/**
 * Solver for problem 09: "Robintron".
 * 
 */
class ProblemG extends AB_ProblemSolver{
	
	public static final int MAX_PLANETS = 1000;
	
	public static void main(String[] args) throws Exception {
                Locale.setDefault( Locale.ENGLISH );
		ProblemG solver = new ProblemG(args);
		solver.run();
	}	
	
	public ProblemG(String[] args){
		super(args);
	}
	
	public void runCase() throws Exception{
		int num_planets = this.in.nextInt(); this.in.nextLine();
		if(num_planets < 2 || num_planets > MAX_PLANETS){
			throw new RuntimeException("EPIC FAIL! number of planets out of bounds");
		}
		
		ArrayList<AB_Planet> planets = new ArrayList<AB_Planet>(num_planets);
		
		for(int i = 0; i < num_planets; i++){
			double planet_x = this.in.nextDouble();
			double planet_y = this.in.nextDouble();
			double planet_well = this.in.nextDouble();
			double planet_speed = this.in.nextDouble();
			
			if(Math.abs(planet_x) > 1e10){
				throw new RuntimeException("EPIC FAIL! planet-x out of bounds");
			}
			if(Math.abs(planet_y) > 1e10){
				throw new RuntimeException("EPIC FAIL! planet-y out of bounds");
			}
			if(planet_well <= 0 || planet_well > 1e5){
				throw new RuntimeException("EPIC FAIL! planet-well out of bounds");
			}
			if(planet_speed < 0 || planet_speed > 2*Math.PI){
				throw new RuntimeException("EPIC FAIL! planet-speed out of bounds");
			}
			
			AB_Planet planet = new AB_Planet(i, planet_x, planet_y, planet_well, planet_speed);
			planets.add(planet);
		}
		
		ArrayList<AB_Planet> planets_to_visit = new ArrayList<AB_Planet>(planets);
		AB_Planet current_planet = planets_to_visit.remove(0);
		current_planet.best_time = 0;

		do{
			this.debug("Looking from planet " + current_planet.id);
		
			// Update all planets
			for(AB_Planet to_planet: planets_to_visit){
				if(!current_planet.canTouch(to_planet)){
					this.debug("* Cannot reach planet " + to_planet.id);
					continue;		// cannot reach this one, so no use in checking it...
				}
				
				double time_to_reach = current_planet.timeToReach(to_planet);
				this.debug("* Can reach planet " + to_planet.id + " at " + time_to_reach);
				if(time_to_reach < to_planet.best_time){
					to_planet.best_time = time_to_reach;
					to_planet.via_planet = current_planet.id;
				}
			}
			
			// Find planet with lowest ETA
			double lowest_time = Double.MAX_VALUE;
			int lowest_index = 0;
			for(int j = 0; j < planets_to_visit.size(); j++){
				AB_Planet planet = planets_to_visit.get(j);
				if(planet.best_time < lowest_time){
					lowest_index = j;
					lowest_time = planet.best_time;
				}
			}
			
			current_planet = planets_to_visit.remove(lowest_index);
			if(current_planet.id == num_planets - 1){
				break;
			}
		}while(planets_to_visit.size() > 0);
		
		AB_Planet target_planet = planets.get(num_planets - 1);
		
		this.debug("---"); this.debug("(Inverse) Route des doods:");
		AB_Planet hop_planet = target_planet;
		while(hop_planet.via_planet != -1){
			this.debug("Via " + hop_planet.via_planet);
			hop_planet = planets.get(hop_planet.via_planet);
		}		
		
		this.out.println((int) Math.ceil(target_planet.best_time));
	}
}

class AB_Planet{
	
	public int id;
	public double x;
	public double y;
	public double well;
	public double speed;
	
	public double best_time = Double.MAX_VALUE;
	public int via_planet = -1;
	
	public final double EPSILON = 10e-9;
	
	public AB_Planet(int id, double x, double y, double well, double speed){
		this.id = id;
		this.x = x;
		this.y = y;
		this.well = well;
		this.speed = speed;
	}
	
	public double distanceToStar(){
		return Math.sqrt((this.x*this.x) + (this.y*this.y));
	}
	
	public double distanceToPlanet(AB_Planet other){
		double x_diff = this.x - other.x;
		double y_diff = this.y - other.y;
		return Math.sqrt((x_diff*x_diff) + (y_diff*y_diff));
	}
	
	public double angleToStar(){
		return Math.atan2(this.y, this.x);
	}
	
	public double angleAtTime(double t){
		return this.angleToStar() + t*this.speed;
	}
	
	public boolean canTouch(AB_Planet other){
		double radial_distance = Math.abs(this.distanceToStar() - other.distanceToStar());
		double euclid_distance = this.distanceToPlanet(other);
		
		if(Math.abs(this.speed - other.speed) > EPSILON){
			// Planets are moving relative to eachother
			return (radial_distance <= other.well);
		}else{
			// Planets are not moving relative to eachother
			return (euclid_distance <= other.well);
		}
	}
	
	/**
	 * Calculate the time to reach other, when this planet has been reached in it's best time thus far.
	 *
	 * This is where all the magic happens
	 */
	public double timeToReach(AB_Planet other){
		if(this.best_time == Double.MAX_VALUE){
			throw new RuntimeException("INSANITY: Source planet cannot be reached yet");
		}
		if(!this.canTouch(other)){
			return Double.MAX_VALUE;
		}
		
		// Calculate positions at the critical time
		double t = this.best_time;
		double self_r = this.distanceToStar();
		double self_angle = this.angleAtTime(t);		
		double self_x = self_r*Math.cos(self_angle);
		double self_y = self_r*Math.sin(self_angle);		
		double other_r = other.distanceToStar();
		double other_angle = other.angleAtTime(t);		
		double other_x = other_r*Math.cos(other_angle);
		double other_y = other_r*Math.sin(other_angle);		
		
		// Check if within the other planet's gravity well at time t
		double x_diff = self_x - other_x;
		double y_diff = self_y - other_y;
		double total_well = this.well + other.well;
		double euclid_distance =  Math.sqrt((x_diff*x_diff) + (y_diff*y_diff));
		if(euclid_distance <= other.well){
			return this.best_time;
		}
		
		// THE IMPORTANT PART: Calculate the moment they _will_ intersect
		// First, we will calculate the angle difference when just inside the gravity well
		// by using the cosine rule.
		double angle_limit;
		if(Math.abs(Math.abs(self_r - other_r) - other.well) < EPSILON){
			// Special case: only one touching point
			angle_limit = 0;
		}else{
			angle_limit = Math.abs(Math.acos((Math.pow(self_r, 2) + Math.pow(other_r, 2) - Math.pow(other.well, 2))/(2*self_r*other_r)));
		}
		
		// We also want to know the number of radians 'self' is ahead of 'other'
		double angle_diff = self_angle - other_angle;
		while(angle_diff >= 2*Math.PI){
			angle_diff -= 2*Math.PI;
		}
		while(angle_diff < 0){
			angle_diff += 2*Math.PI;
		}
		
		// Just some check to make sure my solution doesn't go insane...
		if(Math.abs(angle_diff) < angle_limit){
			throw new RuntimeException("INSANITY: Planet should already be within reach (a_diff=" + angle_diff + "; a_limit=" + angle_limit + ")");
		}
		
		// Now we have two options, depending on which planet is faster...
		double target_angle_diff;
		if(this.speed > other.speed){
			// 1) current planet is faster, so angle difference increases... aim for the 2PI - angle_limit
			target_angle_diff = 2*Math.PI - angle_limit;
		}else{
			// 2) other planet is faster, so angle decreases... aim for the angle_limit
			target_angle_diff = angle_limit;
		}
		
		// Calculate time needed to reach angle_limit
		double relative_speed = this.speed - other.speed;
		double time_to_wait = (target_angle_diff - angle_diff) / relative_speed;
		
		// Just some check to make sure my solution doesn't go insane...
		if(time_to_wait < 0){
			throw new RuntimeException("INSANITY: Negative time is a bit strange");
		}
		
		return t + time_to_wait;
	}
}

/**
 * Quick-'n-dirty framework to simplify some common tasks
 */
abstract class AB_ProblemSolver{	
	protected Scanner in;
	protected PrintStream out;
	protected PrintStream err;
	
	/**
	 * For quickly switching between showing or hiding debug output
	 */
	protected boolean DEBUG = false;
	
	/**
	 * Default input file, can be overridden by first command line argument
	 */
	protected String default_infile = "g.in";

	public AB_ProblemSolver(String[] args){
		try{
			this.in = new Scanner(System.in);
			this.out = System.out;
			this.err = System.err;
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public void run() throws Exception{
		int num_cases = this.in.nextInt();
		this.in.nextLine();
		
		for(int i = 0; i < num_cases; i++){
			this.debug("\r\n=== Testcase " + i + " === ");
			this.runCase();
		}
	}
	
	protected abstract void runCase() throws Exception;
	
	/**
	 * Only outputs text (to stderr) when DEBUG is set to true
	 */
	protected void debug(String str){
		if(DEBUG){
			this.err.println(str);
		}
	}
	
	protected void debug(int i){
		this.debug(String.valueOf(i));
	}
	
	protected void debugList(ArrayList list){
		if(DEBUG){
			int s = list.size(); 
			
			this.err.print("[");
			for(int i = 0; i < s; i++){
				this.err.print(list.get(i).toString());
				
				if(i != s-1){
					this.err.print(",");
				}
			}
			this.err.println("]");
		}
	}
	
	protected void debugMatrix(int[][] matrix){
		if(DEBUG){
			for(int i = 0; i < matrix.length; i++){
				for(int j = 0; j < matrix[i].length; j++){
					String element = String.valueOf(matrix[i][j]);
					element = "     ".substring(element.length()) + element;
					this.err.print(element);
				}
				this.err.println();
			}
		}
	}
}
