#include<cmath>
#include<cstdio>
#include<vector>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const double EPS=1e-7;

template<class T>
struct point{
	T x,y;
	point operator+(const point &a)const{ return (point){x+a.x,y+a.y}; }
	point operator-(const point &a)const{ return (point){x-a.x,y-a.y}; }
};

template<class T>
point<T> operator*(T c,const point<T> &a){ return (point<T>){c*a.x,c*a.y}; }

template<class T>
point<double> operator/(const point<T> &a,double c){
	return (point<double>){a.x/c,a.y/c};
}

bool operator==(const point<double> &a,const point<double> &b){
	return abs(a.x-b.x)<EPS && abs(a.y-b.y)<EPS;
}

bool operator!=(const point<double> &a,const point<double> &b){
	return abs(a.x-b.x)>EPS || abs(a.y-b.y)>EPS;
}

bool operator<(const point<double> &a,const point<double> &b){
	return abs(a.x-b.x)>EPS ? a.x<b.x : a.y<b.y;
}

template<class T>
struct line{
	point<T> a,b;
};

template<class T>
struct segment{
	point<T> a,b;
	operator line<T>(){ return (line<T>){a,b}; }
};

template<class T>
struct polygon:vector< point<T> >{
	polygon(){}
	polygon(int n):vector< point<T> >(n){}
};

template<class T>
T dot(const point<T> &a,const point<T> &b){ return a.x*b.x+a.y*b.y; }

template<class T>
T cross(const point<T> &a,const point<T> &b){ return a.x*b.y-a.y*b.x; }

enum {CCW=1,CW=-1,ON=0};
int ccw(const point<double> &a,const point<double> &b,const point<double> &c){
	double rdir=cross(b-a,c-a);
	if(rdir> EPS) return CCW;
	if(rdir<-EPS) return CW;
	return ON;
}

template<class T>
point<double> get_intersect(const line<T> &L1,const line<T> &L2){
	double a1=cross(L1.b-L1.a,L2.b-L2.a);
	double a2=cross(L1.b-L1.a,L1.b-L2.a);
	if(abs(a1)<EPS) return L1.a; // L1 == L2
	return L2.a+a2/a1*(L2.b-L2.a);
}

bool intersect(const line<double> &L,const segment<double> &S){
	return cross(L.b-L.a,S.a-L.a)*cross(L.b-L.a,S.b-L.a)<EPS;
}

template<class T>
double dist(const point<T> &a,const point<T> &b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

template<class T>
bool cover(const polygon<T> &G,const point<T> &p){
	int n=G.size();
	bool res=false;
	rep(i,n){
		point<T> v1=G[i]-p,v2=G[(i+1)%n]-p;
		if(v1.y>v2.y) swap(v1,v2);
		if(v1.y<EPS && EPS<v2.y && cross(v1,v2)>EPS) res=!res;
		if(abs(cross(v1,v2))<EPS && dot(v1,v2)<EPS) return true;
	}
	return res;
}

int n;
polygon<double> G;

// 直線 L と G の辺 S が点 G[k] で交わっているとき、G[k] を候補点として採用するかどうかを判定する
bool is_candidate(const line<double> &L,const segment<double> &S,int k){
	point<double> prev=G[(k-1+n)%n],next=G[(k+1)%n];
	int c1=ccw(L.a,L.b,prev);
	int c2=ccw(L.a,L.b,next);
	if(c1==CCW && c2==CW || c1==CW && c2==CCW) return true;
	return ccw(prev,G[k],next)==CCW;
}

double solve(){
	double ans=0;
	rep(j,n) rep(i,j) {
		vector< point<double> > P;
		line<double> L={G[i],G[j]};
		rep(k,n){
			segment<double> S={G[k],G[(k+1)%n]};
			if(intersect(L,S)){
				point<double> p=get_intersect((line<double>)S,L);
				if(p!=S.a && p!=S.b
				|| p==S.a && is_candidate(L,S,k)
				|| p==S.b && is_candidate(L,S,(k+1)%n)) P.push_back(p);
			}
		}

		sort(P.begin(),P.end());

		rep(k,(int)P.size()-1){
			point<double> p=P[k],q=P[k+1],r=(p+q)/2;
			if(cover(G,r)) ans=max(ans,dist(p,q));
		}
	}

	return ans;
}

int main(){
	for(int T=1;scanf("%d",&n),n;T++){
		G.resize(n);
		rep(i,n) scanf("%lf%lf",&G[i].x,&G[i].y);
		printf("Case %d: %.9f\n",T,solve());
	}

	return 0;
}

Measured memory_bytes: 872