<commit_before>const _ = require('lodash');
const uid = require('uid');
const update = require('immutability-helper');
const actions = require('./actions');
const utils = require('./utils');

const SWIPE_DELAY_TOLERANCE = 100;

const initialState = {
  clusters: {},
  clients: {},
  swipes: [],
};

function createReducer (config) {
  return (state = initialState, { type, data }) => {
    switch (type) {
      case actions.TYPE.NEXT_STATE:
        return nextState(state);

      case actions.TYPE.CLIENT_ACTION:
        return clientAction(state, data);

      case actions.TYPE.CONNECT:
        return connect(state, data);

      case actions.TYPE.SWIPE:
        return doSwipe(state, data);

      case actions.TYPE.DISCONNECT:
        return disconnect(state, data);

      case actions.TYPE.RECONNECT:
        return reconnect(state, data);

      case actions.TYPE.LEAVE_CLUSTER: {
         return leaveCluster(state, data);
       }
      default:
        return state;
    }
  };

  function nextState (state) {
    const updateClient = config.client.events.update;
    const updateCluster = config.cluster.events.update;
    const changes = {};

    if (_.isFunction(updateCluster)) {
      changes.clusters = getAllChanges(state.clusters, _.partial(getClusterChanges, state, updateCluster));
    }

    if (_.isFunction(updateClient)) {
      changes.clients = getAllChanges(state.clients, _.partial(getClientChanges, state, updateClient));
    }

    return update(state, changes);
  }

  function getAllChanges (entities, update) {
    const changes = _.map(entities, update);
    const ids = _.keys(entities);
    return _.zipObject(ids, changes);
  }

  function getClusterChanges (state, next, cluster) {
    const clusterState = utils.getClusterState(state, cluster.id);
    return { data: next(clusterState) };
  }

  function getClientChanges (state, next, client) {
    const clientState = utils.getClientState(state, client.id);
    return { data: next(clientState) };
  }

  function clientAction (state, { id, type, data }) {
    const handler = config.client.events[type];

    if (!_.isFunction(handler)) {
      throw new Error(`Unhandled event: ${type}`);
    }

    const client = state.clients[id];

    if (!client) {
      return state;
    }

    const clientEventState = utils.getClientState(state, client.id);
    const stateUpdates = handler(clientEventState, data);
    const changes = {};


    if (stateUpdates.cluster) {
      changes.clusters = {
        [client.clusterID]: stateUpdates.cluster,
      };
    }

    if (stateUpdates.client) {
      changes.clients = {
        [client.id]: stateUpdates.client,
      };
    }

    return update(state, changes);
  }

  function connect (state, { id, size }) {
    const clusterID = uid();
    const openings = {
      top: [],
      bottom: [],
      right: [],
      left: [],
    };
    const client = { id, size, transform: { x: 0, y: 0 }, adjacentClientIDs: [], clusterID, openings };

    const clientData = config.client.init(client);
    const clusterData = config.cluster.init(client);

    const changes = {
      clusters: {
        [clusterID]: { $set: { id: clusterID, data: clusterData } },
      },
      clients: {
        [id]: { $set: _.assign({}, client, { data: clientData }) },
      },
    };

    return update(state, changes);
  }

  function doSwipe (state, swipe) {
    const swipes = getCoincidentSwipes(state.swipes);

    if (swipes.length === 0) {
      return addSwipe(state, swipes, swipe);
    }

    const swipeA = swipe;
    const clientA = state.clients[swipeA.id];
    const swipeB = swipes[0];
    const clientB = state.clients[swipeB.id];


    //////////////////////////////////////////////////////////do a functionn
    let updatedState = state;
    if(!clientA || !clientB) {
      return clearSwipes(state);
    }
    const clientACluster = state.clusters[clientA.clusterID];
    const clientBCluster = state.clusters[clientB.clusterID];
    if(clientACluster.data.currentScreenId !== 0 || clientBCluster.data.currentScreenId !== 0) {
      const direction = clientACluster.data.currentScreenId !== swipeA.id ? swipeA.direction : swipeB.direction;
      let originCluster = null;
      let targetCluster = null;
      if(clientACluster.data.maze.getNbMove() > clientBCluster.data.maze.getNbMove()) {
        originCluster = clientACluster;
        targetCluster = clientBCluster;
      } else {
        originCluster = clientBCluster;
        targetCluster = clientACluster;
      }
      const originMaze = originCluster.data.maze;
      //move and check if out of map
      if(!originMaze.movePosition(direction)) {
        return clearSwipes(state);
      }
      updatedState = copyMaze(state, originCluster, targetCluster);
      console.log(direction)
      console.log(updatedState.clusters[targetCluster.id].data.maze)
    }
    //////////////////////////////////////////////////// end of the the function

    if (clientA.clusterID === clientB.clusterID) {
      return clearSwipes(state);
    }

    const { clients, clusters } = mergeAndRecalculateClusters(updatedState, clientA, swipeA, clientB, swipeB);

    return update(updatedState, {
      swipes: { $set: [] },
      clients: { $set: clients },
      clusters: { $set: clusters },
    });
  }

  function getCoincidentSwipes (swipes) {
    return _.filter(swipes, ({ timestamp }) => (Date.now() - timestamp) < SWIPE_DELAY_TOLERANCE);
  }

  function addSwipe (state, swipes, swipe) {<commit_msg>add comments<commit_after>const _ = require('lodash');
const uid = require('uid');
const update = require('immutability-helper');
const actions = require('./actions');
const utils = require('./utils');

const SWIPE_DELAY_TOLERANCE = 100;

const initialState = {
  clusters: {},
  clients: {},
  swipes: [],
};

function createReducer (config) {
  return (state = initialState, { type, data }) => {
    switch (type) {
      case actions.TYPE.NEXT_STATE:
        return nextState(state);

      case actions.TYPE.CLIENT_ACTION:
        return clientAction(state, data);

      case actions.TYPE.CONNECT:
        return connect(state, data);

      case actions.TYPE.SWIPE:
        return doSwipe(state, data);

      case actions.TYPE.DISCONNECT:
        return disconnect(state, data);

      case actions.TYPE.RECONNECT:
        return reconnect(state, data);

      case actions.TYPE.LEAVE_CLUSTER: {
         return leaveCluster(state, data);
       }
      default:
        return state;
    }
  };

  function nextState (state) {
    const updateClient = config.client.events.update;
    const updateCluster = config.cluster.events.update;
    const changes = {};

    if (_.isFunction(updateCluster)) {
      changes.clusters = getAllChanges(state.clusters, _.partial(getClusterChanges, state, updateCluster));
    }

    if (_.isFunction(updateClient)) {
      changes.clients = getAllChanges(state.clients, _.partial(getClientChanges, state, updateClient));
    }

    return update(state, changes);
  }

  function getAllChanges (entities, update) {
    const changes = _.map(entities, update);
    const ids = _.keys(entities);
    return _.zipObject(ids, changes);
  }

  function getClusterChanges (state, next, cluster) {
    const clusterState = utils.getClusterState(state, cluster.id);
    return { data: next(clusterState) };
  }

  function getClientChanges (state, next, client) {
    const clientState = utils.getClientState(state, client.id);
    return { data: next(clientState) };
  }

  function clientAction (state, { id, type, data }) {
    const handler = config.client.events[type];

    if (!_.isFunction(handler)) {
      throw new Error(`Unhandled event: ${type}`);
    }

    const client = state.clients[id];

    if (!client) {
      return state;
    }

    const clientEventState = utils.getClientState(state, client.id);
    const stateUpdates = handler(clientEventState, data);
    const changes = {};


    if (stateUpdates.cluster) {
      changes.clusters = {
        [client.clusterID]: stateUpdates.cluster,
      };
    }

    if (stateUpdates.client) {
      changes.clients = {
        [client.id]: stateUpdates.client,
      };
    }

    return update(state, changes);
  }

  function connect (state, { id, size }) {
    const clusterID = uid();
    const openings = {
      top: [],
      bottom: [],
      right: [],
      left: [],
    };
    const client = { id, size, transform: { x: 0, y: 0 }, adjacentClientIDs: [], clusterID, openings };

    const clientData = config.client.init(client);
    const clusterData = config.cluster.init(client);

    const changes = {
      clusters: {
        [clusterID]: { $set: { id: clusterID, data: clusterData } },
      },
      clients: {
        [id]: { $set: _.assign({}, client, { data: clientData }) },
      },
    };

    return update(state, changes);
  }

  function doSwipe (state, swipe) {
    const swipes = getCoincidentSwipes(state.swipes);

    if (swipes.length === 0) {
      return addSwipe(state, swipes, swipe);
    }

    const swipeA = swipe;
    const clientA = state.clients[swipeA.id];
    const swipeB = swipes[0];
    const clientB = state.clients[swipeB.id];


    //////////////////////////////////////////////////////////do a functionn
    let updatedState = state;
    if(!clientA || !clientB) {
      return clearSwipes(state);
    }
    const clientACluster = state.clusters[clientA.clusterID];
    const clientBCluster = state.clusters[clientB.clusterID];
    if(clientACluster.data.currentScreenId !== 0 || clientBCluster.data.currentScreenId !== 0) {
      const direction = clientACluster.data.currentScreenId !== swipeA.id ? swipeA.direction : swipeB.direction;
      let originCluster = null;
      let targetCluster = null;
      if(clientACluster.data.maze.getNbMove() > clientBCluster.data.maze.getNbMove()) {
        originCluster = clientACluster;
        targetCluster = clientBCluster;
      } else {
        originCluster = clientBCluster;
        targetCluster = clientACluster;
      }
      console.log("beginMovePosition")
      const originMaze = originCluster.data.maze;
      //move and check if out of map
      console.log("endMovePosition")

      if(!originMaze.movePosition(direction)) {
        return clearSwipes(state);
      }
      updatedState = copyMaze(state, originCluster, targetCluster);
      console.log(direction)
      console.log(updatedState.clusters[targetCluster.id].data.maze)
    }
    //////////////////////////////////////////////////// end of the the function

    if (clientA.clusterID === clientB.clusterID) {
      return clearSwipes(state);
    }

    const { clients, clusters } = mergeAndRecalculateClusters(updatedState, clientA, swipeA, clientB, swipeB);

    return update(updatedState, {
      swipes: { $set: [] },
      clients: { $set: clients },
      clusters: { $set: clusters },
    });
  }

  function getCoincidentSwipes (swipes) {
    return _.filter(swipes, ({ timestamp }) => (Date.now() - timestamp) < SWIPE_DELAY_TOLERANCE);
  }

  function addSwipe (state, swipes, swipe) {
{'fraction_non_alphanumeric': 0.14427591188154568, 'fraction_numerical': 0.0016251354279523294, 'mean_word_length': 2.725866128489741, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, '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': '734263', 'n_tokens_mistral': 3341, 'n_tokens_neox': 3281, 'n_words': 727}