Problem: Spinning tops are one of the most popular and the most traditional toys. Not only spinning them, but also making one’s own is a popular enjoyment.

One of the easiest way to make a top is to cut out a certain shape from a cardboard and pierce an axis stick through its center of mass. Professionally made tops usually have three dimensional shapes, but in this problem we consider only two dimensional ones.

Usually, tops have rotationally symmetric shapes, such as a circle, a rectangle (with 2-fold rotational symmetry) or a regular triangle (with 3-fold symmetry). Although such symmetries are useful in determining their centers of mass, they are not definitely required; an asymmetric top also spins quite well if its axis is properly pierced at the center of mass.

When a shape of a top is given as a path to cut it out from a cardboard of uniform thickness, your task is to find its center of mass to make it spin well. Also, you have to determine whether the center of mass is on the part of the cardboard cut out. If not, you cannot pierce the axis stick, of course.

Hints

An important nature of mass centers is that, when an object O can be decomposed into parts O1 , . . . , On with masses M1 , . . . , Mn , the center of mass of O can be computed by:

<image>

where Gk is the vector pointing the center of mass of Ok.

A circular segment with its radius r and angle θ (in radian) has its arc length s = rθ and its chord length c = r√(2 - 2cosθ). Its area size is A = r2(θ - sinθ)/2 and its center of mass G is y = 2r3sin3(θ/2)/(3A) distant from the circle center.

<image>

Figure 2: Circular segment and its center of mass

<image>

Figure 3: The first sample top



Input

The input consists of multiple datasets, each of which describes a counterclockwise path on a cardboard to cut out a top. A path is indicated by a sequence of command lines, each of which specifies a line segment or an arc.

In the description of commands below, the current position is the position to start the next cut, if any. After executing the cut specified by a command, the current position is moved to the end position of the cut made.

The commands given are one of those listed below. The command name starts from the first column of a line and the command and its arguments are separated by a space. All the command arguments are integers.


start x y


Specifies the start position of a path. This command itself does not specify any cutting; it only sets the current position to be (x, y).


line x y


Specifies a linear cut along a straight line from the current position to the position (x, y), which is not identical to the current position.


arc x y r


Specifies a round cut along a circular arc. The arc starts from the current position and ends at (x, y), which is not identical to the current position. The arc has a radius of |r|. When r is negative, the center of the circle is to the left side of the direction of this round cut; when it is positive, it is to the right side (Figure 1). The absolute value of r is greater than the half distance of the two ends of the arc. Among two arcs connecting the start and the end positions with the specified radius, the arc specified is one with its central angle less than 180 degrees.


close


Closes a path by making a linear cut to the initial start position and terminates a dataset. If the current position is already at the start position, this command simply indicates the end of a dataset.

The figure below gives an example of a command sequence and its corresponding path. Note that, in this case, the given radius -r is negative and thus the center of the arc is to the left of the arc. The arc command should be interpreted as shown in this figure and, not the other way around on the same circle.

<image>

Figure 1: A partial command sequence and the path specified so far

A dataset starts with a start command and ends with a close command.

The end of the input is specified by a line with a command end.

There are at most 100 commands in a dataset and at most 100 datasets are in the input. Absolute values of all the coordinates and radii are less than or equal to 100.

You may assume that the path does not cross nor touch itself. You may also assume that paths will never expand beyond edges of the cardboard, or, in other words, the cardboard is virtually infinitely large.

Output

For each of the dataset, output a line containing x- and y-coordinates of the center of mass of the top cut out by the path specified, and then a character ‘+’ or ‘-’ indicating whether this center is on the top or not, respectively. Two coordinates should be in decimal fractions. There should be a space between two coordinates and between the y-coordinate and the character ‘+’ or ‘-’. No other characters should be output. The coordinates may have errors less than 10-3 . You may assume that the center of mass is at least 10-3 distant from the path.

Example

Input

start 0 0
arc 2 2 -2
line 2 5
arc 0 3 -2
close
start -1 1
line 2 1
line 2 2
line -2 2
arc -3 1 -1
line -3 -2
arc -2 -3 -1
line 2 -3
line 2 -2
line -1 -2
line -1 -1
arc -1 0 2
close
start 0 0
line 3 0
line 5 -1
arc 4 -2 -1
line 6 -2
line 6 1
line 7 3
arc 8 2 -1
line 8 4
line 5 4
line 3 5
arc 4 6 -1
line 2 6
line 2 3
line 1 1
arc 0 2 -1
close
end


Output

1.00000 2.50000 +
-1.01522 -0.50000 -
4.00000 2.00000 +

Solution (in CPP):

Solution:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

using namespace std;

struct point_t {
	double x, y;
	point_t() { x = y = 0; }
	point_t(double tx, double ty) { x = tx, y = ty; }
	point_t operator+(const point_t &r) const { return point_t(x + r.x, y + r.y); }
	point_t operator-(const point_t &r) const { return point_t(x - r.x, y - r.y); }
	point_t operator*(const double &r) const { return point_t(x * r, y * r); }
	point_t operator/(const double &r) const { return point_t(x / r, y / r); }
	double l() const { return sqrt(x * x + y * y); }
	void read() { scanf("%lf%lf", &x, &y); }
};

const double eps = 1e-8;
const double pi = acos(-1.0);

int dblcmp(double x) {
	return x < -eps ? -1 : x > eps;
}

double dot(point_t p1, point_t p2) {
	return p1.x * p2.x + p1.y * p2.y;
}

double cross(point_t p1, point_t p2) {
	return p1.x * p2.y - p1.y * p2.x;
}

double dist(point_t p1, point_t p2) {
	p2 = p2 - p1;
	return p2.l();
}

point_t isLL(point_t a, point_t b, point_t c, point_t d, bool &parell) {
	point_t p1 = b - a, p2 = d - c;
	double a1 = p1.y, b1 = -p1.x, c1;
	double a2 = p2.y, b2 = -p2.x, c2;
	if (dblcmp(a1 * b2 - a2 * b1) == 0) {
		parell = true;
		return point_t();
	} else {
		parell = false;
		c1 = a1 * a.x + b1 * a.y;
		c2 = a2 * c.x + b2 * c.y;
		return point_t((c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1), (c1 * a2 - c2 * a1) / (b1 * a2 - b2 * a1));
	}
}

double area(point_t p1, point_t p2, point_t p3) {
	return cross(p2 - p1, p3 - p1);
}

double angle(point_t p1, point_t p2, point_t o) {
	p1 = p1 - o;
	p2 = p2 - o;
	double alpha = atan2(p1.y, p1.x);
	double beta = atan2(p2.y, p2.x);
	double ret = fabs(alpha - beta);
	if (dblcmp(ret - pi) > 0) ret = 2 * pi - ret;
	return ret;
}

const int maxn = 233;
int n, arc[maxn], side[maxn];
point_t seg[maxn][2], centre[maxn], o, o2;
double radius[maxn];

bool read() {
	n = 0; memset(arc, 0, sizeof(arc));
	point_t last;
	o2 = point_t(0, 0);
	while (true) {
		static char buf[16];
		scanf("%s", buf);
		if (strcmp(buf, "end") == 0) return false;
		if (strcmp(buf, "start") == 0) {
			o.read();
			last = o;
		} else if (strcmp(buf, "close") == 0) {
			++n;
			seg[n][0] = last;
			seg[n][1] = o;
			break;
		} else if (strcmp(buf, "line") == 0) {
			++n;
			seg[n][0] = last;
			seg[n][1].read();
			last = seg[n][1];
		} else {
			++n;
			seg[n][0] = last;
			seg[n][1].read();
			last = seg[n][1];
			arc[n] = true;
			scanf("%lf", radius + n);
			point_t middle = (seg[n][0] + seg[n][1]) / 2;
			point_t dir = seg[n][1] - seg[n][0];
			swap(dir.x, dir.y);
			if (radius[n] < 0) dir.x = -dir.x, side[n] = 1;
			else dir.y = -dir.y, side[n] = -1;
			radius[n] = fabs(radius[n]);
			dir = dir / dir.l();
			double len = sqrt(radius[n] * radius[n] - pow((seg[n][0] - seg[n][1]).l(), 2.0) / 4);
			dir = dir * len;
			centre[n] = middle + dir;
		}
	}
	for (int i = 1; i <= n; ++i) o2 = o2 + seg[i][0];
	o2 = o2 / n;
	return true;
}

pair<double, point_t> get_centre(point_t p1, point_t p2, bool arc = false, point_t centre = point_t(), double r = 0, int side = -1) {
	if (!arc) {
		double a = area(o, p1, p2) / 2;
		point_t c = (p1 + p2 + o) / 3;
		return make_pair(a, c);
	} else {
		double a = area(o, p1, p2) / 2;
		point_t c = (p1 + p2 + o) / 3;
		double alpha = angle(p1, p2, centre);
		double a2 = r * r * (alpha - sin(alpha)) / 2;
		int side2 = dblcmp(cross(p2 - p1, o - p1));
		// if (side2 == 0) puts("??");
		a2 = fabs(a2) * fabs(a) / a;
		if (side2 != side) a2 = -a2;
		double y = 2 * pow(r * sin(alpha / 2), 3.0) / fabs(3 * a2);
		point_t tmp = (p1 + p2) / 2 - centre;
		tmp = tmp / tmp.l();
		tmp = tmp * fabs(y);
		point_t c2 = tmp + centre;
		return make_pair(a + a2, (c * a + c2 * a2) / (a + a2));
	}
}

point_t cal() {
	double area = 0;
	point_t c;
	for (int i = 1; i <= n; ++i) {
		pair<double, point_t> pdp;
		if (!arc[i]) {
			pdp = get_centre(seg[i][0], seg[i][1]);
		} else {
			pdp = get_centre(seg[i][0], seg[i][1], true, centre[i], radius[i], side[i]);
		}
		area += pdp.first;
		c = c + pdp.second * pdp.first;
	}
	// printf("%.10lf\n", area);
	return c / area;
}

bool isinter(point_t a, point_t b, point_t c, point_t d) {
	if (dblcmp(max(a.x, b.x) - min(c.x, d.x)) < 0) return 0;
	if (dblcmp(max(c.x, d.x) - min(a.x, b.x)) < 0) return 0;
	if (dblcmp(max(a.y, b.y) - min(c.y, d.y)) < 0) return 0;
	if (dblcmp(max(c.y, d.y) - min(a.y, b.y)) < 0) return 0;
	int d1 = dblcmp(cross(c - a, b - a));
	int d2 = dblcmp(cross(d - a, b - a));
	int d3 = dblcmp(cross(a - c, d - c));
	int d4 = dblcmp(cross(b - c, d - c));
	if ((d1 * d2 < 0) && (d3 * d4 < 0)) return 1;
	if ((d1 * d2 <= 0 && d3 * d4 == 0) || (d1 * d2 == 0 && d3 * d4 <= 0)) return -1;
	return 0;
}

bool check(point_t p1, point_t p2, point_t p, point_t o) {
	double a1 = angle(p, p1, o);
	double a2 = angle(p, p2, o);
	double a3 = angle(p1, p2, o);
	return dblcmp(a1 + a2 - a3) == 0;
}

bool isinter(point_t a, point_t b, point_t p1, point_t p2, point_t o, double r) {
	double x0 = o.x, y0 = o.y;
	double x1 = a.x, y1 = a.y;
	double x2 = b.x, y2 = b.y;
	double dx = x2 - x1, dy = y2 - y1;
	double A = dx * dx + dy * dy;
	double B = 2 * dx * (x1 - x0) + 2 * dy * (y1 - y0);
	double C = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) - r * r;
	double delta = B * B - 4 * A * C;
	if (dblcmp(delta) >= 0) {
		if (delta < 0) delta = 0;
		delta = sqrt(delta);
		double t1 = (-B - delta) / 2 / A;
		if (dblcmp(t1) >= 0) {
			point_t tmp = point_t(x1 + t1 * dx, y1 + t1 * dy);
			if (check(p1, p2, tmp, o)) return true;
		}
		double t2 = (-B + delta) / 2 / A;
		if (dblcmp(t2) >= 0) {
			point_t tmp = point_t(x1 + t2 * dx, y1 + t2 * dy);
			if (check(p1, p2, tmp, o)) return true;
		}
	}
	return false;
}

bool inside(point_t p) {
	point_t to = point_t(53245, 87684);
	int cnt = 0;
	for (int i = 1; i <= n; ++i) {
		if (arc[i]) {
			if (isinter(p, to, seg[i][0], seg[i][1], centre[i], radius[i])) ++cnt;
		} else {
			if (isinter(p, to, seg[i][0], seg[i][1])) ++cnt;
		}
	}
	if (cnt % 2 == 1) return true;
	return false;
}

int main() {
	while (read()) {
		o = point_t(53456, 67435);
		point_t centre = cal();
		printf("%.10lf %.10lf %c\n", centre.x, centre.y, inside(centre) ? '+' : '-');
	}
	return 0;
}