#include <bits/stdc++.h>
using namespace std;
int n;
struct mtr {
  double m[3][3];
  mtr() {
    m[0][0] = m[0][1] = m[0][2] = 0.0;
    m[1][0] = m[1][1] = m[1][2] = 0.0;
    m[2][0] = m[2][1] = m[2][2] = 0.0;
  }
};
mtr E;
vector<mtr> tree;
void MUL(mtr &mt1, mtr &mt2, mtr &result) {
  mtr res;
  res.m[0][0] = mt1.m[0][0] * mt2.m[0][0] + mt1.m[0][1] * mt2.m[1][0] +
                mt1.m[0][2] * mt2.m[2][0];
  res.m[0][1] = mt1.m[0][0] * mt2.m[0][1] + mt1.m[0][1] * mt2.m[1][1] +
                mt1.m[0][2] * mt2.m[2][1];
  res.m[0][2] = mt1.m[0][0] * mt2.m[0][2] + mt1.m[0][1] * mt2.m[1][2] +
                mt1.m[0][2] * mt2.m[2][2];
  res.m[1][0] = mt1.m[1][0] * mt2.m[0][0] + mt1.m[1][1] * mt2.m[1][0] +
                mt1.m[1][2] * mt2.m[2][0];
  res.m[1][1] = mt1.m[1][0] * mt2.m[0][1] + mt1.m[1][1] * mt2.m[1][1] +
                mt1.m[1][2] * mt2.m[2][1];
  res.m[1][2] = mt1.m[1][0] * mt2.m[0][2] + mt1.m[1][1] * mt2.m[1][2] +
                mt1.m[1][2] * mt2.m[2][2];
  res.m[2][0] = mt1.m[2][0] * mt2.m[0][0] + mt1.m[2][1] * mt2.m[1][0] +
                mt1.m[2][2] * mt2.m[2][0];
  res.m[2][1] = mt1.m[2][0] * mt2.m[0][1] + mt1.m[2][1] * mt2.m[1][1] +
                mt1.m[2][2] * mt2.m[2][1];
  res.m[2][2] = mt1.m[2][0] * mt2.m[0][2] + mt1.m[2][1] * mt2.m[1][2] +
                mt1.m[2][2] * mt2.m[2][2];
  swap(res, result);
}
void MUL(mtr &mt, int ind, vector<double> &result) {
  vector<double> res(3, 0.0);
  res[0] = mt.m[0][0] * (double)ind + mt.m[0][2];
  res[1] = mt.m[1][0] * (double)ind + mt.m[1][2];
  res[2] = mt.m[2][0] * (double)ind + mt.m[2][2];
  result.swap(res);
}
void push(int v, int tl, int tr) {
  if (tl + 1 < tr) {
    MUL(tree[v], tree[2 * v + 1], tree[2 * v + 1]);
    MUL(tree[v], tree[2 * v + 2], tree[2 * v + 2]);
    tree[v] = E;
  }
}
void move(int v, int tl, int tr, int l, int r, mtr &mv) {
  push(v, tl, tr);
  if (tl == l && tr == r) {
    MUL(mv, tree[v], tree[v]);
    return;
  }
  int tm = (tl + tr) / 2;
  if (tm >= r) {
    move(2 * v + 1, tl, tm, l, r, mv);
  } else if (tm <= l) {
    move(2 * v + 2, tm, tr, l, r, mv);
  } else {
    move(2 * v + 1, tl, tm, l, tm, mv);
    move(2 * v + 2, tm, tr, tm, r, mv);
  }
}
void query(int v, int tl, int tr, int ind, mtr &result) {
  push(v, tl, tr);
  if (tl + 1 == tr) {
    result = tree[v];
    return;
  }
  int tm = (tl + tr) / 2;
  if (ind < tm) {
    query(2 * v + 1, tl, tm, ind, result);
  } else {
    query(2 * v + 2, tm, tr, ind, result);
  }
}
void getPoint(int ind, vector<double> &result) {
  mtr res;
  query(0, 0, n + 1, ind, res);
  MUL(res, ind, result);
}
void transform(double dx, double dy, mtr &result) {
  mtr res;
  res.m[0][0] = res.m[1][1] = res.m[2][2] = 1.0;
  res.m[0][2] = dx;
  res.m[1][2] = dy;
  swap(result, res);
}
void rotate(int ind, double angle, mtr &result) {
  mtr res;
  vector<double> p;
  getPoint(ind, p);
  res.m[2][2] = 1.0;
  res.m[0][0] = res.m[1][1] = cos(angle);
  res.m[0][1] = sin(angle);
  res.m[1][0] = -sin(angle);
  mtr res1;
  transform(-p[0], -p[1], res1);
  MUL(res, res1, res);
  transform(p[0], p[1], res1);
  MUL(res1, res, res);
  swap(result, res);
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  E.m[0][0] = E.m[1][1] = E.m[2][2] = 1.0;
  vector<double> ang(360);
  for (int i = 0; i < 360; ++i) {
    ang[i] = (double)i * acos(-1.0) / 180.0;
  }
  int m;
  scanf("%d %d\n", &n, &m);
  tree.resize(4 * (n + 1) + 10, E);
  int x, y, z;
  for (int i = 0; i < m; ++i) {
    scanf("%d %d %d\n", &x, &y, &z);
    if (x == 1) {
      vector<double> p1, p2;
      getPoint(y - 1, p1);
      getPoint(y, p2);
      double len = sqrt((p1[0] - p2[0]) * (p1[0] - p2[0]) +
                        (p1[1] - p2[1]) * (p1[1] - p2[1]));
      double dx, dy;
      dx = (p2[0] - p1[0]) / len * (double)z;
      dy = (p2[1] - p1[1]) / len * (double)z;
      mtr trf;
      transform(dx, dy, trf);
      move(0, 0, n + 1, y, n + 1, trf);
      vector<double> end;
      getPoint(n, end);
      printf("%.10f %.10f\n", end[0], end[1]);
    } else {
      mtr rtf;
      rotate(y - 1, ang[z], rtf);
      move(0, 0, n + 1, y, n + 1, rtf);
      vector<double> end;
      getPoint(n, end);
      printf("%.10f %.10f\n", end[0], end[1]);
    }
  }
  return 0;
}
