<commit_before>import 'dart:io';
import 'dart:async';
import 'dart:convert' show JSON, LATIN1, LineSplitter, UTF8;
import 'dart:math';
import 'package:chesschallenge/shared.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:path/path.dart' as path;
import 'package:http/http.dart' as http;

Map<WebSocket, User> users = {};

List<Challenge> challenges = [];

List<String> pgnGames = [];

List<User> highScores = [];

const GAMES_PER_CHALLENGE = 5;

const PENDING_CHALLENGE_TIME = 9;

Challenge pendingChallenge = null;

Stopwatch pendingChallengeStopwatch = new Stopwatch();

class Challenge {
  List<WebSocket> webSockets = [];
  List<String> games = [];
  Stopwatch stopWatch = new Stopwatch();

  Challenge() {
    addRandomGames(GAMES_PER_CHALLENGE);
  }

  void addRandomGames(int count) {
    var rnd = new Random();
    int length = pgnGames.length;
    for (int i = 0; i < count; i++) {
      int index = rnd.nextInt(length);
      games.add(pgnGames[index]);
    }
  }

  List<User> getUsers() {
    return webSockets.map((ws) => users[ws]).toList();
  }
}

Challenge findChallenge(webSocket) {
  for (var challenge in challenges) {
    if (challenge.webSockets.contains(webSocket)) {
      return challenge;
    }
  }
  return null;
}

void main() {
  // Server port assignment
  var portEnv = Platform.environment['PORT'];
  var port = portEnv != null ? int.parse(portEnv) : 9090;

  _readGames('IB1419.pgn');

  _readHighscores();

  var handler = webSocketHandler(onConnection);

  shelf_io.serve(handler, InternetAddress.ANY_IP_V4, port).then((server) {
    print('Serving at ws://${server.address.host}:${server.port}');
  });
}

void _readHighscores() {
  http.get(firebaseUrl + "/highscores.json").then((response) {
    if (response.statusCode == HttpStatus.OK) {
      String json = response.body;
      if (json != 'null') {
        highScores = getUsersFromJson(json);
      }
    }
  });
}

void _readGames(String fileName) {
  String pgn = '';

  final serverDir = path.dirname(Platform.script.toFilePath());
  final file = new File(serverDir + '/' + fileName);

  Stream<List<int>> inputStream = file.openRead();

  inputStream.transform(
      LATIN1.decoder).transform(new LineSplitter()).listen((String line) {
    if (line.trim().isEmpty) {
      if (pgn.contains('1.')) {
        if (pgn.contains('#')) {
          pgnGames.add(pgn);
        }
        pgn = '';
      }
    } else {
      pgn += line + '\n';
    }
  }, onDone: () {
    print('Ready with ${pgnGames.length} challenges.');
  }, onError: (e) {
    print(e.toString());
  });
}

List<User> getLeaderBoard(Challenge challenge) {
  return challenge.getUsers()..sort((u1, u2) => u2.score.compareTo(u1.score));
}

void onConnection(webSocket) {

  // Set ping interval to prevent disconnection from peers
  webSocket.pingInterval = new Duration(seconds: 5);

  webSocket.listen((String message) {
    if (message.startsWith(Messages.LOGIN)) {
      users.remove(webSocket);
      var user =
          new User.fromMap(JSON.decode(message.substring(Messages.LOGIN.length)));
      print('Login received from ${user.name}');
      users.putIfAbsent(webSocket, () => user);
      sendUpdateStatus();
    } else if (message == Messages.CHALLENGE) {
      print('Start/join challenge received from ${users[webSocket].name}');
      joinChallenge(webSocket);
      sendUpdateStatus();
    } else if (message == Messages.CHECKMATE) {
      print('Checkmate received from ${users[webSocket].name}');
      User user = users[webSocket];
      user.score += 1;
      var challenge = findChallenge(webSocket);
      updateLeaderBoard(challenge);
      if (user.score == challenge.games.length) {
        // We have a winner!
        challenge.stopWatch.stop();
        user.time = challenge.stopWatch.elapsedMilliseconds;
        _storeUser(user);
        _updateHighscores(user);
        challenges.remove(challenge);
        print('Sending gameover message');
        sendGameOver(challenge);
      } else {
        print('Sending new chess problem');
        webSocket.add(Messages.PGN + challenge.games[user.score]);
      }
    } else if (message == Messages.STOPCHALLENGE) {
      print('Stop challenge received from ${users[webSocket].name}');
      var challenge = findChallenge(webSocket);
      if (challenge != null) {
        challenge.webSockets.remove(webSocket);
        if (challenge.webSockets.length == 0) {
          challenge.stopWatch.stop();
          challenges.remove(challenge);
        }
        updateLeaderBoard(challenge);
      }
      sendUpdateStatus();
    }
  }, onDone: () => doneHandler(webSocket));
}

// Updates the highscores list if necessary
void _updateHighscores(User user) {
  if (highScores.isEmpty || user.time <= highScores.last.time) {
    highScores
        ..add(user)
        ..sort((u1, u2) => u1.time.compareTo(u2.time));
    if (highScores.length > 10) highScores.removeLast();
    _storeHighscoreUsers(highScores);
  }<commit_msg>Don't store same user/avatar twice in highscore list<commit_after>import 'dart:io';
import 'dart:async';
import 'dart:convert' show JSON, LATIN1, LineSplitter, UTF8;
import 'dart:math';
import 'package:chesschallenge/shared.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:path/path.dart' as path;
import 'package:http/http.dart' as http;

Map<WebSocket, User> users = {};

List<Challenge> challenges = [];

List<String> pgnGames = [];

List<User> highScores = [];

const GAMES_PER_CHALLENGE = 5;

const PENDING_CHALLENGE_TIME = 9;

Challenge pendingChallenge = null;

Stopwatch pendingChallengeStopwatch = new Stopwatch();

class Challenge {
  List<WebSocket> webSockets = [];
  List<String> games = [];
  Stopwatch stopWatch = new Stopwatch();

  Challenge() {
    addRandomGames(GAMES_PER_CHALLENGE);
  }

  void addRandomGames(int count) {
    var rnd = new Random();
    int length = pgnGames.length;
    for (int i = 0; i < count; i++) {
      int index = rnd.nextInt(length);
      games.add(pgnGames[index]);
    }
  }

  List<User> getUsers() {
    return webSockets.map((ws) => users[ws]).toList();
  }
}

Challenge findChallenge(webSocket) {
  for (var challenge in challenges) {
    if (challenge.webSockets.contains(webSocket)) {
      return challenge;
    }
  }
  return null;
}

void main() {
  // Server port assignment
  var portEnv = Platform.environment['PORT'];
  var port = portEnv != null ? int.parse(portEnv) : 9090;

  _readGames('IB1419.pgn');

  _readHighscores();

  var handler = webSocketHandler(onConnection);

  shelf_io.serve(handler, InternetAddress.ANY_IP_V4, port).then((server) {
    print('Serving at ws://${server.address.host}:${server.port}');
  });
}

void _readHighscores() {
  http.get(firebaseUrl + "/highscores.json").then((response) {
    if (response.statusCode == HttpStatus.OK) {
      String json = response.body;
      if (json != 'null') {
        highScores = getUsersFromJson(json);
      }
    }
  });
}

void _readGames(String fileName) {
  String pgn = '';

  final serverDir = path.dirname(Platform.script.toFilePath());
  final file = new File(serverDir + '/' + fileName);

  Stream<List<int>> inputStream = file.openRead();

  inputStream.transform(
      LATIN1.decoder).transform(new LineSplitter()).listen((String line) {
    if (line.trim().isEmpty) {
      if (pgn.contains('1.')) {
        if (pgn.contains('#')) {
          pgnGames.add(pgn);
        }
        pgn = '';
      }
    } else {
      pgn += line + '\n';
    }
  }, onDone: () {
    print('Ready with ${pgnGames.length} challenges.');
  }, onError: (e) {
    print(e.toString());
  });
}

List<User> getLeaderBoard(Challenge challenge) {
  return challenge.getUsers()..sort((u1, u2) => u2.score.compareTo(u1.score));
}

void onConnection(webSocket) {

  // Set ping interval to prevent disconnection from peers
  webSocket.pingInterval = new Duration(seconds: 5);

  webSocket.listen((String message) {
    if (message.startsWith(Messages.LOGIN)) {
      users.remove(webSocket);
      var user =
          new User.fromMap(JSON.decode(message.substring(Messages.LOGIN.length)));
      print('Login received from ${user.name}');
      users.putIfAbsent(webSocket, () => user);
      sendUpdateStatus();
    } else if (message == Messages.CHALLENGE) {
      print('Start/join challenge received from ${users[webSocket].name}');
      joinChallenge(webSocket);
      sendUpdateStatus();
    } else if (message == Messages.CHECKMATE) {
      print('Checkmate received from ${users[webSocket].name}');
      User user = users[webSocket];
      user.score += 1;
      var challenge = findChallenge(webSocket);
      updateLeaderBoard(challenge);
      if (user.score == challenge.games.length) {
        // We have a winner!
        challenge.stopWatch.stop();
        user.time = challenge.stopWatch.elapsedMilliseconds;
        _storeUser(user);
        _updateHighscores(user);
        challenges.remove(challenge);
        print('Sending gameover message');
        sendGameOver(challenge);
      } else {
        print('Sending new chess problem');
        webSocket.add(Messages.PGN + challenge.games[user.score]);
      }
    } else if (message == Messages.STOPCHALLENGE) {
      print('Stop challenge received from ${users[webSocket].name}');
      var challenge = findChallenge(webSocket);
      if (challenge != null) {
        challenge.webSockets.remove(webSocket);
        if (challenge.webSockets.length == 0) {
          challenge.stopWatch.stop();
          challenges.remove(challenge);
        }
        updateLeaderBoard(challenge);
      }
      sendUpdateStatus();
    }
  }, onDone: () => doneHandler(webSocket));
}

// Updates the highscores list if necessary
void _updateHighscores(User user) {
  if (highScores.isEmpty || user.time <= highScores.last.time) {
    var scores =
        highScores.where((u) => u.name == user.name && u.avatar == user.avatar);
    if (scores.isNotEmpty) {
      var existingUser = scores.first;
      if (user.time < existingUser.time) {
        existingUser.time = user.time;
        _storeHighscoreUsers(highScores);
      }
    } else {
      highScores
          ..add(user)
          ..sort((u1, u2) => u1.time.compareTo(u2.time));
      if (highScores.length > 10) highScores.removeLast();
      _storeHighscoreUsers(highScores);
    }
  }
{'fraction_non_alphanumeric': 0.14442955589586523, 'fraction_numerical': 0.005551301684532925, 'mean_word_length': 3.2596820220138607, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 36, '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': '2077274', 'n_tokens_mistral': 3498, 'n_tokens_neox': 3344, 'n_words': 664}