团建分组的方法

img_0937

背景

公司稍微大点规模以后,各个同事之间的沟通因为部门的存在而减少,甚至有的同事叫不上名字。所以我们设置了“霸王餐”制度让每个同事都有机会每周面对面的轻松沟通:

每周三中午所有同事随机分组下馆子,公司根据每个人最近7天的走路步数报销相应的额度。

开始系统运行稳定,每周三把分组通知发到全员群里,但是人员增减后分组会变的不合理。所以需要对分组方法进行优化。

分组原则

  1. 小于4个人报销额太少没法吃到多样的菜
  2. 大于6个人沟通失去效率 暂时定为6人最多
  3. 尽量分组少
  4. 组人数差不大于1

方法

因为涉及到读取部门和分公司的花名册及运动量,这里省略了读取逻辑,只把分组这块分享一下。

function splitGroups(num, max_size) {
  const default_min_size = 4;
  const default_max_size = 6;
  max_size = max_size || default_max_size;

  if (max_size < default_min_size || max_size > default_max_size) {
    console.warn(`分组失败,当前要求组容量${max_size} 总人数${num}`);
    return [num];
  }

  // console.log('Check MaxSize', max_size);

  const remainder = num % max_size;
  const groupCount = Math.ceil(num / max_size);

  var group = [];
  if (remainder == 0) {
    // 寻找可平均分配的最大解
    for (var i1 = 0; i1 < groupCount; i1++) {
      group[i1] = max_size;
    }
    return group;
  }

  // 不存在平均分配可能
  const diff = max_size - remainder;
  if (diff - 1 >= groupCount || max_size - 1 < default_min_size) return splitGroups(num, max_size - 1);

  for (var i1 = 0; i1 < groupCount; i1++) {
    if (i1 < diff) {
      group[i1] = max_size - 1;
    } else {
      group[i1] = max_size;
    }
  }
  return group;

}

后续

  1. 当天请假的人不能算进来
  2. 各城市的消费水平不同,需要一个参照值(比如当地的海底捞清汤锅底的价格的比率,现在是拍脑袋给一个)
  3. 跳开法定节假日自动触发(现在是“嘿Siri,霸王餐”)

PS. 开源的公司制度 https://rar.firhq.com/3.-ren-shi-zhi-du/xin-chou.html