#include <bits/stdc++.h>
using namespace std;
struct mat {
  double a[3][3];
};
mat e, t, r;
int n, m;
long double F[600001];
struct node {
  node* son[2];
  mat m, d;
};
node STK[700001], *head = STK;
node* Root;
mat operator*(const mat& p1, const mat& p2) {
  mat p;
  memset(p.a, 0, sizeof(p));
  for (int k = 0; k < 3; k++)
    for (int i = 0; i < 3; i++)
      for (int j = 0; j < 3; j++) p.a[i][j] += p1.a[i][k] * p2.a[k][j];
  return p;
}
bool operator!=(const mat& p1, const mat& p2) {
  for (int i = 0; i < 3; i++)
    for (int j = 0; j < 3; j++)
      if (p1.a[i][j] != p2.a[i][j]) return true;
  return false;
}
void update_mat(node* p, mat x) {
  p->m = p->m * x;
  p->d = p->d * x;
}
void pushdown(node* p) {
  if (p->m != e) {
    if (p->son[0]) update_mat(p->son[0], p->m);
    if (p->son[1]) update_mat(p->son[1], p->m);
    p->m = e;
  }
}
void Modify(node* p, int L, int R, int l, int r, const mat& x) {
  if (l > r) return;
  pushdown(p);
  if (L == l && R == r) {
    update_mat(p, x);
    return;
  }
  int mid = (L + R) >> 1;
  if (r <= mid)
    Modify(p->son[0], L, mid, l, r, x);
  else if (l > mid)
    Modify(p->son[1], mid + 1, R, l, r, x);
  else
    Modify(p->son[0], L, mid, l, mid, x),
        Modify(p->son[1], mid + 1, R, mid + 1, r, x);
}
mat Query(node* p, int l, int r, int pos) {
  pushdown(p);
  if (l == r) return p->d;
  int mid = (l + r) >> 1;
  if (pos <= mid)
    return Query(p->son[0], l, mid, pos);
  else
    return Query(p->son[1], mid + 1, r, pos);
}
node* Build_tree(int l, int r) {
  if (l > r) return (node*)(0);
  node* p = ++head;
  p->son[0] = p->son[1] = 0;
  p->d = p->m = e;
  if (l == r) return p;
  int mid = (l + r) >> 1;
  p->son[0] = Build_tree(l, mid);
  p->son[1] = Build_tree(mid + 1, r);
  return p;
}
void Add(int x, long double d) {
  for (; x <= n; x += (x & -x)) F[x] += d;
}
long double Sub(int x) {
  long double sum = 0;
  for (; x; x -= (x & -x)) sum += F[x];
  return sum;
}
int main() {
  int x, type;
  double l;
  memset(e.a, 0, sizeof(e.a));
  memset(t.a, 0, sizeof(t.a));
  memset(r.a, 0, sizeof(r.a));
  r.a[2][2] = 1;
  for (int i = 0; i < 3; i++) e.a[i][i] = t.a[i][i] = 1;
  scanf("%d %d", &n, &m);
  Root = Build_tree(1, n);
  for (int i = 1; i <= m; i++) {
    scanf("%d", &type);
    if (type == 1) {
      scanf("%d %lf", &x, &l);
      long double ang = Sub(x);
      long double dx = l * cos(ang), dy = l * sin(ang);
      t.a[2][0] = (double)dx, t.a[2][1] = (double)dy;
      Modify(Root, 1, n, x, n, t);
    } else {
      scanf("%d %lf", &x, &l);
      long double da = -(long double)l / 180.0 * acos(-1.0);
      long double dx, dy;
      if (x == 1)
        dx = 0, dy = 0;
      else {
        mat tmp = Query(Root, 1, n, x - 1);
        dx = (long double)(x - 1) * tmp.a[0][0] + tmp.a[2][0];
        dy = (long double)(x - 1) * tmp.a[0][1] + tmp.a[2][1];
      }
      t.a[2][0] = -(double)dx, t.a[2][1] = -(double)dy;
      Modify(Root, 1, n, x, n, t);
      r.a[0][0] = cos(da), r.a[0][1] = sin(da);
      r.a[1][0] = -sin(da), r.a[1][1] = cos(da);
      Modify(Root, 1, n, x, n, r);
      t.a[2][0] = dx, t.a[2][1] = dy;
      Modify(Root, 1, n, x, n, t);
      Add(x, da);
    }
    mat tmp = Query(Root, 1, n, n);
    long double dx = (long double)(n)*tmp.a[0][0] + tmp.a[2][0];
    long double dy = (long double)(n)*tmp.a[0][1] + tmp.a[2][1];
    printf("%.9f %.9f\n", (double)dx, (double)dy);
  }
  return 0;
}
