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.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
public class Main {
	private	static	BufferedReader	br = null;

	static {
		br = new BufferedReader(new InputStreamReader(System.in));
	}
 
    /**
     * @param args
     */
	public static void main(String[] args) {
		int			cc = 0;
		int			lc = 0;
		Circle[]	cs = null;
		Line[]		ls = null;

		while ((cc = parseCnt()) != 0) {
			cs = new Circle[cc];
			for (int i = 0; i < cs.length; i++) {
				cs[i] = parseCircle();
			}

			lc = parseCnt();
			ls = new Line[lc];
			for (int i = 0; i < ls.length; i++) {
				ls[i] = parseLine();
				solve(cs, ls[i]);
			}
		}
	}

	private static void solve(Circle[] cs, Line ln) {
		double	dk = 0.0;
		double	xp = 0.0;
		double	yp = 0.0;
		double	sp = 0.0;
		double	ds = 0.0;
		boolean	dg = true;
		Line	lt = null;

		for (int i = 0; i < cs.length && dg; i++) {
			dk = (-1.0)*(ln.da*cs[i].dx+ln.db*cs[i].dy+ln.dc)/(ln.da*ln.dvx+ln.db*ln.dvy);
			sp = (cs[i].dr*cs[i].dr)-(dk*dk);
			if (sp >= 0) {
				xp = cs[i].dx+dk*ln.dvx;
				yp = cs[i].dy+dk*ln.dvy;
				ds = Math.sqrt(sp);
				lt = new Line(xp+ds*ln.dex, yp+ds*ln.dey, xp-ds*ln.dex, yp-ds*ln.dey);

				{
					boolean	i1 = lt.isInner(ln.dxs, ln.dys);
					boolean	i2 = lt.isInner(ln.dxe, ln.dye);

					if (i1 != i2) {
						dg = false;
					} else if (!i1 && !i2) {
						dg = (lt.getDirection(ln.dxs, ln.dys) == lt.getDirection(ln.dxe, ln.dye));
					} else {
						dg = Math.abs(ds*ln.dex) >= 1e-6 || Math.abs(ds*ln.dey) >= 1e-6;
					}
				}
			}
		}

		System.out.println((dg) ? "Danger" : "Safe");
	}

	private static Line parseLine() {
		Line	lin = null;
		String	str = null;

		if ((str = parseStdin()) != null) {
			String[]	lines = str.split(" ");
			lin = new Line(Integer.parseInt(lines[0]), Integer.parseInt(lines[1]), Integer.parseInt(lines[2]), Integer.parseInt(lines[3]));
		}

		return lin;
	}

	private static Circle parseCircle() {
		Circle	cir = null;
		String	str = null;

		if ((str = parseStdin()) != null) {
			String[]	lines = str.split(" ");
			cir = new Circle(Integer.parseInt(lines[0]), Integer.parseInt(lines[1]), Integer.parseInt(lines[2]));
		}

		return cir;
	}

	private static int parseCnt() {
		int		cnt = 0;
		String	str = null;

		if ((str = parseStdin()) != null) {
			cnt = Integer.parseInt(str);
		}

		return cnt;
	}

	private static String parseStdin() {
		String  stdin = null;

		try {
			String  tmp = br.readLine();
			if (tmp != null) {
				if (!tmp.isEmpty()) stdin = tmp;
			}
		}
		catch (IOException e) {}

		return stdin;
	}
}

class Circle {
	public	double	dx = 0.0;
	public	double	dy = 0.0;
	public	double	dr = 0.0;

	public Circle(double x, double y, double r) {
		dx = x;
		dy = y;
		dr = r;
	}
}

class Line {
	public	double	dxs  = 0.0;
	public	double	dys  = 0.0;
	public	double	dxe  = 0.0;
	public	double	dye  = 0.0;
	public	double	dex  = 0.0;
	public	double	dey  = 0.0;
	public	double	dvx  = 0.0;
	public	double	dvy  = 0.0;
	public	double	da   = 0.0;
	public	double	db   = 0.0;
	public	double	dc   = 0.0;
	public	double	dl   = 0.0;
	public	double	dxmn = 0.0;
	public	double	dxmx = 0.0;
	public	double	dymn = 0.0;
	public	double	dymx = 0.0;

	public Line(double xs, double ys, double xe, double ye) {
		dxs  = xs;
		dys  = ys;
		dxe  = xe;
		dye  = ye;
		da   = dye-dys;
		db   = dxs-dxe;
		dc   = (-1.0)*(da*xs+db*ys);
		dl   = Math.sqrt(da*da+db*db);
		dex  = (dxe-dxs) / dl;
		dey  = (dye-dys) / dl;
		dvx  = dey*(-1.0);
		dvy  = dex;
		dxmn = Math.min(dxs, dxe);
		dxmx = Math.max(dxs, dxe);
		dymn = Math.min(dys, dye);
		dymx = Math.max(dys, dye);
	}

	public boolean isInner(double x, double y) {
		return (dxmn <= x && x <= dxmx && dymn <= y && y <= dymx);
	}

	public int getDirection(double x, double y) {
		final	int	D_N = 0;
		final	int	D_U = 1;
		final	int	D_D = 2;
		final	int	D_L = 4;
		final	int	D_R = 8;
				int	dir = D_N;

		dir += (x < dxmn) ? D_L : D_N;
		dir += (x > dxmx) ? D_R : D_N;
		dir += (y < dymn) ? D_U : D_N;
		dir += (y > dymx) ? D_D : D_N;

		return dir;
	}
}