From ece96eecba5cd880bf0cf7eea093fa107b4500a5 Mon Sep 17 00:00:00 2001 From: xuqingshan Date: Tue, 1 Sep 2020 22:18:31 +0800 Subject: [PATCH] feat: resume --- drawing.png | Bin 0 -> 795 bytes drawing2.png | Bin 0 -> 1212 bytes ...er\347\232\204\346\214\202\350\275\275.md" | 177 ++++ .../5.loadRouter\350\277\207\347\250\213.md" | 33 + .../eggsource/FileLoader.js" | 158 +++ .../eggsource/evtEmit.js" | 2 +- .../AppWorkerLoader.js" | 42 + .../EggLoader.js" | 302 ++++++ package.json | 1 + resume.md | 60 ++ resume_tmp.html | 452 +++++++++ test.js | 35 +- unittest/readme.md | 4 - .../package-lock.json" | 934 ------------------ .../package.json" | 19 - .../test\345\216\237\347\220\206/province.js" | 85 -- .../test\345\216\237\347\220\206/sub.js" | 3 - .../test\345\216\237\347\220\206/test.js" | 5 - .../test/a/sub.test.js" | 8 - .../test/province.test.js" | 42 - .../test/test.test.js" | 9 - .../test/time.test.js" | 22 - .../test\345\216\237\347\220\206/time.js" | 5 - ...73\351\231\244\345\271\277\345\221\212.js" | 11 + 24 files changed, 1262 insertions(+), 1147 deletions(-) create mode 100644 drawing.png create mode 100644 drawing2.png create mode 100644 "node\347\233\270\345\205\263/eggsource/4.loadController\347\232\204\346\214\202\350\275\275.md" create mode 100644 "node\347\233\270\345\205\263/eggsource/5.loadRouter\350\277\207\347\250\213.md" create mode 100644 "node\347\233\270\345\205\263/eggsource/FileLoader.js" create mode 100644 "node\347\233\270\345\205\263/eggsource/loder\347\273\247\346\211\277/AppWorkerLoader.js" create mode 100644 "node\347\233\270\345\205\263/eggsource/loder\347\273\247\346\211\277/EggLoader.js" create mode 100644 resume.md create mode 100644 resume_tmp.html delete mode 100644 unittest/readme.md delete mode 100644 "unittest/test\345\216\237\347\220\206/package-lock.json" delete mode 100644 "unittest/test\345\216\237\347\220\206/package.json" delete mode 100644 "unittest/test\345\216\237\347\220\206/province.js" delete mode 100644 "unittest/test\345\216\237\347\220\206/sub.js" delete mode 100644 "unittest/test\345\216\237\347\220\206/test.js" delete mode 100644 "unittest/test\345\216\237\347\220\206/test/a/sub.test.js" delete mode 100644 "unittest/test\345\216\237\347\220\206/test/province.test.js" delete mode 100644 "unittest/test\345\216\237\347\220\206/test/test.test.js" delete mode 100644 "unittest/test\345\216\237\347\220\206/test/time.test.js" delete mode 100644 "unittest/test\345\216\237\347\220\206/time.js" create mode 100644 "\344\270\223\351\242\230demo/\345\220\214\350\212\261\351\241\272\345\216\273\351\231\244\345\271\277\345\221\212.js" diff --git a/drawing.png b/drawing.png new file mode 100644 index 0000000000000000000000000000000000000000..a93c28895f5984b4ac218b1e3c8b4156cfe06602 GIT binary patch literal 795 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&0XCqB=G!1MAjOvC?d}4kf#9d}?s^6WrVE}f zjv*Dd-X3J+1qvQo@ZCR`pIrp3Vw4ySfuR-xA9DUVF)$i-ReS`w+|$+1Wt~$(69CZp B7?c12 literal 0 HcmV?d00001 diff --git a/drawing2.png b/drawing2.png new file mode 100644 index 0000000000000000000000000000000000000000..5c655d9bd12e8edb162fca65b8fb6806a1faf8c9 GIT binary patch literal 1212 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&0Vbfxvi_rq3=AyIo-U3d6}R4AHDo+sz;JlO zx<8ib22~MG56<7;mdnmC>D_AvhKiFMj2^~L43~NY8cdW~6wZ!vM?+&YF^uK~>J$Za YyZJeS^wrAKfTa?Hr>mdKI;Vst04qR7E&u=k literal 0 HcmV?d00001 diff --git "a/node\347\233\270\345\205\263/eggsource/4.loadController\347\232\204\346\214\202\350\275\275.md" "b/node\347\233\270\345\205\263/eggsource/4.loadController\347\232\204\346\214\202\350\275\275.md" new file mode 100644 index 0000000..680adf5 --- /dev/null +++ "b/node\347\233\270\345\205\263/eggsource/4.loadController\347\232\204\346\214\202\350\275\275.md" @@ -0,0 +1,177 @@ +```js +loadController(opt) { + this.timing.start('Load Controller'); + opt = Object.assign({ + caseStyle: 'lower', + directory: path.join(this.options.baseDir, 'app/controller'), + initializer: (obj, opt) => { + if (is.function(obj) && !is.generatorFunction(obj) && !is.class(obj) && !is.asyncFunction(obj)) { + obj = obj(this.app); + } + if (is.class(obj)) { + obj.prototype.pathName = opt.pathName; + obj.prototype.fullPath = opt.path; + return wrapClass(obj); + } + if (is.object(obj)) { + return wrapObject(obj, opt.path); + } + // support generatorFunction for forward compatbility + if (is.generatorFunction(obj) || is.asyncFunction(obj)) { + return wrapObject({ 'module.exports': obj }, opt.path)['module.exports']; + } + return obj; + }, + }, opt); + const controllerBase = opt.directory; + + this.loadToApp(controllerBase, 'controller', opt); + this.options.logger.info('[egg:loader] Controller loaded: %s', controllerBase); + this.timing.end('Load Controller'); + }, +``` + +1. opt: +```js + opt = Object.assign({ + caseStyle: 'lower', + directory: path.join(this.options.baseDir, 'app/controller'), + initializer: (obj, opt) => { + if (is.function(obj) && !is.generatorFunction(obj) && !is.class(obj) && !is.asyncFunction(obj)) { + obj = obj(this.app); + } + if (is.class(obj)) { + obj.prototype.pathName = opt.pathName; + obj.prototype.fullPath = opt.path; + return wrapClass(obj); + } + if (is.object(obj)) { + return wrapObject(obj, opt.path); + } + if (is.generatorFunction(obj) || is.asyncFunction(obj)) { + return wrapObject({ 'module.exports': obj }, opt.path)['module.exports']; + } + return obj; + }, + }, opt); + // opt 是 undefined,这个opt操作初始化了一个opt对象,供后续的fileloader调用 +``` +2. new FileLoader(opt)的过程; +将opt复制一份挂载到 this.options上; + +3. load过程: + 先parse: + files = ['**/*.js']; + directories = ['app/controller']; + 遍历app/controller下的所有文件 + 取出每个文件的: + properties, // app/service/foo/bar.js => [ 'foo', 'bar' ] + 将路径解析成字符串; + pathName,// 文件路径; + + exports = getExports(fullpath, this.options, pathName); + 获取controller内容,执行initializer; + obj.prototype.pathName = opt.pathName; + obj.prototype.fullPath = opt.path; + return wrapClass(obj); + +```js +// Get exports from filepath +// If exports is null/undefined, it will be ignored +function getExports(fullpath, { initializer, call, inject }, pathName) { + let exports = utils.loadFile(fullpath); + if (initializer) { + // { index1: classControllerMiddleware, + // index2: classControllerMiddleware + // } + exports = initializer(exports, { path: fullpath, pathName }); + } + if (is.class(exports) || is.generatorFunction(exports) || is.asyncFunction(exports)) { + return exports; + } + if (call && is.function(exports)) { + exports = exports(inject); + if (exports != null) { + return exports; + } + } + return exports; +} +``` + + 在wrapClass内部: + + ```js + // wrap the class, yield a object with middlewares + function wrapClass(Controller) { + let proto = Controller.prototype; + const ret = {}; + // tracing the prototype chain + while (proto !== Object.prototype) { + const keys = Object.getOwnPropertyNames(proto); + for (const key of keys) { + // getOwnPropertyNames will return constructor + // that should be ignored + if (key === 'constructor') { + continue; + } + // skip getter, setter & non-function properties + const d = Object.getOwnPropertyDescriptor(proto, key); + // prevent to override sub method + if (is.function(d.value) && !ret.hasOwnProperty(key)) { + ret[key] = methodToMiddleware(Controller, key); + ret[key][FULLPATH] = Controller.prototype.fullPath + '#' + Controller.name + '.' + key + '()'; + } + } + proto = Object.getPrototypeOf(proto); + } + return ret; + + function methodToMiddleware(Controller, key) { + return function classControllerMiddleware(...args) { + const controller = new Controller(this); + if (!this.app.config.controller || !this.app.config.controller.supportParams) { + args = [ this ]; + } + // fn.call(ctx, ...args); + return utils.callFn(controller[key], args, controller); + }; + } + } + + // 关键是这一句: + // ret[key] = methodToMiddleware(Controller, key); + // 将home.js里的所有方法放到ret[key]上。 + ``` + + +挂载的关键是 +```js +new FileLoader(opt).load(); +``` +整个过程是: + +1. this.loadController(); + +2. this.loadToApp(controllerBase, 'controller', opt); + +3. new FileLoader(opt).load(); + +4. this.parse(); + +5. this.load(); // 将controller里的各个方法挂到 appWorkerLoader.app.controller上 + +parse() 过程: + + directories = this.options.directory; // controller 目录 + 找到该目录下的所有文件: + 遍历每个文件取得 + properties = getProperties(filepath, this.options); + pathName + exports = getExports(fullpath, this.options, pathName); // 取得controller文件比如home.js里的所有方法, + item.push({fullpath, properties, exports}); + return item; + +load() 过程: + + diff --git "a/node\347\233\270\345\205\263/eggsource/5.loadRouter\350\277\207\347\250\213.md" "b/node\347\233\270\345\205\263/eggsource/5.loadRouter\350\277\207\347\250\213.md" new file mode 100644 index 0000000..324409a --- /dev/null +++ "b/node\347\233\270\345\205\263/eggsource/5.loadRouter\350\277\207\347\250\213.md" @@ -0,0 +1,33 @@ +this.loadFile(path.join(this.options.baseDir, 'app/router')); + +router的初始化,发生在解构赋值的时候 + +```js app/router.js + const { router, controller } = app; // TODO: app的router属性什么时候加上的。 +``` + +```js +class EggCore extends KoaApplication { + constructor(options = {}) {/**/} + /** + * get router + * @member {Router} EggCore#router + * @since 1.0.0 + */ + get router() { + console.log('enter router') + if (this[ROUTER]) { + return this[ROUTER]; + } + const router = this[ROUTER] = new Router({ sensitive: true }, this); + // register router middleware + this.beforeStart(() => { + this.use(router.middleware()); + }); + return router; + } +} +``` + +路由注册的时候,又引进来一个新的类Layer + diff --git "a/node\347\233\270\345\205\263/eggsource/FileLoader.js" "b/node\347\233\270\345\205\263/eggsource/FileLoader.js" new file mode 100644 index 0000000..cc84822 --- /dev/null +++ "b/node\347\233\270\345\205\263/eggsource/FileLoader.js" @@ -0,0 +1,158 @@ +class FileLoader { + + /** + * @class + * @param {Object} options - options + * @param {String|Array} options.directory - directories to be loaded + * @param {Object} options.target - attach the target object from loaded files + * @param {String} options.match - match the files when load, support glob, default to all js files + * @param {String} options.ignore - ignore the files when load, support glob + * @param {Function} options.initializer - custom file exports, receive two parameters, first is the inject object(if not js file, will be content buffer), second is an `options` object that contain `path` + * @param {Boolean} options.call - determine whether invoke when exports is function + * @param {Boolean} options.override - determine whether override the property when get the same name + * @param {Object} options.inject - an object that be the argument when invoke the function + * @param {Function} options.filter - a function that filter the exports which can be loaded + * @param {String|Function} options.caseStyle - set property's case when converting a filepath to property list. + */ + constructor(options) { + assert(options.directory, 'options.directory is required'); + assert(options.target, 'options.target is required'); + this.options = Object.assign({}, defaults, options); + + // compatible old options _lowercaseFirst_ + if (this.options.lowercaseFirst === true) { + deprecate('lowercaseFirst is deprecated, use caseStyle instead'); + this.options.caseStyle = 'lower'; + } + } + + /** + * attach items to target object. Mapping the directory to properties. + * `app/controller/group/repository.js` => `target.group.repository` + * @return {Object} target + * @since 1.0.0 + */ + load() { + const items = this.parse(); + const target = this.options.target; + // debugger; + for (const item of items) { + debug('loading item %j', item); + // item { properties: [ 'a', 'b', 'c'], exports } + // => target.a.b.c = exports + item.properties.reduce((target, property, index) => { + let obj; + const properties = item.properties.slice(0, index + 1).join('.'); + if (index === item.properties.length - 1) { + if (property in target) { + if (!this.options.override) throw new Error(`can't overwrite property '${properties}' from ${target[property][FULLPATH]} by ${item.fullpath}`); + } + obj = item.exports; + if (obj && !is.primitive(obj)) { + obj[FULLPATH] = item.fullpath; + obj[EXPORTS] = true; + } + } else { + obj = target[property] || {}; + } + target[property] = obj; + debug('loaded %s', properties); + return obj; + }, target); + } + return target; + } + + /** + * Parse files from given directories, then return an items list, each item contains properties and exports. + * + * For example, parse `app/controller/group/repository.js` + * + * ``` + * module.exports = app => { + * return class RepositoryController extends app.Controller {}; + * } + * ``` + * + * It returns a item + * + * ``` + * { + * properties: [ 'group', 'repository' ], + * exports: app => { ... }, + * } + * ``` + * + * `Properties` is an array that contains the directory of a filepath. + * + * `Exports` depends on type, if exports is a function, it will be called. if initializer is specified, it will be called with exports for customizing. + * @return {Array} items + * @since 1.0.0 + * 文件加载的这个class 明天看吧。 + */ + parse() { + let files = this.options.match; + if (!files) { + files = (process.env.EGG_TYPESCRIPT === 'true' && utils.extensions['.ts']) + ? [ '**/*.(js|ts)', '!**/*.d.ts' ] + : [ '**/*.js' ]; + } else { + files = Array.isArray(files) ? files : [ files ]; + } + + let ignore = this.options.ignore; + if (ignore) { + ignore = Array.isArray(ignore) ? ignore : [ ignore ]; + ignore = ignore.filter(f => !!f).map(f => '!' + f); + files = files.concat(ignore); + } + + let directories = this.options.directory; + if (!Array.isArray(directories)) { + directories = [ directories ]; + } + + const filter = is.function(this.options.filter) ? this.options.filter : null; + const items = []; + debug('parsing %j', directories); + for (const directory of directories) { + // debugger globby 之后跳到了路由文件,怎么做到的呢。TODO: 也算进步 + const filepaths = globby.sync(files, { cwd: directory }); + for (const filepath of filepaths) { + const fullpath = path.join(directory, filepath); + if (!fs.statSync(fullpath).isFile()) continue; + // get properties + // app/service/foo/bar.js => [ 'foo', 'bar' ] + const properties = getProperties(filepath, this.options); + // app/service/foo/bar.js => service.foo.bar + const pathName = directory.split(/[/\\]/).slice(-1) + '.' + properties.join('.'); + // get exports from the file + const exports = getExports(fullpath, this.options, pathName); + + // ignore exports when it's null or false returned by filter function + if (exports == null || (filter && filter(exports) === false)) continue; + + // set properties of class + if (is.class(exports)) { + exports.prototype.pathName = pathName; + exports.prototype.fullPath = fullpath; + } + + items.push({ fullpath, properties, exports }); + debug('parse %s, properties %j, export %j', fullpath, properties, exports); + } + } + + return items; + } + +} + +/** + * 两个方法:load 和 parse。 + * + * load时,将 + * + * parse时,将 controller/home.js + * 挂载到appWorkerLoader.app.controller上 + */ \ No newline at end of file diff --git "a/node\347\233\270\345\205\263/eggsource/evtEmit.js" "b/node\347\233\270\345\205\263/eggsource/evtEmit.js" index 4f9eee1..f017329 100644 --- "a/node\347\233\270\345\205\263/eggsource/evtEmit.js" +++ "b/node\347\233\270\345\205\263/eggsource/evtEmit.js" @@ -25,4 +25,4 @@ let eventListeners = eventEmitter.listenerCount('connection'); console.log(eventListeners) eventEmitter.emit('connection'); eventEmitter.removeListener('connection', listen1); -console.log(eventEmitter.listenerCount('connection')) \ No newline at end of file +console.log(eventEmitter.listenerCount('connection')) diff --git "a/node\347\233\270\345\205\263/eggsource/loder\347\273\247\346\211\277/AppWorkerLoader.js" "b/node\347\233\270\345\205\263/eggsource/loder\347\273\247\346\211\277/AppWorkerLoader.js" new file mode 100644 index 0000000..d48ec6c --- /dev/null +++ "b/node\347\233\270\345\205\263/eggsource/loder\347\273\247\346\211\277/AppWorkerLoader.js" @@ -0,0 +1,42 @@ +class AppWorkerLoader extends EggLoader { + + /** + * loadPlugin first, then loadConfig + * @since 1.0.0 + */ + loadConfig() { + this.loadPlugin(); + super.loadConfig(); + } + + /** + * Load all directories in convention + * @since 1.0.0 + */ + load() { + // app > plugin > core + this.loadApplicationExtend(); + this.loadRequestExtend(); + this.loadResponseExtend(); + this.loadContextExtend(); + this.loadHelperExtend(); + + this.loadCustomLoader(); + + // app > plugin + this.loadCustomApp(); + // app > plugin + this.loadService(); + // app > plugin > core + this.loadMiddleware(); + // app + this.loadController(); + // app + this.loadRouter(); // Dependent on controllers + } + +} + +/** + * 这一对的关系就是EggLoader封装,AppWorkerLoader调用 + */ \ No newline at end of file diff --git "a/node\347\233\270\345\205\263/eggsource/loder\347\273\247\346\211\277/EggLoader.js" "b/node\347\233\270\345\205\263/eggsource/loder\347\273\247\346\211\277/EggLoader.js" new file mode 100644 index 0000000..f7db38d --- /dev/null +++ "b/node\347\233\270\345\205\263/eggsource/loder\347\273\247\346\211\277/EggLoader.js" @@ -0,0 +1,302 @@ +class EggLoader { + /** + * @class + * @param {Object} options - options + * @param {String} options.baseDir - the directory of application + * @param {EggCore} options.app - Application instance + * @param {Logger} options.logger - logger + * @param {Object} [options.plugins] - custom plugins + * @since 1.0.0 + */ + constructor(options) { + this.options = options; + + this.app = this.options.app; + this.lifecycle = this.app.lifecycle; + this.timing = this.app.timing || new Timing(); + this[REQUIRE_COUNT] = 0; + + this.pkg = utility.readJSONSync(path.join(this.options.baseDir, 'package.json')); + this.eggPaths = this.getEggPaths(); + this.serverEnv = this.getServerEnv(); + this.appInfo = this.getAppInfo(); + this.serverScope = options.serverScope !== undefined + ? options.serverScope + : this.getServerScope(); + } + getServerEnv() { + let serverEnv = this.options.env; + + const envPath = path.join(this.options.baseDir, 'config/env'); + if (!serverEnv && fs.existsSync(envPath)) { + serverEnv = fs.readFileSync(envPath, 'utf8').trim(); + } + + if (!serverEnv) { + serverEnv = process.env.EGG_SERVER_ENV; + } + + if (!serverEnv) { + if (process.env.NODE_ENV === 'test') { + serverEnv = 'unittest'; + } else if (process.env.NODE_ENV === 'production') { + serverEnv = 'prod'; + } else { + serverEnv = 'local'; + } + } else { + serverEnv = serverEnv.trim(); + } + + return serverEnv; + } + getServerScope() { + return process.env.EGG_SERVER_SCOPE || ''; + } + getAppname() { + if (this.pkg.name) { + debug('Loaded appname(%s) from package.json', this.pkg.name); + return this.pkg.name; + } + const pkg = path.join(this.options.baseDir, 'package.json'); + throw new Error(`name is required from ${pkg}`); + } + getHomedir() { + // EGG_HOME for test + return process.env.EGG_HOME || homedir() || '/home/admin'; + } + + getAppInfo() { + const env = this.serverEnv; + const scope = this.serverScope; + const home = this.getHomedir(); + const baseDir = this.options.baseDir; + return { + /** + * The name of the application, retrieve from the name property in `package.json`. + * @member {String} AppInfo#name + */ + name: this.getAppname(), + + /** + * The current directory, where the application code is. + * @member {String} AppInfo#baseDir + */ + baseDir, + + /** + * The environment of the application, **it's not NODE_ENV** + * + * 1. from `$baseDir/config/env` + * 2. from EGG_SERVER_ENV + * 3. from NODE_ENV + * + * env | description + * --- | --- + * test | system integration testing + * prod | production + * local | local on your own computer + * unittest | unit test + * + * @member {String} AppInfo#env + * @see https://eggjs.org/zh-cn/basics/env.html + */ + env, + + /** + * @member {String} AppInfo#scope + */ + scope, + + /** + * The use directory, same as `process.env.HOME` + * @member {String} AppInfo#HOME + */ + HOME: home, + + /** + * parsed from `package.json` + * @member {Object} AppInfo#pkg + */ + pkg: this.pkg, + + /** + * The directory whether is baseDir or HOME depend on env. + * it's good for test when you want to write some file to HOME, + * but don't want to write to the real directory, + * so use root to write file to baseDir instead of HOME when unittest. + * keep root directory in baseDir when local and unittest + * @member {String} AppInfo#root + */ + root: env === 'local' || env === 'unittest' ? baseDir : home, + }; + } + + getEggPaths() { + // avoid require recursively + const EggCore = require('../egg'); + const eggPaths = []; + + let proto = this.app; + + // Loop for the prototype chain + while (proto) { + proto = Object.getPrototypeOf(proto); + // stop the loop if + // - object extends Object + // - object extends EggCore + if (proto === Object.prototype || proto === EggCore.prototype) { + break; + } + + assert(proto.hasOwnProperty(Symbol.for('egg#eggPath')), 'Symbol.for(\'egg#eggPath\') is required on Application'); + const eggPath = proto[Symbol.for('egg#eggPath')]; + assert(eggPath && typeof eggPath === 'string', 'Symbol.for(\'egg#eggPath\') should be string'); + assert(fs.existsSync(eggPath), `${eggPath} not exists`); + const realpath = fs.realpathSync(eggPath); + if (!eggPaths.includes(realpath)) { + eggPaths.unshift(realpath); + } + } + + return eggPaths; + } + + loadFile(filepath, ...inject) { + filepath = filepath && this.resolveModule(filepath); + if (!filepath) { + return null; + } + + // function(arg1, args, ...) {} + if (inject.length === 0) inject = [ this.app ]; + + let ret = this.requireFile(filepath); + console.log((ret)) + if (is.function(ret) && !is.class(ret)) { + ret = ret(...inject); // inject == app + } + return ret; + } + + requireFile(filepath) { + const timingKey = `Require(${this[REQUIRE_COUNT]++}) ${utils.getResolvedFilename(filepath, this.options.baseDir)}`; + this.timing.start(timingKey); + const ret = utils.loadFile(filepath); + this.timing.end(timingKey); + return ret; + } + + getLoadUnits() { + if (this.dirs) { + return this.dirs; + } + + const dirs = this.dirs = []; + + if (this.orderPlugins) { + for (const plugin of this.orderPlugins) { + dirs.push({ + path: plugin.path, + type: 'plugin', + }); + } + } + + // framework or egg path + for (const eggPath of this.eggPaths) { + dirs.push({ + path: eggPath, + type: 'framework', + }); + } + + // application + dirs.push({ + path: this.options.baseDir, + type: 'app', + }); + + debug('Loaded dirs %j', dirs); + return dirs; + } + + /** + * Load files using {@link FileLoader}, inject to {@link Application} + * @param {String|Array} directory - see {@link FileLoader} + * @param {String} property - see {@link FileLoader} + * @param {Object} opt - see {@link FileLoader} + * @since 1.0.0 + */ + loadToApp(directory, property, opt) { + // 将某个属性加载到app + const target = this.app[property] = {}; + opt = Object.assign({}, { + directory, + target, + inject: this.app, + }, opt); + + const timingKey = `Load "${String(property)}" to Application`; + this.timing.start(timingKey); + new FileLoader(opt).load(); + this.timing.end(timingKey); + } + + /** + * Load files using {@link ContextLoader} + * @param {String|Array} directory - see {@link ContextLoader} + * @param {String} property - see {@link ContextLoader} + * @param {Object} opt - see {@link ContextLoader} + * @since 1.0.0 + */ + loadToContext(directory, property, opt) { + opt = Object.assign({}, { + directory, + property, + inject: this.app, + }, opt); + + const timingKey = `Load "${String(property)}" to Context`; + this.timing.start(timingKey); + new ContextLoader(opt).load(); + this.timing.end(timingKey); + } + + get FileLoader() { + return FileLoader; + } + + /** + * @member {ContextLoader} EggLoader#ContextLoader + * @since 1.0.0 + */ + get ContextLoader() { + return ContextLoader; + } + + getTypeFiles(filename) { + const files = [ `${filename}.default` ]; + if (this.serverScope) files.push(`${filename}.${this.serverScope}`); + if (this.serverEnv === 'default') return files; + + files.push(`${filename}.${this.serverEnv}`); + if (this.serverScope) files.push(`${filename}.${this.serverScope}_${this.serverEnv}`); + return files; + } + + resolveModule(filepath) { + let fullPath; + try { + fullPath = require.resolve(filepath); + } catch (e) { + return undefined; + } + + if (process.env.EGG_TYPESCRIPT !== 'true' && fullPath.endsWith('.ts')) { + return undefined; + } + + return fullPath; + } +} \ No newline at end of file diff --git a/package.json b/package.json index 65554fc..87c3caa 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "eslint": "^5.16.0", "eslint-plugin-vue": "^5.0.0", "formidable": "^1.2.2", + "gm": "^1.23.1", "init": "^0.1.2", "koa": "^2.12.0", "koa-convert": "^1.2.0" diff --git a/resume.md b/resume.md new file mode 100644 index 0000000..5d85444 --- /dev/null +++ b/resume.md @@ -0,0 +1,60 @@ +## 个人信息 + +- 姓名:许青山 +- 性别:男 +- 出生年份: 1992 年 +- 学校专业: 硕士/通信工程/西安电子科技大学大学 +- 期望职位:前端工程师 +- 期望城市: 南京 +- 期望薪资:面议 + +## 联系方式 + +- 手机: 157-7191-0973 +- 邮箱: 1294898264@qq.com + +## 自我简介 + +- 2 年 前端 开发经验,熟练掌握 Web/H5 前端相关技术,熟练掌握 JavaScript、HTML、CSS 以及 Node 来搭建前端应用。了解原生 JavaScript 和 JavaScript 类库的使用,有较大型前端项目开发经验(React | Vue | Nuxt | egg )。 +- 熟悉node和vue,对前端工程化有基本了解。 +- 具有较强的学习能力和团队合作能力,分析和解决问题的能力,熟悉项目开发流程和团队协同工作。 + +## 个人经历 + +- 2020 年 5 月- 至今 天眼查 担任前端开发工程师 +- 2018年 6 月 -2020 年 5 月 vipkid 担任前端开发工程师 + +## 工作经历 + +#### 天眼查web + +- 项目地址 + + - https://www.tianyancha.com + +- 项目简介 + + - 天眼查web项目是天眼查主要的在线服务平台,核心功能是查公司,查老板,查关系。项目是一个基于egg的服务端渲染项目,seo非常良好 + +- 项目职责 + + - 主要负责整个web项目的迭代和重构。针对项目开发的页面不能实时重载问题,引入livereload,实现了实时改动页面的实时重载,大大提高了开发效率。 + - 针对项目中git使用混乱,易引起合作的低效问题,推动了git的标准化使用。针对项目中代码风格混乱和node版本不统一,推动了eslint的代码的标准检查和node锁定版本。 + +#### 大米网校H5主站 + +- 项目地址 + - [https://m.damiwangxiao.com/selling/](https://m.damiwangxiao.com/selling/) +- 项目简介 + - 大米网校m站是大米网校的h5项目,项目包含选课,订单、支付和添加辅导老师等功能。 + - 项目采用 Vue + webpack 来进行开发,是一个完整的配置化的商品售卖系统。 +- 项目职责 + - 主要负责整个项目的架构、开发和维护。从零到一的实现了项目的系统化,推动了项目的配置化。 + +#### vipkid内部库的开发和维护 + +- 项目简介 + - 基于公司各个项目的公共业务,抽离组件,提升开发效率。H5主站项目,活动项目等各种项目都需要有登陆,选课菜单,页面分享,资料列表等类似功能,每个项目重新过于低效,且不利于迭代,针对这种问题,分离出相关组件,打包成内部组件库供各端使用。 + - 基于运营方的强烈需求,封装了神策打点工具包。页面的访问效果对项目迭代的方向至关重要,运营活动效果的分析更加离不开用户对页面的访问数据。根据这一需求,封装了打点工具包。通过打点,可以很方便的分析页面的pv/uv 和各点击事件,以及漏斗。 +- 项目职责 + - 负责登陆组件、选课组件库的开发,负责神策打点包。 diff --git a/resume_tmp.html b/resume_tmp.html new file mode 100644 index 0000000..4b3bbb4 --- /dev/null +++ b/resume_tmp.html @@ -0,0 +1,452 @@ + + + +resume.md + + + + + + + + + + + + +

个人信息

+ +

联系方式

+ +

自我简介

+ +

个人经历

+ +

工作经历

+

天眼查web

+ +

大米网校H5主站

+ +

vipkid内部库的开发和维护

+ + + + diff --git a/test.js b/test.js index 840c735..9e2816b 100644 --- a/test.js +++ b/test.js @@ -1,12 +1,27 @@ -let Hi = require('./test2') +var fs = require('fs') + , gm = require('gm'); + + let x = 20, y = 20; +// annotate an image +let img = gm(300, 300, '#ffffff'); +img.drawText(0, y + 80, 'hello world.'); +img.fill('yellow'); // 填充 +img.stroke('#B79FE2'); +img.fontSize(30); +console.log(img.drawText) +img.drawText(0, 0, "from scratch", 'Center'); +// img.fill('red'); +// img.stroke('#B79FE2'); +// img.drawRectangle(x+ 60, y+ 60, x + 204, y + 200); +// // img.drawText(0, y + 80, 'hello world.'); +// // img.fill('#000000'); +// // img.stroke('#ffffff'); +// // img.drawText(0, y + 80, 'hello world.'); +// // img.fontSize(10); +// // img.drawText(0, y + 80, 'hello world.'); -console.log(typeof Hi) -new Hi('hello world.') -const fs = require('fs'); -const path = require('path'); -fs.unlinkSync(path.join(__dirname, 'a')); -fs.unlinkSync(path.join(__dirname, 'b')); -fs.unlinkSync(path.join(__dirname, 'c')); -fs.unlinkSync(path.join(__dirname, 'd')); -fs.unlinkSync(path.join(__dirname, 'e')); \ No newline at end of file +img.write("./drawing2.png", function (err) { + console.log('finish.') + if (!err) console.log('done'); +}); \ No newline at end of file diff --git a/unittest/readme.md b/unittest/readme.md deleted file mode 100644 index d630a33..0000000 --- a/unittest/readme.md +++ /dev/null @@ -1,4 +0,0 @@ -一直都有听说单元测试, -但工作中并没有用到这个东西, -而在前面学习《重构》时,重点降到了单元测试在重构中的重要地位 -是以,这里学习单元测试 \ No newline at end of file diff --git "a/unittest/test\345\216\237\347\220\206/package-lock.json" "b/unittest/test\345\216\237\347\220\206/package-lock.json" deleted file mode 100644 index 7a49b62..0000000 --- "a/unittest/test\345\216\237\347\220\206/package-lock.json" +++ /dev/null @@ -1,934 +0,0 @@ -{ - "name": "unittest", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "http://r.cnpmjs.org/ansi-regex/download/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "http://r.cnpmjs.org/ansi-styles/download/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "http://r.cnpmjs.org/assertion-error/download/assertion-error-1.1.0.tgz", - "integrity": "sha1-5gtrDo8wG9l+U3UhW9pAbIURjAs=" - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "http://r.cnpmjs.org/babel-code-frame/download/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "babel-core": { - "version": "6.26.3", - "resolved": "http://r.cnpmjs.org/babel-core/download/babel-core-6.26.3.tgz", - "integrity": "sha1-suLwnjQtDwyI4vAuBneUEl51wgc=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "http://r.cnpmjs.org/babel-generator/download/babel-generator-6.26.1.tgz", - "integrity": "sha1-GERAjTuPDTWkBOp6wYDwh6YBvZA=", - "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-helper-call-delegate/download/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "http://r.cnpmjs.org/babel-helper-define-map/download/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-helper-function-name/download/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-helper-get-function-arity/download/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-helper-hoist-variables/download/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-helper-optimise-call-expression/download/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "http://r.cnpmjs.org/babel-helper-regex/download/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-helper-replace-supers/download/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, - "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-helpers/download/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "http://r.cnpmjs.org/babel-messages/download/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "http://r.cnpmjs.org/babel-plugin-check-es2015-constants/download/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-arrow-functions/download/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-block-scoped-functions/download/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-block-scoping/download/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-classes/download/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-computed-properties/download/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-destructuring/download/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-duplicate-keys/download/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-for-of/download/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-function-name/download/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-literals/download/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-modules-amd/download/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-modules-commonjs/download/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha1-WKeThjqefKhwvcWogRF/+sJ9tvM=", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-modules-systemjs/download/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-modules-umd/download/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-object-super/download/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-parameters/download/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-shorthand-properties/download/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-spread/download/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-sticky-regex/download/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-template-literals/download/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-typeof-symbol/download/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-es2015-unicode-regex/download/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" - } - }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-regenerator/download/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, - "requires": { - "regenerator-transform": "^0.10.0" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-plugin-transform-strict-mode/download/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-preset-es2015": { - "version": "6.24.1", - "resolved": "http://r.cnpmjs.org/babel-preset-es2015/download/babel-preset-es2015-6.24.1.tgz", - "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.24.1", - "babel-plugin-transform-es2015-classes": "^6.24.1", - "babel-plugin-transform-es2015-computed-properties": "^6.24.1", - "babel-plugin-transform-es2015-destructuring": "^6.22.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1", - "babel-plugin-transform-es2015-for-of": "^6.22.0", - "babel-plugin-transform-es2015-function-name": "^6.24.1", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-plugin-transform-es2015-modules-systemjs": "^6.24.1", - "babel-plugin-transform-es2015-modules-umd": "^6.24.1", - "babel-plugin-transform-es2015-object-super": "^6.24.1", - "babel-plugin-transform-es2015-parameters": "^6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.24.1", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.22.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.24.1", - "babel-plugin-transform-regenerator": "^6.24.1" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "http://r.cnpmjs.org/babel-register/download/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, - "requires": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "http://r.cnpmjs.org/babel-runtime/download/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "http://r.cnpmjs.org/babel-template/download/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "http://r.cnpmjs.org/babel-traverse/download/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "http://r.cnpmjs.org/babel-types/download/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "http://r.cnpmjs.org/babylon/download/babylon-6.18.0.tgz", - "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "http://r.cnpmjs.org/balanced-match/download/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "http://r.cnpmjs.org/brace-expansion/download/brace-expansion-1.1.11.tgz", - "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chai": { - "version": "4.2.0", - "resolved": "http://r.cnpmjs.org/chai/download/chai-4.2.0.tgz", - "integrity": "sha1-dgqnLPION5XoSxKHfODoNzeqKeU=", - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://r.cnpmjs.org/chalk/download/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "check-error": { - "version": "1.0.2", - "resolved": "http://r.cnpmjs.org/check-error/download/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "http://r.cnpmjs.org/concat-map/download/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "http://r.cnpmjs.org/convert-source-map/download/convert-source-map-1.6.0.tgz", - "integrity": "sha1-UbU3qMQ+DwTewZk7/83VBOdYrCA=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "core-js": { - "version": "2.6.9", - "resolved": "http://r.cnpmjs.org/core-js/download/core-js-2.6.9.tgz", - "integrity": "sha1-a0shRiDINBUuF5Mjcn/Bl0GwhPI=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "http://r.cnpmjs.org/debug/download/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "http://r.cnpmjs.org/deep-eql/download/deep-eql-3.0.1.tgz", - "integrity": "sha1-38lARACtHI/gI+faHfHBR8S0RN8=", - "requires": { - "type-detect": "^4.0.0" - } - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "http://r.cnpmjs.org/detect-indent/download/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "http://r.cnpmjs.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "http://r.cnpmjs.org/esutils/download/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "http://r.cnpmjs.org/get-func-name/download/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" - }, - "globals": { - "version": "9.18.0", - "resolved": "http://r.cnpmjs.org/globals/download/globals-9.18.0.tgz", - "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=", - "dev": true - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "http://r.cnpmjs.org/has-ansi/download/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "http://r.cnpmjs.org/home-or-tmp/download/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } - }, - "invariant": { - "version": "2.2.4", - "resolved": "http://r.cnpmjs.org/invariant/download/invariant-2.2.4.tgz", - "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "is-finite": { - "version": "1.0.2", - "resolved": "http://r.cnpmjs.org/is-finite/download/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "http://r.cnpmjs.org/js-tokens/download/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "jsesc": { - "version": "1.3.0", - "resolved": "http://r.cnpmjs.org/jsesc/download/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "http://r.cnpmjs.org/json5/download/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "lodash": { - "version": "4.17.11", - "resolved": "http://r.cnpmjs.org/lodash/download/lodash-4.17.11.tgz", - "integrity": "sha1-s56mIp72B+zYniyN8SU2iRysm40=", - "dev": true - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "http://r.cnpmjs.org/loose-envify/download/loose-envify-1.4.0.tgz", - "integrity": "sha1-ce5R+nvkyuwaY4OffmgtgTLTDK8=", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "http://r.cnpmjs.org/minimatch/download/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "http://r.cnpmjs.org/minimist/download/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "http://r.cnpmjs.org/mkdirp/download/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "http://r.cnpmjs.org/ms/download/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "http://r.cnpmjs.org/number-is-nan/download/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "http://r.cnpmjs.org/os-homedir/download/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "http://r.cnpmjs.org/os-tmpdir/download/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "http://r.cnpmjs.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "pathval": { - "version": "1.1.0", - "resolved": "http://r.cnpmjs.org/pathval/download/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" - }, - "private": { - "version": "0.1.8", - "resolved": "http://r.cnpmjs.org/private/download/private-0.1.8.tgz", - "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=", - "dev": true - }, - "regenerate": { - "version": "1.4.0", - "resolved": "http://r.cnpmjs.org/regenerate/download/regenerate-1.4.0.tgz", - "integrity": "sha1-SoVuxLVuQHfFV1icroXnpMiGmhE=", - "dev": true - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "http://r.cnpmjs.org/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz", - "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=", - "dev": true - }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "http://r.cnpmjs.org/regenerator-transform/download/regenerator-transform-0.10.1.tgz", - "integrity": "sha1-HkmWg3Ix2ot/PPQRTXG1aRoGgN0=", - "dev": true, - "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" - } - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "http://r.cnpmjs.org/regexpu-core/download/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "http://r.cnpmjs.org/regjsgen/download/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "http://r.cnpmjs.org/regjsparser/download/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "http://r.cnpmjs.org/jsesc/download/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "repeating": { - "version": "2.0.1", - "resolved": "http://r.cnpmjs.org/repeating/download/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "http://r.cnpmjs.org/safe-buffer/download/safe-buffer-5.1.2.tgz", - "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=", - "dev": true - }, - "slash": { - "version": "1.0.0", - "resolved": "http://r.cnpmjs.org/slash/download/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "http://r.cnpmjs.org/source-map/download/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-support": { - "version": "0.4.18", - "resolved": "http://r.cnpmjs.org/source-map-support/download/source-map-support-0.4.18.tgz", - "integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "http://r.cnpmjs.org/strip-ansi/download/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "http://r.cnpmjs.org/supports-color/download/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "http://r.cnpmjs.org/to-fast-properties/download/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "http://r.cnpmjs.org/trim-right/download/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "type-detect": { - "version": "4.0.8", - "resolved": "http://r.cnpmjs.org/type-detect/download/type-detect-4.0.8.tgz", - "integrity": "sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw=" - } - } -} diff --git "a/unittest/test\345\216\237\347\220\206/package.json" "b/unittest/test\345\216\237\347\220\206/package.json" deleted file mode 100644 index be9254c..0000000 --- "a/unittest/test\345\216\237\347\220\206/package.json" +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "unittest", - "version": "1.0.0", - "description": "一直都有听说单元测试,\r 但工作中并没有用到这个东西,\r 而在前面学习《重构》时,重点降到了单元测试在重构中的重要地位\r 是以,这里学习单元测试", - "main": "test.js", - "scripts": { - "test": "mocha -t 5000 --recursive" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "chai": "^4.2.0" - }, - "devDependencies": { - "babel-core": "^6.26.3", - "babel-preset-es2015": "^6.24.1" - } -} diff --git "a/unittest/test\345\216\237\347\220\206/province.js" "b/unittest/test\345\216\237\347\220\206/province.js" deleted file mode 100644 index b17ed2c..0000000 --- "a/unittest/test\345\216\237\347\220\206/province.js" +++ /dev/null @@ -1,85 +0,0 @@ -class Province { - constructor(doc) { - this._name = doc.name - this._producers = [] - this._totalProduction = 0 - this._demand = doc.demand - this._price = doc.price - doc.producers.forEach( d => this.addProducer(new Producer(this, d))) - } - addProducer(arg) { - this._producers.push(arg) - this._totalProduction += arg.production - } - get name() {return this._name} - get producers() {return this._producers.slice()} - get totalProduction() {return this._totalProduction} - set totalProduction(arg) {this._totalProduction = arg} - - get demand() {return this._demand} - set demand(arg) {this._demand = arg} - - get price() {return this._price} - set price(arg) {this._price = arg} - - get shortfall() {return this._demand - this.totalProduction} - get profit() { - return this.demandValue - this.demandCost - } - get demandCost() { - let remainingDemand = this.demand - let result = 0 - this.producers - .sort((a, b) => a.cost - b.cost) - .forEach(p => { - const contribution = Math.min(remainingDemand, p.production) - remainingDemand -= contribution - result += contribution * p.cost - }) - return result - } - get demandValue() { - return this.satisfiedDemand * this.price - } - get satisfiedDemand() { - return Math.min(this._demand, this.totalProduction) - } -} -function sampleProvinceData() { - return { - name:'Asia', - producers: [ - {name: 'byz', cost: 10, production: 9}, - {name: 'atta', cost: 12, production: 10}, - {name: 'sino', cost: 10, production: 6} - ], - demand: 30, - price: 20 - } -} - -class Producer { - constructor(aProvince, data) { - this._province = aProvince - this._cost = data.cost - this._name = data.name - this._production = data.production || 0 - } - get name() {return this._name} - get cost() {return this._cost} - set cost(arg) {this._cost = arg} - - get production() {return this._production} - set production(amountStr) { - const amount = parseInt(amountStr) - const newProduction = Number.isNaN(amount) ? 0 : amount - this._province.totalProduction += newProduction - this._production - this._production = newProduction - } -} - -module.exports = { - Province, - sampleProvinceData, - Producer -} \ No newline at end of file diff --git "a/unittest/test\345\216\237\347\220\206/sub.js" "b/unittest/test\345\216\237\347\220\206/sub.js" deleted file mode 100644 index 49c12d4..0000000 --- "a/unittest/test\345\216\237\347\220\206/sub.js" +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = function sub(x, y) { - return x - y -} \ No newline at end of file diff --git "a/unittest/test\345\216\237\347\220\206/test.js" "b/unittest/test\345\216\237\347\220\206/test.js" deleted file mode 100644 index 516709d..0000000 --- "a/unittest/test\345\216\237\347\220\206/test.js" +++ /dev/null @@ -1,5 +0,0 @@ -function add (x, y) { - return x + y -} - -module.exports = add \ No newline at end of file diff --git "a/unittest/test\345\216\237\347\220\206/test/a/sub.test.js" "b/unittest/test\345\216\237\347\220\206/test/a/sub.test.js" deleted file mode 100644 index c9ac08d..0000000 --- "a/unittest/test\345\216\237\347\220\206/test/a/sub.test.js" +++ /dev/null @@ -1,8 +0,0 @@ -let sub = require('../../sub.js') -let expect = require('chai').expect - -describe('减法运算', function (params) { - it('2 - 1 should be 1', function () { - expect(sub(2, 1)).to.be.equal(1) - }) -}) diff --git "a/unittest/test\345\216\237\347\220\206/test/province.test.js" "b/unittest/test\345\216\237\347\220\206/test/province.test.js" deleted file mode 100644 index 3a43dec..0000000 --- "a/unittest/test\345\216\237\347\220\206/test/province.test.js" +++ /dev/null @@ -1,42 +0,0 @@ -let expect = require('chai').expect -let assert = require('chai').assert -let {Province, sampleProvinceData, Producer} = require('../province.js') - -describe('province', function() { - let asia - beforeEach(function() { - asia = new Province(sampleProvinceData()) - }) - it('shortfall', function() { - assert.equal(asia.shortfall, 5) - }) - it('profit', function() { - expect(asia.profit).equal(230) - }) - // it('shortfall', function() { - // expect(asia.shortfall).equal(-6) - // }) - // it('profit', function() { - // expect(asia.profit).equal(292) - // }) - -}) - -describe('no producers', function() { - let noProducers - beforeEach(function() { - const data = { - name: 'no producers', - producers: [], - demand: 30, - price: 20 - } - noProducers = new Province(data) - }) - it('shortfall', function() { - expect(noProducers.shortfall).equal(30) - }) - it('profit', function() { - expect(noProducers.profit).equal(0) - }) -}) \ No newline at end of file diff --git "a/unittest/test\345\216\237\347\220\206/test/test.test.js" "b/unittest/test\345\216\237\347\220\206/test/test.test.js" deleted file mode 100644 index baa2b09..0000000 --- "a/unittest/test\345\216\237\347\220\206/test/test.test.js" +++ /dev/null @@ -1,9 +0,0 @@ -let add = require('../test.js') -let time = require('../time.js') -let expect = require('chai').expect - -describe('加法函数测试', function (params) { - it ('1 add 1 应该等于2', function () { - expect(add(1, 1)).to.be.equal(2) - }) -}) diff --git "a/unittest/test\345\216\237\347\220\206/test/time.test.js" "b/unittest/test\345\216\237\347\220\206/test/time.test.js" deleted file mode 100644 index 1ae957c..0000000 --- "a/unittest/test\345\216\237\347\220\206/test/time.test.js" +++ /dev/null @@ -1,22 +0,0 @@ -var expect = require('chai').expect; - -describe('timeout.test.js - 超时测试', function() { - it.skip('测试应该 4000 毫秒后结束', function(done) { - var x = true; - var f = function() { - x = false; - expect(x).to.be.not.ok; - done(); - }; - setTimeout(f, 4000); - }); - it.skip('测试应该 5000 毫秒后结束', function(done) { - var x = true; - var f = function() { - x = false; - expect(x).to.be.not.ok; - done(); - }; - setTimeout(f, 4900); - }); -}); \ No newline at end of file diff --git "a/unittest/test\345\216\237\347\220\206/time.js" "b/unittest/test\345\216\237\347\220\206/time.js" deleted file mode 100644 index d5aad72..0000000 --- "a/unittest/test\345\216\237\347\220\206/time.js" +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = function time () { - setTimeout( () => { - return 'hello' - }, 3000) -} \ No newline at end of file diff --git "a/\344\270\223\351\242\230demo/\345\220\214\350\212\261\351\241\272\345\216\273\351\231\244\345\271\277\345\221\212.js" "b/\344\270\223\351\242\230demo/\345\220\214\350\212\261\351\241\272\345\216\273\351\231\244\345\271\277\345\221\212.js" new file mode 100644 index 0000000..636bfc4 --- /dev/null +++ "b/\344\270\223\351\242\230demo/\345\220\214\350\212\261\351\241\272\345\216\273\351\231\244\345\271\277\345\221\212.js" @@ -0,0 +1,11 @@ +function rmADs () { + for (let i=1; i<10; i++) { + let ele = document.getElementById('ad'+i); + ele && ele.setAttribute('style', 'display:none;') + } + for (let i=1; i<10; i++) { + let cls = document.getElementsByClassName('ad' + i); + if (cls && cls[0]); + cls[0].setAttribute('style', 'display:none;') + } +} \ No newline at end of file