<commit_before>var Tinkerforge = require('tinkerforge');
var LIGHT,
  LIGHT_2,
  BARO,
  HUMI,
  al,
  h,
  b,
  ipcon,
  Humidity,
  AirPressure,
  Temperature,
  Illuminance;
/* istanbul ignore next */
function ipcon_connect(HOST, PORT) {
  ipcon.connect(HOST, PORT,
    function(error) {
      console.log(require('./error.js').error(error));
      process.exit();
    }
  );
}
/* istanbul ignore next */
function get_uid(HOST, PORT) {
  ipcon = new Tinkerforge.IPConnection();
  ipcon_connect(HOST, PORT);
  ipcon.on(Tinkerforge.IPConnection.CALLBACK_CONNECTED,
    function(connectReason) {
      ipcon.enumerate();
    }
  );
  ipcon.on(Tinkerforge.IPConnection.CALLBACK_ENUMERATE,
    function(uid, connectedUid, position, hardwareVersion, firmwareVersion, deviceIdentifier) {
      if (deviceIdentifier === Tinkerforge.BrickletAmbientLight.DEVICE_IDENTIFIER) {
        LIGHT = uid;
      } else if (deviceIdentifier === Tinkerforge.BrickletAmbientLightV2.DEVICE_IDENTIFIER) {
        LIGHT_2 = uid;
      } else if (deviceIdentifier === Tinkerforge.BrickletBarometer.DEVICE_IDENTIFIER) {
        BARO = uid;
      } else if (deviceIdentifier === Tinkerforge.BrickletHumidity.DEVICE_IDENTIFIER) {
        HUMI = uid;
      }
    }
  );
}
/* istanbul ignore next */
function tfinit(HOST, PORT) {
  ipcon = new Tinkerforge.IPConnection();
  if (LIGHT_2 !== undefined) {
    al = new Tinkerforge.BrickletAmbientLightV2(LIGHT, ipcon);
  } else if (LIGHT !== undefined) {
    al = new Tinkerforge.BrickletAmbientLight(LIGHT, ipcon);
  }
  if (BARO !== undefined) {
    b = new Tinkerforge.BrickletBarometer(BARO, ipcon);
  }
  if (HUMI !== undefined) {
    h = new Tinkerforge.BrickletHumidity(HUMI, ipcon);
  }
  ipcon_connect(HOST, PORT);
}
/* istanbul ignore next */
function tfdata_get() {
  if (h !== undefined) {
    h.getHumidity(
      function(humidity) {
        Humidity = humidity / 10 + ' %RH';
      },
      function(error) {
        Humidity = require('./error.js').error(error);
      }
    );
  }
  if (b !== undefined) {
    b.getAirPressure(
      function(air_pressure) {
        AirPressure = air_pressure / 1000 + ' mbar';
      },
      function(error) {
        AirPressure = require('./error.js').error(error);
      }
    );
    b.getChipTemperature(
      function(temperature) {
        Temperature = temperature / 100 + ' \u00B0C';
      },
      function(error) {
        Temperature = require('./error.js').error(error);
      }
    );
  }
  if (al !== undefined) {
    al.getIlluminance(
      function(illuminance) {
        Illuminance = illuminance / 10 + ' Lux';
      },
      function(error) {
        Illuminance = require('./error.js').error(error);
      }
    );
  }
}
/* istanbul ignore next */
function getTime(date) {
  return ((date.getHours() < 10 ? "0" : "") + date.getHours()) + ":" + ((date.getMinutes() < 10 ? "0" : "") + date.getMinutes()) + ":" + ((date.getSeconds() < 10 ? "0" : "") + date.getSeconds());
}
/* istanbul ignore next */
function output() {
  if (Humidity !== undefined) {
    console.log('Relative Humidity:\t' + Humidity);
  }
  if (AirPressure !== undefined) {
    console.log('Air pressure:\t\t' + AirPressure);
  }
  if (Temperature !== undefined) {
    console.log('Temperature:\t\t' + Temperature);
  }
  if (Illuminance !== undefined) {
    console.log('Illuminance:\t\t' + Illuminance);
  }
  if (Humidity !== undefined || AirPressure !== undefined || Temperature !== undefined || Illuminance !== undefined) {
    console.log('\nTime:\t\t\t' + getTime(new Date()));
  } else {
    console.log('ERROR: nothing connected');
  }
}
/* istanbul ignore next */
exports.get = function tfget(HOST, PORT, WAIT, live) {
  get_uid(HOST, PORT);
  if (live === true) {
    setTimeout(function() {
      setTimeout(function() {
        ipcon.disconnect();
        tfinit(HOST, PORT);
      }, 250);
      setTimeout(function() {
        process.stdin.on('data',
          function(data) {
            ipcon.disconnect();
            process.exit();
          }
        );
        tfdata_get();
        setInterval(function() {
          tfdata_get();
          console.log('\033[2J');
          output();
        }, WAIT);
      }, 300);
    }, 250);
  } else {
    setTimeout(function() {
      tfinit(HOST, PORT);
      ipcon.on(Tinkerforge.IPConnection.CALLBACK_CONNECTED,
        function(connectReason) {
          tfdata_get();
        }
      );
      setTimeout(function() {
        console.log('');
        output();
        console.log('');
        ipcon.disconnect();
        process.exit(0);
      }, 25);
    }, 50);
  }
};
<commit_msg>Revert "Revert ":race_horse: speed up""<commit_after>var Tinkerforge = require('tinkerforge');
var LIGHT,
  LIGHT_2,
  BARO,
  HUMI,
  al,
  h,
  b,
  ipcon,
  Humidity,
  AirPressure,
  Temperature,
  Illuminance;
/* istanbul ignore next */
function ipcon_connect(HOST, PORT) {
  ipcon.connect(HOST, PORT,
    function(error) {
      console.log(require('./error.js').error(error));
      process.exit();
    }
  );
}
/* istanbul ignore next */
function get_uid(HOST, PORT) {
  ipcon = new Tinkerforge.IPConnection();
  ipcon_connect(HOST, PORT);
  ipcon.on(Tinkerforge.IPConnection.CALLBACK_CONNECTED,
    function(connectReason) {
      ipcon.enumerate();
    }
  );
  ipcon.on(Tinkerforge.IPConnection.CALLBACK_ENUMERATE,
    function(uid, connectedUid, position, hardwareVersion, firmwareVersion, deviceIdentifier) {
      switch (deviceIdentifier) {
        case Tinkerforge.BrickletAmbientLight.DEVICE_IDENTIFIER:
          LIGHT = uid;
          break;
        case Tinkerforge.BrickletAmbientLightV2.DEVICE_IDENTIFIER:
          LIGHT = uid;
          break;
        case Tinkerforge.BrickletBarometer.DEVICE_IDENTIFIER:
          BARO = uid;
          break;
        case Tinkerforge.BrickletHumidity.DEVICE_IDENTIFIER:
          HUMI = uid;
          break;
      }
    }
  );
}
/* istanbul ignore next */
function tfinit(HOST, PORT) {
  ipcon = new Tinkerforge.IPConnection();
  if (LIGHT_2 !== undefined) {
    al = new Tinkerforge.BrickletAmbientLightV2(LIGHT, ipcon);
  } else if (LIGHT !== undefined) {
    al = new Tinkerforge.BrickletAmbientLight(LIGHT, ipcon);
  }
  if (BARO !== undefined) {
    b = new Tinkerforge.BrickletBarometer(BARO, ipcon);
  }
  if (HUMI !== undefined) {
    h = new Tinkerforge.BrickletHumidity(HUMI, ipcon);
  }
  ipcon_connect(HOST, PORT);
}
/* istanbul ignore next */
function tfdata_get() {
  if (h !== undefined) {
    h.getHumidity(
      function(humidity) {
        Humidity = humidity / 10 + ' %RH';
      },
      function(error) {
        Humidity = require('./error.js').error(error);
      }
    );
  }
  if (b !== undefined) {
    b.getAirPressure(
      function(air_pressure) {
        AirPressure = air_pressure / 1000 + ' mbar';
      },
      function(error) {
        AirPressure = require('./error.js').error(error);
      }
    );
    b.getChipTemperature(
      function(temperature) {
        Temperature = temperature / 100 + ' \u00B0C';
      },
      function(error) {
        Temperature = require('./error.js').error(error);
      }
    );
  }
  if (al !== undefined) {
    al.getIlluminance(
      function(illuminance) {
        Illuminance = illuminance / 10 + ' Lux';
      },
      function(error) {
        Illuminance = require('./error.js').error(error);
      }
    );
  }
}
/* istanbul ignore next */
function getTime(date) {
  return ((date.getHours() < 10 ? "0" : "") + date.getHours()) + ":" + ((date.getMinutes() < 10 ? "0" : "") + date.getMinutes()) + ":" + ((date.getSeconds() < 10 ? "0" : "") + date.getSeconds());
}
/* istanbul ignore next */
function output() {
  if (Humidity !== undefined) {
    console.log('Relative Humidity:\t' + Humidity);
  }
  if (AirPressure !== undefined) {
    console.log('Air pressure:\t\t' + AirPressure);
  }
  if (Temperature !== undefined) {
    console.log('Temperature:\t\t' + Temperature);
  }
  if (Illuminance !== undefined) {
    console.log('Illuminance:\t\t' + Illuminance);
  }
  if (Humidity !== undefined || AirPressure !== undefined || Temperature !== undefined || Illuminance !== undefined) {
    console.log('\nTime:\t\t\t' + getTime(new Date()));
  } else {
    console.log('ERROR: nothing connected');
  }
}
/* istanbul ignore next */
exports.get = function tfget(HOST, PORT, WAIT, live) {
  get_uid(HOST, PORT);
  if (live === true) {
    setTimeout(function() {
      setTimeout(function() {
        ipcon.disconnect();
        tfinit(HOST, PORT);
      }, 250);
      setTimeout(function() {
        process.stdin.on('data',
          function(data) {
            ipcon.disconnect();
            process.exit();
          }
        );
        tfdata_get();
        setInterval(function() {
          tfdata_get();
          console.log('\033[2J');
          output();
        }, WAIT);
      }, 300);
    }, 250);
  } else {
    setTimeout(function() {
      tfinit(HOST, PORT);
      ipcon.on(Tinkerforge.IPConnection.CALLBACK_CONNECTED,
        function(connectReason) {
          tfdata_get();
        }
      );
      setTimeout(function() {
        console.log('');
        output();
        console.log('');
        ipcon.disconnect();
        process.exit(0);
      }, 25);
    }, 50);
  }
};
<|endoftext|>


<commit_before>var chalk = require('chalk');

Object.getOwnPropertyNames(chalk.styles).forEach(function(item, index, arr) {
	Object.defineProperty(String.prototype, item, {
		get: function() {
			var ck = chalk[item](this);
			return ck;
		}
	})
});
var iconLightRain = {
	chinese: "阵雨",
	icon: [
		"     .-.     ",
		"    (   ).   ",
		"   (___(__)  ",
		"    ‘ ‘ ‘ ‘  ",
		"   ‘ ‘ ‘ ‘   "
	]
}
var iconUnknown = {
	chinese: "Unknown",
	icon: [
		"    .-.      ",
		"     __)     ",
		"    (        ",
		"     `-’     ",
		"      •      "
	]
}
var iconSunny = {
	chinese: "晴",
	icon: [
		"    \\   /    ".bold.yellow,
		"     .-.     ".bold.yellow,
		"  ― (   ) ―  ".bold.yellow,
		"     `-’     ".bold.yellow,
		"    /   \\    ".bold.yellow
	]
}
var iconPartlyCloudy = {
	chinese: "少云",
	icon: [
		"   \\  /      ",
		" _ /\"\".-.    ",
		"   \\_(   ).  ",
		"   /(___(__) ",
		"             "
	]

}
var iconCloudy = {
	chinese: "多云",
	icon: [
		"             ",
		"     .--.    ",
		"  .-(    ).  ",
		" (___.__)__) ",
		"             "
	]
}
var iconVeryCloudy = {
	chinese: "阴",
	icon: [
		"             ",
		"     .--.    ",
		"  .-(    ).  ",
		" (___.__)__) ",
		"             "
	]
}
var iconLightShowers = {
	chinese: "小雨",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"     ‘ ‘ ‘ ‘ ",
		"    ‘ ‘ ‘ ‘  "
	]
}
var iconHeavyShowers = {
	chinese: "大雨",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"   ‚‘‚‘‚‘‚‘  ",
		"   ‚’‚’‚’‚’  "
	]
}
var iconLightSnowShowers = {
	chinese: "",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"     *  *  * ",
		"    *  *  *  "
	]
}
var iconHeavySnowShowers = {
	chinese: "",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"    * * * *  ",
		"   * * * *   "
	]
}
var iconLightSleetShowers = {
	chinese: "",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"     ‘ * ‘ * ",
		"    * ‘ * ‘  "
	]
}
var iconThunderyShowers = {
	chinese: "雷阵雨",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"    ⚡‘ ‘⚡‘ ‘ ",
		"    ‘ ‘ ‘ ‘  "
	]
}
var iconThunderyHeavyRain = {
	chinese: "",
	icon: [
		"     .-.     ",
		"    (   ).   ",
		"   (___(__)  ",
		"  ‚‘⚡‘‚⚡‚‘   ",
		"  ‚’‚’⚡’‚’   "
	]
}
var iconThunderySnowShowers = {
	chinese: "",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"     *⚡ *⚡ * ",
		"    *  *  *  "
	]
}
var iconHeavyRain = {
	chinese: "暴雨",
	icon: [
		"     .-.     ",
		"    (   ).   ",
		"   (___(__)  ",
		"  ‚‘‚‘‚‘‚‘   ",
		"  ‚’‚’‚’‚’   "
	]
}
var iconLightSnow = {
	chinese: "小雪",
	icon: [
		"     .-.     ",
		"    (   ).   ",
		"   (___(__)  ",
		"    *  *  *  ",
		"   *  *  *   "
	]
}
var iconHeavySnow = {
	chinese: "大雪",
	icon: [
		"     .-.     ",
		"    (   ).   ",
		"   (___(__)  ",
		"   * * * *   ",
		"  * * * *    "
	]
}
var iconLightSleet = {
	chinese: "雨夹雪",
	icon: [
		"     .-.     ",
		"    (   ).   ",
		"   (___(__)  ",
		"    ‘ * ‘ *  ",
		"   * ‘ * ‘   "
	]
}
var iconFog = {
	chinese: "大雾",
	icon: [
		"             ",
		" _ - _ - _ - ",
		"  _ - _ - _  ",
		" _ - _ - _ - ",
		"             "
	]
}

// dateFmt应该占用15个字符,每个单元格30行
var header = function(dateFmt, time) {
	dateFmt = autoCompelete(dateFmt, 15);
	// time内的字符串需要为14位长度，不够补全
	for (var i = 0; i < time.length; i++) {
		time[i] = autoCompelete(time[i], 14);
	}

	return [
		"                                                       ┌─────────────┐                                                       ",
		"┌──────────────────────────────┬───────────────────────" + dateFmt + "───────────────────────┬──────────────────────────────┐",
		"│        " + time[0] + "        │        " + time[1] + " └──────┬──────┘ " + time[2] + "        │        " + time[3] + "        │",
		"├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤"
	]
}

// 根据长度补全空格
function autoCompelete(str, len) {
	var length = str.length;
	if (length < len) {
		var remainder = (len - length) % 2;
		if (remainder === 0) {
			var repeat = (new Array((len - length) / 2 + 1)).join(" ");
			str = repeat + str + repeat;
		} else {
			// 往左偏一个" "
			var repeat = (new Array((len - length - 1) / 2 + 1)).join(" ");
			str = repeat + str + repeat + " ";
		}
	} else if (length > len) {
		str = str.substr(0, len);
	}
	return str;
}

var foot = "└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘";

// 占宽16个符号，做对齐，最后一个符号固定为 |，右对齐
var detail = function(weather, temp, wd, ws, param, len, end) {
	var detail = [];
	detail.push(handleDetailStr(weather || "", len||15, end || "│"));
	detail.push(handleDetailStr(temp || "", len||15, end || "│"));
	detail.push(handleDetailStr(wd || "", len||15, end || "│"));
	detail.push(handleDetailStr(ws || "", len||15, end || "│"));
	detail.push(handleDetailStr(param || "", len||15, end || "│"));
	return detail;
}

//计算字符长度 中文字符是英文字符宽度的两倍,最大返回len个字符
function handleDetailStr(str, len, end) {
	var length = str.length;
	/*var len = 0;
	for (var i = 0; i < length; i++) {
		if (str.charCodeAt(i) >= 8000) {
			len += 2;
		} else {
			len++;
		}
		if (len == 15) {
			return str.substring(0, i)+"│";
		} else if (len > 15) {
			return str.substring(0, i - 1) + " │";
		}
	}*/
	var rp = repeat(" ", len - length);
	var brp = repeat(" ", 2);
	return brp + str + rp + end;
}

function repeat(target, n) {
	var s = target,
		total = "";
	while (n > 0) {
		if (n % 2 == 1) {
			total += s;
		}
		if (n == 1) {
			break;
		}
		s += s;
		n = n >> 1;
	}
	return total;
}

// 中文天气与icon字典映射
var Weather = {
	LightRain: iconLightRain,
	Unknown: iconUnknown,
	Sunny: iconSunny,
	PartlyCloudy: iconPartlyCloudy,
	Cloudy: iconCloudy,
	VeryCloudy: iconVeryCloudy,
	LightShowers: iconLightShowers,
	HeavyShowers: iconHeavyShowers,
	LightSnowShowers: iconLightSnowShowers,
	HeavySnowShowers: iconHeavySnowShowers,
	LightSleetShowers: iconLightSleetShowers,
	ThunderyShowers: iconThunderyShowers,
	ThunderyHeavyRain: iconThunderyHeavyRain,
	ThunderySnowShowers: iconThunderySnowShowers,
	HeavyRain: iconHeavyRain,
	LightSnow: iconLightSnow,
	HeavySnow: iconHeavySnow,
	LightSleet: iconLightSleet,
	Fog: iconFog
}

// 通过中文查找对于ICON
var findeIcon = function(str) {
	for (item in Weather) {
		if (Weather[item].chinese == str) {
			return Weather[item].icon;
		}
	}
	return Weather.Unknown.icon;
}

module.exports = {
	Weather: Weather,
	header: header,
	foot: foot,
	detail: detail,
	findeIcon: findeIcon
}

/*var content = [
	'',
	'  v' + "fis.cli.info.version",
	'',
	' __' + '/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'.bold.red + '__' + '/\\\\\\\\\\\\\\\\\\\\\\'.bold.yellow + '_____' + '/\\\\\\\\\\\\\\\\\\\\\\'.bold.green + '___',
	'  _' + '\\/\\\\\\///////////'.bold.red + '__' + '\\/////\\\\\\///'.bold.yellow + '____' + '/\\\\\\/////////\\\\\\'.bold.green + '_' + '       ',
	'   _' + '\\/\\\\\\'.bold.red + '_________________' + '\\/\\\\\\'.bold.yellow + '______' + '\\//\\\\\\'.bold.green + '______' + '\\///'.bold.green + '__',
	'    _' + '\\/\\\\\\\\\\\\\\\\\\\\\\'.bold.red + '_________' + '\\/\\\\\\'.bold.yellow + '_______' + '\\////\\\\\\'.bold.green + '_________' + '     ',
	'     _' + '\\/\\\\\\///////'.bold.red + '__________' + '\\/\\\\\\'.bold.yellow + '__________' + '\\////\\\\\\'.bold.green + '______' + '    ',
	'      _' + '\\/\\\\\\'.bold.red + '_________________' + '\\/\\\\\\'.bold.yellow + '_____________' + '\\////\\\\\\'.bold.green + '___' + '   ',
	'       _' + '\\/\\\\\\'.bold.red + '_________________' + '\\/\\\\\\'.bold.yellow + '______' + '/\\\\\\'.bold.green + '______' + '\\//\\\\\\'.bold.green + '__',
	'        _' + '\\/\\\\\\'.bold.red + '______________' + '/\\\\\\\\\\\\\\\\\\\\\\'.bold.yellow + '_' + '\\///\\\\\\\\\\\\\\\\\\\\\\/'.bold.green + '___',
	'         _' + '\\///'.bold.red + '______________' + '\\///////////'.bold.yellow + '____' + '\\///////////'.bold.green + '_____',
	''
].join('\n');
console.log(content);*/<commit_msg>添加一些颜色<commit_after>var chalk = require('chalk');

Object.getOwnPropertyNames(chalk.styles).forEach(function(item, index, arr) {
	Object.defineProperty(String.prototype, item, {
		get: function() {
			var ck = chalk[item](this);
			return ck;
		}
	})
});
var iconLightRain = {
	chinese: "阵雨",
	icon: [
		"     .-.     ",
		"    (   ).   ",
		"   (___(__)  ",
		"    ‘ ‘ ‘ ‘  ",
		"   ‘ ‘ ‘ ‘   "
	]
}
var iconUnknown = {
	chinese: "Unknown",
	icon: [
		"    .-.      ",
		"     __)     ",
		"    (        ",
		"     `-’     ",
		"      •      "
	]
}
var iconSunny = {
	chinese: "晴",
	icon: [
		"    \\   /    ".bold.yellow,
		"     .-.     ".bold.yellow,
		"  ― (   ) ―  ".bold.yellow,
		"     `-’     ".bold.yellow,
		"    /   \\    ".bold.yellow
	]
}
var iconPartlyCloudy = {
	chinese: "多云",
	icon: [
		"   \\  /".yellow+"      ",
		" _ /\"\".".yellow+"-.    ",
		"   \\".yellow+"_(   ).  ",
		"   /".yellow+"(___(__) ",
		"             "
	]

}
var iconCloudy = {
	chinese: "",
	icon: [
		"             ",
		"     .--.    ",
		"  .-(    ).  ",
		" (___.__)__) ",
		"             "
	]
}
var iconVeryCloudy = {
	chinese: "阴",
	icon: [
		"             ",
		"     .--.    ",
		"  .-(    ).  ",
		" (___.__)__) ",
		"             "
	]
}
var iconLightShowers = {
	chinese: "小雨",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"     ‘ ‘ ‘ ‘ ",
		"    ‘ ‘ ‘ ‘  "
	]
}
var iconHeavyShowers = {
	chinese: "大雨",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"   ‚‘‚‘‚‘‚‘  ",
		"   ‚’‚’‚’‚’  "
	]
}
var iconLightSnowShowers = {
	chinese: "",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"     *  *  * ",
		"    *  *  *  "
	]
}
var iconHeavySnowShowers = {
	chinese: "",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"    * * * *  ",
		"   * * * *   "
	]
}
var iconLightSleetShowers = {
	chinese: "",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"     ‘ * ‘ * ",
		"    * ‘ * ‘  "
	]
}
var iconThunderyShowers = {
	chinese: "",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"    ⚡‘ ‘⚡‘ ‘ ",
		"    ‘ ‘ ‘ ‘  "
	]
}
var iconThunderyHeavyRain = {
	chinese: "雷阵雨",
	icon: [
		"     .-.     ",
		"    (   ).   ",
		"   (___(__)  ",
		"  ‚‘⚡‘‚⚡‚‘   ".blue,
		"  ‚’‚’⚡’‚’   ".blue
	]
}
var iconThunderySnowShowers = {
	chinese: "",
	icon: [
		" _`/\"\".-.    ",
		"  ,\\_(   ).  ",
		"   /(___(__) ",
		"     *⚡ *⚡ * ",
		"    *  *  *  "
	]
}
var iconHeavyRain = {
	chinese: "暴雨",
	icon: [
		"     .-.     ",
		"    (   ).   ",
		"   (___(__)  ",
		"  ‚‘‚‘‚‘‚‘   ",
		"  ‚’‚’‚’‚’   "
	]
}
var iconLightSnow = {
	chinese: "小雪",
	icon: [
		"     .-.     ",
		"    (   ).   ",
		"   (___(__)  ",
		"    *  *  *  ",
		"   *  *  *   "
	]
}
var iconHeavySnow = {
	chinese: "大雪",
	icon: [
		"     .-.     ",
		"    (   ).   ",
		"   (___(__)  ",
		"   * * * *   ",
		"  * * * *    "
	]
}
var iconLightSleet = {
	chinese: "雨夹雪",
	icon: [
		"     .-.     ",
		"    (   ).   ",
		"   (___(__)  ",
		"    ‘ * ‘ *  ",
		"   * ‘ * ‘   "
	]
}
var iconFog = {
	chinese: "大雾",
	icon: [
		"             ",
		" _ - _ - _ - ",
		"  _ - _ - _  ",
		" _ - _ - _ - ",
		"             "
	]
}

// dateFmt应该占用15个字符,每个单元格30行
var header = function(dateFmt, time) {
	dateFmt = autoCompelete(dateFmt, 15);
	// time内的字符串需要为14位长度，不够补全
	for (var i = 0; i < time.length; i++) {
		time[i] = autoCompelete(time[i], 14);
	}

	return [
		"                                                       ┌─────────────┐                                                       ",
		"┌──────────────────────────────┬───────────────────────" + dateFmt + "───────────────────────┬──────────────────────────────┐",
		"│        " + time[0] + "        │        " + time[1] + " └──────┬──────┘ " + time[2] + "        │        " + time[3] + "        │",
		"├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤"
	]
}

// 根据长度补全空格
function autoCompelete(str, len) {
	var length = str.length;
	if (length < len) {
		var remainder = (len - length) % 2;
		if (remainder === 0) {
			var repeat = (new Array((len - length) / 2 + 1)).join(" ");
			str = repeat + str + repeat;
		} else {
			// 往左偏一个" "
			var repeat = (new Array((len - length - 1) / 2 + 1)).join(" ");
			str = repeat + str + repeat + " ";
		}
	} else if (length > len) {
		str = str.substr(0, len);
	}
	return str;
}

var foot = "└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘";

// 占宽16个符号，做对齐，最后一个符号固定为 |，右对齐
var detail = function(weather, temp, wd, ws, param, len, end) {
	var detail = [];
	detail.push(handleDetailStr(weather || "", len||15, end || "│"));
	detail.push(handleDetailStr(temp || "", len||15, end || "│"));
	detail.push(handleDetailStr(wd || "", len||15, end || "│"));
	detail.push(handleDetailStr(ws || "", len||15, end || "│"));
	detail.push(handleDetailStr(param || "", len||15, end || "│"));
	return detail;
}

//计算字符长度 中文字符是英文字符宽度的两倍,最大返回len个字符
function handleDetailStr(str, len, end) {
	var length = str.length;
	/*var len = 0;
	for (var i = 0; i < length; i++) {
		if (str.charCodeAt(i) >= 8000) {
			len += 2;
		} else {
			len++;
		}
		if (len == 15) {
			return str.substring(0, i)+"│";
		} else if (len > 15) {
			return str.substring(0, i - 1) + " │";
		}
	}*/
	var rp = repeat(" ", len - length);
	var brp = repeat(" ", 2);
	return brp + str + rp + end;
}

function repeat(target, n) {
	var s = target,
		total = "";
	while (n > 0) {
		if (n % 2 == 1) {
			total += s;
		}
		if (n == 1) {
			break;
		}
		s += s;
		n = n >> 1;
	}
	return total;
}

// 中文天气与icon字典映射
var Weather = {
	LightRain: iconLightRain,
	Unknown: iconUnknown,
	Sunny: iconSunny,
	PartlyCloudy: iconPartlyCloudy,
	Cloudy: iconCloudy,
	VeryCloudy: iconVeryCloudy,
	LightShowers: iconLightShowers,
	HeavyShowers: iconHeavyShowers,
	LightSnowShowers: iconLightSnowShowers,
	HeavySnowShowers: iconHeavySnowShowers,
	LightSleetShowers: iconLightSleetShowers,
	ThunderyShowers: iconThunderyShowers,
	ThunderyHeavyRain: iconThunderyHeavyRain,
	ThunderySnowShowers: iconThunderySnowShowers,
	HeavyRain: iconHeavyRain,
	LightSnow: iconLightSnow,
	HeavySnow: iconHeavySnow,
	LightSleet: iconLightSleet,
	Fog: iconFog
}

// 通过中文查找对于ICON
var findeIcon = function(str) {
	for (item in Weather) {
		if (Weather[item].chinese == str) {
			return Weather[item].icon;
		}
	}
	return Weather.Unknown.icon;
}

module.exports = {
	Weather: Weather,
	header: header,
	foot: foot,
	detail: detail,
	findeIcon: findeIcon
}

// 测试字符颜色
/*var content = [
	'',
	'  v' + "fis.cli.info.version",
	'',
	' __' + '/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'.bold.red + '__' + '/\\\\\\\\\\\\\\\\\\\\\\'.bold.yellow + '_____' + '/\\\\\\\\\\\\\\\\\\\\\\'.bold.green + '___',
	'  _' + '\\/\\\\\\///////////'.bold.red + '__' + '\\/////\\\\\\///'.bold.yellow + '____' + '/\\\\\\/////////\\\\\\'.bold.green + '_' + '       ',
	'   _' + '\\/\\\\\\'.bold.red + '_________________' + '\\/\\\\\\'.bold.yellow + '______' + '\\//\\\\\\'.bold.green + '______' + '\\///'.bold.green + '__',
	'    _' + '\\/\\\\\\\\\\\\\\\\\\\\\\'.bold.red + '_________' + '\\/\\\\\\'.bold.yellow + '_______' + '\\////\\\\\\'.bold.green + '_________' + '     ',
	'     _' + '\\/\\\\\\///////'.bold.red + '__________' + '\\/\\\\\\'.bold.yellow + '__________' + '\\////\\\\\\'.bold.green + '______' + '    ',
	'      _' + '\\/\\\\\\'.bold.red + '_________________' + '\\/\\\\\\'.bold.yellow + '_____________' + '\\////\\\\\\'.bold.green + '___' + '   ',
	'       _' + '\\/\\\\\\'.bold.red + '_________________' + '\\/\\\\\\'.bold.yellow + '______' + '/\\\\\\'.bold.green + '______' + '\\//\\\\\\'.bold.green + '__',
	'        _' + '\\/\\\\\\'.bold.red + '______________' + '/\\\\\\\\\\\\\\\\\\\\\\'.bold.yellow + '_' + '\\///\\\\\\\\\\\\\\\\\\\\\\/'.bold.green + '___',
	'         _' + '\\///'.bold.red + '______________' + '\\///////////'.bold.yellow + '____' + '\\///////////'.bold.green + '_____',
	''
].join('\n');
console.log(content);*/<|endoftext|>


<commit_before>var sys = require("sys");
var redis = require("./redisclient");

var client = new redis.Client();
client.connect(learn_to_count);

function learn_to_count () {
  client.incr('counter').addCallback(function (value) {
    sys.puts("counter is now " + value);
    client.close();
  }).addErrback(function (error) {
    sys.puts("oops! " + error);
    client.close();
  });
}
<commit_msg>Fixed example<commit_after>var sys = require("sys");
var redis = require("./redisclient");

var client = new redis.Client();
client.connect(learn_to_count);

function learn_to_count () {
  client.incr('counter', function (err, value) {
    if(!err) {
      sys.puts("counter is now " + value);
      client.close();
    }
    else {
      sys.puts("oops! " + error);
      client.close();
    }
  });
}
<|endoftext|>


<commit_before>/**
 * =================
 * MAIN - Start
 * =================
 * App launcher
 */

var	express = require("express"),
	http = require('http'),
	fs = require("fs"),
	path = require('path'),
	engine = require('ejs-locals'),
	connect = require('connect'),
	config = require("./config"),
	logger = require("./logger");

// Catch for all exception
process.on('uncaughtException', function (error) {
   logger.error(error.stack);
});

var securityActivated = config.getProperty("security.auth");
logger.warn("Security activated : " + securityActivated);

var sslActivated = config.getProperty("security.ssl");
logger.warn("SSL activated : " + sslActivated);

/* ------------------------
 * DB connection
 * ------------------------
 */
var Sequelize = require('sequelize-sqlite').sequelize;

var sequelize = new Sequelize(config.getProperty("db.name"), config.getProperty("db.username"), config.getProperty("db.password"), {
  dialect: 'sqlite',
  omitNull: true,
  storage: path.join(__dirname,'../'+config.getProperty("db.uri"))
})

/* ------------------------
 * Devices Drivers
 * ------------------------
 */

// Loading the drivers modules:
var	actuatorsDriversFiles = fs.readdirSync(path.join(__dirname,'drivers/actuators/')),
	sensorsDriversFiles = fs.readdirSync(path.join(__dirname,'drivers/sensors/')),

	sensorsDrivers = [],
	actuatorsDrivers = [];

for(var f in actuatorsDriversFiles) {
	var extension = actuatorsDriversFiles[f].slice(actuatorsDriversFiles[f].length-3, actuatorsDriversFiles[f].length);
	if (extension == '.js') {
		var type = actuatorsDriversFiles[f].slice(0, actuatorsDriversFiles[f].length-3); // Removing the '.js' extension
		actuatorsDrivers[type] = require(path.join(__dirname,'drivers/actuators/'+actuatorsDriversFiles[f]));
		logger.info('Actuators Driver - ' + type);
	}
}
for(var f in sensorsDriversFiles) {
	var extension = sensorsDriversFiles[f].slice(sensorsDriversFiles[f].length-3, sensorsDriversFiles[f].length);
	if (extension == '.js') {
		var type = sensorsDriversFiles[f].slice(0, sensorsDriversFiles[f].length-3); // Removing the '.js' extension
		sensorsDrivers[type] = require(path.join(__dirname,'drivers/sensors/'+sensorsDriversFiles[f]));
		logger.info('Sensors Driver - ' + type);
	}
}

/* ------------------------
 * MVC
 * ------------------------
 */

var	models = require('./models')(sequelize),
	services = require("./services")(models, sensorsDrivers, actuatorsDrivers, sequelize),
	views = require("./views")(services.local);

/* ------------------------
 * REST Server config
 * ------------------------
 */

var rest;
if(sslActivated) {
	rest = express({
		key: fs.readFileSync('security/server.key'),
		cert: fs.readFileSync('security/server.crt')
	});
} else {
	rest = express();
}
rest.configure(function() {
	rest.use(express.bodyParser()); // retrieves automatically req bodies
	rest.use(rest.router); // manually defines the routes
});

/* ------------------------
 * HTML Server config
 * ------------------------
 */
var html;
if(sslActivated) {
	html = express({
		key: fs.readFileSync('security/server.key'),
		cert: fs.readFileSync('security/server.crt')
	});
} else {
	html = express();
}

// Session config:
var	cookieParser = express.cookieParser(config.getProperty("session.secret")),
	sessionStore = new connect.middleware.session.MemoryStore();

html.configure(function() {
	// use ejs-locals for all ejs templates:
	html.engine('ejs', engine);
	html.use(express.bodyParser());
	html.use(express.static(__dirname + '/public'));
	html.set('views', __dirname + '/views');
	html.set('view engine', 'ejs');

	// Stuff needed for sessions
	html.use(cookieParser);
	html.use(express.session({ store: sessionStore }));
});

// Services:
for (var url in services.rest) {
	for (var action in services.rest[url]) {
		if (action == 'POST') {
			html.post('/api/'+url, services.rest[url][action]);
			logger.info('REST routing - '+url+' / POST defined');
		}
		else if (action == 'GET') {
			html.get('/api/'+url, services.rest[url][action]);
			logger.info('REST routing - '+url+' / GET defined');
		}
		else if (action == 'PUT') {
			html.put('/api/'+url, services.rest[url][action]);
			logger.info('REST routing - '+url+' / PUT defined');
		}
		else if (action == 'DELETE') {
			html.delete('/api/'+url, services.rest[url][action]);
			logger.info('REST routing - '+url+' / DELETE defined');
		}
		else {
			logger.error('Unknown HTTP action "'+action+'" for the URL '+url);
		}
	}
}

logger.warn("REST routes activated.");

// Different views of the HTML server :
viewHandler = {};
viewHandler["/(index)?"] = views.index;
viewHandler["/login"] = views.login;
viewHandler["/signin"] = views.signin;
viewHandler["/help"] = views.help;
viewHandler["/behaviors"] = views.behaviors;
viewHandler["/records"] = views.records;
viewHandler["/about"] = views.about;

viewHandler["*"] = views.notfound;

for (var url in viewHandler) {
	(securityActivated) ? /* TO DO */ html.get(url, viewHandler[url])
						: html.get(url, viewHandler[url]);
}

logger.warn("HTML Server routes activated.");
var serverHtml = http.createServer(html);
serverHtml.listen(config.getProperty("http.port"));

logger.warn("HTML Server is listening.");

// Loading the already-added devices:
services.local.loadDevices(function(err, dev) {
	if (!dev) { logger.error('<Device> Error when loading devices: ' + err); }
	logger.error('<Device> ' + dev.name + ' (type: ' + dev.type + ', customId: ' + dev.customId + ') - Error when loading: ' + err);
});
<commit_msg><WebServer> Fix an error handler.<commit_after>/**
 * =================
 * MAIN - Start
 * =================
 * App launcher
 */

var	express = require("express"),
	http = require('http'),
	fs = require("fs"),
	path = require('path'),
	engine = require('ejs-locals'),
	connect = require('connect'),
	config = require("./config"),
	logger = require("./logger");

// Catch for all exception
process.on('uncaughtException', function (error) {
   logger.error(error.stack);
});

var securityActivated = config.getProperty("security.auth");
logger.warn("Security activated : " + securityActivated);

var sslActivated = config.getProperty("security.ssl");
logger.warn("SSL activated : " + sslActivated);

/* ------------------------
 * DB connection
 * ------------------------
 */
var Sequelize = require('sequelize-sqlite').sequelize;

var sequelize = new Sequelize(config.getProperty("db.name"), config.getProperty("db.username"), config.getProperty("db.password"), {
  dialect: 'sqlite',
  omitNull: true,
  storage: path.join(__dirname,'../'+config.getProperty("db.uri"))
})

/* ------------------------
 * Devices Drivers
 * ------------------------
 */

// Loading the drivers modules:
var	actuatorsDriversFiles = fs.readdirSync(path.join(__dirname,'drivers/actuators/')),
	sensorsDriversFiles = fs.readdirSync(path.join(__dirname,'drivers/sensors/')),

	sensorsDrivers = [],
	actuatorsDrivers = [];

for(var f in actuatorsDriversFiles) {
	var extension = actuatorsDriversFiles[f].slice(actuatorsDriversFiles[f].length-3, actuatorsDriversFiles[f].length);
	if (extension == '.js') {
		var type = actuatorsDriversFiles[f].slice(0, actuatorsDriversFiles[f].length-3); // Removing the '.js' extension
		actuatorsDrivers[type] = require(path.join(__dirname,'drivers/actuators/'+actuatorsDriversFiles[f]));
		logger.info('Actuators Driver - ' + type);
	}
}
for(var f in sensorsDriversFiles) {
	var extension = sensorsDriversFiles[f].slice(sensorsDriversFiles[f].length-3, sensorsDriversFiles[f].length);
	if (extension == '.js') {
		var type = sensorsDriversFiles[f].slice(0, sensorsDriversFiles[f].length-3); // Removing the '.js' extension
		sensorsDrivers[type] = require(path.join(__dirname,'drivers/sensors/'+sensorsDriversFiles[f]));
		logger.info('Sensors Driver - ' + type);
	}
}

/* ------------------------
 * MVC
 * ------------------------
 */

var	models = require('./models')(sequelize),
	services = require("./services")(models, sensorsDrivers, actuatorsDrivers, sequelize),
	views = require("./views")(services.local);

/* ------------------------
 * REST Server config
 * ------------------------
 */

var rest;
if(sslActivated) {
	rest = express({
		key: fs.readFileSync('security/server.key'),
		cert: fs.readFileSync('security/server.crt')
	});
} else {
	rest = express();
}
rest.configure(function() {
	rest.use(express.bodyParser()); // retrieves automatically req bodies
	rest.use(rest.router); // manually defines the routes
});

/* ------------------------
 * HTML Server config
 * ------------------------
 */
var html;
if(sslActivated) {
	html = express({
		key: fs.readFileSync('security/server.key'),
		cert: fs.readFileSync('security/server.crt')
	});
} else {
	html = express();
}

// Session config:
var	cookieParser = express.cookieParser(config.getProperty("session.secret")),
	sessionStore = new connect.middleware.session.MemoryStore();

html.configure(function() {
	// use ejs-locals for all ejs templates:
	html.engine('ejs', engine);
	html.use(express.bodyParser());
	html.use(express.static(__dirname + '/public'));
	html.set('views', __dirname + '/views');
	html.set('view engine', 'ejs');

	// Stuff needed for sessions
	html.use(cookieParser);
	html.use(express.session({ store: sessionStore }));
});

// Services:
for (var url in services.rest) {
	for (var action in services.rest[url]) {
		if (action == 'POST') {
			html.post('/api/'+url, services.rest[url][action]);
			logger.info('REST routing - '+url+' / POST defined');
		}
		else if (action == 'GET') {
			html.get('/api/'+url, services.rest[url][action]);
			logger.info('REST routing - '+url+' / GET defined');
		}
		else if (action == 'PUT') {
			html.put('/api/'+url, services.rest[url][action]);
			logger.info('REST routing - '+url+' / PUT defined');
		}
		else if (action == 'DELETE') {
			html.delete('/api/'+url, services.rest[url][action]);
			logger.info('REST routing - '+url+' / DELETE defined');
		}
		else {
			logger.error('Unknown HTTP action "'+action+'" for the URL '+url);
		}
	}
}

logger.warn("REST routes activated.");

// Different views of the HTML server :
viewHandler = {};
viewHandler["/(index)?"] = views.index;
viewHandler["/login"] = views.login;
viewHandler["/signin"] = views.signin;
viewHandler["/help"] = views.help;
viewHandler["/behaviors"] = views.behaviors;
viewHandler["/records"] = views.records;
viewHandler["/about"] = views.about;

viewHandler["*"] = views.notfound;

for (var url in viewHandler) {
	(securityActivated) ? /* TO DO */ html.get(url, viewHandler[url])
						: html.get(url, viewHandler[url]);
}

logger.warn("HTML Server routes activated.");
var serverHtml = http.createServer(html);
serverHtml.listen(config.getProperty("http.port"));

logger.warn("HTML Server is listening.");

// Loading the already-added devices:
services.local.loadDevices(function(err, dev) {
	if (!dev) { logger.error('<Device> Error when loading devices: ' + err); }
	else logger.error('<Device> ' + dev.name + ' (type: ' + dev.type + ', customId: ' + dev.customId + ') - Error when loading: ' + err);
});
<|endoftext|>


<commit_before>// Import React
import React from "react";

// Import Spectacle Core tags
import {
  BlockQuote,
  Cite,
  Deck,
  Heading,
  ListItem,
  List,
  Quote,
  Slide,
  Text,
  Image,
  Appear,
  CodePane
} from "spectacle";

// Import image preloader util
import preloader from "spectacle/lib/utils/preloader";

// Import theme
import createTheme from "spectacle/lib/themes/default";

// Require CSS
require("normalize.css");
require("spectacle/lib/themes/default/index.css");

const images = {
  anchorman: require("../assets/anchorman.jpg"),
  reactiveDog: require("../assets/reactive_dog.jpg"),
  starlordConfused: require("../assets/starlord_confused.jpg"),
  nightmare: require("../assets/nightmare.jpg")
};

preloader(images);

const theme = createTheme({
  primary: "white",
  secondary: "#1F2022",
  tertiary: "#03A9FC",
  quartenary: "#CECECE"
}, {
  primary: "Monaco",
  secondary: "Helvetica"
});

export default class Presentation extends React.Component {
  render() {
    return (
      <Deck transition={["zoom", "slide"]} transitionDuration={500} theme={theme}>
        <Slide transition={["zoom"]} bgColor="primary">
          <Heading size={1} fit caps lineHeight={1} textColor="secondary">
            Reactive Programming
          </Heading>
          <Appear>
            <Heading size={6} caps lineHeight={1} textColor="secondary">
              - OR -
            </Heading>
          </Appear>
          <Appear>
            <Image src={images.starlordConfused.replace("/", "")} height="500px" width="500px" display="block" />
          </Appear>
        </Slide>

        <Slide transition={["slide"]} bgColor="secondary">
          <Heading size={6} textColor="primary" caps>What it does by definition...</Heading>

            <Text size={6} textColor="primary">
              Projects each element of an observable sequence into a new sequence of observable sequences by incorporating the element's index and then transforms an observable sequence of observable sequences into an observable sequence producing values only from the most recent observable sequence.
            </Text>

        </Slide>

        <Slide transition={["slide"]} bgColor="tertiary">
          <Heading size={4} textColor="primary">Feels like</Heading>
          <Image src={images.anchorman.replace("/", "")} height="500px" width="800px" />
        </Slide>

        <Slide transition={["slide"]} bgColor="secondary">
          <Heading size={4} textColor="primary" caps>Huh?</Heading>
          <List>
            <Appear>
              <ListItem textColor="primary" textSize="1.2em">
                Reactive programming is programming with asynchronous data streams.
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1.2em">
                Streams are event pipelines or your typical events, which you can observe and trigger side effects.
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1.2em">
                Streams are observables.
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1.2em">
                Observables can be subscribed to by observers which "react" to the observed stream data.
              </ListItem>
            </Appear>
          </List>
        </Slide>

        <Slide transition={["slide"]} bgColor="tertiary">
          <Heading size={4} textColor="primary" caps>Why?</Heading>
          <List>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                Managing user events flow is hard
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                Managing broadcast events is harder
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                Managing both is a NIGHTMARE
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                The bad news is you have to handle both
              </ListItem>
            </Appear>
          </List>
          <Appear>
            <Image src={images.nightmare.replace("/", "")} width="400" height="300" />
          </Appear>
        </Slide>

        <Slide transition={["slide"]} bgColor="secondary">
          <Heading size={4} textColor="primary" caps>How?</Heading>
          <List>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                The fundament of the implementation in reactive programming is the Observer Pattern.
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                The most popular library is Rx. It has multiple language implementations (JS, Python, Java, Scala, C# etc.)
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                RP can be useful both in UI and on the server side as a logical progression in event driven systems
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                These libraries provide great tools for composing and aggregating these events queues.
              </ListItem>
            </Appear>
          </List>
        </Slide>

        <Slide transition={["slide"]} bgColor="tertiary">
          <Heading size={4} textColor="primary" caps>When?</Heading>
          <List>
            <Appear>
              <ListItem textColor="primary">
                You have an UI with complex events on components
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary">
                You have a server side apps that need to have side effects based on async service calls.
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary">
                As a rule of thumb whenever the system has asynchronous service calls and side effects based on these service calls then there can be gains using the reactive approach
              </ListItem>
            </Appear>
          </List>
        </Slide>

        <Slide transition={["slide"]} bgColor="secondary">
          <Heading size={4} textColor="primary" caps>When (Examples)?</Heading>
          <List>
            <Appear>
              <ListItem textColor="primary">
                A grid-like component with functionality similar to MS Excel
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary">
                An interactive shared dashboard
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary">
                A web text editor
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary">
                A highly concurrent message queue
              </ListItem>
            </Appear>
          </List>
        </Slide>

        <Slide transition={["slide"]} bgColor="tertiary">
          <Heading size={4} textColor="primary" caps>Some Code Using Rx</Heading>
          <Heading size={6} textColor="primary" caps>...and Hello World</Heading>
          <CodePane
            lang="javascript"
            source={require("raw-loader!../assets/deck.example")}
            textSize="0.7em"
            margin="20px auto"
          />
        </Slide>

        <Slide transition={["fade"]} bgColor="secondary" textColor="primary">

          <Quote>
            <Image src={images.reactiveDog.replace("/", "")} width="500" height="500" />
          </Quote>
          Every Reactive Programmer Ever

        </Slide>
      </Deck>
    );
  }
}
<commit_msg>Fix some typos<commit_after>// Import React
import React from "react";

// Import Spectacle Core tags
import {
  BlockQuote,
  Cite,
  Deck,
  Heading,
  ListItem,
  List,
  Quote,
  Slide,
  Text,
  Image,
  Appear,
  CodePane
} from "spectacle";

// Import image preloader util
import preloader from "spectacle/lib/utils/preloader";

// Import theme
import createTheme from "spectacle/lib/themes/default";

// Require CSS
require("normalize.css");
require("spectacle/lib/themes/default/index.css");

const images = {
  anchorman: require("../assets/anchorman.jpg"),
  reactiveDog: require("../assets/reactive_dog.jpg"),
  starlordConfused: require("../assets/starlord_confused.jpg"),
  nightmare: require("../assets/nightmare.jpg")
};

preloader(images);

const theme = createTheme({
  primary: "white",
  secondary: "#1F2022",
  tertiary: "#03A9FC",
  quartenary: "#CECECE"
}, {
  primary: "Monaco",
  secondary: "Helvetica"
});

export default class Presentation extends React.Component {
  render() {
    return (
      <Deck transition={["zoom", "slide"]} transitionDuration={500} theme={theme}>
        <Slide transition={["zoom"]} bgColor="primary">
          <Heading size={1} fit caps lineHeight={1} textColor="secondary">
            Reactive Programming
          </Heading>
          <Appear>
            <Heading size={6} caps lineHeight={1} textColor="secondary">
              - OR -
            </Heading>
          </Appear>
          <Appear>
            <Image src={images.starlordConfused.replace("/", "")} height="500px" width="500px" display="block" />
          </Appear>
        </Slide>

        <Slide transition={["slide"]} bgColor="secondary">
          <Heading size={6} textColor="primary" caps>What it does by definition...</Heading>

            <Text size={6} textColor="primary">
              Projects each element of an observable sequence into a new sequence of observable sequences by incorporating the element's index and then transforms an observable sequence of observable sequences into an observable sequence producing values only from the most recent observable sequence.
            </Text>

        </Slide>

        <Slide transition={["slide"]} bgColor="tertiary">
          <Heading size={4} textColor="primary">Feels like</Heading>
          <Image src={images.anchorman.replace("/", "")} height="500px" width="800px" />
        </Slide>

        <Slide transition={["slide"]} bgColor="secondary">
          <Heading size={4} textColor="primary" caps>Huh?</Heading>
          <List>
            <Appear>
              <ListItem textColor="primary" textSize="1.2em">
                Reactive programming is programming with asynchronous data streams.
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1.2em">
                Streams are event pipelines or your typical events, which you can observe and trigger side effects.
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1.2em">
                Streams are observables.
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1.2em">
                Observables can be subscribed to by observers which "react" to the observed stream data.
              </ListItem>
            </Appear>
          </List>
        </Slide>

        <Slide transition={["slide"]} bgColor="tertiary">
          <Heading size={4} textColor="primary" caps>Why?</Heading>
          <List>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                Managing user events flow is hard
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                Managing broadcast events is harder
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                Managing both is a NIGHTMARE
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                The bad news is you have to handle both
              </ListItem>
            </Appear>
          </List>
          <Appear>
            <Image src={images.nightmare.replace("/", "")} width="400" height="300" />
          </Appear>
        </Slide>

        <Slide transition={["slide"]} bgColor="secondary">
          <Heading size={4} textColor="primary" caps>How?</Heading>
          <List>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                The fundament of the implementation in reactive programming is the Observer Pattern.
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                The most popular library is Rx. It has multiple language implementations (JS, Python, Java, Scala, C# etc.)
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                RP can be useful both in UI and on the server side as a logical progression in event driven systems
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary" textSize="1em">
                These libraries provide great tools for composing and aggregating these events queues.
              </ListItem>
            </Appear>
          </List>
        </Slide>

        <Slide transition={["slide"]} bgColor="tertiary">
          <Heading size={4} textColor="primary" caps>When?</Heading>
          <List>
            <Appear>
              <ListItem textColor="primary">
                You have an UI with complex events on components
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary">
                You have a server side app that need to have side effects based on async service calls.
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary">
                As a rule of thumb whenever the system has asynchronous service calls and side effects based on these service calls then there can be gains using the reactive approach
              </ListItem>
            </Appear>
          </List>
        </Slide>

        <Slide transition={["slide"]} bgColor="secondary">
          <Heading size={4} textColor="primary" caps>When (Examples)?</Heading>
          <List>
            <Appear>
              <ListItem textColor="primary">
                A grid-like component with functionality similar to MS Excel
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary">
                An interactive shared dashboard
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary">
                A web text editor
              </ListItem>
            </Appear>
            <Appear>
              <ListItem textColor="primary">
                A highly concurrent message queue
              </ListItem>
            </Appear>
          </List>
        </Slide>

        <Slide transition={["slide"]} bgColor="tertiary">
          <Heading size={4} textColor="primary" caps>Some Code Using Rx</Heading>
          <Heading size={6} textColor="primary" caps>...and Hello World</Heading>
          <CodePane
            lang="javascript"
            source={require("raw-loader!../assets/deck.example")}
            textSize="0.7em"
            margin="20px auto"
          />
        </Slide>

        <Slide transition={["fade"]} bgColor="secondary" textColor="primary">

          <Quote>
            <Image src={images.reactiveDog.replace("/", "")} width="500" height="500" />
          </Quote>
          Every Reactive Programmer Ever

        </Slide>
      </Deck>
    );
  }
}
<|endoftext|>


<commit_before>'use strict';

var clear          = require('es5-ext/object/clear')
  , setPrototypeOf = require('es5-ext/object/set-prototype-of')
  , d              = require('d/d')
  , iterator       = require('es6-iterator/valid-iterable')
  , forOf          = require('es6-iterator/for-of')
  , Set            = require('../polyfill')
  , Iterator       = require('./_iterator')

  , create = Object.create, defineProperties = Object.defineProperties
  , hasOwnProperty = Object.prototype.hasOwnProperty
  , PrimitiveSet;

module.exports = PrimitiveSet = function (/*iterable*/) {
	var iterable = arguments[0];
	if (!(this instanceof PrimitiveSet)) return new PrimitiveSet(iterable);
	if (this.__setData__ !== undefined) {
		throw new TypeError(this + " cannot be reinitialized");
	}
	if (iterable != null) iterator(iterable);
	defineProperties(this, {
		__setData__: d('', create(null)),
		__size__: d('w', 0)
	});
	if (!iterable) return;
	forOf(iterable, function (value) {
		var key = this._serialize(value);
		if (key == null) throw new TypeError(value + " cannot be serialized");
		if (hasOwnProperty.call(this.__setData__, key)) return;
		this.__setData__[key] = value;
		++this.__size__;
	}, this);
};
if (setPrototypeOf) setPrototypeOf(PrimitiveSet, Set);

PrimitiveSet.prototype = create(Set.prototype, {
	constructor: d(PrimitiveSet),
	_serialize: d(function (value) {
		if (value && (typeof value.toString !== 'function')) return null;
		return String(value);
	}),
	add: d(function (value) {
		var key = this._serialize(value);
		if (key == null) throw new TypeError(value + " cannot be serialized");
		if (hasOwnProperty.call(this.__setData__, key)) return this;
		this.__setData__[key] = value;
		++this.__size__;
		this.emit('_add', key);
		return this;
	}),
	clear: d(function () {
		if (!this.__size__) return;
		clear(this.__setData__);
		this.__size__ = 0;
		this.emit('_clear');
	}),
	delete: d(function (value) {
		var key = this._serialize(value);
		if (key == null) return false;
		if (!hasOwnProperty.call(this.__setData__, key)) return false;
		delete this.__setData__[key];
		--this.__size__;
		this.emit('_delete', key);
		return true;
	}),
	entries: d(function () { return new Iterator(this, 'key+value'); }),
	get: d(function (key) {
		key = this._serialize(key);
		if (key == null) return;
		return this.__setData__[key];
	}),
	has: d(function (value) {
		var key = this._serialize(value);
		if (key == null) return false;
		return hasOwnProperty.call(this.__setData__, key);
	}),
	size: d.gs(function () { return this.__size__; }),
	values: d(function () { return new Iterator(this); })
});
<commit_msg>Support `serialize` argument for primitive Sets<commit_after>'use strict';

var callable       = require('es5-ext/object/valid-callable')
  , clear          = require('es5-ext/object/clear')
  , setPrototypeOf = require('es5-ext/object/set-prototype-of')
  , d              = require('d/d')
  , iterator       = require('es6-iterator/valid-iterable')
  , forOf          = require('es6-iterator/for-of')
  , Set            = require('../polyfill')
  , Iterator       = require('./_iterator')

  , create = Object.create, defineProperties = Object.defineProperties
  , defineProperty = Object.defineProperty
  , hasOwnProperty = Object.prototype.hasOwnProperty
  , PrimitiveSet;

module.exports = PrimitiveSet = function (/*iterable, serialize*/) {
	var iterable = arguments[0], serialize = arguments[1];
	if (!(this instanceof PrimitiveSet)) {
		return new PrimitiveSet(iterable, serialize);
	}
	if (this.__setData__ !== undefined) {
		throw new TypeError(this + " cannot be reinitialized");
	}
	if (iterable != null) iterator(iterable);
	if (serialize != null) {
		callable(serialize);
		defineProperty(this, '_serialize', d('', serialize));
	}
	defineProperties(this, {
		__setData__: d('', create(null)),
		__size__: d('w', 0)
	});
	if (!iterable) return;
	forOf(iterable, function (value) {
		var key = this._serialize(value);
		if (key == null) throw new TypeError(value + " cannot be serialized");
		if (hasOwnProperty.call(this.__setData__, key)) return;
		this.__setData__[key] = value;
		++this.__size__;
	}, this);
};
if (setPrototypeOf) setPrototypeOf(PrimitiveSet, Set);

PrimitiveSet.prototype = create(Set.prototype, {
	constructor: d(PrimitiveSet),
	_serialize: d(function (value) {
		if (value && (typeof value.toString !== 'function')) return null;
		return String(value);
	}),
	add: d(function (value) {
		var key = this._serialize(value);
		if (key == null) throw new TypeError(value + " cannot be serialized");
		if (hasOwnProperty.call(this.__setData__, key)) return this;
		this.__setData__[key] = value;
		++this.__size__;
		this.emit('_add', key);
		return this;
	}),
	clear: d(function () {
		if (!this.__size__) return;
		clear(this.__setData__);
		this.__size__ = 0;
		this.emit('_clear');
	}),
	delete: d(function (value) {
		var key = this._serialize(value);
		if (key == null) return false;
		if (!hasOwnProperty.call(this.__setData__, key)) return false;
		delete this.__setData__[key];
		--this.__size__;
		this.emit('_delete', key);
		return true;
	}),
	entries: d(function () { return new Iterator(this, 'key+value'); }),
	get: d(function (key) {
		key = this._serialize(key);
		if (key == null) return;
		return this.__setData__[key];
	}),
	has: d(function (value) {
		var key = this._serialize(value);
		if (key == null) return false;
		return hasOwnProperty.call(this.__setData__, key);
	}),
	size: d.gs(function () { return this.__size__; }),
	values: d(function () { return new Iterator(this); })
});
<|endoftext|>


<commit_before>// Import React
import React from "react";
import mapValues from "lodash/mapValues";

// Import Spectacle Core tags
import {
  Appear,
  //BlockQuote,
  //Cite,
  CodePane,
  Deck,
  //Fill,
  Heading,
  Image,
  Layout,
  Link,
  List,
  ListItem,
  //Markdown,
  //Quote,
  Slide,
  Table,
  TableRow,
  TableHeaderItem,
  TableItem
  //Text
} from "spectacle";

import Counter from './counter_01';

// Import image preloader util
import preloader from "spectacle/lib/utils/preloader";

// Import theme
import createTheme from "spectacle/lib/themes/default";

// Require CSS
require("normalize.css");
require("spectacle/lib/themes/default/index.css");
require("./custom.css");

const slideTransition = ["slide"];
const images = mapValues({
  lifecycle: require("../images/lifecycle.png"),
  survivejs: require("../images/survivejs.png")
}, (v) => v.replace("/", ""));

preloader(images);

const theme = createTheme({
  primary: "white",
  secondary: "black",
  tertiary: "#09b5c4",
  quartenary: "rgba(255, 219, 169, 0.43)"
});

export default class Presentation extends React.Component {
  render() {
    return (
      <Deck transition={slideTransition} transitionDuration={500} theme={theme}>
        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={1} fit caps lineHeight={1} textColor="tertiary">
            React Components
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            React Philosophy
          </Heading>
          <List>
            <Appear><ListItem>Model your application as a component hierarchy</ListItem></Appear>
            <Appear><ListItem>Each component can have props and state</ListItem></Appear>
            <Appear><ListItem>Escape hatches through lifecycle methods and refs</ListItem></Appear>
            <Appear><ListItem>React forces you to think about state (a good thing!)</ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Components
          </Heading>
          <Layout>

                <TableRow>
                  <TableHeaderItem />
                  <TableHeaderItem>createClass</TableHeaderItem>
                  <TableHeaderItem>extends Component</TableHeaderItem>
                  <TableHeaderItem>Functions</TableHeaderItem>
                </TableRow>

                <Appear>
                  <TableRow>
                    <TableItem>props</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>context</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>refs</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>state</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem />
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>Lifecycle</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem />
                  </TableRow>
                </Appear>

          </Layout>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            React.Component
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Cat Counter
          </Heading>
          <Counter />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            <Link href="https://codesandbox.io/s/76gK41lrQ">React.Component</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            <Link href="https://codesandbox.io/s/NxXNAOZAK">No JSX</Link>
          </Heading>
          <CodePane
            lang="js"
            source={require("raw-loader!content!./counter_no_jsx.js")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            <Link href="https://codesandbox.io/s/JZxJgDqNg">React.Component</Link> with <Link href="https://github.com/tc39/proposal-class-public-fields">public fields (stage 2)</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_02.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            <Link href="https://codesandbox.io/s/3lBqVwL5A">React.Component</Link> with Function Style setState
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_03.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            <Link href="https://codesandbox.io/s/g5kzWv3Zl">React.Component</Link> with Function Style setState Extracted
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_04.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Fork the last code example at <Link href="https://codesandbox.io/">CodeSandbox</Link>. You can find a link to it in the header.</ListItem></Appear>
            <Appear><ListItem>1. Make it possible to add two cats at once</ListItem></Appear>
            <Appear><ListItem>2. Add a reset button to restore the count to zero*</ListItem></Appear>
            <Appear><ListItem>3. Add multiple options. Hint: [1, 2, 4].map(...). Look up React <Link href="https://facebook.github.io/react/docs/reconciliation.html">key</Link>. Why is it needed?**</ListItem></Appear>
            <Appear><ListItem>4. Try this.setState(..., cb)***</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/g5kzWv3Zl">0</Link>, <Link href="https://codesandbox.io/s/L98PX9kMp">1</Link>, <Link href="https://codesandbox.io/s/Q1qvPRW55">2</Link>, <Link href="https://codesandbox.io/s/31J17rM7n">3</Link>, <Link href="https://codesandbox.io/s/qvEWNmJ0">4</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            key
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!../examples/key_01.jsx")}
            margin="20px auto"
          />
          <Link href="https://facebook.github.io/react/docs/reconciliation.html">Read React reconciliation documentation to understand more</Link>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            Composition
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            <Link href="https://codesandbox.io/s/qvEWNmJ0">Why composition?</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!../examples/composition_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            <Link href="https://codesandbox.io/s/X6GyyXg9v">Decomposition</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!../examples/composition_02.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Decompose the counter as in the slides</ListItem></Appear>
            <Appear><ListItem>1. Implement App that contains multiple CatCounters</ListItem></Appear>
            <Appear><ListItem>2. Implement a generic Counter so you can count other things*</ListItem></Appear>
            <Appear><ListItem>3. Count total of all things in the user interface**</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/X6GyyXg9v">0</Link>, <Link href="https://codesandbox.io/s/73AKPwX3j">1</Link>, <Link href="https://codesandbox.io/s/O7L2zM0mg">2</Link>, <Link href="https://codesandbox.io/s/X64K29kMo">3</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            refs
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            React.Component with a ref
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!../examples/refs_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            Function based component with a ref
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!../examples/refs_02.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Capture a custom amount using an input and a ref</ListItem></Appear>
            <Appear><ListItem>1. Do the same without a ref*</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/VO7zJD0k5">0</Link> (can you see the bug?), <Link href="https://codesandbox.io/s/RoznJpjpE">1</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            Lifecycle Methods
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Lifecycle Methods
          </Heading>
          <Image src={images.lifecycle} margin="40px auto" height="324px" />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            shouldComponentUpdate(nextProps, nextState)
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!../examples/lifecycle_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Implement a shouldComponentUpdate at Counter so that it returns false and see when it gets triggered</ListItem></Appear>
            <Appear><ListItem>1. Implement a componentDidMount and componentWillUnmount to increase the count given an interval*</ListItem></Appear>
            <Appear><ListItem>2. Encapsulate timer logic within a {`<Timer interval={1000} onTick={() => ...} />`} component**</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/lO8pPZ2Zl">0</Link>, <Link href="https://codesandbox.io/s/JZpQ1Gm3K">1</Link>, <Link href="https://codesandbox.io/s/66m6MVMqN">2</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            Higher-Order Components
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            Why Higher-Order Components?
          </Heading>
          <List>
            <Appear><ListItem>Encapsulate a specific concern</ListItem></Appear>
            <Appear><ListItem>Examples: authenticated route, connect (pass state)</ListItem></Appear>
            <Appear><ListItem>Smaller slices to test</ListItem></Appear>
            <Appear><ListItem><Link href="https://facebook.github.io/react/docs/higher-order-components.html">Read React Higher-Order Components to learn more</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            Higher-Order Component Example
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!../examples/hoc_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Extract reset concern into withReset HOC that contains Counter reset related logic</ListItem></Appear>
            <Appear><ListItem>1. Extract custom value concern into withCustomValue HOC that contains Counter custom input related logic*</ListItem></Appear>
            <Appear><ListItem>2. <Link href="https://github.com/reactjs/redux/blob/master/docs/api/compose.md">compose</Link> withReset and withCustomValue together**</ListItem></Appear>
            <Appear><ListItem>3. Extract state into State HOC that contains React state related logic. <Link href="https://medium.com/merrickchristensen/function-as-child-components-5f3920a9ace9">Hint: use function as a child</Link>***</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/R6OWvlK30">0</Link>, <Link href="https://codesandbox.io/s/73v4G8MPr">1</Link>, <Link href="https://codesandbox.io/s/qjGPwAEwk">2</Link>, <Link href="https://codesandbox.io/s/j2GwNwQ54">3</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Link href="https://www.survivejs.com/">
            <Heading size={1}>
              SurviveJS
            </Heading>
          </Link>
          <Image src={images.survivejs} margin="0px auto 40px" height="524px"/>
        </Slide>

        <Slide transition={slideTransition} bgColor="tertiary">
          <Heading size={1} caps fit textColor="primary">
            Made in Finland by
          </Heading>
          <Link href="https://twitter.com/bebraw">
            <Heading caps fit size={2} textColor="secondary">
              Juho Vepsäläinen
            </Heading>
          </Link>
        </Slide>
      </Deck>
    );
  }
}
<commit_msg>fix: Fix linting error<commit_after>// Import React
import React from "react";
import mapValues from "lodash/mapValues";

// Import Spectacle Core tags
import {
  Appear,
  //BlockQuote,
  //Cite,
  CodePane,
  Deck,
  //Fill,
  Heading,
  Image,
  Layout,
  Link,
  List,
  ListItem,
  //Markdown,
  //Quote,
  Slide,
  Table,
  TableRow,
  TableHeaderItem,
  TableItem
  //Text
} from "spectacle";

import Counter from './counter_01';

// Import image preloader util
import preloader from "spectacle/lib/utils/preloader";

// Import theme
import createTheme from "spectacle/lib/themes/default";

// Require CSS
require("normalize.css");
require("spectacle/lib/themes/default/index.css");
require("./custom.css");

const slideTransition = ["slide"];
const images = mapValues({
  lifecycle: require("../images/lifecycle.png"),
  survivejs: require("../images/survivejs.png")
}, (v) => v.replace("/", ""));

preloader(images);

const theme = createTheme({
  primary: "white",
  secondary: "black",
  tertiary: "#09b5c4",
  quartenary: "rgba(255, 219, 169, 0.43)"
});

export default class Presentation extends React.Component {
  render() {
    return (
      <Deck transition={slideTransition} transitionDuration={500} theme={theme}>
        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={1} fit caps lineHeight={1} textColor="tertiary">
            React Components
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            React Philosophy
          </Heading>
          <List>
            <Appear><ListItem>Model your application as a component hierarchy</ListItem></Appear>
            <Appear><ListItem>Each component can have props and state</ListItem></Appear>
            <Appear><ListItem>Escape hatches through lifecycle methods and refs</ListItem></Appear>
            <Appear><ListItem>React forces you to think about state (a good thing!)</ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Components
          </Heading>
          <Layout>

                <TableRow>
                  <TableHeaderItem />
                  <TableHeaderItem>createClass</TableHeaderItem>
                  <TableHeaderItem>extends Component</TableHeaderItem>
                  <TableHeaderItem>Functions</TableHeaderItem>
                </TableRow>

                <Appear>
                  <TableRow>
                    <TableItem>props</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>context</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>refs</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>state</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem />
                  </TableRow>
                </Appear>
                <Appear>
                  <TableRow>
                    <TableItem>Lifecycle</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem>X</TableItem>
                    <TableItem />
                  </TableRow>
                </Appear>

          </Layout>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            React.Component
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Cat Counter
          </Heading>
          <Counter />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            <Link href="https://codesandbox.io/s/76gK41lrQ">React.Component</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            <Link href="https://codesandbox.io/s/NxXNAOZAK">No JSX</Link>
          </Heading>
          <CodePane
            lang="js"
            source={require("raw-loader!content!./counter_no_jsx.js")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            <Link href="https://codesandbox.io/s/JZxJgDqNg">React.Component</Link> with <Link href="https://github.com/tc39/proposal-class-public-fields">public fields (stage 2)</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_02.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            <Link href="https://codesandbox.io/s/3lBqVwL5A">React.Component</Link> with Function Style setState
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_03.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            <Link href="https://codesandbox.io/s/g5kzWv3Zl">React.Component</Link> with Function Style setState Extracted
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!./counter_04.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Fork the last code example at <Link href="https://codesandbox.io/">CodeSandbox</Link>. You can find a link to it in the header.</ListItem></Appear>
            <Appear><ListItem>1. Make it possible to add two cats at once</ListItem></Appear>
            <Appear><ListItem>2. Add a reset button to restore the count to zero*</ListItem></Appear>
            <Appear><ListItem>3. Add multiple options. Hint: [1, 2, 4].map(...). Look up React <Link href="https://facebook.github.io/react/docs/reconciliation.html">key</Link>. Why is it needed?**</ListItem></Appear>
            <Appear><ListItem>4. Try this.setState(..., cb)***</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/g5kzWv3Zl">0</Link>, <Link href="https://codesandbox.io/s/L98PX9kMp">1</Link>, <Link href="https://codesandbox.io/s/Q1qvPRW55">2</Link>, <Link href="https://codesandbox.io/s/31J17rM7n">3</Link>, <Link href="https://codesandbox.io/s/qvEWNmJ0">4</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            key
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!../examples/key_01.jsx")}
            margin="20px auto"
          />
          <Link href="https://facebook.github.io/react/docs/reconciliation.html">Read React reconciliation documentation to understand more</Link>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            Composition
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            <Link href="https://codesandbox.io/s/qvEWNmJ0">Why composition?</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!../examples/composition_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            <Link href="https://codesandbox.io/s/X6GyyXg9v">Decomposition</Link>
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!content!../examples/composition_02.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Decompose the counter as in the slides</ListItem></Appear>
            <Appear><ListItem>1. Implement App that contains multiple CatCounters</ListItem></Appear>
            <Appear><ListItem>2. Implement a generic Counter so you can count other things*</ListItem></Appear>
            <Appear><ListItem>3. Count total of all things in the user interface**</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/X6GyyXg9v">0</Link>, <Link href="https://codesandbox.io/s/73AKPwX3j">1</Link>, <Link href="https://codesandbox.io/s/O7L2zM0mg">2</Link>, <Link href="https://codesandbox.io/s/X64K29kMo">3</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            refs
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            React.Component with a ref
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!../examples/refs_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            Function based component with a ref
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!../examples/refs_02.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Capture a custom amount using an input and a ref</ListItem></Appear>
            <Appear><ListItem>1. Do the same without a ref*</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/VO7zJD0k5">0</Link> (can you see the bug?), <Link href="https://codesandbox.io/s/RoznJpjpE">1</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            Lifecycle Methods
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Lifecycle Methods
          </Heading>
          <Image src={images.lifecycle} margin="40px auto" height="324px" />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            shouldComponentUpdate(nextProps, nextState)
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!../examples/lifecycle_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Implement a shouldComponentUpdate at Counter so that it returns false and see when it gets triggered</ListItem></Appear>
            <Appear><ListItem>1. Implement a componentDidMount and componentWillUnmount to increase the count given an interval*</ListItem></Appear>
            <Appear><ListItem>2. Encapsulate timer logic within a {"<Timer interval={1000} onTick={() => ...} />"} component**</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/lO8pPZ2Zl">0</Link>, <Link href="https://codesandbox.io/s/JZpQ1Gm3K">1</Link>, <Link href="https://codesandbox.io/s/66m6MVMqN">2</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition} bgColor="secondary">
          <Heading size={2} textColor="tertiary">
            Higher-Order Components
          </Heading>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            Why Higher-Order Components?
          </Heading>
          <List>
            <Appear><ListItem>Encapsulate a specific concern</ListItem></Appear>
            <Appear><ListItem>Examples: authenticated route, connect (pass state)</ListItem></Appear>
            <Appear><ListItem>Smaller slices to test</ListItem></Appear>
            <Appear><ListItem><Link href="https://facebook.github.io/react/docs/higher-order-components.html">Read React Higher-Order Components to learn more</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2} fit>
            Higher-Order Component Example
          </Heading>
          <CodePane
            lang="jsx"
            source={require("raw-loader!../examples/hoc_01.jsx")}
            margin="20px auto"
          />
        </Slide>

        <Slide transition={slideTransition}>
          <Heading size={2}>
            Exercises
          </Heading>
          <List>
            <Appear><ListItem>0. Extract reset concern into withReset HOC that contains Counter reset related logic</ListItem></Appear>
            <Appear><ListItem>1. Extract custom value concern into withCustomValue HOC that contains Counter custom input related logic*</ListItem></Appear>
            <Appear><ListItem>2. <Link href="https://github.com/reactjs/redux/blob/master/docs/api/compose.md">compose</Link> withReset and withCustomValue together**</ListItem></Appear>
            <Appear><ListItem>3. Extract state into State HOC that contains React state related logic. <Link href="https://medium.com/merrickchristensen/function-as-child-components-5f3920a9ace9">Hint: use function as a child</Link>***</ListItem></Appear>
            <Appear><ListItem>Solutions: <Link href="https://codesandbox.io/s/R6OWvlK30">0</Link>, <Link href="https://codesandbox.io/s/73v4G8MPr">1</Link>, <Link href="https://codesandbox.io/s/qjGPwAEwk">2</Link>, <Link href="https://codesandbox.io/s/j2GwNwQ54">3</Link></ListItem></Appear>
          </List>
        </Slide>

        <Slide transition={slideTransition}>
          <Link href="https://www.survivejs.com/">
            <Heading size={1}>
              SurviveJS
            </Heading>
          </Link>
          <Image src={images.survivejs} margin="0px auto 40px" height="524px"/>
        </Slide>

        <Slide transition={slideTransition} bgColor="tertiary">
          <Heading size={1} caps fit textColor="primary">
            Made in Finland by
          </Heading>
          <Link href="https://twitter.com/bebraw">
            <Heading caps fit size={2} textColor="secondary">
              Juho Vepsäläinen
            </Heading>
          </Link>
        </Slide>
      </Deck>
    );
  }
}
<|endoftext|>


<commit_before>import { BackgroundColor } from "../Constants.js";

class Commands extends Phaser.State {

  create() {
    this.game.stage.setBackgroundColor(BackgroundColor);
    const moveText =  "Arrows keys/ Left Pad";
    const aimText = "Mouse cursor / A, Q, S, D";
    const redoText = "Left mouse button / B key";
    const eraseLayer =  "Right mouse button / Spacebar";

    this.game.add.text(350, 80, "Commands", { font: "bold 52px Arial", fill: "#8cc169", stroke: '#4D4D4D',strokeThickness: 1 });

    this.game.add.text(150, 225, "Move", { font: "bold 32px Arial", fill: "#fff" });
    this.game.add.text(500, 225, moveText, { font: "bold 32px Arial", fill: "#fff" });

    this.game.add.text(150, 300, "Aim", { font: "bold 32px Arial", fill: "#fff" });
    this.game.add.text(500, 300, aimText, { font: "bold 32px Arial", fill: "#fff" });

    this.game.add.text(150, 375, "Erase Layer", { font: "bold 32px Arial", fill: "#fff" });
    this.game.add.text(500, 375, eraseLayer, { font: "bold 32px Arial", fill: "#fff" });

    this.game.add.text(150, 450, "Rollback Layer", { font: "bold 32px Arial", fill: "#fff" });
    this.game.add.text(500, 450, redoText, { font: "bold 32px Arial", fill: "#fff" });

    this.enterButton = this.game.input.keyboard.addKey(Phaser.Keyboard.ENTER);
    this.game.input.gamepad.start();
  }

  update() {
    if(this.enterButton.isDown) {
      this.game.goToMainGame();
    }
  }

}

export default Commands;
<commit_msg>wording<commit_after>import { BackgroundColor } from "../Constants.js";

class Commands extends Phaser.State {

  create() {
    this.game.stage.setBackgroundColor(BackgroundColor);
    const moveText =  "Arrows keys/ Left Pad";
    const aimText = "Mouse cursor / A, Q, S, D keys";
    const redoText = "Left mouse button / Spacebar";
    const eraseLayer =  "B key";

    this.game.add.text(350, 80, "Commands", { font: "bold 52px Arial", fill: "#8cc169", stroke: '#4D4D4D',strokeThickness: 1 });

    this.game.add.text(150, 225, "Move", { font: "bold 32px Arial", fill: "#fff" });
    this.game.add.text(500, 225, moveText, { font: "bold 32px Arial", fill: "#fff" });

    this.game.add.text(150, 300, "Aim", { font: "bold 32px Arial", fill: "#fff" });
    this.game.add.text(500, 300, aimText, { font: "bold 32px Arial", fill: "#fff" });

    this.game.add.text(150, 375, "Erase Layer", { font: "bold 32px Arial", fill: "#fff" });
    this.game.add.text(500, 375, eraseLayer, { font: "bold 32px Arial", fill: "#fff" });

    this.game.add.text(150, 450, "Rollback Layer", { font: "bold 32px Arial", fill: "#fff" });
    this.game.add.text(500, 450, redoText, { font: "bold 32px Arial", fill: "#fff" });

    this.enterButton = this.game.input.keyboard.addKey(Phaser.Keyboard.ENTER);
    this.game.input.gamepad.start();
  }

  update() {
    if(this.enterButton.isDown) {
      this.game.goToMainGame();
    }
  }

}

export default Commands;
<|endoftext|>