{"size": 1623, "ext": "js", "max_stars_repo_path": "src/adapters/sudoku-adapter.js", "max_stars_repo_name": "nickstanish/sudoku", "max_stars_repo_stars_event_min_datetime": "2021-03-26T17:51:29.000Z", "max_stars_repo_stars_event_max_datetime": "2021-03-26T17:51:29.000Z", "max_issues_repo_path": "src/adapters/sudoku-adapter.js", "max_issues_repo_name": "nickstanish/sudoku", "max_issues_repo_issues_event_min_datetime": "2019-06-10T03:03:32.000Z", "max_issues_repo_issues_event_max_datetime": "2022-02-17T23:58:11.000Z", "max_forks_repo_path": "src/adapters/sudoku-adapter.js", "max_forks_repo_name": "nickstanish/sudoku", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": 1, "max_issues_count": 23, "max_forks_count": null, "avg_line_length": 22.5416666667, "max_line_length": 99, "alphanum_fraction": 0.5810227973}
const Sudoku = window.sudoku;

const difficulties = [
  'easy',
  'medium',
  'hard',
  'very-hard',
  'insane',
  'inhuman'
];

export default class SudokuGame {
  constructor(difficulty = difficulties[1], _data) {
    if (_data) {
      Object.getOwnPropertyNames(_data).forEach((key) => {
        this[key] = _data[key]
      });
    } else {
      this.difficulty = difficulty;
      this.initialBoard = this.board = Sudoku.generate(difficulty);
    }
  }

  solve(board) {
    return Sudoku.solve(board || this.initialBoard);
  }

  isSolved() {
    return this.solve(this.board) === this.board;
  }

  hasError() {
    return !this.solve(this.board);
  }

  getCells() {
    const initialBoard = Array.from(this.initialBoard);
    return Array.from(this.board).map((value, index) => {
      return {
        hint: initialBoard[index] !== '.',
        value: value === '.' ? '' : value,
        row: Math.floor(index / 9.0),
        column: index % 9,
        index: index
      };
    });
  }

  clone(mergeObj) {
    const data = Object.assign({}, this.toHash(), mergeObj);
    return new SudokuGame(null, data);
  }

  toHash() {
    const obj = {};
    Object.getOwnPropertyNames(this).forEach(key => {
      obj[key] = this[key];
    });
    return obj;
  }

  updateCell(index, value) {
    const selectedCell = this.getCells()[index];
    if (selectedCell.hint) {
      // invalid move
      return this;
    }
    const nextValue = value === '' ? '.' : value;
    const nextBoard = this.board.substring(0, index) + nextValue + this.board.substring(index + 1);
    return this.clone({ board: nextBoard });
  }
}