// Arup Guha
// 10/22/2013
// Solution to 2008 MCPC Regional Problem G: Line and Circle Maze

import java.util.*;

// So we can store lines and circles in the same array and intersect them...
abstract class geo {
	abstract public pt[] intersect(lineseg other);
	abstract public pt[] intersect(circle other);
	abstract public double dist(pt a, pt b);
}

public class g {

	public static void main(String[] args) {

		Scanner stdin = new Scanner(System.in);
		String s = stdin.next();
		int loop = 1;

		// Go through each case.
		while (!s.equals("*")) {

			ArrayList<geo> objects = new ArrayList<geo>();

			// Read in all the objects.
			while (!s.equals("*")) {

				if (s.equals("L") ) {
					double x1 = stdin.nextDouble();
					double y1 = stdin.nextDouble();
					double x2 = stdin.nextDouble();
					double y2 = stdin.nextDouble();
					objects.add(new lineseg(new pt(x1,y1), new pt(x2,y2)));
				}
				else {
					double x = stdin.nextDouble();
					double y = stdin.nextDouble();
					double r = stdin.nextDouble();
					objects.add(new circle(x,y,r));
				}
				s = stdin.next();
			}

			// Solve and go to the next case.
			System.out.printf("Case %d: %.1f\n", loop, solve(objects));
			loop++;
			s = stdin.next();
		}
	}

	public static double solve(ArrayList<geo> objects) {

		// Store all intersections.
		ArrayList<edge> edges = new ArrayList<edge>();

		TreeMap<pt,Integer> map = new TreeMap<pt,Integer>();
		int index = 0;

		// Find everything that intersects with object i.
		for (int i=0; i<objects.size(); i++) {

			// Extra points get added for line segments.
			ArrayList<pt> thesePts = new ArrayList<pt>();
			if (objects.get(i) instanceof lineseg) {
				pt tmpa = ((lineseg)objects.get(i)).start;
				pt tmpb = ((lineseg)objects.get(i)).end;

				thesePts.add(tmpa);
				thesePts.add(tmpb);
				if (!map.containsKey(tmpa)) map.put(tmpa, index++);
				if (!map.containsKey(tmpb)) map.put(tmpb, index++);
			}

			// Try matching everything with object i.
			for (int j=0; j<objects.size(); j++) {
				if (i == j) continue;

				pt[] tmp = null;
				if (objects.get(j) instanceof lineseg)
					tmp = objects.get(i).intersect((lineseg)objects.get(j));
				else
					tmp = objects.get(i).intersect((circle)objects.get(j));

				// Nothing to see here!
				if (tmp == null) continue;

				// Go through each new intersection, adding them to our map, if necessary.
				for (int k=0; k<tmp.length; k++) {
					if (!map.containsKey(tmp[k])) {
						map.put(tmp[k], index);
						thesePts.add(tmp[k]);
						index++;
					}
					else {
						thesePts.add(tmp[k]);
					}
				}
			}

			// Add in an edge between each item on this object that's an intersection point.
			for (int j=0; j<thesePts.size(); j++) {
				for (int k=0; k<thesePts.size(); k++) {
					if (j == k) continue;
					edges.add(new edge(map.get(thesePts.get(j)), map.get(thesePts.get(k)), objects.get(i).dist( thesePts.get(j), thesePts.get(k))));
				}
			}

		}

		// Form graph, calculate girth and return.
		return girth(edges);
	}

	// Returns the girth of the graph specified by edges.
	public static double girth(ArrayList<edge> edges) {

		// Get vertex count.
		int maxV = 0;
		for (int i=0; i<edges.size(); i++) {
			if (edges.get(i).v1 > maxV) maxV = edges.get(i).v1;
			if (edges.get(i).v2 > maxV) maxV = edges.get(i).v2;
		}

		// Set up adjacency array.
		int n = maxV+1;
		double[][] adj = new double[n][n];
		for (int i=0; i<n; i++) {
			Arrays.fill(adj[i], 1000.0);
			adj[i][i] = 0;
		}

		// Form the array.
		for (int i=0; i<edges.size(); i++)
			adj[edges.get(i).v1][edges.get(i).v2] = edges.get(i).w;

		// Finally, we run Floyd's...
		for (int k=0; k<n; k++)
			for (int i=0; i<n; i++)
				for (int j=0; j<n; j++)
					if (adj[i][k] + adj[k][j] < adj[i][j])
						adj[i][j] = adj[i][k] + adj[k][j];

		// Get maximum distance of the valid distances.
		double maxD = 0;
		for (int i=0; i<n; i++)
			for (int j=0; j<n; j++)
				if (adj[i][j] < 999 && adj[i][j] > maxD)
					maxD = adj[i][j];
		return maxD;
	}
}

class pt implements Comparable<pt> {

	public double x;
	public double y;

	public pt(double myx, double myy) {
		x = myx;
		y = myy;
	}

	public pt getVect(pt other) {
		return new pt(other.x-this.x, other.y-this.y);
	}

	public double dist(pt other) {
		return Math.sqrt(Math.pow(other.x-this.x,2) + Math.pow(other.y-this.y,2));
	}

	public double getAngle() {
		return Math.atan2(y,x);
	}

	public pt move(pt other) {
		return new pt(x+other.x, y+other.y);
	}

	// So we can implement the TreeMap to store what we've seen.
	public int compareTo(pt other) {

		// Build in tolerances for doubles...
		if (Math.abs(this.x - other.x) > 1e-9) {
			if (this.x < other.x) return -1;
			return 1;
		}

		if (Math.abs(this.y - other.y) > 1e-9) {
			if (this.y < other.y) return -1;
			return 1;
		}

		return 0;
	}
}

class lineseg extends geo {

	public pt start;
	public pt end;
	public pt vect;

	public lineseg(pt s, pt e) {
		start = s;
		end = e;
		vect = start.getVect(end);
	}

	public double dist(pt a, pt b) {
		return a.dist(b);
	}
	public pt[] intersect(lineseg other) {

		// Setting up system of equations for line segment intersection.
		double den = det(vect.x, -other.vect.x, vect.y, -other.vect.y);
		double num1 = det(other.start.x-start.x, -other.vect.x, other.start.y-start.y, -other.vect.y);
		double num2 = det(vect.x, other.start.x-start.x, vect.y, other.start.y-start.y);

		// No solution.
		if (den == 0) return null;
		double lambda1 = num1/den;
		double lambda2 = num2/den;

		// No segment solution.
		if (lambda1 < 0 || lambda1 > 1 || lambda1 < 0 || lambda2 > 1) return null;

		// Here is our answer.
		pt[] ans = new pt[1];
		ans[0] = new pt(start.x+lambda1*vect.x, start.y+lambda1*vect.y);
		return ans;
	}

	// We did this already...so this is just a wrapper function.
	public pt[] intersect(circle other) {
		return other.intersect(this);
	}

	public static double det(double a, double b, double c, double d) {
		return a*d - b*c;
	}
}

class circle extends geo {

	public pt center;
	public double radius;

	public circle(double x, double y, double r) {
		center = new pt(x,y);
		radius = r;
	}

	// Returns the point on this circle at angle (from the center).
	public pt getPt(double angle) {
		return new pt(center.x+radius*Math.cos(angle), center.y+radius*Math.sin(angle));
	}

	// Returns the two angles of intersection or null, if
	// there is no intersection.
	public pt[] intersect(circle other) {

		double dToC = center.dist(other.center);

		// null case is pretty easy.
		if (dToC > radius + other.radius) return null;

		// Direction to other center.
		pt vect = center.getVect(other.center);

		if (Math.abs(vect.x) < 1e-9 && Math.abs(vect.y) < 1e-9) return null;

		double angle = Math.acos((radius*radius+dToC*dToC-other.radius*other.radius)/(2*radius*dToC));

		// Figure out both points from the angles and return.
		pt[] ans = new pt[2];
		double angle1 = vect.getAngle() + angle;
		double angle2 = vect.getAngle() - angle;
		ans[0] = new pt(center.x+radius*Math.cos(angle1), center.y+radius*Math.sin(angle1));
		ans[1] = new pt(center.x+radius*Math.cos(angle2), center.y+radius*Math.sin(angle2));
		return ans;
	}

	// a and b must be on this object - returns the shortest distance from a to b ON the circle.
	public double dist(pt a, pt b) {

		double angle1 = center.getVect(a).getAngle();
		double angle2 = center.getVect(b).getAngle();
		double diff = angle1 - angle2;

		// Remap in two steps to an equivalent angle.
		if (diff < 0) diff += (2*Math.PI);
		if (diff > Math.PI) diff = 2*Math.PI - diff;
		return radius*diff;
	}

	public pt[] intersect(lineseg other) {

		// Useful constants that we square...
		double c1 = other.start.x-center.x;
		double c2 = other.start.y-center.y;

		// Coefficients of important quadratic.
		double a = other.vect.x*other.vect.x + other.vect.y*other.vect.y;
		double b = 2*(other.vect.x*c1 + other.vect.y*c2);
		double c = c1*c1+c2*c2 - radius*radius;

		double disc = b*b - 4*a*c;
		if (disc < 0) return null;

		// One intersection, maybe.
		if (disc == 0) {
			double lambda = -b/(2*a);
			if (lambda < 0 || lambda > 1) return null;

			// Find it and return.
			pt[] ans = new pt[1];
			ans[0] = new pt(other.start.x+lambda*other.vect.x, other.start.y+lambda*other.vect.y);
			return ans;
		}

		double lambda1 = (-b + Math.sqrt(disc))/(2*a);
		double lambda2 = (-b - Math.sqrt(disc))/(2*a);

		// Find how many intersections are on the segment.
		int size = 0;
		if (lambda1 >= 0 && lambda1 <= 1) size++;
		if (lambda2 >= 0 && lambda2 <= 1) size++;
		if (size == 0) return null;

		// Store them and return.
		pt[] ans = new pt[size];
		int i = 0;
		if (lambda1 >= 0 && lambda1 <= 1)
			ans[i++] = new pt(other.start.x+lambda1*other.vect.x, other.start.y+lambda1*other.vect.y);
		if (lambda2 >= 0 && lambda2 <= 1)
			ans[i] = new pt(other.start.x+lambda2*other.vect.x, other.start.y+lambda2*other.vect.y);

		return ans;
	}
}

class edge {

	public int v1;
	public int v2;
	public double w;

	public edge(int a, int b, double weight) {
		v1 = a;
		v2 = b;
		w = weight;
	}
}