Problem:
かくれんぼう

たろう君はかくれんぼうが苦手です。隠れるとすぐ見つかっちゃうし、隠れている子をなかなか見つけることができません。見かねたお父さんは、超高性能位置探索システムを作ってくれました。これを使うと自分の位置を含めて、友達の位置を正確に知ることができます。鬼になったら、隠れている子を探すことが簡単にできるようになりました。

たろう君はさらにこのシステムを進化させ、鬼から自分が見えるか否かを判定する機能を付加することを思いつきました。これができれば、「もういいかい」と言われても、見える位置にいれば「まあだだよ」だし、見えない位置にいれば「もういいよ」ですね。いつも遊んでいる公園には大小さまざまな円筒形の壁があります。この壁は外からは中は見えないし、中から外も見えません。鬼と一緒に中に入ると別の壁がなければ見えちゃいます。

たろう君はアイデアはいいのですが、ソフトを作るのが苦手です。そこで親友のあなたはたろう君に代わって、「鬼から見えないこと確認システム」のソフトウェアを作ることになりました。公園の壁は固定されていますが、たろう君と鬼のいろいろな位置情報に対して見えるか否かを判定する必要があります。

公園にある壁の情報(中心の座標 (wx, wy) と 半径 r) とたろう君と鬼の位置情報(たろう君の位置の座標 (tx, ty) と鬼の位置の座標 (sx, sy) ) を入力とし、その位置で鬼からたろう君が見えるか否かを判定するプログラムを作成してください。

なお、鬼からたろう君が見える場合には Danger、見えない場合には Safe と出力してください。鬼とたろう君の位置を結んだ線分上に壁がある場合には見えないものとし、鬼もたろう君も壁の上にはいないものとします。

Input

複数のデータセットが与えられます。各データセットは以下の形式で与えられます。

n
wx1 wy1 r1
wx2 wy2 r2
:
wxn wyn rn
m
tx1 ty1 sx1 sy1
tx2 ty2 sx2 sy2
:
txm tym sxm sym

1 行目に円筒形の壁の数 n (0 ≤ n ≤ 100)、続く n 行に壁 i の中心の座標を表す整数 wxi, wyi (0 ≤ wxi, wyi ≤ 255) と半径を表す整数 ri (1 ≤ ri ≤ 255) が与えられます。

続く行にたろう君と鬼の位置情報の個数 m (m ≤ 100)、続く m 行に位置情報 i のたろう君の位置の座標を表す整数 txi, tyi (0 ≤ txi, tyi ≤ 255) と鬼の位置の座標を表す整数 sxi, syi (0 ≤ sxi, syi ≤ 255) が与えられます。

また、円筒形の壁の一部だけが公園にあるということはなく、全ての壁は円筒として、公園の内部に入っています。

n が 0 のとき入力の終わりを示します。データセットの数は 20 を超えません。

Output

各データセットについて、位置情報 i の判定結果 Danger または Safe を i 行目に出力してください。

Sample Input

3
6 6 3
19 7 4
21 8 1
6
5 4 2 11
12 4 2 11
11 9 2 11
14 3 20 5
17 9 20 5
20 10 20 5
0

Output for the Sample Input

Safe
Safe
Danger
Safe
Danger
Safe

Solution in JAVA (judge verdict: Accepted)

import java.util.*;
import java.lang.*;
import java.math.*;
import java.io.*;

// AC
public class Main{

	Scanner sc=new Scanner(System.in);

	int INF=1<<28;
	double EPS=1e-9;

	int n, m;
	P[] cs;
	int[] rs;
	P t, s;

	void run(){
		for(;;){
			n=sc.nextInt();
			if(n==0){
				break;
			}
			cs=new P[n];
			rs=new int[n];
			for(int i=0; i<n; i++){
				int x=sc.nextInt();
				int y=sc.nextInt();
				rs[i]=sc.nextInt();
				cs[i]=new P(x, y);
			}
			m=sc.nextInt();
			for(int i=0; i<m; i++){
				int tx=sc.nextInt();
				int ty=sc.nextInt();
				int sx=sc.nextInt();
				int sy=sc.nextInt();
				t=new P(tx, ty);
				s=new P(sx, sy);
				solve();
			}
		}
	}

	void solve(){
		boolean safe=false;
		for(int i=0; i<n; i++){
			P[] ps=isCL(cs[i], rs[i], t, s);
			for(P p : ps){
				if(between(t.x, s.x, p.x)&&between(t.y, s.y, p.y)){
					safe=true;
				}
			}
		}
		println(safe?"Safe":"Danger");
	}

	boolean between(double x1, double x2, double x){
		return (x1<x+EPS&&x<x2+EPS)||(x1+EPS>x&&x+EPS>x2);
	}

	P[] isCL(P c, double r, P p1, P p2){
		double x=p1.sub(c).dot(p2.sub(p1));
		double y=p2.sub(p1).abs2();
		double d=x*x-y*(p1.sub(c).abs2()-r*r);
		if(d<-EPS)
			return new P[0];
		if(d<0)
			d=0;
		P q1=p1.sub(p2.sub(p1).mul(x/y));
		P q2=p2.sub(p1).mul(Math.sqrt(d)/y);
		return new P[]{q1.sub(q2), q1.add(q2)};
	}

	class P{
		double x, y;

		P(){
			this(0, 0);
		}

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

		P add(P p){
			return new P(x+p.x, y+p.y);
		}

		P sub(P p){
			return new P(x-p.x, y-p.y);
		}

		P mul(double m){
			return new P(x*m, y*m);
		}

		P div(double d){
			return new P(x/d, y/d);
		}

		double abs(){
			return Math.sqrt(abs2());
		}

		double abs2(){
			return x*x+y*y;
		}

		double arg(){
			return Math.atan2(y, x);
		}

		// inner product
		double dot(P p){
			return x*p.x+y*p.y;
		}

		// outer product
		double det(P p){
			return x*p.y-y*p.x;
		}

		P rot90(){
			return new P(-y, x);
		}

		// conjugation
		P conj(){
			return new P(x, -y);
		}
	}

	void debug(Object... os){
		System.err.println(Arrays.deepToString(os));
	}

	void print(String s){
		System.out.print(s);
	}

	void println(String s){
		System.out.println(s);
	}

	public static void main(String[] args){
		// System.setOut(new PrintStream(new BufferedOutputStream(System.out)));
		new Main().run();
	}
}