#include <bits/stdc++.h>
namespace util {
inline size_t flog(int x) { return 8 * sizeof(int) - 1 - __builtin_clz(x); }
template <typename T>
inline void mini(T &a, T b) {
  if (a > b) a = b;
}
template <typename T>
inline void maxi(T &a, T b) {
  if (a < b) a = b;
}
template <typename T>
inline T abs(T a) {
  return a < 0 ? -a : a;
}
template <typename T, typename Cmp>
inline std::vector<T> merge(const std::vector<T> &x, const std::vector<T> &y,
                            Cmp cmp) {
  std::vector<T> z(x.size() + y.size());
  std::merge(x.begin(), x.end(), y.begin(), y.end(), z.begin(), cmp);
  return z;
}
template <typename T>
inline void unique(std::vector<T> &v) {
  std::sort(v.begin(), v.end());
  v.erase(std::unique(v.begin(), v.end()), v.end());
}
};  // namespace util
enum { M = 1000000007 };
struct Edge {
  int b, v;
};
std::vector<int> C;
std::vector<std::vector<Edge>> G;
bool dfs(int v) {
  for (Edge e : G[v]) {
    if (C[e.b] == -1) {
      C[e.b] = C[v] ^ e.v;
      if (!dfs(e.b)) return 0;
    } else if (C[e.b] != C[v] ^ e.v)
      return 0;
  }
  return 1;
}
int main() {
  int n, k;
  scanf("%d%d", &n, &k);
  G.resize(n + 1);
  while (k--) {
    int x, y;
    char c;
    scanf("%d%d %c", &x, &y, &c);
    x--;
    y--;
    int s = x + y, d = util::abs(x - y);
    if (s >= n) s = 2 * n - s - 2;
    assert(d <= s);
    s++;
    d = std::max(0, d - 1);
    G[s].push_back(Edge{d, c == 'o'});
    G[d].push_back(Edge{s, c == 'o'});
  }
  C.resize(n + 1, -1);
  bool ok = 1;
  int r = 0;
  for (int i = 0; i < (n + 1); ++i)
    if (C[i] == -1) {
      r++;
      C[i] = 0;
      ok &= dfs(i);
    }
  int res = 1;
  while (--r) res = res * 2 % M;
  printf("%d\n", ok ? res : 0);
  return 0;
}
