<commit_before>import { lichessVariantRules } from 'chessops/compat';
import { WorkerOpts, Work } from './types';

const EVAL_REGEX = new RegExp(''
  + /^info depth (\d+) seldepth \d+ multipv (\d+) /.source
  + /score (cp|mate) ([-\d]+) /.source
  + /(?:(upper|lower)bound )?nodes (\d+) nps \S+ /.source
  + /(?:hashfull \d+ )?(?:tbhits \d+ )?time (\S+) /.source
  + /pv (.+)/.source);

export default class Protocol {
  private work: Work | null = null;
  private curEval: Tree.ClientEval | null = null;
  private expectedPvs = 1;
  private stopped: DeferPromise.Deferred<void> | null;

  public engineName: string | undefined;

  constructor(private send: (cmd: string) => void, private opts: WorkerOpts) {
    this.stopped = defer<void>();
    this.stopped.resolve();
  }

  init(): void {
    // get engine name/version
    this.send('uci');

    // analyse without contempt
    this.setOption('UCI_AnalyseMode', 'true');
    this.setOption('Analysis Contempt', 'Off');

    if (this.opts.variant === 'fromPosition' || this.opts.variant === 'chess960')
      this.setOption('UCI_Chess960', 'true');
    else if (this.opts.variant === 'antichess')
      this.setOption('UCI_Variant', 'giveaway');
    else if (this.opts.variant !== 'standard')
      this.setOption('UCI_Variant', lichessVariantRules(this.opts.variant));
  }

  private setOption(name: string, value: string | number): void {
    this.send(`setoption name ${name} value ${value}`);
  }

  received(text: string): void {
    if (text.startsWith('id name ')) this.engineName = text.substring('id name '.length);
    else if (text.startsWith('bestmove ')) {
      if (!this.stopped) this.stopped = defer<void>();
      this.stopped.resolve();
      if (this.work && this.curEval) this.work.emit(this.curEval);
      return;
    }
    if (!this.work) return;

    const matches = text.match(EVAL_REGEX);
    if (!matches) return;
<commit_msg>comment giveaway special case<commit_after>import { lichessVariantRules } from 'chessops/compat';
import { WorkerOpts, Work } from './types';

const EVAL_REGEX = new RegExp(''
  + /^info depth (\d+) seldepth \d+ multipv (\d+) /.source
  + /score (cp|mate) ([-\d]+) /.source
  + /(?:(upper|lower)bound )?nodes (\d+) nps \S+ /.source
  + /(?:hashfull \d+ )?(?:tbhits \d+ )?time (\S+) /.source
  + /pv (.+)/.source);

export default class Protocol {
  private work: Work | null = null;
  private curEval: Tree.ClientEval | null = null;
  private expectedPvs = 1;
  private stopped: DeferPromise.Deferred<void> | null;

  public engineName: string | undefined;

  constructor(private send: (cmd: string) => void, private opts: WorkerOpts) {
    this.stopped = defer<void>();
    this.stopped.resolve();
  }

  init(): void {
    // get engine name/version
    this.send('uci');

    // analyse without contempt
    this.setOption('UCI_AnalyseMode', 'true');
    this.setOption('Analysis Contempt', 'Off');

    if (this.opts.variant === 'fromPosition' || this.opts.variant === 'chess960')
      this.setOption('UCI_Chess960', 'true');
    else if (this.opts.variant === 'antichess')
      this.setOption('UCI_Variant', 'giveaway'); // for compatibility with old asmjs fallback
    else if (this.opts.variant !== 'standard')
      this.setOption('UCI_Variant', lichessVariantRules(this.opts.variant));
  }

  private setOption(name: string, value: string | number): void {
    this.send(`setoption name ${name} value ${value}`);
  }

  received(text: string): void {
    if (text.startsWith('id name ')) this.engineName = text.substring('id name '.length);
    else if (text.startsWith('bestmove ')) {
      if (!this.stopped) this.stopped = defer<void>();
      this.stopped.resolve();
      if (this.work && this.curEval) this.work.emit(this.curEval);
      return;
    }
    if (!this.work) return;

    const matches = text.match(EVAL_REGEX);
    if (!matches) return;

{'fraction_non_alphanumeric': 0.17496774193548387, 'fraction_numerical': 0.0036129032258064514, 'mean_word_length': 3.5227537922987167, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6867735', 'n_tokens_mistral': 1321, 'n_tokens_neox': 1276, 'n_words': 315}